diff -u --recursive --new-file v2.4.0-test2/linux/CREDITS linux/CREDITS --- v2.4.0-test2/linux/CREDITS Fri Jun 23 21:55:06 2000 +++ linux/CREDITS Sat Jul 8 19:44:07 2000 @@ -950,7 +950,7 @@ S: United Kingdom N: Kai Harrekilde-Petersen -E: khp@olicom.dk +E: kai.harrekilde@get2net.dk D: Original author of the ftape-HOWTO, i82078 fdc detection code. N: Bart Hartgers @@ -1112,6 +1112,15 @@ S: D-71679 Asperg S: Germany +N: Jan Hubicka +E: hubicka@freesoft.cz +E: hubicka@suse.cz +W: http://www.paru.cas.cz/~hubicka/ +D: Random kernel tweaks and fixes. +S: Dukelskych bojovniku 1944 +S: Tabor 390 03 +S: Czech Republic + N: Gareth Hughes E: gareth@valinux.com E: gareth@precisioninsight.com @@ -1216,6 +1225,10 @@ S: Mid Glamorgan, CF37 1NW, S: Wales, United Kingdom +N: Ani Joshi +E: ajoshi@shell.unixbox.com +D: fbdev hacking + N: Bernhard Kaindl E: bkaindl@netway.at E: edv@bartelt.via.at @@ -2588,7 +2601,7 @@ N: Geert Uytterhoeven E: geert@linux-m68k.org -W: http://www.cs.kuleuven.ac.be/~geert/ +W: http://home.tvd.be/cr26864/ P: 1024/EC4A1EE1 8B 88 38 35 88 1E 95 A1 CD 9E AE DC 4B 4A 2F 41 D: m68k/Amiga and PPC/CHRP Longtrail coordinator D: Frame buffer device and XF68_FBDev maintainer @@ -2662,10 +2675,10 @@ N: Tim Waugh E: tim@cyberelk.demon.co.uk D: Co-architect of the parallel-port sharing system -S: 34 Bladon Close +S: 17 Curling Vale S: GUILDFORD S: Surrey -S: GU1 1TY +S: GU2 7PJ S: United Kingdom N: Juergen Weigert @@ -2730,7 +2743,7 @@ N: Steven Whitehouse E: SteveW@ACM.org -W: http://www-sigproc.eng.cam.ac.uk/~sjw44/ +W: http://www.chygwyn.com/~steve D: Linux DECnet project: http://www.sucs.swan.ac.uk/~rohan/DECnet/index.html D: Minor debugging of other networking protocols. D: Misc bug fixes and filesystem development diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/Changes linux/Documentation/Changes --- v2.4.0-test2/linux/Documentation/Changes Fri Jun 23 21:55:06 2000 +++ linux/Documentation/Changes Mon Jun 26 12:02:37 2000 @@ -41,7 +41,7 @@ with pcmcia-cs. o Gnu C 2.7.2.3 # gcc --version -o binutils 2.9.1.0.7 # ld -v +o binutils 2.9.1.0.22 # ld -v o util-linux 2.10g # chsh -v o modutils 2.3.10 # insmod -V o e2fsprogs 1.18 # /sbin/tune2fs --version @@ -78,7 +78,7 @@ If you can, upgrade to the latest 2.9.5 binutils release. Older releases such as 2.8, 2.8.xx, and the FSF's 2.9.1 should be avoided if -at all possible. The later releases of 2.9.1.0.x (anything where x >= 7) +at all possible. The later releases of 2.9.1.0.x (anything where x >= 22) can and do compile the kernel properly, but there are many benefits to upgrading to 2.9.5 if you're up to it. @@ -248,8 +248,8 @@ 2.9.5 series ------------ -o ftp://ftp.varesearch.com/pub/support/hjl/binutils/binutils-2.9.5.0.29.tar.gz - +o ftp://ftp.varesearch.com/pub/support/hjl/binutils/binutils-2.9.5.0.46.tar.gz + System utilities **************** diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.4.0-test2/linux/Documentation/Configure.help Fri Jun 23 21:55:06 2000 +++ linux/Documentation/Configure.help Mon Jul 10 14:33:04 2000 @@ -1578,6 +1578,16 @@ more details about the Baget see the Linux/MIPS FAQ on http://oss.sgi.com/mips . +Support for Cobalt Microserver +CONFIG_COBALT_MICRO_SERVER + This enables support for the Cobalt Microserver. For more information + see the Linux/MIPS FAQ on http://oss.sgi.com/mips . + +Support for 2800 +CONFIG_COBALT_28 + This adds support for the Cobalt Microserver 2800. A kernel with this + option selected will only work on the 2800. + Support for DECstations CONFIG_DECSTATION This enables support for DEC's MIPS based workstations. For details @@ -2126,6 +2136,20 @@ If unsure, say N. +Legacy kernel start address +CONFIG_ALPHA_LEGACY_START_ADDRESS + The 2.4 kernel changed the kernel start address from 0x310000 + to 0x810000 to make room for the Wildfire's larger SRM console. + + If you're using aboot 0.7 or later, the bootloader will examine + the ELF headers to determine where to transfer control. Unfortunately, + most older bootloaders -- APB, or MILO -- hardcoded the kernel + start address rather than examining the ELF headers, and the result + is a hard lockup. + + Say Y if you have a broken bootloader. Say N if you do not, or + if you wish to run on Wildfire. + Non-standard serial port support CONFIG_SERIAL_NONSTANDARD Say Y here if you have any non-standard serial boards -- boards @@ -2745,7 +2769,7 @@ SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S. - "586" for generic Pentium CPUs, possibly lacking the TSC (time stamp counter) register. - - "Pentium" for the Intel Pentium/Pentium MMX. + - "Pentium-Classic" for the Intel Pentium/Pentium MMX. - "Pentium-Pro" for the Intel Pentium Pro/Celeron/Pentium II. - "Pentium-III" for the Intel Pentium III. - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D). @@ -2753,7 +2777,7 @@ - "Crusoe" for the Transmeta Crusoe series. - "Winchip-C6" for original IDT Winchip. - "Winchip-2" for IDT Winchip 2. - - "Winchip-2A/3" for IDT Winchips with 3dNow! capabilities. + - "Winchip-2A" for IDT Winchips with 3dNow! capabilities. If you don't know what to do, choose "386". @@ -3250,6 +3274,14 @@ If unsure, say N. +CONFIG_FB_SA1100 + This is a framebuffer device for the SA-1100 LCD Controller. + See http://www.linux-fbdev.org/ for information on framebuffer + devices. + + If you plan to use the LCD display with your SA-1100 system, say + Y here. + Advanced low level driver options CONFIG_FBCON_ADVANCED The frame buffer console uses character drawing routines that are @@ -4286,12 +4318,10 @@ modem), in order to send and receive AX.25 packet radio network traffic. - Currently, this driver supports Ottawa PI/PI2 - (http://hydra.carleton.ca/info/pi2.html ) and Gracilis PackeTwin - (http://www.paccomm.com/gracilis.html ) boards. They are detected - automatically. If you have one of these cards, say Y here and read - the AX25-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto . + Currently, this driver supports Ottawa PI/PI2, Paccomm/Gracilis + PackeTwin, and S5SCC/DMA boards. They are detected automatically. + If you have one of these cards, say Y here and read the AX25-HOWTO, + available from http://www.linuxdoc.org/docs.html#howto . This driver can operate multiple boards simultaneously. If you compile it as a module (by saying M instead of Y), it will be called @@ -4307,7 +4337,9 @@ certain parameters, such as channel access timing, clock mode, and DMA channel. This is accomplished with a small utility program, dmascc_cfg, available at - http://www.nt.tuwien.ac.at/~kkudielk/Linux/ . + http://www.nt.tuwien.ac.at/~kkudielk/Linux/ . Please be sure to get + at least version 1.27 of dmascc_cfg, as older versions will not + work with the current driver. Z8530 SCC driver for AX.25 CONFIG_SCC @@ -6430,6 +6462,14 @@ If unsure, say N. +Support for non-IEEE1394 local ports +CONFIG_IEEE1394_PCILYNX_PORTS + This option enables driver code to access the RAM, ROM and AUX ports + of the PCILynx through character devices in /dev. If you don't know + what this is about then you won't need it. + + If unsure, say N. + Adaptec AIC-5800 IEEE 1394 support CONFIG_IEEE1394_AIC5800 Say Y here if you have a IEEE 1394 controller using the Adaptec @@ -9800,7 +9840,38 @@ USB Keyspan PDA Single Port Serial Driver CONFIG_USB_SERIAL_KEYSPAN_PDA Say Y here if you want to use a Keyspan PDA single port USB to - serial converter device. + serial converter device. This driver makes use of firmware + developed from scratch by Brian Warner. + +USB Keyspan USA-xxx Serial Driver +CONFIG_USB_SERIAL_KEYSPAN + Say Y here if you want to use Keyspan USB to serial converter + devices. This driver makes use of Keyspan's official firmware + and was developed with their support. You must also include + firmware to support your particular device(s). + + See http://www.linuxcare.com.au/hugh/keyspan.html for + more information. + +USB Keyspan USA-28 Firmware +CONFIG_USB_SERIAL_KEYSPAN_USA28 + Say Y here to include firmware for the USA-28 converter. + +USB Keyspan USA-28X Firmware +CONFIG_USB_SERIAL_KEYSPAN_USA28X + Say Y here to include firmware for the USA-28X converter. + +USB Keyspan USA-19 Firmware +CONFIG_USB_SERIAL_KEYSPAN_USA19 + Say Y here to include firmware for the USA-19 converter. + +USB Keyspan USA-18X Firmware +CONFIG_USB_SERIAL_KEYSPAN_USA18X + Say Y here to include firmware for the USA-18X converter. + +USB Keyspan USA-19W Firmware +CONFIG_USB_SERIAL_KEYSPAN_USA19W + Say Y here to include firmware for the USA-19W converter. USB ZyXEL omni.net LCD Plus Driver CONFIG_USB_SERIAL_OMNINET @@ -10039,8 +10110,9 @@ Microtek USB scanner support CONFIG_USB_MICROTEK Say Y here if you want support for the Microtek X6USB and possibly - some other scanners. The scanner will appear as a scsi device to the - rest of the system. A patched version of SANE is necessary to use the + some other scanners by that vendor. The scanner will appear as a + scsi generic device to the rest of the system. + A patched version of SANE is necessary to use the scanner. It's available at http://fachschaft.cup.uni-muenchen.de/~neukum/scanner.html This driver can be compiled as a module. @@ -12425,10 +12497,15 @@ below, then ACPI has precedence in the sense that, if your hardware supports ACPI, it will be used and APM won't. - To compile this driver as a module ( = code which can be inserted in - and removed from the running kernel whenever you want), say M here - and read Documentation/modules.txt. The module will be called - acpi.o. +ACPI interpreter (EXPERIMENTAL) +CONFIG_ACPI_INTERPRETER + If you say Y here, an ACPI interpreter will be included in your + kernel, eventually making the full range of ACPI features + available on systems that support ACPI. Note, this option will + enlarge your kernel by about 120K. + + The interpreter is currently experimental so only say Y if + you know what you are doing. Enter S1 for sleep (EXPERIMENTAL) CONFIG_ACPI_S1_SLEEP @@ -15440,6 +15517,20 @@ If you have any questions or comments about the Compaq Personal Server, send e-mail to skiff@crl.dec.com +Include support for Assabet +CONFIG_SA1100_ASSABET + Say Y here if you are using the Intel(R) StrongARM(R) SA-1110 + Microprocessor Development Board (also known as the Assabet). + +Include support for the Compaq iPAQ 3600 +CONFIG_SA1100_BITSY + Say Y here if you intend to run this kernel on the Compaq iPAQ 3600 + handheld computer. Information about this machine and the Linux + port to this machine can be found at: + + http://www.handhelds.org/Compaq/index.html#iPAQ_H3600 + http://www.compaq.com/products/handhelds/pocketpc/ + Math emulation CONFIG_NWFPE Say Y to include the NWFPE floating point emulator in the kernel. @@ -15495,6 +15586,17 @@ footprint of the running kernel but it can increase the amount of time and disk space needed for compilation of the kernel. If in doubt say N. + +Kernel low-level debugging functions +CONFIG_DEBUG_LL + Say Y here to include definitions of printascii, printchar, printhex + in the kernel. This is helpful if you are debugging code that + executes before the console is initialized. + +Kernel low-level debugging messages via footbridge serial port +CONFIG_DEBUG_DC21285_PORT + Say Y here if you want the low-level print routines to direct their + output to the serial port in the DC21285 (Footbridge). Split initialisation functions into discardable section CONFIG_TEXT_SECTIONS diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/DocBook/kernel-locking.tmpl linux/Documentation/DocBook/kernel-locking.tmpl --- v2.4.0-test2/linux/Documentation/DocBook/kernel-locking.tmpl Fri Jun 23 21:55:06 2000 +++ linux/Documentation/DocBook/kernel-locking.tmpl Wed Jul 5 12:57:06 2000 @@ -947,8 +947,10 @@ - printk() can be called in - any context, interestingly enough. + + printk() can be called in + any context, interestingly enough. + diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/DocBook/parportbook.tmpl linux/Documentation/DocBook/parportbook.tmpl --- v2.4.0-test2/linux/Documentation/DocBook/parportbook.tmpl Tue May 23 15:31:32 2000 +++ linux/Documentation/DocBook/parportbook.tmpl Sat Jul 8 19:47:19 2000 @@ -24,30 +24,12 @@ - This documentation is free software; you can redistribute - it and/or modify it under the terms of the GNU General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later - version. - - - - This program is distributed in the hope that it will be - useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, - MA 02111-1307 USA - - - - For more details see the file COPYING in the source - distribution of Linux. + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation License, + Version 1.1 or any later version published by the Free Software + Foundation; with no Invariant Sections, with no Front-Cover Texts, + and with no Back-Cover Texts. A copy of the license is included + in the section entitled "GNU Free Documentation License". @@ -2209,9 +2191,9 @@ - + - API reference + Linux parallel port driver API reference !Fdrivers/parport/daisy.c parport_device_num @@ -2314,10 +2296,375 @@ removed. + + + + GNU Free Documentation License + + + + GNU Free Documentation License + Version 1.1, March 2000 + + Copyright (C) 2000 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +written document "free" in the sense of freedom: to assure everyone +the effective freedom to copy and redistribute it, with or without +modifying it, either commercially or noncommercially. Secondarily, +this License preserves for the author and publisher a way to get +credit for their work, while not being considered responsible for +modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work that contains a +notice placed by the copyright holder saying it can be distributed +under the terms of this License. The "Document", below, refers to any +such manual or work. Any member of the public is a licensee, and is +addressed as "you". + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (For example, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, whose contents can be viewed and edited directly and +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup has been designed to thwart or discourage +subsequent modification by readers is not Transparent. A copy that is +not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML designed for human modification. Opaque formats include +PostScript, PDF, proprietary formats that can be read and edited only +by proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML produced by some word processors for output +purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies of the Document numbering more than 100, +and the Document's license notice requires Cover Texts, you must enclose +the copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a publicly-accessible computer-network location containing a complete +Transparent copy of the Document, free of added material, which the +general network-using public has access to download anonymously at no +charge using public-standard network protocols. If you use the latter +option, you must take reasonably prudent steps, when you begin +distribution of Opaque copies in quantity, to ensure that this +Transparent copy will remain thus accessible at the stated location +until at least one year after the last time you distribute an Opaque +copy (directly or through your agents or retailers) of that edition to +the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has less than five). +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section entitled "History", and its title, and add to + it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. In any section entitled "Acknowledgements" or "Dedications", + preserve the section's title, and preserve in the section all the + substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section as "Endorsements" + or to conflict in title with any Invariant Section. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections entitled "History" +in the various original documents, forming one section entitled +"History"; likewise combine any sections entitled "Acknowledgements", +and any sections entitled "Dedications". You must delete all sections +entitled "Endorsements." + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, does not as a whole count as a Modified Version +of the Document, provided no compilation copyright is claimed for the +compilation. Such a compilation is called an "aggregate", and this +License does not apply to the other self-contained works thus compiled +with the Document, on account of their being thus compiled, if they +are not themselves derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one quarter +of the entire aggregate, the Document's Cover Texts may be placed on +covers that surround only the Document within the aggregate. +Otherwise they must appear on covers around the whole aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License provided that you also include the +original English version of this License. In case of a disagreement +between the translation and the original English version of this +License, the original English version will prevail. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +http:///www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.1 + or any later version published by the Free Software Foundation; + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have no Invariant Sections, write "with no Invariant Sections" +instead of saying which ones are invariant. If you have no +Front-Cover Texts, write "no Front-Cover Texts" instead of +"Front-Cover Texts being LIST"; likewise for Back-Cover Texts. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. + + + - diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/fb/framebuffer.txt linux/Documentation/fb/framebuffer.txt --- v2.4.0-test2/linux/Documentation/fb/framebuffer.txt Fri Jan 21 18:19:15 2000 +++ linux/Documentation/fb/framebuffer.txt Sat Jul 8 19:44:07 2000 @@ -332,7 +332,7 @@ The latest version of fbset can be found at - http://www.cs.kuleuven.ac.be/~geert/bin/ + http://home.tvd.be/cr26864/Linux/fbdev/ 10. Credits diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/fb/matroxfb.txt linux/Documentation/fb/matroxfb.txt --- v2.4.0-test2/linux/Documentation/fb/matroxfb.txt Sat Feb 26 22:31:37 2000 +++ linux/Documentation/fb/matroxfb.txt Wed Jul 5 11:55:45 2000 @@ -191,6 +191,10 @@ limitations which do not allow this. But this option is incompatible with some (if not all yet released) versions of XF86_FBDev. +dfp - enables digital flat panel interface. This option is incompatible with + secondary (TV) output - if DFP is active, TV output must be + inactive and vice versa. DFP always uses same timming as primary + (monitor) output. vesa:X - selects startup videomode. X is number from 0 to 0x1FF, see table above for detailed explanation. Default is 640x480x8bpp if driver has 8bpp support. Otherwise first available of 640x350x4bpp, diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/filesystems/Locking linux/Documentation/filesystems/Locking --- v2.4.0-test2/linux/Documentation/filesystems/Locking Wed Dec 31 16:00:00 1969 +++ linux/Documentation/filesystems/Locking Sat Jul 8 19:33:16 2000 @@ -0,0 +1,315 @@ + The text below describes the locking rules for VFS-related methods. +It is (believed to be) up-to-date. *Please*, if you change anything in +prototypes or locking protocols - update this file. And update the relevant +instances in the tree, don't leave that to maintainers of filesystems/devices/ +etc. At the very least, put the list of dubious cases in the end of this file. +Don't turn it into log - maintainers of out-of-the-tree code are supposed to +be able to use diff(1). + Thing currently missing here: socket operations. Alexey? + +--------------------------- dentry_operations -------------------------- +prototypes: + int (*d_revalidate)(struct dentry *, int); + int (*d_hash) (struct dentry *, struct qstr *); + int (*d_compare) (struct dentry *, struct qstr *, struct qstr *); + int (*d_delete)(struct dentry *); + void (*d_release)(struct dentry *); + void (*d_iput)(struct dentry *, struct inode *); + +locking rules: + none have BKL + dcache_lock may block +d_revalidate: no yes +d_hash no yes +d_compare: yes no +d_delete: yes no +d_release: no yes +d_iput: no yes + +--------------------------- inode_operations --------------------------- +prototypes: + int (*create) (struct inode *,struct dentry *,int); + struct dentry * (*lookup) (struct inode *,struct dentry *); + int (*link) (struct dentry *,struct inode *,struct dentry *); + int (*unlink) (struct inode *,struct dentry *); + int (*symlink) (struct inode *,struct dentry *,const char *); + int (*mkdir) (struct inode *,struct dentry *,int); + int (*rmdir) (struct inode *,struct dentry *); + int (*mknod) (struct inode *,struct dentry *,int,int); + int (*rename) (struct inode *, struct dentry *, + struct inode *, struct dentry *); + int (*readlink) (struct dentry *, char *,int); + int (*follow_link) (struct dentry *, struct nameidata *); + void (*truncate) (struct inode *); + int (*permission) (struct inode *, int); + int (*revalidate) (struct dentry *); + int (*setattr) (struct dentry *, struct iattr *); + int (*getattr) (struct dentry *, struct iattr *); + +locking rules: + all may block + BKL i_sem(inode) i_zombie(inode) +lookup: yes yes no +create: yes yes yes +link: yes yes yes +mknod: yes yes yes +mkdir: yes yes yes +unlink: yes yes yes +rmdir: yes yes yes (see below) +rename: yes yes (both) yes (both) (see below) +readlink: no no no +follow_link: no no no +truncate: yes yes no (see below) +setattr: yes if ATTR_SIZE no +permssion: yes no no +getattr: (see below) +revalidate: no (see below) + Additionally, ->rmdir() has i_zombie on victim and so does ->rename() +in case when target exists and is a directory. + ->revalidate(), it may be called both with and without the i_sem +on dentry->d_inode. VFS never calls it with i_zombie on dentry->d_inode, +but watch for other methods directly calling this one... + ->truncate() is never called directly - it's a callback, not a +method. It's called by vmtruncate() - library function normally used by +->setattr(). Locking information above applies to that call (i.e. is +inherited from ->setattr() - vmtruncate() is used when ATTR_SIZE had been +passed). + ->getattr() is currently unused. + +--------------------------- super_operations --------------------------- +prototypes: + void (*read_inode) (struct inode *); + void (*write_inode) (struct inode *, int); + void (*put_inode) (struct inode *); + void (*delete_inode) (struct inode *); + void (*put_super) (struct super_block *); + void (*write_super) (struct super_block *); + int (*statfs) (struct super_block *, struct statfs *); + int (*remount_fs) (struct super_block *, int *, char *); + void (*clear_inode) (struct inode *); + void (*umount_begin) (struct super_block *); + +locking rules: + All may block. + BKL s_lock mount_sem +read_inode: yes (see below) +write_inode: no +put_inode: no +delete_inode: no +clear_inode: no +put_super: yes yes maybe (see below) +write_super: yes yes maybe (see below) +statfs: yes no no +remount_fs: yes yes maybe (see below) +umount_begin: yes no maybe (see below) + +->read_inode() is not a method - it's a callback used in iget()/iget4(). +rules for mount_sem are not too nice - it is going to die and be replaced +by better scheme anyway. + +--------------------------- file_system_type --------------------------- +prototypes: + struct super_block *(*read_super) (struct super_block *, void *, int); +locking rules: +may block BKL ->s_lock mount_sem +yes yes yes maybe + +--------------------------- address_space_operations -------------------------- +prototypes: + int (*writepage)(struct file *, struct page *); + int (*readpage)(struct file *, struct page *); + int (*sync_page)(struct page *); + int (*prepare_write)(struct file *, struct page *, unsigned, unsigned); + int (*commit_write)(struct file *, struct page *, unsigned, unsigned); + int (*bmap)(struct address_space *, long); +locking rules: + All may block + BKL PageLocked(page) +writepage: no yes +readpage: no yes +sync_page: no maybe +prepare_write: no yes +commit_write: no yes +bmap: yes + + ->prepare_write(), ->commit_write(), ->sync_page() and ->readpage() +may be called from the request handler (/dev/loop). + ->sync_page() locking rules are not well-defined - usually it is called +with lock on page, but that is not guaranteed. Considering the currently +existsing instances of this method ->sync_page() itself doesn't look +well-defined... + ->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some +filesystems and by the swapper. The latter will eventually go away. All +instances do not actually need the BKL. Please, keep it that way and don't +breed new callers. + Note: currently almost all instances of address_space methods are +using BKL for internal serialization and that's one of the worst sources +of contention. Normally they are calling library functions (in fs/buffer.c) +and pass foo_get_block() as a callback (on local block-based filesystems, +indeed). BKL is not needed for library stuff and is usually taken by +foo_get_block(). It's an overkill, since block bitmaps can be protected by +internal fs locking and real critical areas are much smaller than the areas +filesystems protect now. + +--------------------------- file_lock ------------------------------------ +prototypes: + void (*fl_notify)(struct file_lock *); /* unblock callback */ + void (*fl_insert)(struct file_lock *); /* lock insertion callback */ + void (*fl_remove)(struct file_lock *); /* lock removal callback */ + +locking rules: + BKL may block +fl_notify: yes no +fl_insert: yes maybe +fl_remove: yes maybe + Currently only NLM provides instances of this class. None of the +them block. If you have out-of-tree instances - please, show up. Locking +in that area will change. + +--------------------------- buffer_head ----------------------------------- +prototypes: + void (*b_end_io)(struct buffer_head *bh, int uptodate); + +locking rules: + called from interrupts. In other words, extreme care is needed here. +bh is locked, but that's all warranties we have here. Currently only RAID1, +highmem and fs/buffer.c are providing these. Block devices call this method +upon the IO completion. + +--------------------------- block_device_operations ----------------------- +prototypes: + int (*open) (struct inode *, struct file *); + int (*release) (struct inode *, struct file *); + int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); + int (*check_media_change) (kdev_t); + int (*revalidate) (kdev_t); +locking rules: + BKL bd_sem +open: yes yes +release: yes yes +ioctl: yes no +check_media_change: yes no +revalidate: yes no + +The last two are called only from check_disk_change(). Prototypes are very +bad - as soon as we'll get disk_struct they will change (and methods will +become per-disk instead of per-partition). + +--------------------------- file_operations ------------------------------- +prototypes: + loff_t (*llseek) (struct file *, loff_t, int); + ssize_t (*read) (struct file *, char *, size_t, loff_t *); + ssize_t (*write) (struct file *, const char *, size_t, loff_t *); + int (*readdir) (struct file *, void *, filldir_t); + unsigned int (*poll) (struct file *, struct poll_table_struct *); + int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); + int (*mmap) (struct file *, struct vm_area_struct *); + int (*open) (struct inode *, struct file *); + int (*flush) (struct file *); + int (*release) (struct inode *, struct file *); + int (*fsync) (struct file *, struct dentry *, int datasync); + int (*fasync) (int, struct file *, int); + int (*lock) (struct file *, int, struct file_lock *); + ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); + ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); +}; + +locking rules: + All except ->poll() may block. + BKL +llseek: yes +read: no +write: no +readdir: yes (see below) +poll: no +ioctl: yes (see below) +mmap: no +open: maybe (see below) +flush: yes +release: yes +fsync: yes (see below) +fasync: yes (see below) +lock: yes +readv: no +writev: no + +->open() locking is in-transit: big lock partially moved into the methods. +The only exception is ->open() in the instances of file_operations that never +end up in ->i_fop/->proc_fops, i.e. ones that belong to character devices +(chrdev_open() takes lock before replacing ->f_op and calling the secondary +method. As soon as we fix the handling of module reference counters all +instances of ->open() will be called without the BKL. At the same point +->release() will lose BKL. Currently ext2_release() is *the* source of +contention on fs-intensive loads and dropping BKL on ->release() will get +rid of that (we will still need some locking for cases when we close a file +that had been opened r/w, but that can be done using the internal locking with +smaller critical areas). sock_close() is also going to win from that change. + +->fasync() is a mess. This area needs a big cleanup and that will probably +affect locking. + +->readdir() and ->ioctl() on directories must be changed. Ideally we would +move ->readdir() to inode_operations and use a separate method for directory +->ioctl() or kill the latter completely. One of the problems is that for +anything that resembles union-mount we won't have a struct file for all +components. And there are other reasons why the current interface is a mess... + +->read on directories probably must go away - we should just enforce -EISDIR +in sys_read() and friends. + +->fsync() has i_sem on inode. + +--------------------------- dquot_operations ------------------------------- +prototypes: + void (*initialize) (struct inode *, short); + void (*drop) (struct inode *); + int (*alloc_block) (const struct inode *, unsigned long, char); + int (*alloc_inode) (const struct inode *, unsigned long); + void (*free_block) (const struct inode *, unsigned long); + void (*free_inode) (const struct inode *, unsigned long); + int (*transfer) (struct dentry *, struct iattr *); + +locking rules: + BKL +initialize: no +drop: no +alloc_block: yes +alloc_inode: yes +free_block: yes +free_inode: yes +transfer: no + +--------------------------- vm_operations_struct ----------------------------- +prototypes: + void (*open)(struct vm_area_struct*); + void (*close)(struct vm_area_struct*); + void (*unmap)(struct vm_area_struct*, unsigned long, size_t); + void (*protect)(struct vm_area_struct*, unsigned long, size_t, unsigned); + int (*sync)(struct vm_area_struct*, unsigned long, size_t, unsigned); + struct page *(*nopage)(struct vm_area_struct*, unsigned long, int); + struct page *(*wppage)(struct vm_area_struct*, unsigned long, struct page*); + int (*swapout)(struct page *, struct file *); + +locking rules: + BKL mmap_sem +open: no yes +close: no yes +sync: no yes +unmap: no yes +nopage: no yes +swapout: yes yes +wpppage: (see below) +protect: (see below) + +->wppage() and ->protect() have no instances and nothing calls them; looks like +they must die... + +================================================================================ + Dubious stuff + +(if you break something or notice that it is broken and do not fix it yourself +- at least put it here) + +ipc/shm.c::shm_delete() - may need BKL. +->read() and ->write() in many drivers are (probably) missing BKL. +drivers/sgi/char/graphics.c::sgi_graphics_nopage() - may need BKL. diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/filesystems/devfs/ChangeLog linux/Documentation/filesystems/devfs/ChangeLog --- v2.4.0-test2/linux/Documentation/filesystems/devfs/ChangeLog Fri Jun 23 21:55:06 2000 +++ linux/Documentation/filesystems/devfs/ChangeLog Wed Jul 5 21:36:49 2000 @@ -1576,3 +1576,40 @@ - Changed interface to - Changed interface to +=============================================================================== +Changes for patch v173 + +Work sponsored by SGI + +- Simplified interface to + +- Simplified interface to + +- Simplified interface to +=============================================================================== +Changes for patch v174 + +Work sponsored by SGI + +- Updated README from master HTML file +=============================================================================== +Changes for patch v175 + +Work sponsored by SGI + +- DocBook update for fs/devfs/base.c + Thanks to Tim Waugh + +- Removed stale fs/tunnel.c (was never used or completed) +=============================================================================== +Changes for patch v176 + +Work sponsored by SGI + +- Updated ToDo list + +- Removed sample modules.conf: now distributed with devfsd + +- Updated README from master HTML file + +- Ported to kernel 2.4.0-test3-pre4 (which had devfs-patch-v174) diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/filesystems/devfs/README linux/Documentation/filesystems/devfs/README --- v2.4.0-test2/linux/Documentation/filesystems/devfs/README Fri Jun 23 21:55:06 2000 +++ linux/Documentation/filesystems/devfs/README Wed Jul 5 21:36:49 2000 @@ -3,7 +3,7 @@ Linux Devfs (Device File System) FAQ Richard Gooch -14-JUN-2000 +3-JUL-2000 ----------------------------------------------------------------------------- @@ -20,7 +20,8 @@ NEWFLASH: The official 2.3.46 kernel has included the devfs patch. Future patches will be released which -build on this. +build on this. These patches are rolled into Linus' tree from time to +time. A mailing list is available which you may subscribe to. Send email @@ -99,11 +100,11 @@ devfs namespace. The cost of devfs is a small increase in kernel code size and memory -usage. About 7 pages of code (some of that in __init sections) and 49 -bytes for each entry in the namespace (93 bytes if you access the -inode). A modest system has only a couple of hundred device entries, -so this costs a few more pages. Compare this with the suggestion to -put /dev on a ramdisc. +usage. About 7 pages of code (some of that in __init sections) and 72 +bytes for each entry in the namespace. A modest system has only a +couple of hundred device entries, so this costs a few more +pages. Compare this with the suggestion to put /dev on a ramdisc. On a typical machine, the cost is under 0.2 percent. On a modest system with 64 MBytes of RAM, the cost is under 0.1 percent. The @@ -497,6 +498,8 @@ Chroot() gaols +2.2.x kernels + The semantics of inode creation are different when devfs is mounted with the "explicit" option. Now, when a device entry is registered, it will not appear until you use mknod() to create the device. It doesn't @@ -506,6 +509,31 @@ gaol. Only the devices you specifically want to be available (through your mknod() setup) will be accessible. +2.4.x kernels + +As of kernel 2.3.99, the VFS has had the ability to rebind parts of +the global filesystem namespace into another part of the namespace. +This now works even at the leaf-node level, which means that +individual files and device nodes may be bound into other parts of the +namespace. This is like making links, but better, because it works +across filesystems (unlike hard links) and works through chroot() +gaols (unlike symbolic links). + +Because of these improvements to the VFS, the multi-mount capability +in devfs is no longer needed. The administrator may create a minimal +device tree inside a chroot(2) gaol by using VFS bindings. As this +provides most of the features of the devfs multi-mount capability, I +removed the multi-mount support code (after issuing an RFC). This +yielded code size reductions and simplifications. + +If you want to construct a minimal chroot() gaol, the following +command should suffice: + +mount -t bind /dev/null /gaol/dev/null + + +Repeat for other device nodes you want to expose. Simple! + ----------------------------------------------------------------------------- @@ -598,11 +626,11 @@ # man 5 console.perms # file classes -- these are regular expressions --=tty[0-9][0-9]* :[0-9]\.[0-9] :[0-9] -+=tty[0-9][0-9]* [0-9][0-9]* :[0-9]\.[0-9] :[0-9] +-=tty[0-9][0-9]* :[0-9]\.[0-9] :[0-9] ++=tty[0-9][0-9]* [0-9][0-9]* :[0-9]\.[0-9] :[0-9] # device classes -- these are shell-style globs - =/dev/fd[0-1]* + =/dev/fd[0-1]* Disable devpts @@ -692,6 +720,44 @@ permissions for whole groups of devices with a single configuration entry, rather than the conventional single entry per device entry. +Permissions database stored in mounted-over /dev + +If you wish to save and restore your device permissions into the +disc-based /dev while still mounting devfs onto /dev +you may do so. This requires a 2.4.x kernel (in fact, 2.3.99 or +later), which has the VFS binding facility. You need to do the +following to set this up: + + + +make sure the kernel does not mount devfs at boot time + + +create the /dev-state directory + + +add the following lines near the very beginning of your boot +scripts: + +mount -t bind /dev /dev-state +mount -t devfs none /dev +devfsd /dev + + + +add the following lines to your /etc/devfsd.conf file: + +REGISTER .* COPY /dev-state/$devname $devpath +CHANGE .* COPY $devpath /dev-state/$devname +CREATE .* COPY $devpath /dev-state/$devname + + + +reboot. + + + + Dealing with drivers without devfs support @@ -718,7 +784,7 @@ as devfs can manage /dev/pts itself. This saves you some RAM, as you don't need to compile and install devpts. Note that some versions of glibc have a bug with Unix98 pty handling on devfs systems. Contact -the glibc maintainers for a fix. Glibc 2.1.3 should have the fix. +the glibc maintainers for a fix. Glibc 2.1.3 has the fix. Note also that apart from editing /etc/fstab, other things will need to be changed if you *don't* install devfsd. Some software (like the X @@ -742,18 +808,19 @@ All the way with Devfs The devfs kernel patch creates a rationalised device tree. As stated -above, if you want to keep using the old /dev naming scheme, you just -need to configure devfsd appopriately (see the man page). People who -prefer the old names can ignore this section. For those of us who like -the rationalised names and an uncluttered /dev, read on. +above, if you want to keep using the old /dev naming scheme, +you just need to configure devfsd appopriately (see the man +page). People who prefer the old names can ignore this section. For +those of us who like the rationalised names and an uncluttered +/dev, read on. If you don't run devfsd, or don't enable compatibility entry management, then you will have to configure your system to use the new -names. For example, you will then need to edit your /etc/fstab to use -the new disc naming scheme. If you want to be able to boot non-devfs -kernels, you will need compatibility symlinks in the underlying -disc-based /dev pointing back to the old-style names for when you boot -a kernel without devfs. +names. For example, you will then need to edit your +/etc/fstab to use the new disc naming scheme. If you want to +be able to boot non-devfs kernels, you will need compatibility +symlinks in the underlying disc-based /dev pointing back to +the old-style names for when you boot a kernel without devfs. You can selectively decide which devices you want compatibility entries for. For example, you may only want compatibility entries for @@ -797,8 +864,8 @@ mount devfs and then create the named pipe *before* init starts. -The default behaviour now is not to mount devfs onto /dev at boot time -for 2.3.x and later kernels. You can correct this with the +The default behaviour now is not to mount devfs onto /dev at +boot time for 2.3.x and later kernels. You can correct this with the "devfs=mount" boot option. This solves any problems with init, and also prevents the dreaded: @@ -807,16 +874,16 @@ message. For 2.2.x kernels where you need to apply the devfs patch, the default is to mount. -If you have automatic mounting of devfs onto /dev then you may need to -create /dev/initctl in your boot scripts. The following lines should -suffice: +If you have automatic mounting of devfs onto /dev then you +may need to create /dev/initctl in your boot scripts. The +following lines should suffice: mknod /dev/initctl p kill -SIGUSR1 1 # tell init that /dev/initctl now exists -Alternatively, if you don't want the kernel to mount devfs onto /dev -then you could use the following procedure is a guideline for how to -get around /dev/initctl problems: +Alternatively, if you don't want the kernel to mount devfs onto +/dev then you could use the following procedure is a +guideline for how to get around /dev/initctl problems: # cd /sbin # mv init init.real @@ -832,32 +899,31 @@ automatically, so you don't have to worry about this. Module autoloading -Another thing to note is that if you want to support module -autoloading then you need to edit your /etc/modules.conf so -that things work properly. You should include the sample -modules.conf file in the -Documentation/filesystems/devfs directory into your -/etc/modules.conf to ensure correct operation. - -You will also need to configure devfsd to enable module +You will need to configure devfsd to enable module autoloading. The following lines should be placed in your -/etc/devfsd.conf: +/etc/devfsd.conf file: LOOKUP .* MODLOAD +As of devfsd-v1.3.10, a generic /etc/modules.devfs +configuration file is installed, which is used by the MODLOAD +action. This should be sufficient for most configurations. If you +require further configuration, edit your /etc/modules.conf +file. + Mounting root off a devfs device If you wish to mount root off a devfs device when you pass the "devfs=only" boot option, then you need to pass in the "root=" option to the kernel when booting. If you use LILO, then you must have this in lilo.conf: -append = "root=" +append = "root=" Surprised? Yep, so was I. It turns out if you have (as most people do): -root = +root = then LILO will determine the device number of and will write @@ -1144,10 +1210,10 @@ you to specify the probe order for different types of SCSI hosts. The syntax of this parameter is: -scsihosts=:::...: +scsihosts=:::...: -where ,,..., are the names of drivers used in -/proc filesystem. For example: +where ,,..., are the names +of drivers used in the /proc filesystem. For example: scsihosts=aha1542:ppa:aha1542::ncr53c7xx @@ -1309,7 +1375,7 @@ This is not a bug. Network devices have their own, completely separate namespace. They are accessed via socket(2) and setsockopt(2) calls, and thus require no device nodes. I have -raised the possibilty of moving network devices in the device +raised the possibilty of moving network devices into the device namespace, but have had no response. @@ -1418,7 +1484,7 @@ a ramdisc-based solution would take more kernel memory, since the backing store would be (at best) normal VFS inodes and dentries, which take 284 bytes and 112 bytes, respectively, for each entry. Compare -that to 49 or 93 bytes for devfs +that to 72 bytes for devfs @@ -1438,7 +1504,7 @@ simplying increasing the device number size is insufficient. Apart from causing a lot of pain, it doesn't solve the management issues -with a /dev with thousands or more device nodes +of a /dev with thousands or more device nodes ignoring the problem of a huge /dev will not make it go @@ -1473,8 +1539,17 @@ Douglas Gilbert has written yet another useful document at -http://www.torque.net/scsi/linux_scsi_24 which +http://www.torque.net/scsi/linux_scsi_24/ which discusses the Linux SCSI subsystem in 2.4. + + +Johannes Erdfelt has started a discussion paper on Linux and +hot-swap devices, describing what the requirements are for a scalable +solution and how and why he's used devfs+devfsd. Note that this is an +early draft only, available in plain text form at: + +http://johannes.erdfelt.com/hotswap.txt. +Johannes has promised a HTML version will follow. diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/filesystems/devfs/ToDo linux/Documentation/filesystems/devfs/ToDo --- v2.4.0-test2/linux/Documentation/filesystems/devfs/ToDo Sun Feb 20 21:12:38 2000 +++ linux/Documentation/filesystems/devfs/ToDo Wed Jul 5 21:36:49 2000 @@ -2,7 +2,7 @@ Richard Gooch - 18-FEB-2000 + 3-JUL-2000 This is a list of things to be done for better devfs support in the Linux kernel. If you'd like to contribute to the devfs, please have a @@ -17,8 +17,6 @@ - Amiga floppy driver (drivers/block/amiflop.c) - Atari floppy driver (drivers/block/ataflop.c) - -- Network block device (drivers/block/nbd.c) - SWIM3 (Super Woz Integrated Machine 3) floppy driver (drivers/block/swim3.c) diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/filesystems/devfs/modules.conf linux/Documentation/filesystems/devfs/modules.conf --- v2.4.0-test2/linux/Documentation/filesystems/devfs/modules.conf Fri Jun 23 21:55:06 2000 +++ linux/Documentation/filesystems/devfs/modules.conf Wed Dec 31 16:00:00 1969 @@ -1,92 +0,0 @@ -# Sample entries for /etc/modules.conf for devfs - -############################################################################### -# Configuration section: change to suit your hardware -# -alias /dev/sound sb -alias /dev/v4l bttv -alias gen-watchdog pcwd -alias gen-md raid0 -alias /dev/joysticks joystick -probeall scsi-hosts sym53c8xx - -############################################################################### -# Generic section: do not change -# -# All HDDs -probeall /dev/discs scsi-hosts sd_mod ide-probe-mod ide-disk DAC960 - -# All CD-ROMs -probeall /dev/cdroms scsi-hosts sr_mod ide-probe-mod ide-cd - -# All tapes -probeall /dev/tapes scsi-hosts st ide-probe-mod ide-tape - -# All SCSI devices -probeall /dev/scsi scsi-hosts sd_mod sr_mod st sg - -# All IDE devices -probeall /dev/ide ide-probe-mod ide-disk ide-cd ide-tape ide-floppy - -# SCSI HDDs -probeall /dev/sd scsi-hosts sd_mod -alias /dev/sd* /dev/sd - -# SCSI CD-ROMs -probeall /dev/sr scsi-hosts sr_mod -alias /dev/sr* /dev/sr - -# SCSI tapes -probeall /dev/st scsi-hosts st -alias /dev/st* /dev/st -alias /dev/nst* /dev/st - -# SCSI generic -probeall /dev/sg scsi-hosts sg -alias /dev/sg* /dev/sg - -# Floppies -alias /dev/floppy floppy -alias /dev/fd* floppy - -# RAMDISCs -alias /dev/rd rd -alias /dev/ram* rd - -# Loop devices -alias /dev/loop* loop - -# Meta devices -alias /dev/md* gen-md - -# Parallel port printers -alias /dev/printers lp -alias /dev/lp* lp - -# Soundcard -alias /dev/audio /dev/sound -alias /dev/mixer /dev/sound -alias /dev/dsp /dev/sound -alias /dev/dspW /dev/sound -alias /dev/midi /dev/sound - -# Joysticks -alias /dev/js* /dev/joysticks - -# Serial ports -alias /dev/tts serial -alias /dev/ttyS* /dev/tts -alias /dev/cua* /dev/tts - -# Miscellaneous devices -alias /dev/watchdog gen-watchdog # alias for gen-watchdog needed! -alias /dev/atibm atixlmouse -alias /dev/inportbm msbusmouse -alias /dev/logibm busmouse - -# PPP devices -alias /dev/ppp* ppp_generic - -# Video capture devices -alias /dev/video* /dev/v4l -alias /dev/vbi* /dev/v4l diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/filesystems/vfs.txt linux/Documentation/filesystems/vfs.txt --- v2.4.0-test2/linux/Documentation/filesystems/vfs.txt Tue Dec 7 09:32:38 1999 +++ linux/Documentation/filesystems/vfs.txt Thu Jun 29 15:00:31 2000 @@ -176,7 +176,7 @@ struct super_operations { void (*read_inode) (struct inode *); - void (*write_inode) (struct inode *); + void (*write_inode) (struct inode *, int); void (*put_inode) (struct inode *); void (*delete_inode) (struct inode *); int (*notify_change) (struct dentry *, struct iattr *); @@ -198,7 +198,8 @@ read. Other members are filled in by this method write_inode: this method is called when the VFS needs to write an - inode to disc + inode to disc. The second parameter indicates whether the write + should be synchronous or not, not all filesystems check this flag. put_inode: called when the VFS inode is removed from the inode cache. This method is optional diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/kernel-docs.txt linux/Documentation/kernel-docs.txt --- v2.4.0-test2/linux/Documentation/kernel-docs.txt Wed Apr 26 16:34:06 2000 +++ linux/Documentation/kernel-docs.txt Wed Jul 5 12:58:05 2000 @@ -130,7 +130,7 @@ * Title: "Dynamic Kernels: Discovery" Author: Alessandro Rubini. - URL: http://www.ssc.com/lj/issue24/kk24.html + URL: http://www2.linuxjournal.com/lj-issues/issue24/1220.html Keywords: character driver, init_module, clean_up module, autodetection, mayor number, minor number, file operations, open(), close(). @@ -142,7 +142,7 @@ * Title: "The Devil's in the Details" Author: Georg v. Zezschwitz and Alessandro Rubini. - URL: http://www.ssc.com/lj/issue25/kk25.html + URL: http://www2.linuxjournal.com/lj-issues/issue25/1221.html Keywords: read(), write(), select(), ioctl(), blocking/non blocking mode, interrupt handler. Description: Linux Journal Kernel Korner article. Here is it's @@ -178,7 +178,7 @@ * Title: "Network Buffers And Memory Management" Author: Alan Cox. - URL: http://www.ssc.com/lj/issue30/kk30.html + URL: http://www2.linuxjournal.com/lj-issues/issue30/1312.html Keywords: sk_buffs, network devices, protocol/link layer variables, network devices flags, transmit, receive, configuration, multicast. @@ -406,6 +406,77 @@ different". Freely redistributable under the conditions of the GNU General Public License. + * Title: "Porting Linux 2.0 Drivers To Linux 2.2: Changes and New + Features " + Author: Alan Cox. + URL: http://www.linux-mag.com/1999-05/gear_01.html + Keywords: ports, porting. + Description: Article from Linux Magazine on porting from 2.0 to + 2.2 kernels. + + * Title: "Porting Device Drivers To Linux 2.2: part II" + Author: Alan Cox. + URL: http://www.linux-mag.com/1999-06/gear_01.html + Keywords: ports, porting. + Description: Second part on porting from 2.0 to 2.2 kernels. + + * Title: "How To Make Sure Your Driver Will Work On The Power + Macintosh" + Author: Paul Mackerras. + URL: http://www.linux-mag.com/1999-07/gear_01.html + Keywords: Mac, Power Macintosh, porting, drivers, compatibility. + Description: The title says it all. + + * Title: "An Introduction to SCSI Drivers" + Author: Alan Cox. + URL: http://www.linux-mag.com/1999-08/gear_01.html + Keywords: SCSI, device, driver. + Description: The title says it all. + + * Title: "Advanced SCSI Drivers And Other Tales" + Author: Alan Cox. + URL: http://www.linux-mag.com/1999-09/gear_01.html + Keywords: SCSI, device, driver, advanced. + Description: The title says it all. + + * Title: "Writing Linux Mouse Drivers" + Author: Alan Cox. + URL: http://www.linux-mag.com/1999-10/gear_01.html + Keywords: mouse, driver, gpm. + Description: The title says it all. + + * Title: "More on Mouse Drivers" + Author: Alan Cox. + URL: http://www.linux-mag.com/1999-11/gear_01.html + Keywords: mouse, driver, gpm, races, asynchronous I/O. + Description: The title still says it all. + + * Title: "Writing Video4linux Radio Driver" + Author: Alan Cox. + URL: http://www.linux-mag.com/1999-12/gear_01.html + Keywords: video4linux, driver, radio, radio devices. + Description: The title says it all. + + * Title: "Video4linux Drivers, Part 1: Video-Capture Device" + Author: Alan Cox. + URL: http://www.linux-mag.com/2000-01/gear_01.html + Keywords: video4linux, driver, video capture, capture devices, + camera driver. + Description: The title says it all. + + * Title: "Video4linux Drivers, Part 2: Video-capture Devices" + Author: Alan Cox. + URL: http://www.linux-mag.com/2000-02/gear_01.html + Keywords: video4linux, driver, video capture, capture devices, + camera driver, control, query capabilities, capability, facility. + Description: The title says it all. + + * Title: "PCI Management in Linux 2.2" + Author: Alan Cox. + URL: http://www.linux-mag.com/2000-03/gear_01.html + Keywords: PCI, bus, bus-mastering. + Description: The title says it all. + BOOKS: (Not on-line) * Title: "Linux Device Drivers" @@ -475,7 +546,7 @@ ISBN: 0-13-101908-2 * Title: "Linux Core Kernel Commentary. Guide to Insider's Knowledge - on the Core Kernel od the Linux Code" + on the Core Kernel of the Linux Code" Author: Scott Maxwell. Publisher: Coriolis. Date: 1999. @@ -598,9 +669,10 @@ * Name: "linux-kernel mailing list archives and search engines" URL: http://www.uwsg.indiana.edu/hypermail/linux/kernel/index.html URL: http://www.kernelnotes.org/lnxlists/linux-kernel/ + URL: http://www.geocrawler.com Keywords: linux-kernel, archives, search. Description: Some of the linux-kernel mailing list archivers. If you have a better/another one, please let me know. _________________________________________________________________ - Document last updated on Mon Apr 17 18:07:07 CEST 2000 + Document last updated on Thu Jun 1 21:58:18 CEST 2000DATE$ diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/networking/decnet.txt linux/Documentation/networking/decnet.txt --- v2.4.0-test2/linux/Documentation/networking/decnet.txt Fri Mar 10 16:40:38 2000 +++ linux/Documentation/networking/decnet.txt Wed Jul 5 22:15:27 2000 @@ -5,7 +5,7 @@ o Project Home Pages http://www.sucs.swan.ac.uk/~rohan/DECnet/index.html - Kernel info - http://linux.dreamtime.org/decnet/ - Userland tools + http://linux-decnet.sourceforge.net/ - Userland tools o FTP sites ftp://ftp.sucs.swan.ac.uk/pub/Linux/DECnet/ @@ -15,7 +15,7 @@ - Mirror of Alexey Kuznetsov's iproute2 package and other utilities - ftp://ftp.dreamtime.org/pub/linux/decnet/ + ftp://linux-decnet.sourceforge.net/pub/linux-decnet/ - Patrick Caulfield's archive of userland tools and Eduardo Serrat's kernel patches @@ -153,17 +153,16 @@ - Can you use tcpdump to get a trace ? (N.B. Most (all?) versions of tcpdump don't understand how to dump DECnet properly, so including the hex listing of the packet contents is _essential_, usually the -x flag. - You may also need to increase the length grabbed with the -s flag) + You may also need to increase the length grabbed with the -s flag. The + -e flag also provides very useful information (ethernet MAC addresses)) 7) Mailing list If you are keen to get involved in development, or want to ask questions about configuration, or even just report bugs, then there is a mailing -list that you can join: send mail to majordomo@dreamtime.org with +list that you can join, details are at: -subscribe linux-decnet - -as the body of the message. +http://sourceforge.net/mail/?group_id=4993 8) Legal Info diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/networking/tulip.txt linux/Documentation/networking/tulip.txt --- v2.4.0-test2/linux/Documentation/networking/tulip.txt Fri Jun 23 21:55:06 2000 +++ linux/Documentation/networking/tulip.txt Thu Jun 29 10:14:01 2000 @@ -142,6 +142,10 @@ Version history =============== +0.9.7 (June 17, 2000): +* Timer cleanups (Andrew Morton) +* Alpha compile fix (somebody?) + 0.9.6 (May 31, 2000): * Revert 21143-related support flag patch * Add HPPA/media-table debugging printk diff -u --recursive --new-file v2.4.0-test2/linux/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt --- v2.4.0-test2/linux/Documentation/usb/ov511.txt Fri Jun 23 21:55:06 2000 +++ linux/Documentation/usb/ov511.txt Thu Jun 29 09:53:14 2000 @@ -6,7 +6,7 @@ Homepage: http://alpha.dyndns.org/ov511 NEW IN THIS VERSION: - o Race conditions and other bugs fixed + o Preliminary support for YUV422 and YUV422P V4L modes INTRODUCTION: @@ -209,7 +209,7 @@ o Setting of contrast and brightness not working with 7620 o Driver/camera state save/restore for when USB supports suspend/resume o Multiple cameras reportedly do not work simultaneously - o Problems with OHCI + o Unstable on SMP systems HOW TO CONTACT ME: diff -u --recursive --new-file v2.4.0-test2/linux/MAINTAINERS linux/MAINTAINERS --- v2.4.0-test2/linux/MAINTAINERS Fri Jun 23 21:55:07 2000 +++ linux/MAINTAINERS Sun Jul 9 10:10:44 2000 @@ -282,7 +282,7 @@ P: Steven Whitehouse M: SteveW@ACM.org W: http://www.sucs.swan.ac.uk/~rohan/DECnet/index.html -L: linux-decnet@dreamtime.org +L: linux-decnet-user@lists.sourceforge.net S: Maintained DEVICE NUMBER REGISTRY @@ -438,8 +438,9 @@ HIGH-SPEED SCC DRIVER FOR AX.25 P: Klaus Kudielka -M: oe1kib@oe1kib.ampr.org +M: klaus.kudielka@ieee.org L: linux-hams@vger.rutgers.edu +W: http://www.nt.tuwien.ac.at/~kkudielk/Linux/ S: Maintained LOGICAL VOLUME MANAGER @@ -524,27 +525,25 @@ S: Maintained IEEE 1394 AIC5800 DRIVER -P: Emanuel Pirker -M: epirker@edu.uni-klu.ac.at -L: linux1394-devel@eclipt.uni-klu.ac.at -S: Maintained +L: linux1394-devel@lists.sourceforge.net +S: Orphan IEEE 1394 OHCI DRIVER P: Sebastien Rougeaux M: sebastien.rougeaux@anu.edu.au -L: linux1394-devel@eclipt.uni-klu.ac.at +L: linux1394-devel@lists.sourceforge.net S: Maintained IEEE 1394 PCILYNX DRIVER P: Andreas Bombe M: andreas.bombe@munich.netsurf.de -L: linux1394-devel@eclipt.uni-klu.ac.at +L: linux1394-devel@lists.sourceforge.net S: Maintained IEEE 1394 RAW I/O DRIVER P: Andreas Bombe M: andreas.bombe@munich.netsurf.de -L: linux1394-devel@eclipt.uni-klu.ac.at +L: linux1394-devel@lists.sourceforge.net S: Maintained INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT @@ -784,8 +783,8 @@ S: Odd Fixes NVIDIA (RIVA) FRAMEBUFFER DRIVER -P: Jeff Garzik -M: jgarzik@mandrakesoft.com +P: Ani Joshi +M: ajoshi@shell.unixbox.com L: linux-nvidia@lists.surfsouth.com S: Maintained @@ -1135,7 +1134,8 @@ USB SUBSYSTEM P: Randy Dunlap M: randy.dunlap@intel.com -L: linux-usb@suse.com +L: linux-usb-users@lists.sourceforge.net +L: linux-usb-devel@lists.sourceforge.net W: http://www.linux-usb.org S: Supported diff -u --recursive --new-file v2.4.0-test2/linux/Makefile linux/Makefile --- v2.4.0-test2/linux/Makefile Fri Jun 23 21:55:07 2000 +++ linux/Makefile Mon Jul 10 15:37:07 2000 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -test2 +EXTRAVERSION = -test3 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -85,11 +85,6 @@ CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS) -# use '-fno-strict-aliasing', but only if the compiler can take it -CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strict-aliasing"; fi) - -export CPPFLAGS CFLAGS AFLAGS - # # ROOT_DEV specifies the default root-device when making the image. # This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case @@ -152,6 +147,7 @@ DRIVERS-$(CONFIG_SOUND) += drivers/sound/sounddrivers.o DRIVERS-$(CONFIG_PCI) += drivers/pci/pci.a +DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o DRIVERS-$(CONFIG_PCMCIA) += drivers/pcmcia/pcmcia.o DRIVERS-$(CONFIG_PCMCIA_NETCARD) += drivers/net/pcmcia/pcmcia_net.o DRIVERS-$(CONFIG_PCMCIA_CHRDEV) += drivers/char/pcmcia/pcmcia_char.o @@ -172,11 +168,17 @@ DRIVERS-$(CONFIG_IRDA) += drivers/net/irda/irda_drivers.a DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.a +DRIVERS-$(CONFIG_ACPI_INTERPRETER) += drivers/acpi/acpi.o DRIVERS += $(DRIVERS-y) include arch/$(ARCH)/Makefile +# use '-fno-strict-aliasing', but only if the compiler can take it +CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strict-aliasing"; fi) + +export CPPFLAGS CFLAGS AFLAGS + export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS .S.s: @@ -329,8 +331,10 @@ if [ -f SK98LIN_MODULES ]; then inst_mod SK98LIN_MODULES net; fi; \ if [ -f SKFP_MODULES ]; then inst_mod SKFP_MODULES net; fi; \ if [ -f USB_MODULES ]; then inst_mod USB_MODULES usb; fi; \ + if [ -f USB_STORAGE_MODULES ]; then inst_mod USB_STORAGE_MODULES usb; fi; \ if [ -f USB_SERIAL_MODULES ]; then inst_mod USB_SERIAL_MODULES usb; fi; \ if [ -f IEEE1394_MODULES ]; then inst_mod IEEE1394_MODULES ieee1394; fi; \ + if [ -f MTD_MODULES ]; then inst_mod MTD_MODULES mtd; fi; \ if [ -f PCMCIA_MODULES ]; then inst_mod PCMCIA_MODULES pcmcia; fi; \ if [ -f PCMCIA_NET_MODULES ]; then inst_mod PCMCIA_NET_MODULES pcmcia; fi; \ if [ -f PCMCIA_CHAR_MODULES ]; then inst_mod PCMCIA_CHAR_MODULES pcmcia; fi; \ @@ -430,7 +434,7 @@ dep-files: scripts/mkdep archdep include/linux/version.h scripts/mkdep init/*.c > .depend - scripts/mkdep `find $(FINDHPATH) -name SCCS -prune -or -follow -name \*.h ! -name modversions.h -print` > .hdepend + scripts/mkdep `find $(FINDHPATH) -name SCCS -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend $(MAKE) $(patsubst %,_sfdep_%,$(SUBDIRS)) _FASTDEP_ALL_SUB_DIRS="$(SUBDIRS)" ifdef CONFIG_MODVERSIONS diff -u --recursive --new-file v2.4.0-test2/linux/arch/alpha/Makefile linux/arch/alpha/Makefile --- v2.4.0-test2/linux/arch/alpha/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/alpha/Makefile Mon Jun 26 11:26:56 2000 @@ -10,7 +10,7 @@ NM := nm -B -LINKFLAGS = -static -T arch/alpha/vmlinux.lds #-N -relax +LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N #-relax CFLAGS := $(CFLAGS) -pipe -mno-fp-regs -ffixed-8 # Determine if we can use the BWX instructions with GAS. @@ -90,7 +90,7 @@ LIBS := $(TOPDIR)/arch/alpha/lib/lib.a $(LIBS) $(TOPDIR)/arch/alpha/lib/lib.a -MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot +MAKEBOOT = $(MAKE) -C arch/alpha/boot rawboot: @$(MAKEBOOT) rawboot @@ -109,13 +109,15 @@ @$(MAKEBOOT) srmboot archclean: - @$(MAKE) -C arch/$(ARCH)/kernel clean + @$(MAKE) -C arch/alpha/kernel clean @$(MAKEBOOT) clean + rm -f arch/alpha/vmlinux.lds archmrproper: archdep: @$(MAKEBOOT) dep + $(CPP) $(CPPFLAGS) -xc -P arch/alpha/vmlinux.lds.in -o arch/alpha/vmlinux.lds bootpfile: @$(MAKEBOOT) bootpfile diff -u --recursive --new-file v2.4.0-test2/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v2.4.0-test2/linux/arch/alpha/config.in Fri Jun 23 21:55:07 2000 +++ linux/arch/alpha/config.in Wed Jul 5 13:10:35 2000 @@ -228,6 +228,8 @@ source drivers/parport/Config.in endmenu +source drivers/mtd/Config.in + source drivers/pnp/Config.in source drivers/block/Config.in @@ -331,7 +333,6 @@ mainmenu_option next_comment comment 'Kernel hacking' -#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'Kernel FP software completion' CONFIG_MATHEMU else @@ -339,4 +340,7 @@ fi bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ + +bool 'Legacy kernel start address' CONFIG_ALPHA_LEGACY_START_ADDRESS + endmenu diff -u --recursive --new-file v2.4.0-test2/linux/arch/alpha/kernel/core_cia.c linux/arch/alpha/kernel/core_cia.c --- v2.4.0-test2/linux/arch/alpha/kernel/core_cia.c Mon Mar 27 08:08:21 2000 +++ linux/arch/alpha/kernel/core_cia.c Mon Jun 26 11:26:56 2000 @@ -19,6 +19,7 @@ #include #include +#include #define __EXTERN_INLINE inline #include @@ -712,6 +713,25 @@ void __init pyxis_init_arch(void) { + /* On pyxis machines we can precisely calculate the + CPU clock frequency using pyxis real time counter. + It's especially useful for SX164 with broken RTC. + + Both CPU and chipset are driven by the single 16.666M + or 16.667M crystal oscillator. PYXIS_RT_COUNT clock is + 66.66 MHz. -ink */ + + unsigned int cc0, cc1; + unsigned long pyxis_cc; + + __asm__ __volatile__ ("rpcc %0" : "=r"(cc0)); + pyxis_cc = *(vulp)PYXIS_RT_COUNT; + do { } while(*(vulp)PYXIS_RT_COUNT - pyxis_cc < 4096); + __asm__ __volatile__ ("rpcc %0" : "=r"(cc1)); + cc1 -= cc0; + hwrpb->cycle_freq = ((cc1 >> 11) * 100000000UL) / 3; + hwrpb_update_checksum(hwrpb); + do_init_arch(1); } diff -u --recursive --new-file v2.4.0-test2/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.4.0-test2/linux/arch/alpha/kernel/osf_sys.c Fri Jun 23 21:55:07 2000 +++ linux/arch/alpha/kernel/osf_sys.c Wed Jul 5 11:31:00 2000 @@ -146,7 +146,6 @@ buf.count = count; buf.error = 0; - lock_kernel(); error = vfs_readdir(file, osf_filldir, &buf); if (error < 0) goto out_putf; @@ -156,7 +155,6 @@ error = count - buf.count; out_putf: - unlock_kernel(); fput(file); out: return error; @@ -230,7 +228,6 @@ struct file *file = NULL; unsigned long ret = -EBADF; - lock_kernel(); #if 0 if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED)) printk("%s: unimplemented OSF mmap flags %04lx\n", @@ -248,7 +245,6 @@ if (file) fput(file); out: - unlock_kernel(); return ret; } @@ -320,9 +316,7 @@ retval = -EBADF; file = fget(fd); if (file) { - lock_kernel(); retval = do_osf_statfs(file->f_dentry, buffer, bufsiz); - unlock_kernel(); fput(file); } return retval; @@ -491,14 +485,12 @@ int fd[2]; int error; - lock_kernel(); error = do_pipe(fd); if (error) goto out; (®s)->r20 = fd[1]; error = fd[0]; out: - unlock_kernel(); return error; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/alpha/kernel/pci.c linux/arch/alpha/kernel/pci.c --- v2.4.0-test2/linux/arch/alpha/kernel/pci.c Fri Jun 23 21:55:07 2000 +++ linux/arch/alpha/kernel/pci.c Mon Jun 26 11:26:56 2000 @@ -369,6 +369,22 @@ return 0; } +/* + * If we set up a device for bus mastering, we need to check the latency + * timer as certain firmware forgets to set it properly, as seen + * on SX164 and LX164 with SRM. + */ +void +pcibios_set_master(struct pci_dev *dev) +{ + u8 lat; + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + if (lat >= 16) return; + printk("PCI: Setting latency timer of device %s to 64\n", + dev->slot_name); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); +} + #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) static void __init diff -u --recursive --new-file v2.4.0-test2/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v2.4.0-test2/linux/arch/alpha/kernel/process.c Wed Apr 26 16:34:06 2000 +++ linux/arch/alpha/kernel/process.c Mon Jul 10 13:16:56 2000 @@ -74,7 +74,7 @@ cpu_idle(void) { /* An endless idle loop with no priority at all. */ - current->priority = 0; + current->nice = 20; current->counter = -100; while (1) { diff -u --recursive --new-file v2.4.0-test2/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c --- v2.4.0-test2/linux/arch/alpha/kernel/setup.c Fri Jun 23 21:55:07 2000 +++ linux/arch/alpha/kernel/setup.c Thu Jun 29 11:04:58 2000 @@ -246,11 +246,12 @@ } static void __init -setup_memory(void * kernel_end) +setup_memory(void *kernel_end) { struct memclust_struct * cluster; struct memdesc_struct * memdesc; - unsigned long start_pfn, bootmap_size, bootmap_pages, bootmap_start; + unsigned long start_kernel_pfn, end_kernel_pfn; + unsigned long bootmap_size, bootmap_pages, bootmap_start; unsigned long start, end; int i; @@ -282,12 +283,13 @@ max_low_pfn = mem_size_limit; } - /* Find the end of the memory used by the kernel. */ - start_pfn = PFN_UP(virt_to_phys(kernel_end)); + /* Find the bounds of kernel memory. */ + start_kernel_pfn = PFN_DOWN(KERNEL_START_PHYS); + end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end)); bootmap_start = -1; try_again: - if (max_low_pfn <= start_pfn) + if (max_low_pfn <= end_kernel_pfn) panic("not enough memory to boot"); /* We need to know how many physically contiguous pages @@ -301,14 +303,19 @@ start = cluster->start_pfn; end = start + cluster->numpages; - if (end <= start_pfn) - continue; if (start >= max_low_pfn) continue; - if (start < start_pfn) - start = start_pfn; if (end > max_low_pfn) end = max_low_pfn; + if (start < start_kernel_pfn) { + if (end > end_kernel_pfn + && end - end_kernel_pfn >= bootmap_pages) { + bootmap_start = end_kernel_pfn; + break; + } else if (end > start_kernel_pfn) + end = start_kernel_pfn; + } else if (start < end_kernel_pfn) + start = end_kernel_pfn; if (end - start >= bootmap_pages) { bootmap_start = start; break; @@ -329,22 +336,28 @@ continue; start = cluster->start_pfn; - if (start < start_pfn) - start = start_pfn; - end = cluster->start_pfn + cluster->numpages; + if (start >= max_low_pfn) + continue; if (end > max_low_pfn) end = max_low_pfn; - + if (start < start_kernel_pfn) { + if (end > end_kernel_pfn) { + free_bootmem(PFN_PHYS(start), + (PFN_PHYS(start_kernel_pfn) + - PFN_PHYS(start))); + printk("freeing pages %ld:%ld\n", + start, start_kernel_pfn); + start = end_kernel_pfn; + } else if (end > start_kernel_pfn) + end = start_kernel_pfn; + } else if (start < end_kernel_pfn) + start = end_kernel_pfn; if (start >= end) continue; - start = PFN_PHYS(start); - end = PFN_PHYS(end); - - free_bootmem(start, end - start); - printk("freeing pages %ld:%ld\n", - PFN_UP(start), PFN_DOWN(end)); + free_bootmem(PFN_PHYS(start), PFN_PHYS(end) - PFN_PHYS(start)); + printk("freeing pages %ld:%ld\n", start, end); } /* Reserve the bootmap memory. */ @@ -461,11 +474,12 @@ void __init setup_arch(char **cmdline_p) { + extern char _end[]; + struct alpha_machine_vector *vec = NULL; struct percpu_struct *cpu; char *type_name, *var_name, *p; - extern char _end; - void * kernel_end = &_end; /* end of kernel */ + void *kernel_end = _end; /* end of kernel */ hwrpb = (struct hwrpb_struct*) __va(INIT_HWRPB->phys_addr); boot_cpuid = hard_smp_processor_id(); diff -u --recursive --new-file v2.4.0-test2/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c --- v2.4.0-test2/linux/arch/alpha/kernel/smp.c Fri Jun 23 21:55:07 2000 +++ linux/arch/alpha/kernel/smp.c Mon Jul 10 14:22:00 2000 @@ -651,7 +651,7 @@ } if (user) { - if (current->priority < DEF_PRIORITY) { + if (current->nice > 0) { kstat.cpu_nice++; kstat.per_cpu_nice[cpu]++; } else { diff -u --recursive --new-file v2.4.0-test2/linux/arch/alpha/kernel/sys_sx164.c linux/arch/alpha/kernel/sys_sx164.c --- v2.4.0-test2/linux/arch/alpha/kernel/sys_sx164.c Sun Mar 19 18:35:30 2000 +++ linux/arch/alpha/kernel/sys_sx164.c Mon Jun 26 11:26:56 2000 @@ -24,6 +24,7 @@ #include #include #include +#include #include "proto.h" #include "irq_impl.h" @@ -114,6 +115,36 @@ SMC669_Init(0); } +static void __init +sx164_init_arch(void) +{ + /* + * OSF palcode v1.23 forgets to enable PCA56 Motion Video + * Instructions. Let's enable it. + * We have to check palcode revision because CSERVE interface + * is subject to change without notice. For example, it + * has been changed completely since v1.16 (found in MILO + * distribution). -ink + */ + struct percpu_struct *cpu = (struct percpu_struct*) + ((char*)hwrpb + hwrpb->processor_offset); + + if (alpha_using_srm && (cpu->pal_revision & 0xffff) == 0x117) { + __asm__ __volatile__( + "lda $16,8($31)\n" + "call_pal 9\n" /* Allow PALRES insns in kernel mode */ + ".long 0x64000118\n\n" /* hw_mfpr $0,icsr */ + "ldah $16,(1<<(19-16))($31)\n" + "or $0,$16,$0\n" /* set MVE bit */ + ".long 0x74000118\n" /* hw_mtpr $0,icsr */ + "lda $16,9($31)\n" + "call_pal 9" /* Disable PALRES insns */ + : : : "$0", "$16"); + printk("PCA56 MVI set enabled\n"); + } + + pyxis_init_arch(); +} /* * The System Vector @@ -133,7 +164,7 @@ nr_irqs: 48, device_interrupt: pyxis_device_interrupt, - init_arch: pyxis_init_arch, + init_arch: sx164_init_arch, init_irq: sx164_init_irq, init_rtc: common_init_rtc, init_pci: sx164_init_pci, diff -u --recursive --new-file v2.4.0-test2/linux/arch/alpha/vmlinux.lds linux/arch/alpha/vmlinux.lds --- v2.4.0-test2/linux/arch/alpha/vmlinux.lds Fri Jun 23 21:55:07 2000 +++ linux/arch/alpha/vmlinux.lds Wed Dec 31 16:00:00 1969 @@ -1,88 +0,0 @@ -OUTPUT_FORMAT("elf64-alpha") -ENTRY(__start) -SECTIONS -{ - . = 0xfffffc0000810000; - _text = .; - .text : { *(.text) } - _etext = .; - - /* Exception table */ - . = ALIGN(16); - __start___ex_table = .; - __ex_table : { *(__ex_table) } - __stop___ex_table = .; - - /* Kernel symbol table */ - . = ALIGN(8); - __start___ksymtab = .; - __ksymtab : { *(__ksymtab) } - __stop___ksymtab = .; - .kstrtab : { *(.kstrtab) } - - /* Startup code */ - . = ALIGN(8192); - __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } - - . = ALIGN(16); - __setup_start = .; - .setup.init : { *(.setup.init) } - __setup_end = .; - - . = ALIGN(8); - __initcall_start = .; - .initcall.init : { *(.initcall.init) } - __initcall_end = .; - - . = ALIGN(2*8192); /* Align double page for init_task_union */ - __init_end = .; - - /* The initial task and kernel stack */ - init_task : { *(init_task) } - - /* Global data */ - _data = .; - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - .rodata : { *(.rodata) } - .data : { *(.data) CONSTRUCTORS } - .got : { *(.got) } - .sdata : { *(.sdata) } - _edata = .; - - __bss_start = .; - .sbss : { *(.sbss) *(.scommon) } - .bss : { *(.bss) *(COMMON) } - __bss_stop = .; - _end = .; - - .mdebug 0 : { *(.mdebug) } - .note 0 : { *(.note) } - .comment 0 : { *(.comment) } - - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - - /DISCARD/ : { *(.text.exit) *(.data.exit) } -} diff -u --recursive --new-file v2.4.0-test2/linux/arch/alpha/vmlinux.lds.in linux/arch/alpha/vmlinux.lds.in --- v2.4.0-test2/linux/arch/alpha/vmlinux.lds.in Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/vmlinux.lds.in Mon Jun 26 11:26:56 2000 @@ -0,0 +1,96 @@ +#include + +OUTPUT_FORMAT("elf64-alpha") +ENTRY(__start) +PHDRS { kernel PT_LOAD ; } +SECTIONS +{ +#ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS + . = 0xfffffc0000310000; +#else + . = 0xfffffc0000810000; +#endif + + _text = .; + .text : { *(.text) } :kernel + _etext = .; + + /* Exception table */ + . = ALIGN(16); + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + /* Kernel symbol table */ + . = ALIGN(8); + __start___ksymtab = .; + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; + .kstrtab : { *(.kstrtab) } + + /* Startup code */ + . = ALIGN(8192); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + + . = ALIGN(16); + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + + . = ALIGN(8); + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; + + . = ALIGN(2*8192); /* Align double page for init_task_union */ + __init_end = .; + + /* The initial task and kernel stack */ + init_task : { *(init_task) } + + /* Global data */ + _data = .; + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + .rodata : { *(.rodata) } + .data : { *(.data) CONSTRUCTORS } + .got : { *(.got) } + .sdata : { *(.sdata) } + _edata = .; + + __bss_start = .; + .sbss : { *(.sbss) *(.scommon) } + .bss : { *(.bss) *(COMMON) } + __bss_stop = .; + _end = .; + + .mdebug 0 : { *(.mdebug) } + .note 0 : { *(.note) } + .comment 0 : { *(.comment) } + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + /DISCARD/ : { *(.text.exit) *(.data.exit) } +} diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/config.in linux/arch/arm/config.in --- v2.4.0-test2/linux/arch/arm/config.in Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/config.in Wed Jul 5 13:10:35 2000 @@ -12,6 +12,7 @@ mainmenu_option next_comment comment 'Code maturity level options' bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL +bool 'Prompt for obsolete code/drivers' CONFIG_OBSOLETE endmenu @@ -45,8 +46,8 @@ if [ "$CONFIG_SA1100_ASSABET" = "y" ]; then bool ' Include support for Neponset' CONFIG_ASSABET_NEPONSET fi - bool ' Include support for Bitsy' CONFIG_SA1100_BITSY bool ' Include support for Brutus' CONFIG_SA1100_BRUTUS + bool ' Include support for Compaq iPAQ 3600 (Bitsy)' CONFIG_SA1100_BITSY # bool ' Include support for Empeg' CONFIG_SA1100_EMPEG # bool ' Include support for Itsy' CONFIG_SA1100_ITSY bool ' Include support for LART' CONFIG_SA1100_LART @@ -270,6 +271,8 @@ fi endmenu +source drivers/mtd/Config.in + source drivers/ieee1394/Config.in source drivers/i2o/Config.in @@ -342,7 +345,7 @@ bool 'Kernel low-level debugging functions' CONFIG_DEBUG_LL if [ "$CONFIG_DEBUG_LL" = "y" ]; then if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then - bool 'Kernel low-level debugging messages via DC21285 port' CONFIG_DEBUG_DC21285_PORT + bool 'Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT fi fi fi diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/armksyms.c linux/arch/arm/kernel/armksyms.c --- v2.4.0-test2/linux/arch/arm/kernel/armksyms.c Wed Apr 26 16:34:06 2000 +++ linux/arch/arm/kernel/armksyms.c Mon Jun 26 12:04:00 2000 @@ -31,6 +31,8 @@ extern unsigned int local_bh_count[NR_CPUS]; extern unsigned int local_irq_count[NR_CPUS]; +extern void __bad_xchg(volatile void *ptr, int size); + /* * syscalls */ @@ -90,7 +92,6 @@ EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(udelay); -EXPORT_SYMBOL(xchg_str); EXPORT_SYMBOL(local_bh_count); EXPORT_SYMBOL(local_irq_count); #ifdef CONFIG_CPU_32 @@ -103,6 +104,7 @@ EXPORT_SYMBOL(system_serial_high); EXPORT_SYMBOL(mem_fclk_21285); EXPORT_SYMBOL(__bug); +EXPORT_SYMBOL(__bad_xchg); EXPORT_SYMBOL(__readwrite_bug); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/arthur.c linux/arch/arm/kernel/arthur.c --- v2.4.0-test2/linux/arch/arm/kernel/arthur.c Wed Apr 26 16:34:06 2000 +++ linux/arch/arm/kernel/arthur.c Mon Jun 26 12:04:00 2000 @@ -3,8 +3,8 @@ * Copyright (C) 1998-1999 Philip Blundell */ -#include #include +#include #include #include #include diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/bios32.c linux/arch/arm/kernel/bios32.c --- v2.4.0-test2/linux/arch/arm/kernel/bios32.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/bios32.c Mon Jun 26 12:04:00 2000 @@ -8,7 +8,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/dma-footbridge.c linux/arch/arm/kernel/dma-footbridge.c --- v2.4.0-test2/linux/arch/arm/kernel/dma-footbridge.c Fri Oct 22 13:21:44 1999 +++ linux/arch/arm/kernel/dma-footbridge.c Mon Jun 26 12:04:00 2000 @@ -13,7 +13,6 @@ #include #include -#include #include #include diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/dma-rpc.c linux/arch/arm/kernel/dma-rpc.c --- v2.4.0-test2/linux/arch/arm/kernel/dma-rpc.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/dma-rpc.c Mon Jun 26 12:04:00 2000 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/dma.c linux/arch/arm/kernel/dma.c --- v2.4.0-test2/linux/arch/arm/kernel/dma.c Fri Sep 10 23:57:27 1999 +++ linux/arch/arm/kernel/dma.c Mon Jun 26 12:04:00 2000 @@ -14,9 +14,9 @@ * * Moved DMA resource allocation here... */ +#include #include #include -#include #include #include #include diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/ecard.c linux/arch/arm/kernel/ecard.c --- v2.4.0-test2/linux/arch/arm/kernel/ecard.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/ecard.c Mon Jun 26 12:04:00 2000 @@ -33,9 +33,7 @@ #include #include #include -#include #include -#include #include #include @@ -913,7 +911,6 @@ ecard_t **ecp; ecard_t *ec; struct ex_ecid cid; - char buffer[200]; int i, rc = -ENOMEM; ec = kmalloc(sizeof(ecard_t), GFP_KERNEL); @@ -994,12 +991,9 @@ nodev: if (rc && ec) kfree(ec); - else { + else slot_to_expcard[slot] = ec; - ecard_prints(buffer, ec); - printk("%s", buffer); - } return rc; } @@ -1075,7 +1069,7 @@ init_waitqueue_head(&ecard_done); #endif - printk("Probing expansion cards: (does not imply support)\n"); + printk("Probing expansion cards\n"); for (slot = 0; slot < 8; slot ++) { if (ecard_probe(slot, ECARD_EASI) == -ENODEV) diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/hw-footbridge.c linux/arch/arm/kernel/hw-footbridge.c --- v2.4.0-test2/linux/arch/arm/kernel/hw-footbridge.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/hw-footbridge.c Mon Jun 26 12:04:00 2000 @@ -8,19 +8,12 @@ #include #include #include +#include #include #include -#include -#include -#include -#include -#include -#include #include -#include #include -#include #include #include @@ -28,6 +21,13 @@ #define GP1_IO_BASE 0x338 #define GP2_IO_BASE 0x33a + +#ifdef CONFIG_LEDS +#define DEFAULT_LEDS 0 +#else +#define DEFAULT_LEDS GPIO_GREEN_LED +#endif + /* * Netwinder stuff */ @@ -396,9 +396,9 @@ 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 }; #ifndef DEBUG -#define dprintk if (0) printk +#define dprintk(x...) #else -#define dprintk printk +#define dprintk(x...) printk(x) #endif #define WRITE_RWA(r,v) do { outb((r), 0x279); udelay(10); outb((v), 0xa79); } while (0) @@ -602,74 +602,13 @@ EXPORT_SYMBOL(gpio_modify_io); EXPORT_SYMBOL(cpld_modify); -#endif - -#ifdef CONFIG_LEDS -#define DEFAULT_LEDS 0 -#else -#define DEFAULT_LEDS GPIO_GREEN_LED -#endif - -/* - * CATS stuff - */ -#ifdef CONFIG_ARCH_CATS - -#define CONFIG_PORT 0x370 -#define INDEX_PORT (CONFIG_PORT) -#define DATA_PORT (CONFIG_PORT + 1) - -static void __init cats_hw_init(void) -{ - /* Set Aladdin to CONFIGURE mode */ - outb(0x51, CONFIG_PORT); - outb(0x23, CONFIG_PORT); - - /* Select logical device 3 */ - outb(0x07, INDEX_PORT); - outb(0x03, DATA_PORT); - - /* Set parallel port to DMA channel 3, ECP+EPP1.9, - enable EPP timeout */ - outb(0x74, INDEX_PORT); - outb(0x03, DATA_PORT); - - outb(0xf0, INDEX_PORT); - outb(0x0f, DATA_PORT); - - outb(0xf1, INDEX_PORT); - outb(0x07, DATA_PORT); - - /* Select logical device 4 */ - outb(0x07, INDEX_PORT); - outb(0x04, DATA_PORT); - - /* UART1 high speed mode */ - outb(0xf0, INDEX_PORT); - outb(0x02, DATA_PORT); - - /* Select logical device 5 */ - outb(0x07, INDEX_PORT); - outb(0x05, DATA_PORT); - - /* UART2 high speed mode */ - outb(0xf0, INDEX_PORT); - outb(0x02, DATA_PORT); - - /* Set Aladdin to RUN mode */ - outb(0xbb, CONFIG_PORT); -} - -#endif - /* * Initialise any other hardware after we've got the PCI bus * initialised. We may need the PCI bus to talk to this other * hardware. */ -static int __init hw_init(void) +static int __init nw_hw_init(void) { -#ifdef CONFIG_ARCH_NETWINDER /* * this ought to have a better home... * Since this calls the above routines, which are @@ -688,12 +627,66 @@ gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS); spin_unlock_irqrestore(&gpio_lock, flags); } + return 0; +} + +__initcall(nw_hw_init); #endif + +/* + * CATS stuff + */ #ifdef CONFIG_ARCH_CATS - if (machine_is_cats()) - cats_hw_init(); -#endif + +#define CONFIG_PORT 0x370 +#define INDEX_PORT (CONFIG_PORT) +#define DATA_PORT (CONFIG_PORT + 1) + +static int __init cats_hw_init(void) +{ + if (machine_is_cats()) { + /* Set Aladdin to CONFIGURE mode */ + outb(0x51, CONFIG_PORT); + outb(0x23, CONFIG_PORT); + + /* Select logical device 3 */ + outb(0x07, INDEX_PORT); + outb(0x03, DATA_PORT); + + /* Set parallel port to DMA channel 3, ECP+EPP1.9, + enable EPP timeout */ + outb(0x74, INDEX_PORT); + outb(0x03, DATA_PORT); + + outb(0xf0, INDEX_PORT); + outb(0x0f, DATA_PORT); + + outb(0xf1, INDEX_PORT); + outb(0x07, DATA_PORT); + + /* Select logical device 4 */ + outb(0x07, INDEX_PORT); + outb(0x04, DATA_PORT); + + /* UART1 high speed mode */ + outb(0xf0, INDEX_PORT); + outb(0x02, DATA_PORT); + + /* Select logical device 5 */ + outb(0x07, INDEX_PORT); + outb(0x05, DATA_PORT); + + /* UART2 high speed mode */ + outb(0xf0, INDEX_PORT); + outb(0x02, DATA_PORT); + + /* Set Aladdin to RUN mode */ + outb(0xbb, CONFIG_PORT); + } + return 0; } -__initcall(hw_init); +__initcall(cats_hw_init); +#endif + diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/hw-sa1100.c linux/arch/arm/kernel/hw-sa1100.c --- v2.4.0-test2/linux/arch/arm/kernel/hw-sa1100.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/hw-sa1100.c Mon Jun 26 12:04:00 2000 @@ -10,9 +10,9 @@ * */ #include +#include #include #include -#include #include #include diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/irq.c linux/arch/arm/kernel/irq.c --- v2.4.0-test2/linux/arch/arm/kernel/irq.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/irq.c Mon Jun 26 12:04:01 2000 @@ -17,7 +17,6 @@ */ #include #include -#include #include #include #include @@ -26,7 +25,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/isa.c linux/arch/arm/kernel/isa.c --- v2.4.0-test2/linux/arch/arm/kernel/isa.c Tue Aug 31 17:29:12 1999 +++ linux/arch/arm/kernel/isa.c Mon Jun 26 12:04:01 2000 @@ -13,7 +13,6 @@ #include #include -#include #include #include #include diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/leds-footbridge.c linux/arch/arm/kernel/leds-footbridge.c --- v2.4.0-test2/linux/arch/arm/kernel/leds-footbridge.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/leds-footbridge.c Mon Jun 26 12:04:01 2000 @@ -18,8 +18,8 @@ * 02-05-1999 RMK Various cleanups */ #include -#include #include +#include #include #include diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/leds-sa1100.c linux/arch/arm/kernel/leds-sa1100.c --- v2.4.0-test2/linux/arch/arm/kernel/leds-sa1100.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/leds-sa1100.c Mon Jun 26 12:04:01 2000 @@ -29,8 +29,8 @@ * */ #include -#include #include +#include #include #include diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c --- v2.4.0-test2/linux/arch/arm/kernel/process.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/process.c Mon Jul 10 13:16:56 2000 @@ -7,28 +7,22 @@ #include -#include +#include #include #include #include -#include -#include #include #include #include #include -#include #include -#include -#include -#include #include #include #include -#include #include #include +#include /* * Values for cpu_do_idle() @@ -81,7 +75,7 @@ { /* endless idle loop with no priority at all */ init_idle(); - current->priority = 0; + current->nice = 20; current->counter = -100; while (1) { diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/ptrace.c linux/arch/arm/kernel/ptrace.c --- v2.4.0-test2/linux/arch/arm/kernel/ptrace.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/ptrace.c Mon Jun 26 12:04:01 2000 @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -16,6 +15,10 @@ #include #include +#include "ptrace.h" + +#define REG_PC 15 +#define REG_PSR 16 /* * does not yet catch signals sent when the child dies. * in exit.c or in signal.c. @@ -27,6 +30,18 @@ #define BREAKINST 0xef9f0001 /* + * Get the address of the live pt_regs for the specified task. + * These are saved onto the top kernel stack when the process + * is not running. + */ +static inline struct pt_regs * +get_user_regs(struct task_struct *task) +{ + return (struct pt_regs *) + ((unsigned long)task + 8192 - sizeof(struct pt_regs)); +} + +/* * this routine will get a word off of the processes privileged stack. * the offset is how far from the base addr as stored in the THREAD. * this routine assumes that all the privileged stacks are in our @@ -34,11 +49,7 @@ */ static inline long get_stack_long(struct task_struct *task, int offset) { - struct pt_regs *regs; - - regs = (struct pt_regs *)((unsigned long)task + 8192 - sizeof(struct pt_regs)); - - return regs->uregs[offset]; + return get_user_regs(task)->uregs[offset]; } /* @@ -47,20 +58,16 @@ * this routine assumes that all the privileged stacks are in our * data space. */ -static inline long put_stack_long(struct task_struct *task, int offset, - unsigned long data) +static inline int +put_stack_long(struct task_struct *task, int offset, long data) { - struct pt_regs *regs; - - regs = (struct pt_regs *)((unsigned long)task + 8192 - sizeof(struct pt_regs)); - - regs->uregs[offset] = data; + get_user_regs(task)->uregs[offset] = data; return 0; } -static int -read_long(struct task_struct *child, unsigned long addr, unsigned long *res) +static inline int +read_tsk_long(struct task_struct *child, unsigned long addr, unsigned long *res) { int copied; @@ -69,8 +76,8 @@ return copied != sizeof(*res) ? -EIO : 0; } -static int -write_long(struct task_struct *child, unsigned long addr, unsigned long val) +static inline int +write_tsk_long(struct task_struct *child, unsigned long addr, unsigned long val) { int copied; @@ -82,35 +89,33 @@ /* * Get value of register `rn' (in the instruction) */ -static unsigned long ptrace_getrn (struct task_struct *child, unsigned long insn) +static unsigned long +ptrace_getrn(struct task_struct *child, unsigned long insn) { unsigned int reg = (insn >> 16) & 15; unsigned long val; + val = get_stack_long(child, reg); if (reg == 15) - val = pc_pointer (get_stack_long (child, reg)); - else - val = get_stack_long (child, reg); + val = pc_pointer(val); -printk ("r%02d=%08lX ", reg, val); return val; } /* * Get value of operand 2 (in an ALU instruction) */ -static unsigned long ptrace_getaluop2 (struct task_struct *child, unsigned long insn) +static unsigned long +ptrace_getaluop2(struct task_struct *child, unsigned long insn) { unsigned long val; int shift; int type; -printk ("op2="); if (insn & 1 << 25) { val = insn & 255; shift = (insn >> 8) & 15; type = 3; -printk ("(imm)"); } else { val = get_stack_long (child, insn & 15); @@ -120,9 +125,8 @@ shift = (insn >> 7) & 31; type = (insn >> 5) & 3; -printk ("(r%02ld)", insn & 15); } -printk ("sh%dx%d", type, shift); + switch (type) { case 0: val <<= shift; break; case 1: val >>= shift; break; @@ -133,24 +137,23 @@ val = (val >> shift) | (val << (32 - shift)); break; } -printk ("=%08lX ", val); return val; } /* * Get value of operand 2 (in a LDR instruction) */ -static unsigned long ptrace_getldrop2 (struct task_struct *child, unsigned long insn) +static unsigned long +ptrace_getldrop2(struct task_struct *child, unsigned long insn) { unsigned long val; int shift; int type; - val = get_stack_long (child, insn & 15); + val = get_stack_long(child, insn & 15); shift = (insn >> 7) & 31; type = (insn >> 5) & 3; -printk ("op2=r%02ldsh%dx%d", insn & 15, shift, type); switch (type) { case 0: val <<= shift; break; case 1: val >>= shift; break; @@ -161,7 +164,6 @@ val = (val >> shift) | (val << (32 - shift)); break; } -printk ("=%08lX ", val); return val; } @@ -170,95 +172,72 @@ { unsigned long alt = 0; -printk(KERN_DEBUG "ptrace_set_bpt: insn=%08lX pc=%08lX ", insn, pc); - switch (insn & 0x0e100000) { + switch (insn & 0x0e000000) { case 0x00000000: - case 0x00100000: - case 0x02000000: - case 0x02100000: /* data processing */ - printk ("data "); - switch (insn & 0x01e0f000) { - case 0x0000f000: - alt = ptrace_getrn(child, insn) & ptrace_getaluop2(child, insn); - break; - case 0x0020f000: - alt = ptrace_getrn(child, insn) ^ ptrace_getaluop2(child, insn); - break; - case 0x0040f000: - alt = ptrace_getrn(child, insn) - ptrace_getaluop2(child, insn); - break; - case 0x0060f000: - alt = ptrace_getaluop2(child, insn) - ptrace_getrn(child, insn); - break; - case 0x0080f000: - alt = ptrace_getrn(child, insn) + ptrace_getaluop2(child, insn); - break; - case 0x00a0f000: - alt = ptrace_getrn(child, insn) + ptrace_getaluop2(child, insn) + - (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0); - break; - case 0x00c0f000: - alt = ptrace_getrn(child, insn) - ptrace_getaluop2(child, insn) + - (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0); - break; - case 0x00e0f000: - alt = ptrace_getaluop2(child, insn) - ptrace_getrn(child, insn) + - (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0); - break; - case 0x0180f000: - alt = ptrace_getrn(child, insn) | ptrace_getaluop2(child, insn); - break; - case 0x01a0f000: - alt = ptrace_getaluop2(child, insn); - break; - case 0x01c0f000: - alt = ptrace_getrn(child, insn) & ~ptrace_getaluop2(child, insn); - break; - case 0x01e0f000: - alt = ~ptrace_getaluop2(child, insn); + case 0x02000000: { + /* + * data processing + */ + long aluop1, aluop2, ccbit; + + if ((insn & 0xf000) != 0xf000) break; + + aluop1 = ptrace_getrn(child, insn); + aluop2 = ptrace_getaluop2(child, insn); + ccbit = get_stack_long(child, REG_PSR) & CC_C_BIT ? 1 : 0; + + switch (insn & 0x01e00000) { + case 0x00000000: alt = aluop1 & aluop2; break; + case 0x00200000: alt = aluop1 ^ aluop2; break; + case 0x00400000: alt = aluop1 - aluop2; break; + case 0x00600000: alt = aluop2 - aluop1; break; + case 0x00800000: alt = aluop1 + aluop2; break; + case 0x00a00000: alt = aluop1 + aluop2 + ccbit; break; + case 0x00c00000: alt = aluop1 - aluop2 + ccbit; break; + case 0x00e00000: alt = aluop2 - aluop1 + ccbit; break; + case 0x01800000: alt = aluop1 | aluop2; break; + case 0x01a00000: alt = aluop2; break; + case 0x01c00000: alt = aluop1 & ~aluop2; break; + case 0x01e00000: alt = ~aluop2; break; } break; + } + + case 0x04000000: + case 0x06000000: + /* + * ldr + */ + if ((insn & 0x0010f000) == 0x0010f000) { + unsigned long base; - case 0x04100000: /* ldr */ - if ((insn & 0xf000) == 0xf000) { -printk ("ldr "); - alt = ptrace_getrn(child, insn); + base = ptrace_getrn(child, insn); if (insn & 1 << 24) { - if (insn & 1 << 23) - alt += ptrace_getldrop2 (child, insn); + long aluop2; + + if (insn & 0x02000000) + aluop2 = ptrace_getldrop2(child, insn); else - alt -= ptrace_getldrop2 (child, insn); - } - if (read_long (child, alt, &alt) < 0) - alt = 0; /* not valid */ - else - alt = pc_pointer (alt); - } - break; + aluop2 = insn & 0xfff; - case 0x06100000: /* ldr imm */ - if ((insn & 0xf000) == 0xf000) { -printk ("ldrimm "); - alt = ptrace_getrn(child, insn); - if (insn & 1 << 24) { if (insn & 1 << 23) - alt += insn & 0xfff; + base += aluop2; else - alt -= insn & 0xfff; + base -= aluop2; } - if (read_long (child, alt, &alt) < 0) - alt = 0; /* not valid */ - else - alt = pc_pointer (alt); + if (read_tsk_long(child, base, &alt) == 0) + alt = pc_pointer(alt); } break; - case 0x08100000: /* ldm */ - if (insn & (1 << 15)) { + case 0x08000000: + /* + * ldm + */ + if ((insn & 0x00108000) == 0x00108000) { unsigned long base; - int nr_regs; -printk ("ldm "); + unsigned int nr_regs; if (insn & (1 << 23)) { nr_regs = insn & 65535; @@ -278,23 +257,22 @@ nr_regs = 0; } - base = ptrace_getrn (child, insn); + base = ptrace_getrn(child, insn); - if (read_long (child, base + nr_regs, &alt) < 0) - alt = 0; /* not valid */ - else + if (read_tsk_long(child, base + nr_regs, &alt) == 0) alt = pc_pointer (alt); break; } break; - case 0x0a000000: - case 0x0a100000: { /* bl or b */ + case 0x0a000000: { + /* + * bl or b + */ signed long displ; -printk ("b/bl "); /* It's a branch/branch link: instead of trying to * figure out whether the branch will be taken or not, - * we'll put a breakpoint at either location. This is + * we'll put a breakpoint at both locations. This is * simpler, more reliable, and probably not a whole lot * slower than the alternative approach of emulating the * branch. @@ -306,7 +284,6 @@ } break; } -printk ("=%08lX\n", alt); return alt; } @@ -318,9 +295,9 @@ int res = -EINVAL; if (nr < 2) { - res = read_long(child, addr, &dbg->bp[nr].insn); + res = read_tsk_long(child, addr, &dbg->bp[nr].insn); if (res == 0) - res = write_long(child, addr, BREAKINST); + res = write_tsk_long(child, addr, BREAKINST); if (res == 0) { dbg->bp[nr].address = addr; @@ -332,257 +309,309 @@ return res; } -int ptrace_set_bpt (struct task_struct *child) +int ptrace_set_bpt(struct task_struct *child) { - struct debug_info *dbg = &child->thread.debug; - unsigned long insn, pc, alt; + unsigned long insn, pc; int res; - pc = pc_pointer (get_stack_long (child, 15/*REG_PC*/)); + pc = pc_pointer(get_stack_long(child, REG_PC)); - res = read_long(child, pc, &insn); - if (res >= 0) { - res = 0; + res = read_tsk_long(child, pc, &insn); + if (!res) { + struct debug_info *dbg = &child->thread.debug; + unsigned long alt; dbg->nsaved = 0; - res = add_breakpoint(child, dbg, pc + 4); + alt = get_branch_address(child, pc, insn); + if (alt) + res = add_breakpoint(child, dbg, alt); - if (res == 0) { - alt = get_branch_address(child, pc, insn); - if (alt) - res = add_breakpoint(child, dbg, alt); - } + if (!res && (!alt || predicate(insn) != PREDICATE_ALWAYS)) + res = add_breakpoint(child, dbg, pc + 4); } return res; } -/* Ensure no single-step breakpoint is pending. Returns non-zero +/* + * Ensure no single-step breakpoint is pending. Returns non-zero * value if child was being single-stepped. */ -int ptrace_cancel_bpt (struct task_struct *child) +void __ptrace_cancel_bpt(struct task_struct *child) { struct debug_info *dbg = &child->thread.debug; - unsigned long tmp; int i, nsaved = dbg->nsaved; dbg->nsaved = 0; if (nsaved > 2) { - printk ("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved); + printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved); nsaved = 2; } for (i = 0; i < nsaved; i++) { - read_long(child, dbg->bp[i].address, &tmp); + unsigned long tmp; + + read_tsk_long(child, dbg->bp[i].address, &tmp); if (tmp != BREAKINST) printk(KERN_ERR "ptrace_cancel_bpt: weirdness\n"); - write_long(child, dbg->bp[i].address, dbg->bp[i].insn); + write_tsk_long(child, dbg->bp[i].address, dbg->bp[i].insn); } - - return nsaved != 0; } -asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +static int do_ptrace(int request, struct task_struct *child, long addr, long data) { - struct task_struct *child; + unsigned long tmp; int ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - if (pid == 1) /* you may not mess with init */ - goto out; - ret = -ESRCH; - if (!(child = find_task_by_pid(pid))) - goto out; - ret = -EPERM; - if (request == PTRACE_ATTACH) { - if (child == current) - goto out; - if ((!child->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out; - /* the same process cannot be attached many times */ - if (child->ptrace & PT_PTRACED) - goto out; - child->ptrace |= PT_PTRACED; - if (child->p_pptr != current) { - REMOVE_LINKS(child); - child->p_pptr = current; - SET_LINKS(child); - } - send_sig(SIGSTOP, child, 1); - ret = 0; - goto out; - } - ret = -ESRCH; - if (!(child->ptrace & PT_PTRACED)) - goto out; - if (child->state != TASK_STOPPED) { - if (request != PTRACE_KILL) - goto out; - } - if (child->p_pptr != current) - goto out; - switch (request) { - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: { - unsigned long tmp; - - ret = read_long(child, addr, &tmp); + /* + * read word at location "addr" in the child process. + */ + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + ret = read_tsk_long(child, addr, &tmp); if (!ret) ret = put_user(tmp, (unsigned long *) data); - goto out; - } - - case PTRACE_PEEKUSR: { /* read the word at location addr in the USER area. */ - unsigned long tmp; + break; + /* + * read the word at location "addr" in the user registers. + */ + case PTRACE_PEEKUSR: ret = -EIO; if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) - goto out; + break; tmp = 0; /* Default return condition */ - if (addr < sizeof (struct pt_regs)) + if (addr < sizeof(struct pt_regs)) tmp = get_stack_long(child, (int)addr >> 2); ret = put_user(tmp, (unsigned long *)data); - goto out; - } + break; - case PTRACE_POKETEXT: /* write the word at location addr. */ + /* + * write the word at location addr. + */ + case PTRACE_POKETEXT: case PTRACE_POKEDATA: - ret = write_long(child, addr, data); - goto out; + ret = write_tsk_long(child, addr, data); + break; - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ + /* + * write the word at location addr in the user registers. + */ + case PTRACE_POKEUSR: ret = -EIO; if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) - goto out; + break; if (addr < sizeof (struct pt_regs)) ret = put_stack_long(child, (int)addr >> 2, data); - goto out; + break; - case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: /* restart after signal. */ + /* + * continue/restart and stop at next (return from) syscall + */ + case PTRACE_SYSCALL: + case PTRACE_CONT: ret = -EIO; if ((unsigned long) data > _NSIG) - goto out; + break; if (request == PTRACE_SYSCALL) child->ptrace |= PT_TRACESYS; else child->ptrace &= ~PT_TRACESYS; child->exit_code = data; - wake_up_process (child); /* make sure single-step breakpoint is gone. */ - ptrace_cancel_bpt (child); + __ptrace_cancel_bpt(child); + wake_up_process(child); ret = 0; - goto out; + break; - /* make the child exit. Best I can do is send it a sigkill. + /* + * make the child exit. Best I can do is send it a sigkill. * perhaps it should be put in the status that it wants to * exit. */ case PTRACE_KILL: - if (child->state == TASK_ZOMBIE) /* already dead */ - return 0; - wake_up_process (child); + /* already dead */ + ret = 0; + if (child->state == TASK_ZOMBIE) + break; child->exit_code = SIGKILL; /* make sure single-step breakpoint is gone. */ - ptrace_cancel_bpt (child); + __ptrace_cancel_bpt(child); + wake_up_process(child); ret = 0; - goto out; + break; - case PTRACE_SINGLESTEP: /* execute single instruction. */ + /* + * execute single instruction. + */ + case PTRACE_SINGLESTEP: ret = -EIO; if ((unsigned long) data > _NSIG) - goto out; + break; child->thread.debug.nsaved = -1; child->ptrace &= ~PT_TRACESYS; - wake_up_process(child); child->exit_code = data; /* give it a chance to run. */ + wake_up_process(child); ret = 0; - goto out; - - case PTRACE_GETREGS: - { /* Get all gp regs from the child. */ - unsigned char *stack; + break; + /* + * detach a process that was attached. + */ + case PTRACE_DETACH: + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); + child->exit_code = data; + write_lock_irq(&tasklist_lock); + REMOVE_LINKS(child); + child->p_pptr = child->p_opptr; + SET_LINKS(child); + write_unlock_irq(&tasklist_lock); + /* make sure single-step breakpoint is gone. */ + __ptrace_cancel_bpt(child); + wake_up_process (child); ret = 0; - stack = (unsigned char *)((unsigned long)child + 8192 - sizeof(struct pt_regs)); - if (copy_to_user((void *)data, stack, + break; + + /* + * Get all gp regs from the child. + */ + case PTRACE_GETREGS: { + struct pt_regs *regs = get_user_regs(child); + + ret = 0; + if (copy_to_user((void *)data, regs, sizeof(struct pt_regs))) ret = -EFAULT; - goto out; - }; + break; + } - case PTRACE_SETREGS: - { - /* Set all gp regs in the child. */ - unsigned char *stack; + /* + * Set all gp regs in the child. + */ + case PTRACE_SETREGS: { + struct pt_regs *regs = get_user_regs(child); ret = 0; - stack = (unsigned char *)((unsigned long)child + 8192 - sizeof(struct pt_regs)); - if (copy_from_user(stack, (void *)data, + if (copy_from_user(regs, (void *)data, sizeof(struct pt_regs))) ret = -EFAULT; - goto out; - }; + break; + } - case PTRACE_GETFPREGS: - /* Get the child FPU state. */ - ret = 0; - if (copy_to_user((void *)data, &child->thread.fpstate, - sizeof(struct user_fp))) - ret = -EFAULT; - goto out; + /* + * Get the child FPU state. + */ + case PTRACE_GETFPREGS: + ret = -EIO; + if (!access_ok(VERIFY_WRITE, (void *)data, sizeof(struct user_fp))) + break; + + /* we should check child->used_math here */ + ret = __copy_to_user((void *)data, &child->thread.fpstate, + sizeof(struct user_fp)) ? -EFAULT : 0; + break; + /* + * Set the child FPU state. + */ case PTRACE_SETFPREGS: - /* Set the child FPU state. */ - ret = 0; - if (copy_from_user(&child->thread.fpstate, (void *)data, - sizeof(struct user_fp))) - ret = -EFAULT; - goto out; - - case PTRACE_DETACH: /* detach a process that was attached. */ ret = -EIO; - if ((unsigned long) data > _NSIG) - goto out; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - wake_up_process (child); - child->exit_code = data; - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - /* make sure single-step breakpoint is gone. */ - ptrace_cancel_bpt (child); - ret = 0; - goto out; + if (!access_ok(VERIFY_READ, (void *)data, sizeof(struct user_fp))) + break; + + child->used_math = 1; + ret = __copy_from_user(&child->thread.fpstate, (void *)data, + sizeof(struct user_fp)) ? -EFAULT : 0; + break; default: ret = -EIO; + break; + } + + return ret; +} + +asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +{ + struct task_struct *child; + int ret; + + lock_kernel(); + ret = -EPERM; + if (request == PTRACE_TRACEME) { + /* are we already being traced? */ + if (current->ptrace & PT_PTRACED) goto out; + /* set the ptrace bit in the process flags. */ + current->ptrace |= PT_PTRACED; + ret = 0; + goto out; } + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) + goto out; + + ret = -EPERM; + if (pid == 1) /* you may not mess with init */ + goto out_tsk; + + if (request == PTRACE_ATTACH) { + if (child == current) + goto out_tsk; + if ((!child->dumpable || + (current->uid != child->euid) || + (current->uid != child->suid) || + (current->uid != child->uid) || + (current->gid != child->egid) || + (current->gid != child->sgid) || + (!cap_issubset(child->cap_permitted, current->cap_permitted)) || + (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) + goto out_tsk; + /* the same process cannot be attached many times */ + if (child->ptrace & PT_PTRACED) + goto out_tsk; + child->ptrace |= PT_PTRACED; + + write_lock_irq(&tasklist_lock); + if (child->p_pptr != current) { + REMOVE_LINKS(child); + child->p_pptr = current; + SET_LINKS(child); + } + write_unlock_irq(&tasklist_lock); + + send_sig(SIGSTOP, child, 1); + ret = 0; + goto out_tsk; + } + ret = -ESRCH; + if (!(child->ptrace & PT_PTRACED)) + goto out_tsk; + if (child->state != TASK_STOPPED && request != PTRACE_KILL) + goto out_tsk; + if (child->p_pptr != current) + goto out_tsk; + + ret = do_ptrace(request, child, addr, data); + +out_tsk: + free_task_struct(child); out: unlock_kernel(); return ret; diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/ptrace.h linux/arch/arm/kernel/ptrace.h --- v2.4.0-test2/linux/arch/arm/kernel/ptrace.h Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/ptrace.h Mon Jun 26 12:04:01 2000 @@ -0,0 +1,16 @@ +extern void __ptrace_cancel_bpt(struct task_struct *); +extern int ptrace_set_bpt(struct task_struct *); + +/* + * Clear a breakpoint, if one exists. + */ +static inline int ptrace_cancel_bpt(struct task_struct *tsk) +{ + int nsaved = tsk->thread.debug.nsaved; + + if (nsaved) + __ptrace_cancel_bpt(tsk); + + return nsaved; +} + diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/semaphore.c linux/arch/arm/kernel/semaphore.c --- v2.4.0-test2/linux/arch/arm/kernel/semaphore.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/semaphore.c Mon Jun 26 12:04:01 2000 @@ -8,7 +8,6 @@ * Modified for ARM by Russell King */ #include -#include #include diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c --- v2.4.0-test2/linux/arch/arm/kernel/setup.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/setup.c Mon Jun 26 12:04:01 2000 @@ -35,6 +35,7 @@ extern void bootmem_init(struct meminfo *); extern void reboot_setup(char *str); extern void disable_hlt(void); +extern unsigned long memparse(char *ptr, char **retptr); extern int root_mountflags; extern int _stext, _text, _etext, _edata, _end; diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/signal.c linux/arch/arm/kernel/signal.c --- v2.4.0-test2/linux/arch/arm/kernel/signal.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/signal.c Mon Jun 26 12:04:01 2000 @@ -10,18 +10,19 @@ #include #include #include -#include #include +#include #include #include -#include #include -#include +#include #include +#include #include #include -#include + +#include "ptrace.h" #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) @@ -31,8 +32,6 @@ asmlinkage int sys_wait4(pid_t pid, unsigned long * stat_addr, int options, unsigned long *ru); asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall); -extern int ptrace_cancel_bpt (struct task_struct *); -extern int ptrace_set_bpt (struct task_struct *); int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from) { @@ -234,7 +233,7 @@ goto badframe; /* Send SIGTRAP if we're single-stepping */ - if (ptrace_cancel_bpt (current)) + if (ptrace_cancel_bpt(current)) send_sig(SIGTRAP, current, 1); return regs->ARM_r0; @@ -274,7 +273,7 @@ goto badframe; /* Send SIGTRAP if we're single-stepping */ - if (ptrace_cancel_bpt (current)) + if (ptrace_cancel_bpt(current)) send_sig(SIGTRAP, current, 1); return regs->ARM_r0; @@ -500,7 +499,7 @@ if (!oldset) oldset = ¤t->blocked; - single_stepping = ptrace_cancel_bpt (current); + single_stepping = ptrace_cancel_bpt(current); for (;;) { unsigned long signr; @@ -518,7 +517,7 @@ current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); - single_stepping |= ptrace_cancel_bpt (current); + single_stepping |= ptrace_cancel_bpt(current); /* We're back. Did the debugger cancel the sig? */ if (!(signr = current->exit_code)) @@ -617,7 +616,7 @@ /* Whee! Actually deliver the signal. */ handle_signal(signr, ka, &info, oldset, regs); if (single_stepping) - ptrace_set_bpt (current); + ptrace_set_bpt(current); return 1; } @@ -629,6 +628,6 @@ regs->ARM_pc -= 4; } if (single_stepping) - ptrace_set_bpt (current); + ptrace_set_bpt(current); return 0; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c --- v2.4.0-test2/linux/arch/arm/kernel/sys_arm.c Fri May 12 14:18:55 2000 +++ linux/arch/arm/kernel/sys_arm.c Sat Jul 8 19:26:11 2000 @@ -39,9 +39,7 @@ int fd[2]; int error; - lock_kernel(); error = do_pipe(fd); - unlock_kernel(); if (!error) { if (copy_to_user(fildes, fd, 2*sizeof(int))) error = -EFAULT; @@ -66,11 +64,7 @@ } down(¤t->mm->mmap_sem); - lock_kernel(); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - - unlock_kernel(); up(¤t->mm->mmap_sem); if (file) @@ -236,7 +230,6 @@ int error; char * filename; - lock_kernel(); filename = getname(filenamei); error = PTR_ERR(filename); if (IS_ERR(filename)) @@ -244,7 +237,6 @@ error = do_execve(filename, argv, envp, regs); putname(filename); out: - unlock_kernel(); return error; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/time.c linux/arch/arm/kernel/time.c --- v2.4.0-test2/linux/arch/arm/kernel/time.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/time.c Mon Jun 26 12:04:01 2000 @@ -13,7 +13,6 @@ * "A Kernel Model for Precision Timekeeping" by Dave Mills */ #include -#include #include #include #include diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c --- v2.4.0-test2/linux/arch/arm/kernel/traps.c Tue May 23 15:31:33 2000 +++ linux/arch/arm/kernel/traps.c Mon Jun 26 12:04:01 2000 @@ -17,16 +17,18 @@ #include #include #include +#include #include -#include -#include -#include #include +#include #include +#include +#include + +#include "ptrace.h" extern void c_backtrace (unsigned long fp, int pmode); -extern int ptrace_cancel_bpt (struct task_struct *); char *processor_modes[]= { "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , @@ -46,8 +48,6 @@ console_loglevel = 15; } -int kstack_depth_to_print = 200; - /* * Stack pointers should always be within the kernels view of * physical memory. If it is not there, then we can't dump @@ -199,37 +199,48 @@ die(str, regs, err); } -void bad_user_access_alignment(const void *ptr) -{ - printk(KERN_ERR "bad user access alignment: ptr = %p, pc = %p\n", ptr, - __builtin_return_address(0)); - current->thread.error_code = 0; - current->thread.trap_no = 11; - force_sig(SIGBUS, current); -/* die_if_kernel("Oops - bad user access alignment", regs, mode);*/ -} - asmlinkage void do_undefinstr(int address, struct pt_regs *regs, int mode) { + unsigned long addr = instruction_pointer(regs); + siginfo_t info; + #ifdef CONFIG_DEBUG_USER printk(KERN_INFO "%s (%d): undefined instruction: pc=%08lx\n", - current->comm, current->pid, instruction_pointer(regs)); + current->comm, current->pid, addr); #endif + current->thread.error_code = 0; current->thread.trap_no = 6; - force_sig(SIGILL, current); + + info.si_signo = SIGILL; + info.si_errno = 0; + info.si_code = ILL_ILLOPC; + info.si_addr = (void *)addr; + + force_sig_info(SIGILL, &info, current); + die_if_kernel("Oops - undefined instruction", regs, mode); } asmlinkage void do_excpt(int address, struct pt_regs *regs, int mode) { + siginfo_t info; + #ifdef CONFIG_DEBUG_USER printk(KERN_INFO "%s (%d): address exception: pc=%08lx\n", current->comm, current->pid, instruction_pointer(regs)); #endif + current->thread.error_code = 0; current->thread.trap_no = 11; - force_sig(SIGBUS, current); + + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void *)address; + + force_sig_info(SIGBUS, &info, current); + die_if_kernel("Oops - address exception", regs, mode); } @@ -269,32 +280,38 @@ } /* - * 'math_state_restore()' saves the current math information in the - * old math state array, and gets the new ones from the current task. - * - * We no longer save/restore the math state on every context switch - * any more. We only do this now if it actually gets used. - */ -asmlinkage void math_state_restore (void) -{ - current->used_math = 1; -} - -/* * Handle some more esoteric system calls */ -asmlinkage int arm_syscall (int no, struct pt_regs *regs) +asmlinkage int arm_syscall(int no, struct pt_regs *regs) { + siginfo_t info; + switch (no) { case 0: /* branch through 0 */ - force_sig(SIGSEGV, current); + info.si_signo = SIGSEGV; + info.si_errno = 0; + info.si_code = SEGV_MAPERR; + info.si_addr = NULL; + + force_sig_info(SIGSEGV, &info, current); + die_if_kernel("branch through zero", regs, 0); break; - case 1: /* SWI_BREAK_POINT */ - regs->ARM_pc -= 4; /* Decrement PC by one instruction */ - ptrace_cancel_bpt(current); - force_sig(SIGTRAP, current); + case 1: /* SWI BREAK_POINT */ + /* + * The PC is always left pointing at the next + * instruction. Fix this. + */ + regs->ARM_pc -= 4; + __ptrace_cancel_bpt(current); + + info.si_signo = SIGTRAP; + info.si_errno = 0; + info.si_code = TRAP_BRKPT; + info.si_addr = (void *)instruction_pointer(regs); + + force_sig_info(SIGTRAP, &info, current); return regs->ARM_r0; case 2: /* sys_cacheflush */ @@ -350,29 +367,24 @@ die_if_kernel("Oops", regs, n); } -asmlinkage void arm_malalignedptr(const char *str, void *pc, volatile void *ptr) +void __bad_xchg(volatile void *ptr, int size) { - printk("Mal-aligned pointer in %s: %p (PC=%p)\n", str, ptr, pc); -} - -asmlinkage void arm_invalidptr(const char *function, int size) -{ - printk("Invalid pointer size in %s (pc=%p) size %d\n", - function, __builtin_return_address(0), size); + printk("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n", + __builtin_return_address(0), ptr, size); + BUG(); } /* - * A data abort trap was taken, but the instruction was not an instruction - * which should cause the trap to be taken. Try to abort it. Note that - * the while(1) is there because we cannot currently handle returning from - * this function. + * A data abort trap was taken, but we did not handle the instruction. + * Try to abort the user program, or panic if it was the kernel. */ asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs) { unsigned long addr = instruction_pointer(regs); + siginfo_t info; -#ifdef CONFIG_DEBUG_ERRORS +#ifdef CONFIG_DEBUG_USER dump_instr(addr, 1); { pgd_t *pgd; @@ -389,16 +401,22 @@ printk ("\n"); } #endif - force_sig(SIGILL, current); + + info.si_signo = SIGILL; + info.si_errno = 0; + info.si_code = ILL_ILLOPC; + info.si_addr = (void *)addr; + + force_sig_info(SIGILL, &info, current); die_if_kernel("unknown data abort code", regs, instr); - while (1); } void __bug(const char *file, int line, void *data) { - printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line); + printk(KERN_CRIT"kernel BUG at %s:%d!", file, line); if (data) - printk(KERN_CRIT"extra data = %p\n", data); + printk(KERN_CRIT" - extra data = %p", data); + printk("\n"); BUG(); } diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/mm/fault-common.c linux/arch/arm/mm/fault-common.c --- v2.4.0-test2/linux/arch/arm/mm/fault-common.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/mm/fault-common.c Mon Jun 26 12:04:01 2000 @@ -187,6 +187,7 @@ tsk->thread.error_code = mode; tsk->thread.trap_no = 14; si.si_signo = SIGSEGV; + si.si_errno = 0; si.si_code = fault == -1 ? SEGV_ACCERR : SEGV_MAPERR; si.si_addr = (void *)addr; force_sig_info(SIGSEGV, &si, tsk); diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c --- v2.4.0-test2/linux/arch/arm/mm/mm-armv.c Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/mm/mm-armv.c Mon Jun 26 12:04:01 2000 @@ -410,9 +410,24 @@ flush_cache_all(); } -/* - * The mem_map array can get very big. Free the unused area of the memory map. - */ +static inline void free_memmap(unsigned long start, unsigned long end) +{ + unsigned long pg, pgend; + + start = __phys_to_virt(start); + end = __phys_to_virt(end); + + pg = PAGE_ALIGN((unsigned long)(mem_map + MAP_NR(start))); + pgend = ((unsigned long)(mem_map + MAP_NR(end))) & PAGE_MASK; + + start = __virt_to_phys(pg); + end = __virt_to_phys(pgend); + /* + * The mem_map is always stored in node 0 + */ + free_bootmem_node(0, start, end - start); +} + static inline void free_unused_memmap_node(int node, struct meminfo *mi) { unsigned long bank_start, prev_bank_end = 0; @@ -434,14 +449,17 @@ * between the current bank and the previous, free it. */ if (prev_bank_end && prev_bank_end != bank_start) - free_bootmem_node(node, prev_bank_end, - bank_start - prev_bank_end); + free_memmap(prev_bank_end, bank_start); prev_bank_end = PAGE_ALIGN(mi->bank[i].start + mi->bank[i].size); } } +/* + * The mem_map array can get very big. Free + * the unused area of the memory map. + */ void __init create_memmap_holes(struct meminfo *mi) { int node; diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/mm/proc-arm2,3.S linux/arch/arm/mm/proc-arm2,3.S --- v2.4.0-test2/linux/arch/arm/mm/proc-arm2,3.S Tue Dec 7 09:32:40 1999 +++ linux/arch/arm/mm/proc-arm2,3.S Mon Jun 26 12:04:01 2000 @@ -286,7 +286,6 @@ .word _arm2_proc_fin .word _arm2_set_pgd .word _arm2_xchg_1 - .word SYMBOL_NAME(abort) .word _arm2_xchg_4 cpu_arm2_info: @@ -300,7 +299,6 @@ .word _arm2_proc_fin .word _arm2_set_pgd .word _arm3_xchg_1 - .word SYMBOL_NAME(abort) .word _arm3_xchg_4 cpu_arm250_info: @@ -314,7 +312,6 @@ .word _arm3_proc_fin .word _arm3_set_pgd .word _arm3_xchg_1 - .word SYMBOL_NAME(abort) .word _arm3_xchg_4 cpu_arm3_info: diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/mm/proc-arm6,7.S linux/arch/arm/mm/proc-arm6,7.S --- v2.4.0-test2/linux/arch/arm/mm/proc-arm6,7.S Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/mm/proc-arm6,7.S Mon Jun 26 12:04:01 2000 @@ -158,8 +158,8 @@ mov r0, r2 mov r1, r4 mov r2, r3 - b baddataabort - + bl baddataabort + b ret_from_sys_call Ldata_lateldrpreconst: tst r4, #1 << 21 @ check writeback bit diff -u --recursive --new-file v2.4.0-test2/linux/arch/arm/mm/proc-arm720.S linux/arch/arm/mm/proc-arm720.S --- v2.4.0-test2/linux/arch/arm/mm/proc-arm720.S Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/mm/proc-arm720.S Mon Jun 26 12:04:01 2000 @@ -146,8 +146,8 @@ mov r0, r2 mov r1, r4 mov r2, r3 - b baddataabort - + bl baddataabort + b ret_from_sys_call Ldata_lateldrpreconst: tst r4, #1 << 21 @ check writeback bit diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/boot/compressed/head.S linux/arch/i386/boot/compressed/head.S --- v2.4.0-test2/linux/arch/i386/boot/compressed/head.S Tue Apr 11 15:09:12 2000 +++ linux/arch/i386/boot/compressed/head.S Wed Jul 5 12:03:12 2000 @@ -43,6 +43,7 @@ movl %eax,0x000000 # loop forever if it isn't cmpl %eax,0x100000 je 1b + /* * Initialize eflags. Some BIOS's leave bits like NT set. This would * confuse the debugger if this code is traced. @@ -64,10 +65,14 @@ * Do the decompression, and jump to the new kernel.. */ subl $16,%esp # place for structure on the stack - pushl %esp # address of structure as first arg + movl %esp,%eax + pushl %esi # real mode pointer as second arg + pushl %eax # address of structure as first arg call SYMBOL_NAME(decompress_kernel) orl %eax,%eax jnz 3f + popl %esi # discard address + popl %esi # real mode pointer xorl %ebx,%ebx ljmp $(__KERNEL_CS), $0x100000 @@ -82,11 +87,14 @@ movl $0x1000,%edi movl $move_routine_end,%ecx subl %esi,%ecx + addl $3,%ecx + shrl $2,%ecx cld rep - movsb + movsl popl %esi # discard the address + popl %ebx # real mode pointer popl %esi # low_buffer_start popl %ecx # lcount popl %edx # high_buffer_start @@ -100,18 +108,21 @@ * if we were high loaded. This _must_ PIC-code ! */ move_routine_start: + movl %ecx,%ebp + shrl $2,%ecx + rep + movsl + movl %ebp,%ecx + andl $3,%ecx rep movsb movl %edx,%esi movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0 + addl $3,%ecx + shrl $2,%ecx rep - movsb + movsl + movl %ebx,%esi # Restore setup pointer xorl %ebx,%ebx -/* - * Well, the kernel relies on %esp pointing into low mem, - * with the decompressor loaded high this is no longer true, - * so we set esp here. - */ - mov $0x90000,%esp ljmp $(__KERNEL_CS), $0x100000 move_routine_end: diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/boot/compressed/misc.c linux/arch/i386/boot/compressed/misc.c --- v2.4.0-test2/linux/arch/i386/boot/compressed/misc.c Mon Mar 27 08:08:21 2000 +++ linux/arch/i386/boot/compressed/misc.c Wed Jul 5 12:03:12 2000 @@ -73,11 +73,13 @@ /* * This is set up by the setup-routine at boot-time */ -#define EXT_MEM_K (*(unsigned short *)0x90002) +static unsigned char *real_mode; /* Pointer to real-mode data */ + +#define EXT_MEM_K (*(unsigned short *)(real_mode + 0x2)) #ifndef STANDARD_MEMORY_BIOS_CALL -#define ALT_MEM_K (*(unsigned long *) 0x901e0) +#define ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0)) #endif -#define SCREEN_INFO (*(struct screen_info *)0x90000) +#define SCREEN_INFO (*(struct screen_info *)(real_mode+0)) extern char input_data[]; extern int input_len; @@ -97,13 +99,13 @@ extern int end; static long free_mem_ptr = (long)&end; -static long free_mem_end_ptr = 0x90000; - +static long free_mem_end_ptr; + #define INPLACE_MOVE_ROUTINE 0x1000 #define LOW_BUFFER_START 0x2000 -#define LOW_BUFFER_END 0x90000 -#define LOW_BUFFER_SIZE ( LOW_BUFFER_END - LOW_BUFFER_START ) +#define LOW_BUFFER_MAX 0x90000 #define HEAP_SIZE 0x3000 +static unsigned int low_buffer_end, low_buffer_size; static int high_loaded =0; static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/; @@ -256,7 +258,7 @@ in = window; for (n = 0; n < outcnt; n++) { ch = *output_data++ = *in++; - if ((ulg)output_data == LOW_BUFFER_END) output_data=high_buffer_start; + if ((ulg)output_data == low_buffer_end) output_data=high_buffer_start; c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); } crc = c; @@ -312,10 +314,13 @@ if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory.\n"); #endif mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START; + low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX + ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff; + low_buffer_size = low_buffer_end - LOW_BUFFER_START; high_loaded = 1; free_mem_end_ptr = (long)high_buffer_start; - if ( (0x100000 + LOW_BUFFER_SIZE) > ((ulg)high_buffer_start)) { - high_buffer_start = (uch *)(0x100000 + LOW_BUFFER_SIZE); + if ( (0x100000 + low_buffer_size) > ((ulg)high_buffer_start)) { + high_buffer_start = (uch *)(0x100000 + low_buffer_size); mv->hcount = 0; /* say: we need not to move high_buffer */ } else mv->hcount = -1; @@ -324,17 +329,21 @@ void close_output_buffer_if_we_run_high(struct moveparams *mv) { - mv->lcount = bytes_out; - if (bytes_out > LOW_BUFFER_SIZE) { - mv->lcount = LOW_BUFFER_SIZE; - if (mv->hcount) mv->hcount = bytes_out - LOW_BUFFER_SIZE; + if (bytes_out > low_buffer_size) { + mv->lcount = low_buffer_size; + if (mv->hcount) + mv->hcount = bytes_out - low_buffer_size; + } else { + mv->lcount = bytes_out; + mv->hcount = 0; } - else mv->hcount = 0; } -int decompress_kernel(struct moveparams *mv) +int decompress_kernel(struct moveparams *mv, void *rmode) { + real_mode = rmode; + if (SCREEN_INFO.orig_video_mode == 7) { vidmem = (char *) 0xb0000; vidport = 0x3b4; @@ -356,4 +365,3 @@ if (high_loaded) close_output_buffer_if_we_run_high(mv); return high_loaded; } - diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S --- v2.4.0-test2/linux/arch/i386/boot/setup.S Sun Feb 20 21:12:38 2000 +++ linux/arch/i386/boot/setup.S Wed Jul 5 12:03:12 2000 @@ -70,7 +70,7 @@ # This is the setup header, and it must start at %cs:2 (old 0x9020:2) .ascii "HdrS" # header signature - .word 0x0201 # header version number (>= 0x0105) + .word 0x0202 # header version number (>= 0x0105) # or else old loadlin-1.5 will fail) realmode_swtch: .word 0, 0 # default_switch, SETUPSEG start_sys_seg: .word SYSSEG @@ -128,9 +128,27 @@ bootsect_kludge: .word bootsect_helper, SETUPSEG -heap_end_ptr: .word modelist+1024 # space from here (exclusive) down to +heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later) + # space from here (exclusive) down to # end of setup code can be used by setup # for local heap purposes. + +pad1: .word 0 +cmd_line_ptr: .long 0 # (Header version 0x0202 or later) + # If nonzero, a 32-bit pointer + # to the kernel command line. + # The command line should be + # located between the start of + # setup and the end of low + # memory (0xa0000), or it may + # get overwritten before it + # gets read. If this field is + # used, there is no longer + # anything magical about the + # 0x90000 segment; the setup + # can be located anywhere in + # low memory 0x10000 or higher. + trampoline: call start_of_setup .space 1024 # End of setup header ##################################################### @@ -551,7 +569,14 @@ # then we load the segment descriptors movw %cs, %ax # aka SETUPSEG movw %ax, %ds + +# Check whether we need to be downward compatible with version <=201 + cmpl $0, cmd_line_ptr + jne end_move_self # loader uses version >=202 features + cmpb $0x20, type_of_loader + je end_move_self # bootsect loader, we know of it +# Boot loader doesnt support boot protocol version 2.02. # If we have our code not at 0x90000, we need to move it there now. # We also then need to move the params behind it (commandline) # Because we would overwrite the code on the current IP, we move @@ -597,6 +622,11 @@ movw %dx, %ss end_move_self: # now we are at the right place lidt idt_48 # load idt with 0,0 + xorl %eax, %eax # Compute gdt_base + movw %ds, %ax # (Convert %ds:gdt to a linear ptr) + shll $4, %eax + addl $gdt, %eax + movl %eax, (gdt_48+2) lgdt gdt_48 # load gdt with whatever is # appropriate @@ -615,8 +645,7 @@ # time on certain systems; Toshiba Tecras are known to have this # problem. The memory location used here (0x200) is the int 0x80 # vector, which should be safe to use. - push %ds - push %es + xorw %ax, %ax # segment 0x0000 movw %ax, %fs decw %ax # segment 0xffff (HMA) @@ -663,7 +692,10 @@ flush_instr: xorw %bx, %bx # Flag to indicate a boot - + xorl %esi, %esi # Pointer to real-mode code + movw %cs, %si + subw $DELTA_INITSEG, %si + shll $4, %esi # Convert to 32-bit pointer # NOTE: For high loaded big kernels we need a # jmpi 0x100000,__KERNEL_CS # @@ -852,7 +884,7 @@ .word 0x8000 # gdt limit=2048, # 256 GDT entries - .word 512+gdt, 0x9 # gdt base = 0X9xxxx + .word 0, 0 # gdt base (filled in later) # Include video setup & detection code diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.4.0-test2/linux/arch/i386/config.in Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/config.in Fri Jul 7 17:55:02 2000 @@ -21,7 +21,7 @@ "386 CONFIG_M386 \ 486 CONFIG_M486 \ 586/K5/5x86/6x86/6x86MX CONFIG_M586 \ - Pentium/Pentium-MMX CONFIG_M586TSC \ + Pentium-Classic/Pentium-MMX CONFIG_M586TSC \ Pentium-Pro/Celeron/Pentium-II CONFIG_M686 \ Pentium-III CONFIG_M686FXSR \ K6/K6-II/K6-III CONFIG_MK6 \ @@ -29,11 +29,12 @@ Crusoe CONFIG_MCRUSOE \ Winchip-C6 CONFIG_MWINCHIPC6 \ Winchip-2 CONFIG_MWINCHIP2 \ - Winchip-2A/3 CONFIG_MWINCHIP3D" Pentium-Pro + Winchip-2A/Winchip-3 CONFIG_MWINCHIP3D" Pentium-Pro # # Define implied options from the CPU selection here # if [ "$CONFIG_M386" = "y" ]; then + define_bool CONFIG_X86_CMPXCHG n define_int CONFIG_X86_L1_CACHE_BYTES 16 else define_bool CONFIG_X86_WP_WORKS_OK y @@ -73,8 +74,6 @@ define_bool CONFIG_X86_USE_PPRO_CHECKSUM y define_bool CONFIG_X86_FXSR y define_bool CONFIG_X86_XMM y -else - define_bool CONFIG_X86_FXSR n fi if [ "$CONFIG_MK6" = "y" ]; then define_int CONFIG_X86_L1_CACHE_BYTES 32 @@ -141,6 +140,9 @@ define_bool CONFIG_X86_LOCAL_APIC y fi fi +if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then + define_bool CONFIG_HAVE_DEC_LOCK y +fi endmenu mainmenu_option next_comment @@ -209,9 +211,10 @@ bool 'Power Management support' CONFIG_PM -dep_tristate ' ACPI support' CONFIG_ACPI $CONFIG_PM +dep_bool ' ACPI support' CONFIG_ACPI $CONFIG_PM if [ "$CONFIG_ACPI" != "n" ]; then if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool ' ACPI interpreter (EXPERIMENTAL)' CONFIG_ACPI_INTERPRETER bool ' Enter S1 for sleep (EXPERIMENTAL)' CONFIG_ACPI_S1_SLEEP fi fi @@ -229,6 +232,8 @@ fi endmenu + +source drivers/mtd/Config.in source drivers/parport/Config.in diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.4.0-test2/linux/arch/i386/defconfig Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/defconfig Sun Jul 9 22:48:50 2000 @@ -36,7 +36,6 @@ CONFIG_X86_GOOD_APIC=y CONFIG_X86_PGE=y CONFIG_X86_USE_PPRO_CHECKSUM=y -# CONFIG_X86_FXSR is not set # CONFIG_MICROCODE is not set # CONFIG_X86_MSR is not set # CONFIG_X86_CPUID is not set @@ -46,6 +45,7 @@ # CONFIG_MATH_EMULATION is not set # CONFIG_MTRR is not set CONFIG_SMP=y +CONFIG_HAVE_DEC_LOCK=y # # Loadable module support @@ -91,6 +91,11 @@ # CONFIG_APM is not set # +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# # Parallel port support # # CONFIG_PARPORT is not set @@ -137,14 +142,10 @@ # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_IP_ALIAS is not set +# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # -# (it is safe to leave these untouched) -# -CONFIG_SKB_LARGE=y - -# # # # CONFIG_IPX is not set @@ -506,6 +507,7 @@ # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set # CONFIG_RAMFS is not set CONFIG_ISO9660_FS=y diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile --- v2.4.0-test2/linux/arch/i386/kernel/Makefile Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/kernel/Makefile Wed Jul 5 11:23:12 2000 @@ -35,12 +35,16 @@ obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o -obj-$(CONFIG_ACPI) += acpi.o obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o + +# if the interpreter is used, it overrides acpi.c +ifneq ($(CONFIG_ACPI_INTERPRETER),y) +obj-$(CONFIG_ACPI) += acpi.o +endif O_OBJS := $(filter-out $(export-objs), $(obj-y)) OX_OBJS := $(filter $(export-objs), $(obj-y)) diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c --- v2.4.0-test2/linux/arch/i386/kernel/apic.c Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/kernel/apic.c Mon Jul 10 14:20:49 2000 @@ -5,8 +5,9 @@ * * Fixes * Maciej W. Rozycki : Bits for genuine 82489DX APICs; - * thanks to Eric Gilmore for - * testing these extensively + * thanks to Eric Gilmore + * and Rolf G. Tews + * for testing these extensively */ #include @@ -588,7 +589,7 @@ p->counter = 0; p->need_resched = 1; } - if (p->priority < DEF_PRIORITY) { + if (p->nice > 0) { kstat.cpu_nice += user; kstat.per_cpu_nice[cpu] += user; } else { @@ -597,7 +598,9 @@ } kstat.cpu_system += system; kstat.per_cpu_system[cpu] += system; - + } else if (local_bh_count(cpu) || local_irq_count(cpu) > 1) { + kstat.cpu_system += system; + kstat.per_cpu_system[cpu] += system; } irq_exit(cpu, 0); } diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c --- v2.4.0-test2/linux/arch/i386/kernel/apm.c Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/kernel/apm.c Fri Jul 7 15:55:24 2000 @@ -660,6 +660,7 @@ #endif } +#ifdef CONFIG_APM_DO_ENABLE static int apm_enable_power_management(int enable) { u32 eax; @@ -675,6 +676,7 @@ apm_bios_info.flags |= APM_BIOS_DISABLED; return APM_SUCCESS; } +#endif static int apm_get_power_status(u_short *status, u_short *bat, u_short *life) { diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S --- v2.4.0-test2/linux/arch/i386/kernel/entry.S Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/kernel/entry.S Mon Jul 10 09:57:52 2000 @@ -77,8 +77,8 @@ addr_limit = 12 exec_domain = 16 need_resched = 20 -processor = 56 -tsk_ptrace = 60 +tsk_ptrace = 24 +processor = 52 ENOSYS = 38 diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S --- v2.4.0-test2/linux/arch/i386/kernel/head.S Wed Apr 26 16:34:06 2000 +++ linux/arch/i386/kernel/head.S Wed Jul 5 12:03:12 2000 @@ -16,11 +16,11 @@ #include #include - -#define CL_MAGIC_ADDR 0x90020 -#define CL_MAGIC 0xA33F -#define CL_BASE_ADDR 0x90000 -#define CL_OFFSET 0x90022 +#define OLD_CL_MAGIC_ADDR 0x90020 +#define OLD_CL_MAGIC 0xA33F +#define OLD_CL_BASE_ADDR 0x90000 +#define OLD_CL_OFFSET 0x90022 +#define NEW_CL_POINTER 0x228 /* Relative to real mode data */ /* * References to members of the boot_cpu_data structure. @@ -38,6 +38,8 @@ /* * swapper_pg_dir is the main page directory, address 0x00101000 + * + * On entry, %esi points to the real-mode code as a 32-bit pointer. */ ENTRY(stext) ENTRY(_stext) @@ -54,6 +56,7 @@ #ifdef CONFIG_SMP orw %bx,%bx jz 1f + /* * New page tables may be in 4Mbyte page mode and may * be using the global pages. @@ -113,6 +116,7 @@ jmp checkCPUtype 1: #endif CONFIG_SMP + /* * Clear BSS first so that there are no surprises... */ @@ -123,6 +127,7 @@ cld rep stosb + /* * start system 32-bit setup. We need to re-do some of the things done * in 16-bit mode for the "real" operations. @@ -139,8 +144,9 @@ * Copy bootup parameters out of the way. First 2kB of * _empty_zero_page is for boot parameters, second 2kB * is for the command line. + * + * Note: %esi still has the pointer to the real-mode data. */ - movl $0x90000,%esi movl $ SYMBOL_NAME(empty_zero_page),%edi movl $512,%ecx cld @@ -150,11 +156,15 @@ movl $512,%ecx rep stosl - cmpw $(CL_MAGIC),CL_MAGIC_ADDR + movl SYMBOL_NAME(empty_zero_page)+NEW_CL_POINTER,%esi + andl %esi,%esi + jnz 2f # New command line protocol + cmpw $(OLD_CL_MAGIC),OLD_CL_MAGIC_ADDR jne 1f + movzwl OLD_CL_OFFSET,%esi + addl $(OLD_CL_BASE_ADDR),%esi +2: movl $ SYMBOL_NAME(empty_zero_page)+2048,%edi - movzwl CL_OFFSET,%esi - addl $(CL_BASE_ADDR),%esi movl $512,%ecx rep movsl @@ -455,7 +465,7 @@ .quad 0x00009a0000000000 /* 0x50 APM CS 16 code (16 bit) */ .quad 0x0040920000000000 /* 0x58 APM DS data */ .fill NR_CPUS*4,8,0 /* space for TSS's and LDT's */ - + /* * This is to aid debugging, the various locking macros will be putting * code fragments here. When an oops occurs we'd rather know that it's diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/i8259.c linux/arch/i386/kernel/i8259.c --- v2.4.0-test2/linux/arch/i386/kernel/i8259.c Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/kernel/i8259.c Wed Jul 5 13:24:10 2000 @@ -363,6 +363,8 @@ * when acking. */ i8259A_irq_type.ack = disable_8259A_irq; + else + i8259A_irq_type.ack = mask_and_ack_8259A; udelay(100); /* wait for 8259A to initialize */ diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c --- v2.4.0-test2/linux/arch/i386/kernel/io_apic.c Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/kernel/io_apic.c Wed Jul 5 13:24:10 2000 @@ -14,8 +14,9 @@ * * Fixes * Maciej W. Rozycki : Bits for genuine 82489DX APICs; - * thanks to Eric Gilmore for - * testing these extensively + * thanks to Eric Gilmore + * and Rolf G. Tews + * for testing these extensively */ #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include @@ -227,9 +229,9 @@ } /* - * Find the pin to which IRQ0 (ISA) is connected + * Find the pin to which IRQ[irq] (ISA) is connected */ -static int __init find_timer_pin(int type) +static int __init find_isa_irq_pin(int irq, int type) { int i; @@ -240,7 +242,7 @@ mp_bus_id_to_type[lbus] == MP_BUS_EISA || mp_bus_id_to_type[lbus] == MP_BUS_MCA) && (mp_irqs[i].mpc_irqtype == type) && - (mp_irqs[i].mpc_srcbusirq == 0x00)) + (mp_irqs[i].mpc_srcbusirq == irq)) return mp_irqs[i].mpc_dstirq; } @@ -1246,6 +1248,22 @@ } } +static void enable_lapic_irq (unsigned int irq) +{ + unsigned long v; + + v = apic_read(APIC_LVT0); + apic_write_around(APIC_LVT0, v & ~APIC_LVT_MASKED); +} + +static void disable_lapic_irq (unsigned int irq) +{ + unsigned long v; + + v = apic_read(APIC_LVT0); + apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED); +} + static void ack_lapic_irq (unsigned int irq) { ack_APIC_irq(); @@ -1257,8 +1275,8 @@ "local-APIC-edge", NULL, /* startup_irq() not used for IRQ0 */ NULL, /* shutdown_irq() not used for IRQ0 */ - NULL, /* enable_irq() not used for IRQ0 */ - NULL, /* disable_irq() not used for IRQ0 */ + enable_lapic_irq, + disable_lapic_irq, ack_lapic_irq, end_lapic_irq }; @@ -1295,6 +1313,61 @@ } /* + * This looks a bit hackish but it's about the only one way of sending + * a few INTA cycles to 8259As and any associated glue logic. ICR does + * not support the ExtINT mode, unfortunately. We need to send these + * cycles as some i82489DX-based boards have glue logic that keeps the + * 8259A interrupt line asserted until INTA. --macro + */ +static inline void unlock_ExtINT_logic(void) +{ + int pin, i; + struct IO_APIC_route_entry entry0, entry1; + unsigned char save_control, save_freq_select; + + pin = find_isa_irq_pin(8, mp_INT); + if (pin == -1) + return; + + *(((int *)&entry0) + 1) = io_apic_read(0, 0x11 + 2 * pin); + *(((int *)&entry0) + 0) = io_apic_read(0, 0x10 + 2 * pin); + clear_IO_APIC_pin(0, pin); + + memset(&entry1, 0, sizeof(entry1)); + + entry1.dest_mode = 0; /* physical delivery */ + entry1.mask = 0; /* unmask IRQ now */ + entry1.dest.physical.physical_dest = hard_smp_processor_id(); + entry1.delivery_mode = dest_ExtINT; + entry1.polarity = entry0.polarity; + entry1.trigger = 0; + entry1.vector = 0; + + io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry1) + 1)); + io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry1) + 0)); + + save_control = CMOS_READ(RTC_CONTROL); + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); + CMOS_WRITE((save_freq_select & ~RTC_RATE_SELECT) | 0x6, + RTC_FREQ_SELECT); + CMOS_WRITE(save_control | RTC_PIE, RTC_CONTROL); + + i = 100; + while (i-- > 0) { + mdelay(10); + if ((CMOS_READ(RTC_INTR_FLAGS) & RTC_PF) == RTC_PF) + i -= 10; + } + + CMOS_WRITE(save_control, RTC_CONTROL); + CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + clear_IO_APIC_pin(0, pin); + + io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry0) + 1)); + io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry0) + 0)); +} + +/* * This code may look a bit paranoid, but it's supposed to cooperate with * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ * is so screwy. Thanks to Brian Perkins for testing/hacking this beast @@ -1325,8 +1398,8 @@ timer_ack = 1; enable_8259A_irq(0); - pin1 = find_timer_pin(mp_INT); - pin2 = find_timer_pin(mp_ExtINT); + pin1 = find_isa_irq_pin(0, mp_INT); + pin2 = find_isa_irq_pin(0, mp_ExtINT); printk(KERN_INFO "..TIMER: vector=%d pin1=%d pin2=%d\n", vector, pin1, pin2); @@ -1381,6 +1454,21 @@ irq_desc[0].handler = &lapic_irq_type; apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */ enable_8259A_irq(0); + + if (timer_irq_works()) { + printk(" works.\n"); + return; + } + apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector); + printk(" failed.\n"); + + printk(KERN_INFO "...trying to set up timer as ExtINT IRQ..."); + + init_8259A(0); + make_8259A_irq(0); + apic_write_around(APIC_LVT0, APIC_DM_EXTINT); + + unlock_ExtINT_logic(); if (timer_irq_works()) { printk(" works.\n"); diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/microcode.c linux/arch/i386/kernel/microcode.c --- v2.4.0-test2/linux/arch/i386/kernel/microcode.c Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/kernel/microcode.c Thu Jul 6 01:20:14 2000 @@ -11,6 +11,8 @@ * * http://developer.intel.com/design/pentiumii/manuals/243192.htm * + * For more information, go to http://www.urbanmyth.org/microcode + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version @@ -226,7 +228,7 @@ } wrmsr(0x79, (unsigned int)(m->bits), 0); - __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx", "cc"); + __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx"); rdmsr(0x8B, val[0], val[1]); req->err = 0; diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/pci-irq.c linux/arch/i386/kernel/pci-irq.c --- v2.4.0-test2/linux/arch/i386/kernel/pci-irq.c Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/kernel/pci-irq.c Mon Jun 26 12:02:16 2000 @@ -464,7 +464,7 @@ } } -void __init pcibios_penalize_isa_irq(int irq) +void pcibios_penalize_isa_irq(int irq) { /* * If any ISAPnP device reports an IRQ in its list of possible diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v2.4.0-test2/linux/arch/i386/kernel/process.c Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/kernel/process.c Mon Jul 10 13:15:45 2000 @@ -88,16 +88,42 @@ } /* + * On SMP it's slightly faster (but much more power-consuming!) + * to poll the ->need_resched flag instead of waiting for the + * cross-CPU IPI to arrive. Use this option with caution. + */ +static void poll_idle (void) +{ + int oldval; + + __sti(); + + /* + * Deal with another CPU just having chosen a thread to + * run here: + */ + oldval = xchg(¤t->need_resched, -1); + + if (!oldval) + asm volatile( + "2:" + "cmpl $-1, %0;" + "rep; nop;" + "je 2b;" + : :"m" (current->need_resched)); +} + +/* * The idle thread. There's no useful work to be * done, so just try to conserve power and have a * low exit latency (ie sit in a loop waiting for * somebody to say that they'd like to reschedule) */ -void cpu_idle(void) +void cpu_idle (void) { /* endless idle loop with no priority at all */ init_idle(); - current->priority = 0; + current->nice = 20; current->counter = -100; while (1) { @@ -111,6 +137,18 @@ } } +static int __init idle_setup (char *str) +{ + if (!strncmp(str, "poll", 4)) { + printk("using polling idle threads.\n"); + pm_idle = poll_idle; + } + + return 1; +} + +__setup("idle=", idle_setup); + static long no_idt[2] = {0, 0}; static int reboot_mode = 0; static int reboot_thru_bios = 0; @@ -344,7 +382,7 @@ void show_regs(struct pt_regs * regs) { - long cr0 = 0L, cr2 = 0L, cr3 = 0L; + unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; printk("\n"); printk("EIP: %04x:[<%08lx>]",0xffff & regs->xcs,regs->eip); @@ -361,7 +399,14 @@ __asm__("movl %%cr0, %0": "=r" (cr0)); __asm__("movl %%cr2, %0": "=r" (cr2)); __asm__("movl %%cr3, %0": "=r" (cr3)); - printk("CR0: %08lx CR2: %08lx CR3: %08lx\n", cr0, cr2, cr3); + /* This could fault if %cr4 does not exist */ + __asm__("1: movl %%cr4, %0 \n" + "2: \n" + ".section __ex_table,\"a\" \n" + ".long 1b,2b \n" + ".previous \n" + : "=r" (cr4): "0" (0)); + printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4); } /* diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.4.0-test2/linux/arch/i386/kernel/setup.c Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/kernel/setup.c Thu Jul 6 19:42:06 2000 @@ -43,6 +43,11 @@ * Pentium III FXSR, SSE support * General FPU state handling cleanups * Gareth Hughes , May 2000 + * + * Added proper Cascades CPU and L2 cache detection for Cascades + * and 8-way type cache happy bunch from Intel:^) + * Dragan Stancevic , May 2000 + * */ /* @@ -1630,7 +1635,8 @@ x86_cap_flags[10] = "sep"; if (c->x86 < 6) x86_cap_flags[16] = "fcmov"; - x86_cap_flags[16] = "pat"; + else + x86_cap_flags[16] = "pat"; x86_cap_flags[22] = "mmxext"; x86_cap_flags[24] = "fxsr"; x86_cap_flags[30] = "3dnowext"; diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c --- v2.4.0-test2/linux/arch/i386/kernel/signal.c Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/kernel/signal.c Wed Jul 5 22:09:45 2000 @@ -682,7 +682,6 @@ /* FALLTHRU */ default: - lock_kernel(); sigaddset(¤t->signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/sys_i386.c linux/arch/i386/kernel/sys_i386.c --- v2.4.0-test2/linux/arch/i386/kernel/sys_i386.c Fri Jan 28 15:09:07 2000 +++ linux/arch/i386/kernel/sys_i386.c Wed Jul 5 11:31:00 2000 @@ -31,9 +31,7 @@ int fd[2]; int error; - lock_kernel(); error = do_pipe(fd); - unlock_kernel(); if (!error) { if (copy_to_user(fildes, fd, 2*sizeof(int))) error = -EFAULT; @@ -58,11 +56,7 @@ } down(¤t->mm->mmap_sem); - lock_kernel(); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - - unlock_kernel(); up(¤t->mm->mmap_sem); if (file) diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c --- v2.4.0-test2/linux/arch/i386/kernel/time.c Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/kernel/time.c Mon Jul 10 14:33:03 2000 @@ -79,7 +79,7 @@ unsigned long fast_gettimeoffset_quotient=0; extern rwlock_t xtime_lock; -extern volatile unsigned long lost_ticks; +extern unsigned long wall_jiffies; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; @@ -262,7 +262,7 @@ read_lock_irqsave(&xtime_lock, flags); usec = do_gettimeoffset(); { - unsigned long lost = lost_ticks; + unsigned long lost = jiffies - wall_jiffies; if (lost) usec += lost * (1000000 / HZ); } @@ -282,14 +282,14 @@ void do_settimeofday(struct timeval *tv) { write_lock_irq(&xtime_lock); - /* This is revolting. We need to set the xtime.tv_usec - * correctly. However, the value in this location is - * is value at the last tick. - * Discover what correction gettimeofday - * would have done, and then undo it! + /* + * This is revolting. We need to set "xtime" correctly. However, the + * value in this location is the value at the most recent update of + * wall time. Discover what correction gettimeofday() would have + * made, and then undo it! */ tv->tv_usec -= do_gettimeoffset(); - tv->tv_usec -= lost_ticks * (1000000 / HZ); + tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ); while (tv->tv_usec < 0) { tv->tv_usec += 1000000; diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.4.0-test2/linux/arch/i386/kernel/traps.c Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/kernel/traps.c Wed Jul 5 22:01:37 2000 @@ -19,8 +19,6 @@ #include #include #include -#include -#include #include #include #include @@ -77,68 +75,6 @@ console_loglevel = 15; } -#define DO_ERROR(trapnr, signr, str, name, tsk) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ -{ \ - tsk->thread.error_code = error_code; \ - tsk->thread.trap_no = trapnr; \ - die_if_no_fixup(str,regs,error_code); \ - force_sig(signr, tsk); \ -} - -#define DO_ERROR_INFO(trapnr, signr, str, name, tsk, sicode, siaddr) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ -{ \ - siginfo_t info; \ - tsk->thread.error_code = error_code; \ - tsk->thread.trap_no = trapnr; \ - die_if_no_fixup(str,regs,error_code); \ - info.si_signo = signr; \ - info.si_errno = 0; \ - info.si_code = sicode; \ - info.si_addr = (void *)siaddr; \ - force_sig_info(signr, &info, tsk); \ -} - -#define DO_VM86_ERROR(trapnr, signr, str, name, tsk) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ -{ \ - lock_kernel(); \ - if (regs->eflags & VM_MASK) { \ - if (!handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr)) \ - goto out; \ - /* else fall through */ \ - } \ - tsk->thread.error_code = error_code; \ - tsk->thread.trap_no = trapnr; \ - force_sig(signr, tsk); \ - die_if_kernel(str,regs,error_code); \ -out: \ - unlock_kernel(); \ -} - -#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, tsk, sicode, siaddr) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ -{ \ - siginfo_t info; \ - lock_kernel(); \ - if (regs->eflags & VM_MASK) { \ - if (!handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr)) \ - goto out; \ - /* else fall through */ \ - } \ - tsk->thread.error_code = error_code; \ - tsk->thread.trap_no = trapnr; \ - info.si_signo = signr; \ - info.si_errno = 0; \ - info.si_code = sicode; \ - info.si_addr = (void *)siaddr; \ - force_sig_info(signr, &info, tsk); \ - die_if_kernel(str,regs,error_code); \ -out: \ - unlock_kernel(); \ -} - asmlinkage void divide_error(void); asmlinkage void debug(void); asmlinkage void nmi(void); @@ -285,20 +221,6 @@ die(str, regs, err); } -static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err) -{ - if (!(regs->eflags & VM_MASK) && !(3 & regs->xcs)) - { - unsigned long fixup; - fixup = search_exception_table(regs->eip); - if (fixup) { - regs->eip = fixup; - return; - } - die(str, regs, err); - } -} - static inline unsigned long get_cr2(void) { unsigned long address; @@ -308,19 +230,88 @@ return address; } -DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, current, FPE_INTDIV, regs->eip) -DO_VM86_ERROR( 3, SIGTRAP, "int3", int3, current) -DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow, current) -DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds, current) -DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, current, ILL_ILLOPN, regs->eip) -DO_VM86_ERROR( 7, SIGSEGV, "device not available", device_not_available, current) -DO_ERROR( 8, SIGSEGV, "double fault", double_fault, current) -DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun, current) -DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current) -DO_ERROR(11, SIGBUS, "segment not present", segment_not_present, current) -DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current) -DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, current, BUS_ADRALN, get_cr2()) -DO_ERROR(18, SIGSEGV, "reserved", reserved, current) +static void inline do_trap(int trapnr, int signr, char *str, int vm86, + struct pt_regs * regs, long error_code, siginfo_t *info) +{ + if (vm86 && regs->eflags & VM_MASK) + goto vm86_trap; + if (!(regs->xcs & 3)) + goto kernel_trap; + + trap_signal: { + struct task_struct *tsk = current; + tsk->thread.error_code = error_code; + tsk->thread.trap_no = trapnr; + if (info) + force_sig_info(signr, info, tsk); + else + force_sig(signr, tsk); + return; + } + + kernel_trap: { + unsigned long fixup = search_exception_table(regs->eip); + if (fixup) + regs->eip = fixup; + else + die(str, regs, error_code); + return; + } + + vm86_trap: { + int ret = handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr); + if (ret) goto trap_signal; + return; + } +} + +#define DO_ERROR(trapnr, signr, str, name) \ +asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +{ \ + do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \ +} + +#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ +asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +{ \ + siginfo_t info; \ + info.si_signo = signr; \ + info.si_errno = 0; \ + info.si_code = sicode; \ + info.si_addr = (void *)siaddr; \ + do_trap(trapnr, signr, str, 0, regs, error_code, &info); \ +} + +#define DO_VM86_ERROR(trapnr, signr, str, name) \ +asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +{ \ + do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \ +} + +#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ +asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +{ \ + siginfo_t info; \ + info.si_signo = signr; \ + info.si_errno = 0; \ + info.si_code = sicode; \ + info.si_addr = (void *)siaddr; \ + do_trap(trapnr, signr, str, 1, regs, error_code, &info); \ +} + +DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->eip) +DO_VM86_ERROR( 3, SIGTRAP, "int3", int3) +DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) +DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) +DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip) +DO_VM86_ERROR( 7, SIGSEGV, "device not available", device_not_available) +DO_ERROR( 8, SIGSEGV, "double fault", double_fault) +DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) +DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) +DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) +DO_ERROR(12, SIGBUS, "stack segment", stack_segment) +DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2()) +DO_ERROR(18, SIGSEGV, "reserved", reserved) asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) { @@ -336,9 +327,7 @@ return; gp_in_vm86: - lock_kernel(); handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); - unlock_kernel(); return; gp_in_kernel: @@ -561,9 +550,7 @@ return; debug_vm86: - lock_kernel(); handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1); - unlock_kernel(); return; clear_dr7: @@ -752,12 +739,10 @@ asmlinkage void math_emulate(long arg) { - lock_kernel(); printk("math-emulation not enabled and no coprocessor found.\n"); printk("killing %s.\n",current->comm); force_sig(SIGFPE,current); schedule(); - unlock_kernel(); } #endif /* CONFIG_MATH_EMULATION */ diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c --- v2.4.0-test2/linux/arch/i386/kernel/vm86.c Fri Jun 23 21:55:07 2000 +++ linux/arch/i386/kernel/vm86.c Wed Jul 5 22:08:27 2000 @@ -69,7 +69,6 @@ struct pt_regs *ret; unsigned long tmp; - lock_kernel(); if (!current->thread.vm86_info) { printk("no vm86_info: BAD\n"); do_exit(SIGSEGV); @@ -87,7 +86,6 @@ tss->esp0 = current->thread.esp0 = current->thread.saved_esp0; current->thread.saved_esp0 = 0; ret = KVM86->regs32; - unlock_kernel(); return ret; } @@ -138,7 +136,6 @@ struct task_struct *tsk; int tmp, ret = -EPERM; - lock_kernel(); tsk = current; if (tsk->thread.saved_esp0) goto out; @@ -154,7 +151,6 @@ do_sys_vm86(&info, tsk); ret = 0; /* we never return here */ out: - unlock_kernel(); return ret; } @@ -169,7 +165,6 @@ struct task_struct *tsk; int tmp, ret; - lock_kernel(); tsk = current; switch (subfunction) { case VM86_REQUEST_IRQ: @@ -204,7 +199,6 @@ do_sys_vm86(&info, tsk); ret = 0; /* we never return here */ out: - unlock_kernel(); return ret; } @@ -258,7 +252,6 @@ tsk->thread.screen_bitmap = info->screen_bitmap; if (info->flags & VM86_SCREEN_BITMAP) mark_screen_rdonly(tsk); - unlock_kernel(); __asm__ __volatile__( "xorl %%eax,%%eax; movl %%eax,%%fs; movl %%eax,%%gs\n\t" "movl %0,%%esp\n\t" @@ -274,7 +267,6 @@ regs32 = save_v86_state(regs16); regs32->eax = retval; - unlock_kernel(); __asm__ __volatile__("movl %0,%%esp\n\t" "jmp ret_from_sys_call" : : "r" (regs32), "b" (current)); @@ -432,7 +424,6 @@ return_to_32bit(regs, VM86_INTx + (i << 8)); } -/* This must be called with the kernel lock held. */ int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno) { if (VMPI.is_vm86pus) { @@ -456,7 +447,6 @@ return 0; } -/* This must be called with the kernel lock held. */ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code) { unsigned char *csp, *ssp; @@ -586,7 +576,6 @@ int irq_bit; unsigned long flags; - lock_kernel(); save_flags(flags); cli(); irq_bit = 1 << intno; @@ -598,7 +587,6 @@ /* else user will poll for IRQs */ out: restore_flags(flags); - unlock_kernel(); } static inline void free_vm86_irq(int irqnumber) diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/lib/Makefile linux/arch/i386/lib/Makefile --- v2.4.0-test2/linux/arch/i386/lib/Makefile Tue Apr 11 15:09:12 2000 +++ linux/arch/i386/lib/Makefile Fri Jul 7 17:55:39 2000 @@ -13,4 +13,8 @@ L_OBJS += mmx.o endif +ifdef CONFIG_HAVE_DEC_LOCK +L_OBJS += dec_and_lock.o +endif + include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/lib/dec_and_lock.c linux/arch/i386/lib/dec_and_lock.c --- v2.4.0-test2/linux/arch/i386/lib/dec_and_lock.c Wed Dec 31 16:00:00 1969 +++ linux/arch/i386/lib/dec_and_lock.c Fri Jul 7 18:20:16 2000 @@ -0,0 +1,40 @@ +/* + * x86 version of "atomic_dec_and_lock()" using + * the atomic "cmpxchg" instruction. + * + * (For CPU's lacking cmpxchg, we use the slow + * generic version, and this one never even gets + * compiled). + */ + +#include +#include + +int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) +{ + int counter; + int newcount; + +repeat: + counter = atomic_read(atomic); + newcount = counter-1; + + if (!newcount) + goto slow_path; + + asm volatile("lock; cmpxchgl %1,%2" + :"=a" (newcount) + :"r" (newcount), "m" (atomic->counter), "0" (counter)); + + /* If the above failed, "eax" will have changed */ + if (newcount != counter) + goto repeat; + return 0; + +slow_path: + spin_lock(lock); + if (atomic_dec_and_test(atomic)) + return 1; + spin_unlock(lock); + return 0; +} diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/math-emu/poly_tan.c linux/arch/i386/math-emu/poly_tan.c --- v2.4.0-test2/linux/arch/i386/math-emu/poly_tan.c Sun Nov 7 16:37:34 1999 +++ linux/arch/i386/math-emu/poly_tan.c Wed Jul 5 10:56:13 2000 @@ -89,7 +89,7 @@ { FPU_settag0(TAG_Valid); significand(st0_ptr) = 0x8a51e04daabda360LL; - setexponent16(st0_ptr, 0x41 + EXTENDED_Ebias | SIGN_Negative); + setexponent16(st0_ptr, (0x41 + EXTENDED_Ebias) | SIGN_Negative); return; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/i386/vmlinux.lds linux/arch/i386/vmlinux.lds --- v2.4.0-test2/linux/arch/i386/vmlinux.lds Fri Jan 21 18:19:16 2000 +++ linux/arch/i386/vmlinux.lds Wed Jul 5 13:42:37 2000 @@ -68,6 +68,7 @@ /DISCARD/ : { *(.text.exit) *(.data.exit) + *(.exitcall.exit) } /* Stabs debugging sections. */ diff -u --recursive --new-file v2.4.0-test2/linux/arch/ia64/config.in linux/arch/ia64/config.in --- v2.4.0-test2/linux/arch/ia64/config.in Fri Jun 23 21:55:07 2000 +++ linux/arch/ia64/config.in Wed Jul 5 13:10:35 2000 @@ -85,6 +85,7 @@ endmenu +source drivers/mtd/Config.in source drivers/pnp/Config.in source drivers/block/Config.in source drivers/i2o/Config.in diff -u --recursive --new-file v2.4.0-test2/linux/arch/ia64/ia32/sys_ia32.c linux/arch/ia64/ia32/sys_ia32.c --- v2.4.0-test2/linux/arch/ia64/ia32/sys_ia32.c Fri Jun 23 21:55:07 2000 +++ linux/arch/ia64/ia32/sys_ia32.c Sat Jul 8 19:26:11 2000 @@ -111,12 +111,10 @@ * `munmap' if the `execve' failes. */ down(¤t->mm->mmap_sem); - lock_kernel(); av = (char **) do_mmap_pgoff(0, 0UL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0); - unlock_kernel(); up(¤t->mm->mmap_sem); if (IS_ERR(av)) @@ -258,11 +256,15 @@ return -EINVAL; if (!file->f_op->read) return -EINVAL; + lock_kernel(); if (file->f_op->llseek) { - if (file->f_op->llseek(file,off,0) != off) + if (file->f_op->llseek(file,off,0) != off) { + unlock_kernel(); return -EINVAL; + } } else file->f_pos = off; + unlock_kernel(); r = file->f_op->read(file, (char *)addr, len, &file->f_pos); return (r < 0) ? -EINVAL : addr; } @@ -292,7 +294,6 @@ if (copy_from_user(&a, arg, sizeof(a))) return -EFAULT; - lock_kernel(); if (!(a.flags & MAP_ANONYMOUS)) { error = -EBADF; file = fget(a.fd); @@ -302,9 +303,7 @@ a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if ((a.flags & MAP_FIXED) && ((a.addr & ~PAGE_MASK) || (a.offset & ~PAGE_MASK))) { - unlock_kernel(); error = do_mmap_fake(file, a.addr, a.len, a.prot, a.flags, a.offset); - lock_kernel(); } else { down(¤t->mm->mmap_sem); error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); @@ -313,7 +312,6 @@ if (file) fput(file); out: - unlock_kernel(); return error; } @@ -323,14 +321,12 @@ int retval; int fds[2]; - lock_kernel(); retval = do_pipe(fds); if (retval) goto out; if (copy_to_user(fd, fds, sizeof(fds))) retval = -EFAULT; out: - unlock_kernel(); return retval; } @@ -712,7 +708,6 @@ buf.count = count; buf.error = 0; - lock_kernel(); error = vfs_readdir(file, filldir32, &buf); if (error < 0) goto out_putf; @@ -724,7 +719,6 @@ } out_putf: - unlock_kernel(); fput(file); out: return error; @@ -763,12 +757,9 @@ buf.count = 0; buf.dirent = dirent; - lock_kernel(); error = vfs_readdir(file, fillonedir32, &buf); if (error >= 0) error = buf.count; - unlock_kernel(); - fput(file); out: return error; @@ -1032,7 +1023,6 @@ struct file *file; long ret = -EBADF; - lock_kernel(); file = fget(fd); if(!file) goto bad_file; @@ -1045,7 +1035,6 @@ out: fput(file); bad_file: - unlock_kernel(); return ret; } @@ -1055,7 +1044,6 @@ struct file *file; int ret = -EBADF; - lock_kernel(); file = fget(fd); if(!file) goto bad_file; @@ -1070,7 +1058,6 @@ out: fput(file); bad_file: - unlock_kernel(); return ret; } @@ -1856,7 +1843,6 @@ { int version, err; - lock_kernel(); version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; @@ -1908,7 +1894,6 @@ break; } - unlock_kernel(); return err; } @@ -3723,7 +3708,6 @@ } kern_msg.msg_flags = user_flags; - lock_kernel(); sock = sockfd_lookup(fd, &err); if (sock != NULL) { if (sock->file->f_flags & O_NONBLOCK) @@ -3731,7 +3715,6 @@ err = sock_sendmsg(sock, &kern_msg, total_len); sockfd_put(sock); } - unlock_kernel(); /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ if(ctl_buf != ctl) @@ -3771,7 +3754,6 @@ cmsg_ptr = (unsigned long) kern_msg.msg_control; kern_msg.msg_flags = 0; - lock_kernel(); sock = sockfd_lookup(fd, &err); if (sock != NULL) { struct scm_cookie scm; @@ -3779,6 +3761,7 @@ if (sock->file->f_flags & O_NONBLOCK) user_flags |= MSG_DONTWAIT; memset(&scm, 0, sizeof(scm)); + lock_kernel(); err = sock->ops->recvmsg(sock, &kern_msg, total_len, user_flags, &scm); if(err >= 0) { @@ -3809,9 +3792,9 @@ scm_detach_fds32(&kern_msg, &scm); } } + unlock_kernel(); sockfd_put(sock); } - unlock_kernel(); if(uaddr != NULL && err >= 0) err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, @@ -4711,11 +4694,9 @@ sys32_personality(unsigned long personality) { int ret; - lock_kernel(); if (current->personality == PER_LINUX32 && personality == PER_LINUX) personality = PER_LINUX32; ret = sys_personality(personality); - unlock_kernel(); if (ret == PER_LINUX32) ret = PER_LINUX; return ret; diff -u --recursive --new-file v2.4.0-test2/linux/arch/ia64/kernel/process.c linux/arch/ia64/kernel/process.c --- v2.4.0-test2/linux/arch/ia64/kernel/process.c Fri Jun 23 21:55:07 2000 +++ linux/arch/ia64/kernel/process.c Mon Jul 10 13:16:56 2000 @@ -114,7 +114,7 @@ { /* endless idle loop with no priority at all */ init_idle(); - current->priority = 0; + current->nice = 20; current->counter = -100; #ifdef CONFIG_SMP diff -u --recursive --new-file v2.4.0-test2/linux/arch/ia64/kernel/smp.c linux/arch/ia64/kernel/smp.c --- v2.4.0-test2/linux/arch/ia64/kernel/smp.c Fri Jun 23 21:55:07 2000 +++ linux/arch/ia64/kernel/smp.c Mon Jul 10 14:22:00 2000 @@ -412,7 +412,7 @@ } if (user) { - if (current->priority < DEF_PRIORITY) { + if (current->nice > 0) { kstat.cpu_nice++; kstat.per_cpu_nice[cpu]++; } else { diff -u --recursive --new-file v2.4.0-test2/linux/arch/ia64/kernel/sys_ia64.c linux/arch/ia64/kernel/sys_ia64.c --- v2.4.0-test2/linux/arch/ia64/kernel/sys_ia64.c Fri Jun 23 21:55:07 2000 +++ linux/arch/ia64/kernel/sys_ia64.c Sat Jul 8 19:26:12 2000 @@ -83,14 +83,12 @@ int fd[2]; int retval; - lock_kernel(); retval = do_pipe(fd); if (retval) goto out; retval = fd[0]; regs->r9 = fd[1]; out: - unlock_kernel(); return retval; } @@ -132,11 +130,7 @@ } down(¤t->mm->mmap_sem); - lock_kernel(); - addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - - unlock_kernel(); up(¤t->mm->mmap_sem); if (file) @@ -186,27 +180,21 @@ asmlinkage long sys_iopl (int level, long arg1, long arg2, long arg3) { - lock_kernel(); printk(KERN_ERR "sys_iopl(level=%d)!\n", level); - unlock_kernel(); return -ENOSYS; } asmlinkage long sys_vm86 (long arg0, long arg1, long arg2, long arg3) { - lock_kernel(); printk(KERN_ERR "sys_vm86(%lx, %lx, %lx, %lx)!\n", arg0, arg1, arg2, arg3); - unlock_kernel(); return -ENOSYS; } asmlinkage long sys_modify_ldt (long arg0, long arg1, long arg2, long arg3) { - lock_kernel(); printk(KERN_ERR "sys_modify_ldt(%lx, %lx, %lx, %lx)!\n", arg0, arg1, arg2, arg3); - unlock_kernel(); return -ENOSYS; } @@ -302,7 +290,6 @@ struct nameidata nd; int error; - lock_kernel(); error = user_path_walk(filename, &nd); if (!error) { error = do_revalidate(nd.dentry); @@ -310,7 +297,6 @@ error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf); path_release(&nd); } - unlock_kernel(); return error; } @@ -320,7 +306,6 @@ struct nameidata nd; int error; - lock_kernel(); error = user_path_walk_link(filename, &nd); if (!error) { error = do_revalidate(nd.dentry); @@ -328,7 +313,6 @@ error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf); path_release(&nd); } - unlock_kernel(); return error; } @@ -338,7 +322,6 @@ struct file * f; int err = -EBADF; - lock_kernel(); f = fget(fd); if (f) { struct dentry * dentry = f->f_dentry; @@ -348,7 +331,6 @@ err = cp_ia64_old_stat(dentry->d_inode, statbuf); fput(f); } - unlock_kernel(); return err; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/m68k/config.in linux/arch/m68k/config.in --- v2.4.0-test2/linux/arch/m68k/config.in Fri Jun 23 21:55:07 2000 +++ linux/arch/m68k/config.in Wed Jul 5 13:10:35 2000 @@ -145,6 +145,8 @@ fi endmenu +source drivers/mtd/Config.in + source drivers/block/Config.in if [ "$CONFIG_NET" = "y" ]; then diff -u --recursive --new-file v2.4.0-test2/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c --- v2.4.0-test2/linux/arch/m68k/kernel/process.c Thu Nov 11 20:11:31 1999 +++ linux/arch/m68k/kernel/process.c Mon Jul 10 13:16:56 2000 @@ -81,7 +81,7 @@ { /* endless idle loop with no priority at all */ init_idle(); - current->priority = 0; + current->nice = 20; current->counter = -100; idle(); } diff -u --recursive --new-file v2.4.0-test2/linux/arch/m68k/kernel/sys_m68k.c linux/arch/m68k/kernel/sys_m68k.c --- v2.4.0-test2/linux/arch/m68k/kernel/sys_m68k.c Fri Jun 23 21:55:07 2000 +++ linux/arch/m68k/kernel/sys_m68k.c Wed Jul 5 11:31:00 2000 @@ -34,13 +34,11 @@ int fd[2]; int error; - lock_kernel(); error = do_pipe(fd); if (!error) { if (copy_to_user(fildes, fd, 2*sizeof(int))) error = -EFAULT; } - unlock_kernel(); return error; } @@ -61,11 +59,7 @@ } down(¤t->mm->mmap_sem); - lock_kernel(); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - - unlock_kernel(); up(¤t->mm->mmap_sem); if (file) @@ -143,7 +137,6 @@ if ((a.offset >> PAGE_SHIFT) != pgoff) return -EINVAL; - lock_kernel(); if (!(a.flags & MAP_ANONYMOUS)) { error = -EBADF; file = fget(a.fd); @@ -158,7 +151,6 @@ if (file) fput(file); out: - unlock_kernel(); return error; } #endif diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/Makefile linux/arch/mips/Makefile --- v2.4.0-test2/linux/arch/mips/Makefile Tue May 23 15:31:33 2000 +++ linux/arch/mips/Makefile Sun Jul 9 22:18:15 2000 @@ -1,4 +1,3 @@ -# $Id: Makefile,v 1.22 2000/01/26 00:07:44 ralf Exp $ # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive @@ -101,6 +100,12 @@ LOADADDR += 0x80080000 endif +ifdef CONFIG_COBALT_MICRO_SERVER +ARCHIVES += arch/mips/cobalt/cobalt.o +SUBDIRS += arch/mips/cobalt +LOADADDR += 0x80000000 +endif + ifdef CONFIG_SNI_RM200_PCI CORE_FILES += arch/mips/sni/sni.o SUBDIRS += arch/mips/sni arch/mips/arc @@ -193,6 +198,11 @@ $(MAKE) -C arch/mips/baget clean archmrproper: + @$(MAKEBOOT) mrproper + $(MAKE) -C arch/$(ARCH)/tools mrproper archdep: + if [ ! -f $(TOPDIR)/include/asm-$(ARCH)/offset.h ]; then \ + touch $(TOPDIR)/include/asm-$(ARCH)/offset.h; \ + fi; @$(MAKEBOOT) dep diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/arc/memory.c linux/arch/mips/arc/memory.c --- v2.4.0-test2/linux/arch/mips/arc/memory.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/arc/memory.c Sun Jul 9 22:18:15 2000 @@ -144,7 +144,7 @@ void __init prom_meminit(void) { struct prom_pmemblock *largest; - unsigned long bootmap_size, kbegin, kend; + unsigned long bootmap_size; struct linux_mdesc *p; int totram; int i = 0; diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/baget/vacserial.c linux/arch/mips/baget/vacserial.c --- v2.4.0-test2/linux/arch/mips/baget/vacserial.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/baget/vacserial.c Wed Jul 5 11:24:40 2000 @@ -115,6 +115,9 @@ static void autoconfig(struct serial_state * info); static void change_speed(struct async_struct *info); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); +static void rs_timer(unsigned long dummy); + +static struct timer_list vacs_timer; /* * Here we define the default xmit fifo size used for each type of @@ -750,8 +753,7 @@ /* * Set up serial timers... */ - timer_table[RS_TIMER].expires = jiffies + 2*HZ/100; - timer_active |= 1 << RS_TIMER; + mod_timer(&vacs_timer, jiffies + 2*HZ/100); /* * and set the speed of the serial port @@ -2255,7 +2257,7 @@ * Important function for VAC UART check and reanimation. */ -static void rs_timer(void) +static void rs_timer(unsigned long dummy) { static unsigned long last_strobe = 0; struct async_struct *info; @@ -2285,8 +2287,7 @@ } } last_strobe = jiffies; - timer_table[RS_TIMER].expires = jiffies + RS_STROBE_TIME; - timer_active |= 1 << RS_TIMER; + mod_timer(&vacs_timer, jiffies + RS_STROBE_TIME); /* * It looks this code for case we share IRQ with console... @@ -2301,7 +2302,7 @@ #endif restore_flags(flags); - timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2; + mod_timer(&vacs_timer, jiffies + IRQ_timeout[0] - 2); } } @@ -2323,8 +2324,9 @@ #endif init_bh(SERIAL_BH, do_serial_bh); - timer_table[RS_TIMER].fn = rs_timer; - timer_table[RS_TIMER].expires = 0; + init_timer(&vacs_timer); + vacs_timer.function = rs_timer; + vacs_timer.expires = 0; for (i = 0; i < NR_IRQS; i++) { IRQ_ports[i] = 0; @@ -2528,9 +2530,7 @@ save_flags(flags); cli(); - timer_active &= ~(1 << RS_TIMER); - timer_table[RS_TIMER].fn = NULL; - timer_table[RS_TIMER].expires = 0; + del_timer_sync(&vacs_timer); remove_bh(SERIAL_BH); if ((e1 = tty_unregister_driver(&serial_driver))) diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/boot/Makefile linux/arch/mips/boot/Makefile --- v2.4.0-test2/linux/arch/mips/boot/Makefile Tue May 23 15:31:33 2000 +++ linux/arch/mips/boot/Makefile Sun Jul 9 22:18:15 2000 @@ -46,8 +46,25 @@ clean: rm -f vmlinux.ecoff + rm -f zImage zImage.tmp mkboot + +mrproper: + rm -f vmlinux.ecoff rm -f addinitrd rm -f elf2ecoff + +zImage: $(CONFIGURE) mkboot $(TOPDIR)/vmlinux + $(OBJCOPY) $(strip-flags) $(TOPDIR)/vmlinux zImage.tmp + ./mkboot zImage.tmp zImage + rm -f zImage.tmp + +mkboot: mkboot.c + $(HOSTCC) -o $@ $^ + +zdisk: zImage + cp $(TOPDIR)/vmlinux $(TOPDIR)/vm + $(STRIP) $(TOPDIR)/vm + gzip -9f $(TOPDIR)/vm dummy: diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/cobalt/Makefile linux/arch/mips/cobalt/Makefile --- v2.4.0-test2/linux/arch/mips/cobalt/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/cobalt/Makefile Sun Jul 9 22:18:15 2000 @@ -0,0 +1,24 @@ +# +# Makefile for the Cobalt micro systems family specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# $Id: Makefile,v 1.1 1997/10/23 22:25:41 ralf Exp $ +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: cobalt.o +O_TARGET := cobalt.o +O_OBJS := cobaltscc.o hw-access.o int-handler.o pci.o reset.o setup.o via.o + +int-handler.o: int-handler.S + +clean: + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/cobalt/cobaltscc.c linux/arch/mips/cobalt/cobaltscc.c --- v2.4.0-test2/linux/arch/mips/cobalt/cobaltscc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/cobalt/cobaltscc.c Sun Jul 9 22:18:15 2000 @@ -0,0 +1,350 @@ +/* + * Filename: cobaltscc.c + * + * Description: Functions for supporting and testing serial I/O + * + * Author(s): Timothy Stonis + * + * Copyright 1997, Cobalt Microserver, Inc. + */ +#include "z8530.h" +#include "diagdefs.h" +#include "serial.h" +#include "asm/io.h" + +/* + * Function prototypes + */ +void InitSerialPort(unsigned char *); +void RegisterDelay(void); +void InitScc(void); + +/* + * Function: RegisterDelay + * + * Description: A little delay since the SCC can't handle quick consecutive + * accesses + * In: none + * Out: none + */ +void RegisterDelay(void) +{ + register int ctr; + + for(ctr=0;ctr<0x40;ctr++); +} + +/* + * Function: SccInit + * + * Description: Initialize all the SCC registers for 19200 baud, asynchronous, + * 8 bit, 1 stop bit, no parity communication (Channel A) + * + * In: none + * + * Out: none + */ +void InitScc(void) +{ + /* Force hardware reset */ + Write8530(kSCC_ChanA | kSCC_Command, R9 | NULLCODE); + RegisterDelay(); + Write8530(kSCC_ChanA, FHWRES); + RegisterDelay(); + + /* x32 clock, 1 stop bit, no parity */ + Write8530(kSCC_ChanA | kSCC_Command, R4 | NULLCODE); + RegisterDelay(); + Write8530(kSCC_ChanA, X16CLK | SB1); + RegisterDelay(); + + /* Rx 8 bits, Rx disabled */ + Write8530(kSCC_ChanA | kSCC_Command, R3 | NULLCODE); + RegisterDelay(); + Write8530(kSCC_ChanA, Rx8); + RegisterDelay(); + + /* Tx 8 bits, DTR, RTS, Tx off */ + Write8530(kSCC_ChanA | kSCC_Command, R5 | NULLCODE); + RegisterDelay(); + Write8530(kSCC_ChanA, Tx8 | DTR | RTS); + RegisterDelay(); + + /* Int. Disabled */ + Write8530(kSCC_ChanA | kSCC_Command, R9 | NULLCODE); + RegisterDelay(); + Write8530(kSCC_ChanA, 0x0); + RegisterDelay(); + + /* NRZ */ + Write8530(kSCC_ChanA | kSCC_Command, R10 | NULLCODE); + RegisterDelay(); + Write8530(kSCC_ChanA, NRZ); + RegisterDelay(); + + /* Tx & Rx = BRG out, TRxC = BRG out */ + Write8530(kSCC_ChanA | kSCC_Command, R11 | NULLCODE); + RegisterDelay(); + Write8530(kSCC_ChanA, TCBR | RCBR | TRxCBR | TRxCOI); + RegisterDelay(); + + /* Time constant = 0x01 */ + Write8530(kSCC_ChanA | kSCC_Command, R12 | NULLCODE); + RegisterDelay(); + Write8530(kSCC_ChanA, kSCC_115200 ); + RegisterDelay(); + + /* Time constant high = 0x00 */ + Write8530(kSCC_ChanA | kSCC_Command, R13 | NULLCODE); + RegisterDelay(); + Write8530(kSCC_ChanA, 0x00); + RegisterDelay(); + + /* BRG in = ~RTxC, BRG off, loopback */ + Write8530(kSCC_ChanA | kSCC_Command, R14 | NULLCODE); + RegisterDelay(); + Write8530(kSCC_ChanA, LOOPBAK | BRSRC); + RegisterDelay(); +} + +/* + * Function: EnableScc + * + * Description: Enable transmit and receive on SCC Channel A + * In: none + * Out: none + */ +void EnableScc(void) +{ + /* Enable BRG */ + Write8530(kSCC_ChanA | kSCC_Command, R14 | NULLCODE); + RegisterDelay(); + Write8530(kSCC_ChanA, BRENABL | BRSRC); + RegisterDelay(); + + /* Rx enable (Rx 8 bits) */ + Write8530(kSCC_ChanA | kSCC_Command, R3 | NULLCODE); + RegisterDelay(); + Write8530(kSCC_ChanA, RxENABLE | Rx8); + RegisterDelay(); + + /* Tx enable (Tx8, DTR, RTS) */ + Write8530(kSCC_ChanA | kSCC_Command, R5 | NULLCODE); + RegisterDelay(); + Write8530(kSCC_ChanA, TxENAB | Tx8 | DTR | RTS); + RegisterDelay(); +} + +/* + * Function: SccOutb + * + * Description: Write a byte to the SCC (Channel A) and blink LED + * In: Byte to send + * Out: none + */ +void SccOutb(unsigned char byte) +{ + /* LED on.. */ + Write8530(kSCC_ChanB | kSCC_Command, R5); + RegisterDelay(); + Write8530(kSCC_ChanB | kSCC_Command, RTS); + RegisterDelay(); + + while ((Read8530(kSCC_ChanA) & Tx_BUF_EMP) == 0) + RegisterDelay(); + + Write8530(kSCC_ChanA | kSCC_Direct, byte); + RegisterDelay(); + + /* LED off.. */ + Write8530(kSCC_ChanB | kSCC_Command, R9); + RegisterDelay(); + Write8530(kSCC_ChanB | kSCC_Command, CHRB); + RegisterDelay(); +} + +/* + * Function: SccInb + * + * Description: Read a byte from the SCC (Channel A) + * In: Byte to send + * Out: none + */ +void SccInb(unsigned char *byte) +{ + while ((Read8530(kSCC_ChanA) & Rx_CH_AV) == 0) + RegisterDelay(); + + *byte = Read8530(kSCC_ChanA | kSCC_Direct); + RegisterDelay(); +} + +/* + * Function: SccWrite + * + * Description: Write a null terminated string to the SCC + * In: C string + * Out: none + */ +void SccWrite(const unsigned char *string) +{ + while((*string) != 0) { + if (*string == 10) + SccOutb((unsigned char) 13); + SccOutb(*(string++)); + } +} + +/* + * Function: InitSerialPort + * + * Description: Initialize the SCC and spit out the header message + * In: Header message + * Out: none + */ +void InitSerialPort(unsigned char *msg) +{ + InitScc(); + EnableScc(); + SccWrite(msg); +} + +/* + * Function: SccInbTimeout + * + * Description: Read a byte from the SCC (Channel A) with timeout + * In: Byte to send + * Out: Timeout status + */ +unsigned char SccInbTimeout(unsigned char *byte, unsigned long timeout) +{ + unsigned long ctr = 0; + + while ((Read8530(kSCC_ChanA) & Rx_CH_AV) == 0) { + RegisterDelay(); + if ((ctr++) > timeout) + return 0xFF; + } + + *byte = Read8530(kSCC_ChanA | kSCC_Direct); + RegisterDelay(); + + return 0; +} + +#include + +extern int serial_echo_init (int base); +extern int serial_echo_print (const char *s); + +/* + * this defines the address for the port to which printk echoing is done + * when CONFIG_SERIAL_ECHO is defined + */ +#define SERIAL_ECHO_PORT 0x1C800000 + +static int serial_echo_port = 0; + +#define serial_echo_outb(v,a) outb((v),(a)+serial_echo_port) +#define serial_echo_inb(a) inb((a)+serial_echo_port) + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +/* Wait for transmitter & holding register to empty */ +#define WAIT_FOR_XMITR \ + do { \ + lsr = serial_echo_inb(UART_LSR); \ + } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY) + +/* + * These two functions abstract the actual communications with the + * debug port. This is so we can change the underlying communications + * mechanism without modifying the rest of the code. + */ +int +serial_echo_print(const char *s) +{ + int lsr, ier; + int i; + + if (!serial_echo_port) + return 0; + + /* + * First save the IER then disable the interrupts + */ + ier = serial_echo_inb(UART_IER); + serial_echo_outb(0x00, UART_IER); + + /* + * Now, do each character + */ + for (i = 0; *s; i++, s++) { + WAIT_FOR_XMITR; + + /* Send the character out. */ + serial_echo_outb(*s, UART_TX); + + /* if a LF, also do CR... */ + if (*s == 10) { + WAIT_FOR_XMITR; + serial_echo_outb(13, UART_TX); + } + } + + /* + * Finally, Wait for transmitter & holding register to empty + * and restore the IER + */ + do { + lsr = serial_echo_inb(UART_LSR); + } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY); + serial_echo_outb(ier, UART_IER); + + return 0; +} + + +int +serial_echo_init(int base) +{ + int comstat, hi, lo; + + serial_echo_port = base; + + /* + * read the Divisor Latch + */ + comstat = serial_echo_inb(UART_LCR); + serial_echo_outb(comstat | UART_LCR_DLAB, UART_LCR); + hi = serial_echo_inb(UART_DLM); + lo = serial_echo_inb(UART_DLL); + serial_echo_outb(comstat, UART_LCR); + + /* + * now do hardwired init + */ + serial_echo_outb(0x03, UART_LCR); /* No parity, 8 data bits, 1 stop */ + serial_echo_outb(0x83, UART_LCR); /* Access divisor latch */ + + /* This is computed using: + * + * const BASE_BAUD = (18432000 / 16); + * UART_DLM = (BASE_BAUD / baud_I_want) >> 8; + * UART_DLL = (BASE_BAUD / baud_I_want) & 0xff; + */ + serial_echo_outb(0x00, UART_DLM); /* 115200 baud */ + serial_echo_outb(0x0A, UART_DLL); + + serial_echo_outb(0x03, UART_LCR); /* Done with divisor */ + + /* + * Prior to disabling interrupts, read the LSR and RBR + * registers + */ + comstat = serial_echo_inb(UART_LSR); /* COM? LSR */ + comstat = serial_echo_inb(UART_RX); /* COM? RBR */ + serial_echo_outb(0x00, UART_IER); /* Disable all interrupts */ + + return 0; +} diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/cobalt/diagdefs.h linux/arch/mips/cobalt/diagdefs.h --- v2.4.0-test2/linux/arch/mips/cobalt/diagdefs.h Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/cobalt/diagdefs.h Sun Jul 9 22:18:15 2000 @@ -0,0 +1,177 @@ +/* + * Filename: diagdefs.h + * + * Description: Some general definitions used by the diagnostics + * + * Author(s): Timothy Stonis + * + * Copyright 1997, Cobalt Microserver, Inc. + */ + +#define KSEG0_Base 0x80000000 +#define KSEG1_Base 0xA0000000 + +// Some useful Galileo registers/base addresses (boot time kseg1 mapping) +#define kGal_InternalBase ( 0x14000000 | KSEG1_Base ) +#define kGal_DevBank0Base ( 0x1C000000 | KSEG1_Base ) +#define kGal_DevBank1Base ( 0x1C800000 | KSEG1_Base ) + +#define kGal_RAS10Lo 0x008 +#define kGal_RAS10Hi 0x010 +#define kGal_RAS32Lo 0x018 +#define kGal_RAS32Hi 0x020 + +#define kGal_PCIIOLo 0x048 +#define kGal_PCIIOHi 0x050 + +#define kGal_RAS10LoCfg 0x000 +#define kGal_RAS10HiCfg 0x03 +#define kGal_RAS32LoCfg 0x004 +#define kGal_RAS32HiCfg 0x07 + +#define kGal_PCIIOLoCfg 0x000 +#define kGal_PCIIOHiCfg 0x0F + + +#define kGal_DevBank0PReg 0x45C +#define kGal_DevBank1PReg 0x460 +#define kGal_DevBank2PReg 0x464 +#define kGal_DevBank3PReg 0x468 +#define kGal_DevBankBPReg 0x46C + +#define kGal_DRAMCReg 0x448 +#define kGal_DRAM0PReg 0x44C +#define kGal_DRAM1PReg 0x450 +#define kGal_DRAM2PReg 0x454 +#define kGal_DRAM3PReg 0x458 + +#define kGal_ConfigAddr 0xCF8 +#define kGal_ConfigData 0xCFC +#define kGal_PCICfgEn 0x1F // Generate config cycle +#define kGal_DevNum 0x00 // Technically 0x06, but 0 works too +#define kGal_MasMemEn 0x06 +#define kGal_Latency 0x700 + +#define kGal_RAS01StartReg 0x10 +#define kGal_RAS23StartReg 0x14 +#define kGal_RAS01SizeReg 0x0C08 +#define kGal_RAS23SizeReg 0x0C0C + + +#define kGal_RAS01Start 0x000 +#define kGal_RAS23Start 0x00800000 +#define kGal_RAS01Size 0x007FFFFF +#define kGal_RAS23Size 0x007FFFFF + + +// Paramter information for devices, DRAM, etc +#define kGal_DevBank0Cfg 0x1446DB33 +#define kGal_DevBank1Cfg 0x144FE667 +#define kGal_DevBankBCfg 0x1446DC43 +#define kGal_DRAMConfig 0x00000300 +#define kGal_DRAM0Config 0x00000010 +#define kGal_DRAM1Config 0x00000010 +#define kGal_DRAM2Config 0x00000010 +#define kGal_DRAM3Config 0x00000010 + +#define kGal_DRAM0Hi 0x00000003 +#define kGal_DRAM0Lo 0x00000000 +#define kGal_DRAM1Hi 0x00000007 +#define kGal_DRAM1Lo 0x00000004 +#define kGal_DRAM2Hi 0x0000000B +#define kGal_DRAM2Lo 0x00000008 +#define kGal_DRAM3Hi 0x0000000F +#define kGal_DRAM3Lo 0x0000000C + +#define kGal_RAS0Lo 0x400 +#define kGal_RAS0Hi 0x404 +#define kGal_RAS1Lo 0x408 +#define kGal_RAS1Hi 0x40C +#define kGal_RAS2Lo 0x410 +#define kGal_RAS2Hi 0x414 +#define kGal_RAS3Lo 0x418 +#define kGal_RAS3Hi 0x41C + +// Feedback LED indicators during setup code (reset.S, main.c) +#define kLED_AllOn 0x0F +#define kLED_FlashTest 0x01 +#define kLED_MemTest 0x02 +#define kLED_SCCTest 0x03 +#define kLED_GalPCI 0x04 +#define kLED_EnetTest 0x05 +#define kLED_SCSITest 0x06 +#define kLED_IOCTest 0x07 +#define kLED_Quickdone 0x0A +#define kLED_Exception 0x0B +#define kLED_ProcInit 0x0E +#define kLED_AllOff 0x00 + +#define kLEDBase kGal_DevBank0Base + +// Some memory related constants +#define kRAM_Start (0x00000000 | KSEG0_Base) + +#define kTestPat1 0xA5A5A5A5 +#define kTestPat2 0x5A5A5A5A + +#define k1Meg_kseg1 (0x00100000 | KSEG0_Base) +#define k2Meg_kseg1 (0x00200000 | KSEG0_Base) +#define k4Meg_kseg1 (0x00400000 | KSEG0_Base) +#define k8Meg_kseg1 (0x00800000 | KSEG0_Base) +#define k16Meg_kseg1 (0x01000000 | KSEG0_Base) + +#define kInit_SP k4Meg_kseg1 - 0x100 +#define kVectorBase 0x200 +#define kDebugVectors 0x400 +#define kMallocCheese 0x80E00000 +#define kDecompAddr 0x80700000 +#define kCompAddr 0x80500000 + + +// Ethernet definitions +#define kEnet_VIOBase ( 0x12100000 | KSEG1_Base ) +#define kEnet_PIOBase 0x12100000 +#define kEnet_CSCfg 0x46 +#define kEnet_DevNum 0x07 +#define kEnet_CSR3 0x18 +#define kEnet_CSR15 0x78 + + +#define kEnet_GEPOut 0x080f0000 +#define kEnet_GEPOn 0x000f0000 + + +// SCSI definitions +#define kSCSI_VIOBase ( 0x12200000 | KSEG1_Base ) +#define kSCSI_PIOBase 0x12200000 +#define kSCSI_CSCfg 0x46 +#define kSCSI_DevNum 0x08 +#define kSCSI_GPCNTL 0x47 +#define kSCSI_GPREG 0x07 +#define kSCSI_SCRTCHA 0x34 + +#define kSCSI_GPIOOut 0x0C +#define kSCSI_LEDsOn 0x00 + +// I/O Controller definitions +#define kIOC_VIOBase ( 0x10000000 | KSEG1_Base ) +#define kIOC_RIOBase 0x10000000 +#define kIOC_DevNum 0x09 +#define kIOC_ISAFunc 0x00 +#define kIOC_IDEFunc 0x01 +#define kIOC_USBFunc 0x02 +#define kIOC_MiscC0 0x44 +#define kIOC_IDEEnable 0x40 + +#define kIOC_PCIIDEOn 0x02800085 +#define kIOC_PriIDEOn 0x0A + +// Some PCI Definitions +#define kPCI_StatCmd 0x04 +#define kPCI_LatCache 0x0C +#define kPCI_CBIO 0x10 +#define kPCI_CBMEM 0x14 + +// Random constants +#define kBogoSec 0x0003F940 +#define kSCCDelay 0x00000001 diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/cobalt/hw-access.c linux/arch/mips/cobalt/hw-access.c --- v2.4.0-test2/linux/arch/mips/cobalt/hw-access.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/cobalt/hw-access.c Sun Jul 9 22:18:15 2000 @@ -0,0 +1,58 @@ +/* + * Low-level hardware access stuff for Cobalt Microserver 27 board. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1996, 1997 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include + +void +dummy(void) +{ + panic("What the hell is this called for?"); +} + +static unsigned char cobalt_read_cmos(unsigned long reg) +{ + unsigned char retval; + + VIA_PORT_WRITE(0x70, reg); + retval = VIA_PORT_READ(0x71); + VIA_DELAY(); + + return retval; +} + +static void cobalt_write_cmos(unsigned char val, unsigned long reg) +{ + VIA_PORT_WRITE(0x70, reg); + VIA_PORT_WRITE(0x71, val); +} + +struct feature cobalt_feature = { + /* + * How to access the floppy controller's ports + */ + (void *)dummy, (void *)dummy, + /* + * How to access the floppy DMA functions. + */ + (void *)dummy, (void *)dummy, (void *)dummy, (void *)dummy, + (void *)dummy, (void *)dummy, (void *)dummy, (void *)dummy, + (void *)dummy, (void *)dummy, (void *)dummy, + /* + * How to access the RTC functions. + */ + cobalt_read_cmos, + cobalt_write_cmos +}; diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/cobalt/int-handler.S linux/arch/mips/cobalt/int-handler.S --- v2.4.0-test2/linux/arch/mips/cobalt/int-handler.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/cobalt/int-handler.S Sun Jul 9 22:18:15 2000 @@ -0,0 +1,140 @@ +/* + * arch/mips/cobalt/int-handler.S + */ +#include +#include +#include +#include +#include +#include +#include + +/* + * cobalt_handle_int: Interrupt handler for the twenty-seven board. + */ + .align 5 + .set noreorder + NESTED(cobalt_handle_int, PT_SIZE, ra) + .set noat + SAVE_ALL + REG_S sp,PT_OR2(sp) + CLI + .set at + mfc0 t0,CP0_CAUSE + mfc0 t1,CP0_STATUS + and t0,t1 + xor t1,t0 + mtc0 t1,CP0_STATUS # mask all active ints + /* Such a kind of cascade is optimal for R5000 */ + + andi t1,t0,STATUSF_IP2 + bnez t1,ll_galileo_irq + andi t1,t0,STATUSF_IP3 + bnez t1,ll_ethernet0_irq +/* + * This should be conditional, and not used for the cube-1, but + * there is not a config flag that is useful. + */ + + andi t1,t0,STATUSF_IP4 + bnez t1,ll_ethernet1_irq +/* #endif */ + andi t1,t0,STATUSF_IP6 + bnez t1,ll_via_irq + andi t1,t0,STATUSF_IP5 + bnez t1,ll_serial_irq + andi t1,t0,STATUSF_IP7 + bnez t1,ll_pci_irq + nop + /* wrong alarm ... */ + j spurious_interrupt + nop + END(cobalt_handle_int) + + + .align 5 + .set reorder +ll_galileo_irq: move a0,sp + INC_INTR_COUNT(s1,s2) + jal galileo_irq + nop + DEC_INTR_COUNT(s1,s2) + j ret_from_irq + nop + + .align 5 + .set reorder +ll_via_irq: move a0,sp + INC_INTR_COUNT(s1,s2) + jal via_irq + nop + DEC_INTR_COUNT(s1,s2) + j ret_from_irq + nop + + .align 5 + .set reorder +ll_ethernet0_irq: + INC_INTR_COUNT(s1,s2) + mfc0 s0,CP0_STATUS # mask interrupt + ori t0,s0,(STATUSF_IP3 | STATUSF_IP4) + xori t0,(STATUSF_IP3 | STATUSF_IP4) + mtc0 t0,CP0_STATUS + li a0,4 + move a1,sp + jal do_IRQ + nop + mtc0 s0,CP0_STATUS + DEC_INTR_COUNT(s1,s2) + j ret_from_irq + nop + + .align 5 + .set reorder +ll_serial_irq: li a0,7 + INC_INTR_COUNT(s1,s2) + move a1,sp + jal do_IRQ + nop + DEC_INTR_COUNT(s1,s2) + j ret_from_irq + nop + + + .align 5 + .set reorder +ll_ethernet1_irq: + INC_INTR_COUNT(s1,s2) + mfc0 s0,CP0_STATUS # mask interrupt + + ori t0,s0, (STATUSF_IP3 | STATUSF_IP4) + xori t0,(STATUSF_IP3 | STATUSF_IP4) + + mtc0 t0,CP0_STATUS + li a0,13 + move a1,sp + jal do_IRQ + nop + mtc0 s0,CP0_STATUS + DEC_INTR_COUNT(s1,s2) + j ret_from_irq + nop + + # + # This is pretty weird. The "pci" interrupt on the hardware + # skematic is from the PCI side of the galileo, so we would + # only get interrupts here if WE write the control register + # that normally enables the cpu to send interrupts to the PCI. + # + # If you want to interrupt a PCI card, look elsewhere. + # + .align 5 + .set reorder +ll_pci_irq: li a0,7 + INC_INTR_COUNT(s1,s2) + move a1,sp + jal do_IRQ + nop + DEC_INTR_COUNT(s1,s2) + j ret_from_irq + nop diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/cobalt/pci.c linux/arch/mips/cobalt/pci.c --- v2.4.0-test2/linux/arch/mips/cobalt/pci.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/cobalt/pci.c Sun Jul 9 22:18:15 2000 @@ -0,0 +1,348 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Cobalt Qube specific PCI support. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#undef PCI_DEBUG + +#ifdef CONFIG_PCI + +static void qube_expansion_slot_bist(void) +{ + unsigned char ctrl; + int timeout = 100000; + + pcibios_read_config_byte(0, (0x0a<<3), PCI_BIST, &ctrl); + if(!(ctrl & PCI_BIST_CAPABLE)) + return; + + pcibios_write_config_byte(0, (0x0a<<3), PCI_BIST, ctrl|PCI_BIST_START); + do { + pcibios_read_config_byte(0, (0x0a<<3), PCI_BIST, &ctrl); + if(!(ctrl & PCI_BIST_START)) + break; + } while(--timeout > 0); + if((timeout <= 0) || (ctrl & PCI_BIST_CODE_MASK)) + printk("PCI: Expansion slot card failed BIST with code %x\n", + (ctrl & PCI_BIST_CODE_MASK)); +} + +static void qube_expansion_slot_fixup(void) +{ + unsigned short pci_cmd; + unsigned long ioaddr_base = 0x10108000; /* It's magic, ask Doug. */ + unsigned long memaddr_base = 0x12000000; + int i; + + /* Enable bits in COMMAND so driver can talk to it. */ + pcibios_read_config_word(0, (0x0a<<3), PCI_COMMAND, &pci_cmd); + pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + pcibios_write_config_word(0, (0x0a<<3), PCI_COMMAND, pci_cmd); + + /* Give it a working IRQ. */ + pcibios_write_config_byte(0, (0x0a<<3), PCI_INTERRUPT_LINE, 9); + + /* Fixup base addresses, we only support I/O at the moment. */ + for(i = 0; i <= 5; i++) { + unsigned int regaddr = (PCI_BASE_ADDRESS_0 + (i * 4)); + unsigned int rval, mask, size, alignme, aspace; + unsigned long *basep = &ioaddr_base; + + /* Check type first, punt if non-IO. */ + pcibios_read_config_dword(0, (0x0a<<3), regaddr, &rval); + aspace = (rval & PCI_BASE_ADDRESS_SPACE); + if(aspace != PCI_BASE_ADDRESS_SPACE_IO) + basep = &memaddr_base; + + /* Figure out how much it wants, if anything. */ + pcibios_write_config_dword(0, (0x0a<<3), regaddr, 0xffffffff); + pcibios_read_config_dword(0, (0x0a<<3), regaddr, &rval); + + /* Unused? */ + if(rval == 0) + continue; + + rval &= PCI_BASE_ADDRESS_IO_MASK; + mask = (~rval << 1) | 0x1; + size = (mask & rval) & 0xffffffff; + alignme = size; + if(alignme < 0x400) + alignme = 0x400; + rval = ((*basep + (alignme - 1)) & ~(alignme - 1)); + *basep = (rval + size); + pcibios_write_config_dword(0, (0x0a<<3), regaddr, rval | aspace); + } + qube_expansion_slot_bist(); +} + +static void qube_raq_tulip_fixup(void) +{ + unsigned short pci_cmd; + + /* Enable the device. */ + pcibios_read_config_word(0, (0x0c<<3), PCI_COMMAND, &pci_cmd); + pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MASTER); + pcibios_write_config_word(0, (0x0c<<3), PCI_COMMAND, pci_cmd); + + /* Give it it's IRQ. */ + /* NOTE: RaQ board #1 has a bunch of green wires which swapped the + * IRQ line values of Tulip 0 and Tulip 1. All other + * boards have eth0=4,eth1=13. -DaveM + */ +#ifndef RAQ_BOARD_1_WITH_HWHACKS + pcibios_write_config_byte(0, (0x0c<<3), PCI_INTERRUPT_LINE, 13); +#else + pcibios_write_config_byte(0, (0x0c<<3), PCI_INTERRUPT_LINE, 4); +#endif + + /* And finally, a usable I/O space allocation, right after what + * the first Tulip uses. + */ + pcibios_write_config_dword(0, (0x0c<<3), PCI_BASE_ADDRESS_0, 0x10101001); +} + +static void qube_raq_scsi_fixup(void) +{ + unsigned short pci_cmd; + + /* Enable the device. */ + pcibios_read_config_word(0, (0x08<<3), PCI_COMMAND, &pci_cmd); + + pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY + | PCI_COMMAND_INVALIDATE); + pcibios_write_config_word(0, (0x08<<3), PCI_COMMAND, pci_cmd); + + /* Give it it's IRQ. */ + pcibios_write_config_byte(0, (0x08<<3), PCI_INTERRUPT_LINE, 4); + + /* And finally, a usable I/O space allocation, right after what + * the second Tulip uses. + */ + pcibios_write_config_dword(0, (0x08<<3), PCI_BASE_ADDRESS_0, 0x10102001); + pcibios_write_config_dword(0, (0x08<<3), PCI_BASE_ADDRESS_1, 0x00002000); + pcibios_write_config_dword(0, (0x08<<3), PCI_BASE_ADDRESS_2, 0x00100000); +} + +static unsigned long +qube_pcibios_fixup(unsigned long mem_start, unsigned long mem_end) +{ + extern int cobalt_is_raq; + int raq_p = cobalt_is_raq; + unsigned int tmp; + + /* Fixup I/O and Memory space decoding on Galileo. */ + isa_slot_offset = COBALT_LOCAL_IO_SPACE; + + /* Fix PCI latency-timer and cache-line-size values in Galileo + * host bridge. + */ + pcibios_write_config_byte(0, 0, PCI_LATENCY_TIMER, 64); + pcibios_write_config_byte(0, 0, PCI_CACHE_LINE_SIZE, 7); + + /* + * Now tell the SCSI device that we expect an interrupt at + * IRQ 7 and not the default 0. + */ + pcibios_write_config_byte(0, 0x08<<3, PCI_INTERRUPT_LINE, + COBALT_SCSI_IRQ); + + /* + * Now tell the Ethernet device that we expect an interrupt at + * IRQ 13 and not the default 189. + * + * The IRQ of the first Tulip is different on Qube and RaQ + * hardware except for the weird first RaQ bringup board, + * see above for details. -DaveM + */ + if (! raq_p) { + /* All Qube's route this the same way. */ + pcibios_write_config_byte(0, 0x07<<3, PCI_INTERRUPT_LINE, + COBALT_ETHERNET_IRQ); + } else { +#ifndef RAQ_BOARD_1_WITH_HWHACKS + pcibios_write_config_byte(0, (0x07<<3), PCI_INTERRUPT_LINE, 4); +#else + pcibios_write_config_byte(0, (0x07<<3), PCI_INTERRUPT_LINE, 13); +#endif + } + + if (! raq_p) { + /* See if there is a device in the expansion slot, if so + * fixup IRQ, fix base addresses, and enable master + + * I/O + memory accesses in config space. + */ + pcibios_read_config_dword(0, 0x0a<<3, PCI_VENDOR_ID, &tmp); + if(tmp != 0xffffffff && tmp != 0x00000000) + qube_expansion_slot_fixup(); + } else { + /* If this is a RAQ, we may need to setup the second Tulip + * and SCSI as well. Due to the different configurations + * a RaQ can have, we need to explicitly check for the + * presence of each of these (optional) devices. -DaveM + */ + pcibios_read_config_dword(0, 0x0c<<3, PCI_VENDOR_ID, &tmp); + if(tmp != 0xffffffff && tmp != 0x00000000) + qube_raq_tulip_fixup(); + + pcibios_read_config_dword(0, 0x08<<3, PCI_VENDOR_ID, &tmp); + if(tmp != 0xffffffff && tmp != 0x00000000) + qube_raq_scsi_fixup(); + + /* And if we are a 2800 we have to setup the expansion slot + * too. + */ + pcibios_read_config_dword(0, 0x0a<<3, PCI_VENDOR_ID, &tmp); + if(tmp != 0xffffffff && tmp != 0x00000000) + qube_expansion_slot_fixup(); + } + + return mem_start; +} + +static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev) +{ + if ((bus == 0) && ( (dev==0) || ((dev>6) && (dev <= 12))) ) + return 0; /* OK device number */ + + return -1; /* NOT ok device number */ +} + +#define PCI_CFG_DATA ((volatile unsigned long *)0xb4000cfc) +#define PCI_CFG_CTRL ((volatile unsigned long *)0xb4000cf8) + +#define PCI_CFG_SET(dev,fun,off) \ + ((*PCI_CFG_CTRL) = (0x80000000 | ((dev)<<11) | \ + ((fun)<<8) | (off))) + +static int qube_pcibios_read_config_dword (unsigned char bus, + unsigned char dev, + unsigned char offset, + unsigned int *val) +{ + unsigned char fun = dev & 0x07; + + dev >>= 3; + if (offset & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck(bus, dev)) { + *val = 0xFFFFFFFF; + return PCIBIOS_DEVICE_NOT_FOUND; + } + PCI_CFG_SET(dev, fun, offset); + *val = *PCI_CFG_DATA; + return PCIBIOS_SUCCESSFUL; +} + +static int qube_pcibios_read_config_word (unsigned char bus, + unsigned char dev, + unsigned char offset, + unsigned short *val) +{ + unsigned char fun = dev & 0x07; + + dev >>= 3; + if (offset & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck(bus, dev)) { + *val = 0xffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + PCI_CFG_SET(dev, fun, (offset & ~0x3)); + *val = *PCI_CFG_DATA >> ((offset & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +static int qube_pcibios_read_config_byte (unsigned char bus, + unsigned char dev, + unsigned char offset, + unsigned char *val) +{ + unsigned char fun = dev & 0x07; + + dev >>= 3; + if (pci_range_ck(bus, dev)) { + *val = 0xff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + PCI_CFG_SET(dev, fun, (offset & ~0x3)); + *val = *PCI_CFG_DATA >> ((offset & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +static int qube_pcibios_write_config_dword (unsigned char bus, + unsigned char dev, + unsigned char offset, + unsigned int val) +{ + unsigned char fun = dev & 0x07; + + dev >>= 3; + if(offset & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + PCI_CFG_SET(dev, fun, offset); + *PCI_CFG_DATA = val; + return PCIBIOS_SUCCESSFUL; +} + +static int +qube_pcibios_write_config_word (unsigned char bus, unsigned char dev, + unsigned char offset, unsigned short val) +{ + unsigned char fun = dev & 0x07; + unsigned long tmp; + + dev >>= 3; + if (offset & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + PCI_CFG_SET(dev, fun, (offset & ~0x3)); + tmp = *PCI_CFG_DATA; + tmp &= ~(0xffff << ((offset & 0x3) * 8)); + tmp |= (val << ((offset & 0x3) * 8)); + *PCI_CFG_DATA = tmp; + return PCIBIOS_SUCCESSFUL; +} + +static int +qube_pcibios_write_config_byte (unsigned char bus, unsigned char dev, + unsigned char offset, unsigned char val) +{ + unsigned char fun = dev & 0x07; + unsigned long tmp; + + dev >>= 3; + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + PCI_CFG_SET(dev, fun, (offset & ~0x3)); + tmp = *PCI_CFG_DATA; + tmp &= ~(0xff << ((offset & 0x3) * 8)); + tmp |= (val << ((offset & 0x3) * 8)); + *PCI_CFG_DATA = tmp; + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops qube_pci_ops = { + qube_pcibios_fixup, + qube_pcibios_read_config_byte, + qube_pcibios_read_config_word, + qube_pcibios_read_config_dword, + qube_pcibios_write_config_byte, + qube_pcibios_write_config_word, + qube_pcibios_write_config_dword +}; + +#endif /* CONFIG_PCI */ diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/cobalt/reset.c linux/arch/mips/cobalt/reset.c --- v2.4.0-test2/linux/arch/mips/cobalt/reset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/cobalt/reset.c Sun Jul 9 22:18:15 2000 @@ -0,0 +1,60 @@ +/* + * Reset a Cobalt Qube. + */ +#include +#include +#include +#include +#include +#include +#include + +void cobalt_machine_restart(char *command) +{ + *(volatile char *)0xbc000000 = 0x0f; + + /* + * Ouch, we're still alive ... This time we take the silver bullet ... + * ... and find that we leave the hardware in a state in which the + * kernel in the flush locks up somewhen during of after the PCI + * detection stuff. + */ + set_cp0_status((ST0_BEV | ST0_ERL), (ST0_BEV | ST0_ERL)); + set_cp0_config(CONFIG_CM_CMASK, CONFIG_CM_UNCACHED); + flush_cache_all(); + write_32bit_cp0_register(CP0_WIRED, 0); + __asm__ __volatile__( + "jr\t%0" + : + : "r" (0xbfc00000)); +} + +extern int led_state; +#define kLED 0xBC000000 +#define LEDSet(x) (*(volatile unsigned char *) kLED) = (( unsigned char)x) + +void cobalt_machine_halt(void) +{ + int mark; + + // Blink our cute little LED (number 3)... + while (1) { + led_state = led_state | ( 1 << 3 ); + LEDSet(led_state); + mark = jiffies; + while (jiffies<(mark+HZ)); + led_state = led_state & ~( 1 << 3 ); + LEDSet(led_state); + mark = jiffies; + while (jiffies<(mark+HZ)); + } +} + +/* + * This triggers the luser mode device driver for the power switch ;-) + */ +void cobalt_machine_power_off(void) +{ + printk("You can switch the machine off now.\n"); + cobalt_machine_halt(); +} diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/cobalt/serial.h linux/arch/mips/cobalt/serial.h --- v2.4.0-test2/linux/arch/mips/cobalt/serial.h Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/cobalt/serial.h Sun Jul 9 22:18:15 2000 @@ -0,0 +1,28 @@ +/* + * + * Filename: serial.h + * + * Description: Some general definitions used for serial code + * + * Author(s): Timothy Stonis + * + * Copyright 1997, Cobalt Microserver, Inc. + */ + +/* + * Serial port definitions + */ +#define kSCC_Base kGal_DevBank1Base +#define kHelloWorldMsg "Cobalt Networks Diagnostics - 'We serve it, you surf it'\n\r" +#define kSCC_ChanA 0x01 +#define kSCC_ChanB 0x00 +#define kSCC_Direct 0x02 +#define kSCC_Command 0x00 + +#define kSCC_TestVal 0xA5 +#define kSCC_19200 0x07 /* x32 clock mode, 19200 baud */ +#define kSCC_115200 0x01 /* x16 clock mode, 115200 baud */ + +#define Read8530(n) (*((unsigned char *) (kSCC_Base | (n)))) + +#define Write8530(x,y) (*((unsigned char *) (kSCC_Base | (x))) = (y)) diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/cobalt/setup.c linux/arch/mips/cobalt/setup.c --- v2.4.0-test2/linux/arch/mips/cobalt/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/cobalt/setup.c Sun Jul 9 22:18:15 2000 @@ -0,0 +1,411 @@ +/* + * Setup pointers to hardware dependand routines. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void cobalt_machine_restart(char *command); +extern void cobalt_machine_halt(void); +extern void cobalt_machine_power_off(void); + +extern int serial_console; + +/* + * Initial irq handlers. + */ +static void no_action(int cpl, void *dev_id, struct pt_regs *regs) +{ +} + +/* + * IRQ2 is cascade interrupt to second interrupt controller + */ +static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; + +extern struct feature cobalt_feature; +extern asmlinkage void cobalt_handle_int(void); + +static void cobalt_irq_setup(void) +{ + /* + * Clear all of the interrupts while we change the able around a bit. + */ + set_cp0_status(ST0_IM, 0); + + /* Sets the exception_handler array. */ + set_except_vector(0, cobalt_handle_int); + + request_region(0xb0000020, 0x20, "pic1"); + request_region(0xb00000A0, 0x20, "pic2"); + setup_x86_irq(2, &irq2); + + cli(); + + set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1 | IE_IRQ0); + + /* Setup VIA irq mask */ + VIA_PORT_WRITE(0x20, 0x10); + VIA_PORT_WRITE(0x21, 0x00); + VIA_PORT_WRITE(0x21, 0x00); + + VIA_PORT_WRITE(0xa0, 0x10); + VIA_PORT_WRITE(0xa1, 0x00); + VIA_PORT_WRITE(0xa1, 0x00); +} + +void (*board_time_init)(struct irqaction *irq); + +static void cobalt_calibrate_timer(void) +{ + volatile unsigned long *timer_reg = (volatile unsigned long *)0xb4000850; + + /* Default to 150MHZ, since this is what we are shipping. */ + *timer_reg = 500000; +} + +static void cobalt_time_init(struct irqaction *irq) +{ + /* Load timer value for 100 Hz */ + cobalt_calibrate_timer(); + /* *((volatile unsigned long *) 0xb4000850) = (unsigned long) 440000; */ + + setup_x86_irq(0, irq); + + /* Enable timer ints */ + *((volatile unsigned long *) 0xb4000864) = (unsigned long) 0x00000003; + /* Unmask timer int */ + *((volatile unsigned long *) 0xb4000c1c) = (unsigned long) 0x00000100; +} + +extern struct pci_ops qube_pci_ops; +int cobalt_serial_present; +int cobalt_serial_type; +int cobalt_is_raq; + +void cobalt_setup(void) +{ + tag *atag; + + /* + * We just check if a tag_screen_info can be gathered + * in setup_arch(), if yes we don't proceed futher... + */ + atag = bi_TagFind(tag_screen_info); + if (!atag) { + /* + * If no, we try to find the tag_arc_displayinfo which is + * always created by Milo for an ARC box (for now Milo only + * works on ARC boxes :) -Stoned. + */ + atag = bi_TagFind(tag_arcdisplayinfo); + if (atag) { + + screen_info.orig_x = + ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_x; + screen_info.orig_y = + ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_y; + screen_info.orig_video_cols = + ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->columns; + screen_info.orig_video_lines = + ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->lines; + } + } + + _machine_restart = cobalt_machine_restart; + _machine_halt = cobalt_machine_halt; + _machine_power_off = cobalt_machine_power_off; + + irq_setup = cobalt_irq_setup; + board_time_init = cobalt_time_init; + feature = &cobalt_feature; + mips_io_port_base = COBALT_LOCAL_IO_SPACE; + + pci_ops = &qube_pci_ops; + +#ifdef CONFIG_COBALT_SERIAL + serial_console = 1; +#endif /* CONFIG_COBALT_SERIAL */ + + /* We have to do this early, here, before the value could + * possibly be overwritten by the bootup sequence. + */ + cobalt_serial_present = *((unsigned long *) 0xa020001c); + cobalt_serial_type = *((unsigned long *) 0xa0200020); + cobalt_is_raq = (cobalt_serial_present != 0x0 + && cobalt_serial_type == 0x1); +} + +void AddTagsEndSymbol(void); +int bi_TagAdd (enum bi_tag type, unsigned long size, void *data); +unsigned long next_tag = (unsigned long) NULL; +unsigned long memory_upper = (unsigned long) NULL; + +int bi_TagAdd (enum bi_tag type, unsigned long size, void *data) +{ + tag t; + unsigned long addr; + + t.tag = type; + t.size = size; + + /* + * If next_tag equals NULL it means it's the first tag we're asked + * to create. + */ + if (next_tag == (unsigned long) NULL) { + /* + * If memory_upper not equals NULL it means that identify() + * was able to figure out how much memory is present in the + * box so we initialize next_tag from it. + */ + if (memory_upper != (unsigned long) NULL) + next_tag = memory_upper; + + /* Else we rely on the fact that the first tag we create for + * a box for which we don't know how RAM it gots is a tag of + * type tag_memupper. This is ensured by the first entry in + * the defaults tag list for such a box (see identify.c). + * First we check this. + */ + else { + /* Ok it's a memupper tag: we put it's value in + * memory_upper so launch() can pass it to the + * kernel in register a0 and we initialize next_tag. + */ + next_tag = *(unsigned long *) data; + memory_upper = *((unsigned long *) data); + } + } + + /* We put the tag structure. */ + addr = next_tag - (sizeof (tag)); + + memcpy ((void *) addr, (void *) &t, (size_t) (sizeof (tag))); + + /* We put the tag's data if any. */ + if (size != 0) { + addr = addr - size; + memcpy ((void *) addr, data, (size_t) (t.size)); + } + + /* + * Set next_tag ready for the next tag creation. + */ + next_tag = addr; + AddTagsEndSymbol(); + + return 0; +} + +void SetUpBootInfo(void) +{ + unsigned long LongVar; + int atag; + + /* + * This is hard coded here but will change when we have a + * Size mem routine. + */ + + /* + * 64mb of memory. + */ + + //mips_memory_upper = 0x84000000; + + +#ifndef BOOTLOADER + +#if 0 /* You break'a the kernel I break'a ya face. -DaveM */ + + /* Eight meg of memory. */ + mips_memory_upper = 0x80800000; /* XXX this appears to be unused - + this assignment is not present in the normal + $cvstree/linux/arch/mips/cobalt/setup.c */ +#endif +#else +#include "../../../../include/diagdefs.h" + mips_memory_upper = (unsigned long) kBootloaderMipsMemoryUpper; +#endif + + LongVar = mips_memory_upper; + atag = bi_TagAdd(tag_memupper, ULONGSIZE, &LongVar); + + /* Here is the machine type. + */ + LongVar = MACH_COBALT_27; + atag = bi_TagAdd(tag_machtype, ULONGSIZE, &LongVar); + + LongVar = 0x80000000; + atag = bi_TagAdd(tag_memlower, ULONGSIZE, &LongVar); + + LongVar = CPU_R4300; + atag = bi_TagAdd(tag_cputype, ULONGSIZE, &LongVar); + + LongVar = MACH_GROUP_COBALT; + atag = bi_TagAdd(tag_machgroup, ULONGSIZE, &LongVar); + + LongVar = 0; + atag = bi_TagAdd(tag_scache_size, ULONGSIZE, &LongVar); + + LongVar = 48; + atag = bi_TagAdd(tag_tlb_entries, ULONGSIZE, &LongVar); + + LongVar = 0; + atag = bi_TagAdd(tag_drive_info, ULONGSIZE, &LongVar); + + LongVar = 0xe0800000; + atag = bi_TagAdd(tag_vram_base, ULONGSIZE, &LongVar); + + LongVar = 0; + atag = bi_TagAdd(tag_dummy, 0, &LongVar); +} + +void AddTagsEndSymbol(void) +{ + short X; + X = 1; +} + +/* + * Oh shit, this is so crappy ... + */ +#include +#include +int my_cacheflush(unsigned long start, unsigned long size, unsigned int what) +{ + flush_cache_range(current->mm, start, start + size); + return 0; +} + + +/* + * The ROM set the flag to 0x1 to turn off output. This is interpreted + * as "valid", "no kernel output", and index '0' into the following + * tables. We overload entry '0' to specify a sensible default rate. + */ +static int cons_baud_int[] = { 9600, 0, 9600, 0, 0, 115200, 0, 0 }; +static int cons_baud_baud[] = { B9600, 0, B9600, 0, 0, B115200, 0, 0 }; + +static union cobalt_cons_info +cobalt_get_console_info(void) +{ + char board_id = 0; + static union cobalt_cons_info cons_info; + static int read_info = 0; + extern void add_init_env(char *); + + if (read_info) + return cons_info; + + VIA_PORT_WRITE(VIA_CMOS_ADDR, VIA_CMOS_CONSOLE_FLG); + cons_info.ccons_char = VIA_PORT_READ(VIA_CMOS_DATA); + +#if 0 + printk("cobalt_get_console_info: read 0x%x from console flag\n", + cons_info.ccons_char); +#endif + + /* + * CMOS hasn't been initialized or baud rate isn't known. + * - read the board id and provide backwards compat. + */ + if (cons_info.ccons_bits.valid != VIA_CMOS_CONS_VALID + || ! cons_baud_int[cons_info.ccons_bits.baud] + || ! cons_baud_baud[cons_info.ccons_bits.baud]) { + pcibios_read_config_byte(0, PCI_DEVSHFT(COBALT_PCICONF_VIA), + VIA_COBALT_BRD_ID_REG, &board_id); + +#if 0 + printk("cobalt_get_console_info: read 0x%x from board config\n", + board_id); +#endif + + switch (VIA_COBALT_BRD_REG_to_ID(board_id)) { + case COBALT_BRD_ID_QUBE1: + cons_info.ccons_bits.baud = VIA_CMOS_CONS_115K; + cons_info.ccons_bits.kout = 1; + break; + case COBALT_BRD_ID_RAQ1: + cons_info.ccons_bits.baud = VIA_CMOS_CONS_9600; + cons_info.ccons_bits.kout = 1; + break; + case COBALT_BRD_ID_QUBE2: + cons_info.ccons_bits.baud = VIA_CMOS_CONS_9600; + cons_info.ccons_bits.kout = 0; + break; + case COBALT_BRD_ID_RAQ2: + cons_info.ccons_bits.baud = VIA_CMOS_CONS_9600; + cons_info.ccons_bits.kout = 1; + break; + } + cons_info.ccons_bits.valid = VIA_CMOS_CONS_VALID; + } + + read_info = 1; + +#if defined(DEBUG_LOADER) + cons_info.ccons_bits.kout = 1; +#endif + + if (!cons_info.ccons_bits.kout) { + add_init_env("CONSOLE=/dev/null"); + } + +#if 0 + printk("cobalt_get_console_info: returning 0x%x\n", + cons_info.ccons_char); +#endif + + return cons_info; +} + +int +cobalt_cons_koutok(void) +{ + union cobalt_cons_info cons; + + cons = cobalt_get_console_info(); + + return cons.ccons_bits.kout; +} + +int +cobalt_cons_baudbaud(void) +{ + union cobalt_cons_info cons; + + cons = cobalt_get_console_info(); + + return cons_baud_baud[cons.ccons_bits.baud]; +} + +int +cobalt_cons_baudint(void) +{ + union cobalt_cons_info cons; + + cons = cobalt_get_console_info(); + + return cons_baud_int[cons.ccons_bits.baud]; +} diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/cobalt/via.c linux/arch/mips/cobalt/via.c --- v2.4.0-test2/linux/arch/mips/cobalt/via.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/cobalt/via.c Sun Jul 9 22:18:15 2000 @@ -0,0 +1,90 @@ +/* + * Interrupt handling for the VIA ISA bridge. + * + * Everything the same ... just different ... + */ +#include +#include +#include +#include + +extern asmlinkage void do_IRQ(int irq, struct pt_regs * regs); + +extern unsigned char cache_21; +extern unsigned char cache_A1; + +/* + * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and + * PCI devices. Other onboard hardware needs specific routines. + */ +void mask_irq(unsigned int irq_nr) +{ + unsigned char mask; + + mask = 1 << (irq_nr & 7); + if (irq_nr < 8) { + cache_21 |= mask; + outb(cache_21, 0x10000021); + } else { + cache_A1 |= mask; + outb(cache_A1, 0x100000a1); + } +} + +void unmask_irq(unsigned int irq_nr) +{ + unsigned char mask; + + mask = ~(1 << (irq_nr & 7)); + if (irq_nr < 8) { + cache_21 &= mask; + outb(cache_21, 0x10000021); + } else { + cache_A1 &= mask; + outb(cache_A1, 0x100000a1); + } +} + +asmlinkage void via_irq(struct pt_regs *regs) +{ + char mstat, sstat; + + /* Read Master Status */ + VIA_PORT_WRITE(0x20, 0x0C); + mstat = VIA_PORT_READ(0x20); + + if (mstat < 0) { + mstat &= 0x7f; + if (mstat != 2) { + do_IRQ(mstat, regs); + VIA_PORT_WRITE(0x20, mstat | 0x20); + } else { + sstat = VIA_PORT_READ(0xA0); + + /* Slave interrupt */ + VIA_PORT_WRITE(0xA0, 0x0C); + sstat = VIA_PORT_READ(0xA0); + + if (sstat < 0) { + do_IRQ((sstat + 8) & 0x7f, regs); + VIA_PORT_WRITE(0x20, 0x22); + VIA_PORT_WRITE(0xA0, (sstat & 0x7f) | 0x20); + } else { + printk("Spurious slave interrupt...\n"); + } + } + } else + printk("Spurious master interrupt..."); +} + +asmlinkage void galileo_irq(struct pt_regs *regs) +{ + unsigned long irq_src = *((unsigned long *) 0xb4000c18); + + /* Check for timer irq ... */ + if (irq_src & 0x00000100) { + *((volatile unsigned long *) 0xb4000c18) = 0; + do_IRQ(0, regs); + } else + printk("Spurious Galileo interrupt...\n"); +} diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/cobalt/z8530.h linux/arch/mips/cobalt/z8530.h --- v2.4.0-test2/linux/arch/mips/cobalt/z8530.h Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/cobalt/z8530.h Sun Jul 9 22:18:15 2000 @@ -0,0 +1,219 @@ +/* 8530 Serial Communications Controller Register definitions */ +#define FLAG 0x7e + +/* Write Register 0 */ +#define R0 0 /* Register selects */ +#define R1 1 +#define R2 2 +#define R3 3 +#define R4 4 +#define R5 5 +#define R6 6 +#define R7 7 +#define R8 8 +#define R9 9 +#define R10 10 +#define R11 11 +#define R12 12 +#define R13 13 +#define R14 14 +#define R15 15 + +#define NULLCODE 0 /* Null Code */ +#define POINT_HIGH 0x8 /* Select upper half of registers */ +#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */ +#define SEND_ABORT 0x18 /* HDLC Abort */ +#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */ +#define RES_Tx_P 0x28 /* Reset TxINT Pending */ +#define ERR_RES 0x30 /* Error Reset */ +#define RES_H_IUS 0x38 /* Reset highest IUS */ + +#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */ +#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */ +#define RES_EOM_L 0xC0 /* Reset EOM latch */ + +/* Write Register 1 */ + +#define EXT_INT_ENAB 0x1 /* Ext Int Enable */ +#define TxINT_ENAB 0x2 /* Tx Int Enable */ +#define PAR_SPEC 0x4 /* Parity is special condition */ + +#define RxINT_DISAB 0 /* Rx Int Disable */ +#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */ +#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */ +#define INT_ERR_Rx 0x18 /* Int on error only */ + +#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */ +#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */ +#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */ + +/* Write Register #2 (Interrupt Vector) */ + +/* Write Register 3 */ + +#define RxENABLE 0x1 /* Rx Enable */ +#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */ +#define ADD_SM 0x4 /* Address Search Mode (SDLC) */ +#define RxCRC_ENAB 0x8 /* Rx CRC Enable */ +#define ENT_HM 0x10 /* Enter Hunt Mode */ +#define AUTO_ENAB 0x20 /* Auto Enables */ +#define Rx5 0x0 /* Rx 5 Bits/Character */ +#define Rx7 0x40 /* Rx 7 Bits/Character */ +#define Rx6 0x80 /* Rx 6 Bits/Character */ +#define Rx8 0xc0 /* Rx 8 Bits/Character */ + +/* Write Register 4 */ + +#define PAR_ENA 0x1 /* Parity Enable */ +#define PAR_EVEN 0x2 /* Parity Even/Odd* */ + +#define SYNC_ENAB 0 /* Sync Modes Enable */ +#define SB1 0x4 /* 1 stop bit/char */ +#define SB15 0x8 /* 1.5 stop bits/char */ +#define SB2 0xc /* 2 stop bits/char */ + +#define MONSYNC 0 /* 8 Bit Sync character */ +#define BISYNC 0x10 /* 16 bit sync character */ +#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */ +#define EXTSYNC 0x30 /* External Sync Mode */ + +#define X1CLK 0x0 /* x1 clock mode */ +#define X16CLK 0x40 /* x16 clock mode */ +#define X32CLK 0x80 /* x32 clock mode */ +#define X64CLK 0xC0 /* x64 clock mode */ + +/* Write Register 5 */ + +#define TxCRC_ENAB 0x1 /* Tx CRC Enable */ +#define RTS 0x2 /* RTS */ +#define SDLC_CRC 0x4 /* SDLC/CRC-16 */ +#define TxENAB 0x8 /* Tx Enable */ +#define SND_BRK 0x10 /* Send Break */ +#define Tx5 0x0 /* Tx 5 bits (or less)/character */ +#define Tx7 0x20 /* Tx 7 bits/character */ +#define Tx6 0x40 /* Tx 6 bits/character */ +#define Tx8 0x60 /* Tx 8 bits/character */ +#define DTR 0x80 /* DTR */ + +/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */ + +/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */ + +/* Write Register 8 (transmit buffer) */ + +/* Write Register 9 (Master interrupt control) */ +#define VIS 1 /* Vector Includes Status */ +#define NV 2 /* No Vector */ +#define DLC 4 /* Disable Lower Chain */ +#define MIE 8 /* Master Interrupt Enable */ +#define STATHI 0x10 /* Status high */ +#define NORESET 0 /* No reset on write to R9 */ +#define CHRB 0x40 /* Reset channel B */ +#define CHRA 0x80 /* Reset channel A */ +#define FHWRES 0xc0 /* Force hardware reset */ + +/* Write Register 10 (misc control bits) */ +#define BIT6 1 /* 6 bit/8bit sync */ +#define LOOPMODE 2 /* SDLC Loop mode */ +#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */ +#define MARKIDLE 8 /* Mark/flag on idle */ +#define GAOP 0x10 /* Go active on poll */ +#define NRZ 0 /* NRZ mode */ +#define NRZI 0x20 /* NRZI mode */ +#define FM1 0x40 /* FM1 (transition = 1) */ +#define FM0 0x60 /* FM0 (transition = 0) */ +#define CRCPS 0x80 /* CRC Preset I/O */ + +/* Write Register 11 (Clock Mode control) */ +#define TRxCXT 0 /* TRxC = Xtal output */ +#define TRxCTC 1 /* TRxC = Transmit clock */ +#define TRxCBR 2 /* TRxC = BR Generator Output */ +#define TRxCDP 3 /* TRxC = DPLL output */ +#define TRxCOI 4 /* TRxC O/I */ +#define TCRTxCP 0 /* Transmit clock = RTxC pin */ +#define TCTRxCP 8 /* Transmit clock = TRxC pin */ +#define TCBR 0x10 /* Transmit clock = BR Generator output */ +#define TCDPLL 0x18 /* Transmit clock = DPLL output */ +#define RCRTxCP 0 /* Receive clock = RTxC pin */ +#define RCTRxCP 0x20 /* Receive clock = TRxC pin */ +#define RCBR 0x40 /* Receive clock = BR Generator output */ +#define RCDPLL 0x60 /* Receive clock = DPLL output */ +#define RTxCX 0x80 /* RTxC Xtal/No Xtal */ + +/* Write Register 12 (lower byte of baud rate generator time constant) */ + +/* Write Register 13 (upper byte of baud rate generator time constant) */ + +/* Write Register 14 (Misc control bits) */ +#define BRENABL 1 /* Baud rate generator enable */ +#define BRSRC 2 /* Baud rate generator source */ +#define DTRREQ 4 /* DTR/Request function */ +#define AUTOECHO 8 /* Auto Echo */ +#define LOOPBAK 0x10 /* Local loopback */ +#define SEARCH 0x20 /* Enter search mode */ +#define RMC 0x40 /* Reset missing clock */ +#define DISDPLL 0x60 /* Disable DPLL */ +#define SSBR 0x80 /* Set DPLL source = BR generator */ +#define SSRTxC 0xa0 /* Set DPLL source = RTxC */ +#define SFMM 0xc0 /* Set FM mode */ +#define SNRZI 0xe0 /* Set NRZI mode */ + +/* Write Register 15 (external/status interrupt control) */ +#define ZCIE 2 /* Zero count IE */ +#define DCDIE 8 /* DCD IE */ +#define SYNCIE 0x10 /* Sync/hunt IE */ +#define CTSIE 0x20 /* CTS IE */ +#define TxUIE 0x40 /* Tx Underrun/EOM IE */ +#define BRKIE 0x80 /* Break/Abort IE */ + + +/* Read Register 0 */ +#define Rx_CH_AV 0x1 /* Rx Character Available */ +#define ZCOUNT 0x2 /* Zero count */ +#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */ +#define DCD 0x8 /* DCD */ +#define SYNC_HUNT 0x10 /* Sync/hunt */ +#define CTS 0x20 /* CTS */ +#define TxEOM 0x40 /* Tx underrun */ +#define BRK_ABRT 0x80 /* Break/Abort */ + +/* Read Register 1 */ +#define ALL_SNT 0x1 /* All sent */ +/* Residue Data for 8 Rx bits/char programmed */ +#define RES3 0x8 /* 0/3 */ +#define RES4 0x4 /* 0/4 */ +#define RES5 0xc /* 0/5 */ +#define RES6 0x2 /* 0/6 */ +#define RES7 0xa /* 0/7 */ +#define RES8 0x6 /* 0/8 */ +#define RES18 0xe /* 1/8 */ +#define RES28 0x0 /* 2/8 */ +/* Special Rx Condition Interrupts */ +#define PAR_ERR 0x10 /* Parity error */ +#define Rx_OVR 0x20 /* Rx Overrun Error */ +#define CRC_ERR 0x40 /* CRC/Framing Error */ +#define END_FR 0x80 /* End of Frame (SDLC) */ + +/* Read Register 2 (channel b only) - Interrupt vector */ + +/* Read Register 3 (interrupt pending register) ch a only */ +#define CHBEXT 0x1 /* Channel B Ext/Stat IP */ +#define CHBTxIP 0x2 /* Channel B Tx IP */ +#define CHBRxIP 0x4 /* Channel B Rx IP */ +#define CHAEXT 0x8 /* Channel A Ext/Stat IP */ +#define CHATxIP 0x10 /* Channel A Tx IP */ +#define CHARxIP 0x20 /* Channel A Rx IP */ + +/* Read Register 8 (receive data register) */ + +/* Read Register 10 (misc status bits) */ +#define ONLOOP 2 /* On loop */ +#define LOOPSEND 0x10 /* Loop sending */ +#define CLK2MIS 0x40 /* Two clocks missing */ +#define CLK1MIS 0x80 /* One clock missing */ + +/* Read Register 12 (lower byte of baud rate generator constant) */ + +/* Read Register 13 (upper byte of baud rate generator constant) */ + +/* Read Register 15 (value of WR 15) */ diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/config.in linux/arch/mips/config.in --- v2.4.0-test2/linux/arch/mips/config.in Fri Jun 23 21:55:07 2000 +++ linux/arch/mips/config.in Sun Jul 9 22:18:15 2000 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.46 2000/03/26 22:59:01 ralf Exp $ +# # For a description of the syntax of this configuration file, # see Documentation/kbuild/config-language.txt. # @@ -11,10 +11,14 @@ mainmenu_option next_comment comment 'Machine selection' -bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61 bool 'Support for Algorithmics P4032 (EXPERIMENTAL)' CONFIG_ALGOR_P4032 bool 'Support for BAGET MIPS series (EXPERIMENTAL)' CONFIG_BAGET_MIPS + bool 'Support for Cobalt Server' CONFIG_COBALT_MICRO_SERVER + if [ "$CONFIG_COBALT_MICRO_SERVER" = "y" ]; then + bool ' Support for 2800' CONFIG_COBALT_28 + fi bool 'Support for DECstations (EXPERIMENTAL)' CONFIG_DECSTATION bool 'Support for NEC DDB Vrc-5074 (EXPERIMENTAL)' CONFIG_DDB5074 fi @@ -27,10 +31,11 @@ # Select some configuration options automatically for certain systems. # unset CONFIG_ARC32 -unset CONFIG_PCI unset CONFIG_ISA +unset CONFIG_PCI unset CONFIG_MIPS_JAZZ unset CONFIG_VIDEO_G364 +unset CONFIG_PC_KEYB define_bool CONFIG_SBUS n @@ -40,25 +45,37 @@ if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \ "$CONFIG_OLIVETTI_M700" = "y" ]; then define_bool CONFIG_ARC32 y - define_bool CONFIG_HAVE_IO_PORTS y + define_bool CONFIG_ISA y define_bool CONFIG_FB y define_bool CONFIG_FB_G364 y define_bool CONFIG_MIPS_JAZZ y + define_bool CONFIG_PC_KEYB y fi if [ "$CONFIG_ACER_PICA_61" = "y" ]; then define_bool CONFIG_ARC32 y - define_bool CONFIG_HAVE_IO_PORTS y + define_bool CONFIG_ISA y define_bool CONFIG_MIPS_JAZZ y + define_bool CONFIG_PC_KEYB y +fi +if [ "$CONFIG_COBALT_MICRO_SERVER" = "y" ]; then + define_bool CONFIG_ISA n + define_bool CONFIG_COBALT_27 y + define_bool CONFIG_COBALT_LCD y + define_bool CONFIG_COBALT_SERIAL y + define_bool CONFIG_PCI y fi if [ "$CONFIG_SGI_IP22" = "y" ]; then define_bool CONFIG_ARC32 y + define_bool CONFIG_PC_KEYB y + define_bool CONFIG_SGI y fi if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then define_bool CONFIG_ARC32 y - define_bool CONFIG_HAVE_IO_PORTS y + define_bool CONFIG_PCI y + define_bool CONFIG_ISA y + define_bool CONFIG_PC_KEYB y fi if [ "$CONFIG_DDB5074" = "y" ]; then - define_bool CONFIG_HAVE_IO_PORTS y define_bool CONFIG_ISA y define_bool CONFIG_PCI y fi @@ -85,7 +102,7 @@ R8000 CONFIG_CPU_R8000 \ R10000 CONFIG_CPU_R10000" R4x00 - bool 'Advanced CPU Config' CONFIG_CPU_ADVANCED + bool 'Override CPU Options' CONFIG_CPU_ADVANCED if [ "$CONFIG_CPU_ADVANCED" = "y" ]; then bool ' ll/sc Instructions available' CONFIG_CPU_HAS_LLSC @@ -149,6 +166,9 @@ if [ "$CONFIG_DECSTATION" = "y" ]; then bool 'TURBOchannel support' CONFIG_TC +# if [ "$CONFIG_TC" = "y" ]; then +# bool ' Access.Bus support' CONFIG_ACCESSBUS +# fi fi endmenu @@ -162,19 +182,21 @@ define_bool CONFIG_PCMCIA n fi +source drivers/mtd/Config.in + source drivers/block/Config.in if [ "$CONFIG_NET" = "y" ]; then source net/Config.in fi -if [ "$CONFIG_DECSTATION" != "n" -a \ - "$CONFIG_SGI_IP22" != "n" ]; then +if [ "$CONFIG_DECSTATION" != "y" -a \ + "$CONFIG_SGI_IP22" != "y" ]; then source drivers/telephony/Config.in fi -if [ "$CONFIG_SGI_IP22" != "n" -a \ - "$CONFIG_DECSTATION" != "n" ]; then +if [ "$CONFIG_SGI_IP22" != "y" -a \ + "$CONFIG_DECSTATION" != "y" ]; then mainmenu_option next_comment comment 'ATA/IDE/MFM/RLL support' @@ -200,8 +222,8 @@ fi endmenu -if [ "$CONFIG_DECSTATION" != "n" -a \ - "$CONFIG_SGI_IP22" != "n" ]; then +if [ "$CONFIG_DECSTATION" != "y" -a \ + "$CONFIG_SGI_IP22" != "y" ]; then source drivers/i2o/Config.in fi @@ -268,8 +290,8 @@ endmenu fi -if [ "$CONFIG_DECSTATION" != "n" -a \ - "$CONFIG_SGI_IP22" != "n" ]; then +if [ "$CONFIG_DECSTATION" != "y" -a \ + "$CONFIG_SGI_IP22" != "y" ]; then source drivers/char/Config.in fi @@ -293,8 +315,9 @@ if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 fi - bool 'Keyboard Support' CONFIG_KEYBOARD - bool 'Mouse Support' CONFIG_MOUSE +# if [ "$CONFIG_ACCESSBUS" = "y" ]; then +# bool 'MAXINE Access.Bus mouse (VSXXX-BB/GB) support' CONFIG_DTOP_MOUSE +# fi bool 'Enhanced Real Time Clock Support' CONFIG_RTC endmenu fi diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/ddb5074/pci.c linux/arch/mips/ddb5074/pci.c --- v2.4.0-test2/linux/arch/mips/ddb5074/pci.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/ddb5074/pci.c Sun Jul 9 22:18:15 2000 @@ -320,6 +320,13 @@ int idx; struct resource *r; + /* + * Don't touch the Nile 4 + */ + if (dev->vendor == PCI_VENDOR_ID_NEC && + dev->device == PCI_DEVICE_ID_NEC_NILE4) + return 0; + pci_read_config_word(dev, PCI_COMMAND, &cmd); old_cmd = cmd; for(idx=0; idx<6; idx++) { diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/ddb5074/setup.c linux/arch/mips/ddb5074/setup.c --- v2.4.0-test2/linux/arch/mips/ddb5074/setup.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/ddb5074/setup.c Sun Jul 9 22:18:15 2000 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,7 @@ extern void console_setup(char *); #endif +extern struct ide_ops std_ide_ops; extern struct rtc_ops ddb_rtc_ops; static void (*back_to_prom)(void) = (void (*)(void))0xbfc00000; @@ -107,6 +109,9 @@ _machine_halt = ddb_machine_halt; _machine_power_off = ddb_machine_power_off; +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &std_ide_ops; +#endif rtc_ops = &ddb_rtc_ops; /* Reboot on panic */ diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/dec/prom/memory.c linux/arch/mips/dec/prom/memory.c --- v2.4.0-test2/linux/arch/mips/dec/prom/memory.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/dec/prom/memory.c Sun Jul 9 22:18:15 2000 @@ -155,6 +155,6 @@ addr += PAGE_SIZE; } - printk("Freeing unused PROM memory: %dk freed\n", + printk("Freeing unused PROM memory: %ldk freed\n", (end - PAGE_SIZE) >> 10); } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/defconfig linux/arch/mips/defconfig --- v2.4.0-test2/linux/arch/mips/defconfig Tue May 23 15:31:33 2000 +++ linux/arch/mips/defconfig Sun Jul 9 22:18:15 2000 @@ -13,6 +13,7 @@ # CONFIG_ACER_PICA_61 is not set # CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set +# CONFIG_COBALT_MICRO_SERVER is not set # CONFIG_DECSTATION is not set # CONFIG_DDB5074 is not set # CONFIG_MIPS_MAGNUM_4000 is not set @@ -21,6 +22,8 @@ # CONFIG_SNI_RM200_PCI is not set # CONFIG_SBUS is not set CONFIG_ARC32=y +CONFIG_PC_KEYB=y +CONFIG_SGI=y # CONFIG_ISA is not set # CONFIG_PCI is not set @@ -65,6 +68,11 @@ # CONFIG_PCMCIA is not set # +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set @@ -72,17 +80,14 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_RAID0 is not set -# CONFIG_RAID15_DANGEROUS is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set @@ -121,9 +126,9 @@ # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_BRIDGE is not set # CONFIG_LLC is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -232,6 +237,7 @@ # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set # CONFIG_RAMFS is not set CONFIG_ISO9660_FS=y diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/defconfig-cobalt linux/arch/mips/defconfig-cobalt --- v2.4.0-test2/linux/arch/mips/defconfig-cobalt Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/defconfig-cobalt Sun Jul 9 22:18:15 2000 @@ -0,0 +1,572 @@ +# +# Automatically generated make config: don't edit +# + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_ALGOR_P4032 is not set +# CONFIG_BAGET_MIPS is not set +CONFIG_COBALT_MICRO_SERVER=y +CONFIG_COBALT_28=y +# CONFIG_DECSTATION is not set +# CONFIG_DDB5074 is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_SBUS is not set +# CONFIG_ISA is not set +CONFIG_COBALT_27=y +CONFIG_COBALT_LCD=y +CONFIG_COBALT_SERIAL=y +CONFIG_PCI=y +# CONFIG_ISA is not set + +# +# CPU selection +# +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_R5000 is not set +CONFIG_CPU_NEVADA=y +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +# CONFIG_CPU_HAS_WB is not set + +# +# General setup +# +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_KCORE_ELF=y +CONFIG_ELF_KERNEL=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=m +CONFIG_NET=y +CONFIG_PCI_NAMES=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y +# CONFIG_PCMCIA is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_BOOT is not set +# CONFIG_AUTODETECT_RAID is not set +CONFIG_BLK_DEV_RAM=m +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +# CONFIG_UNIX is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +CONFIG_IP_MROUTE=y +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +CONFIG_IP_ALIAS=y +CONFIG_SYN_COOKIES=y + +# +# (it is safe to leave these untouched) +# +CONFIG_SKB_LARGE=y +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set + +# +# +# +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +# CONFIG_SPX is not set +CONFIG_ATALK=m +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 +CONFIG_CHR_DEV_ST=m +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_SR_EXTRA_DEVS=2 +CONFIG_CHR_DEV_SG=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_DEBUG_QUEUES is not set +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +CONFIG_SCSI_AIC7XXX=y +# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set +CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 +# CONFIG_AIC7XXX_PROC_STATS is not set +CONFIG_AIC7XXX_RESET_DELAY=5 +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_NCR53C7xx is not set +CONFIG_SCSI_NCR53C8XX=y +# CONFIG_SCSI_SYM53C8XX is not set +CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 +CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4 +CONFIG_SCSI_NCR53C8XX_SYNC=5 +# CONFIG_SCSI_NCR53C8XX_PROFILE is not set +CONFIG_SCSI_NCR53C8XX_IOMAPPED=y +# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_DEBUG is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# Appletalk devices +# +# CONFIG_APPLETALK is not set +CONFIG_DUMMY=m +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_ASYNC is not set +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPPOE is not set +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ISDN subsystem +# +CONFIG_ISDN=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_ISDN_AUDIO=y +# CONFIG_ISDN_TTY_FAX is not set + +# +# ISDN feature submodules +# +# CONFIG_ISDN_DRV_LOOP is not set +# CONFIG_ISDN_DIVERSION is not set + +# +# low-level hardware drivers +# + +# +# Passive ISDN cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +# CONFIG_HISAX_NO_SENDCOMPLETE is not set +# CONFIG_HISAX_NO_LLC is not set +# CONFIG_HISAX_NO_KEYPAD is not set +CONFIG_HISAX_1TR6=y + +# +# HiSax supported cards +# +# CONFIG_HISAX_16_0 is not set +# CONFIG_HISAX_16_3 is not set +# CONFIG_HISAX_TELESPCI is not set +# CONFIG_HISAX_S0BOX is not set +# CONFIG_HISAX_AVM_A1 is not set +# CONFIG_HISAX_FRITZPCI is not set +# CONFIG_HISAX_AVM_A1_PCMCIA is not set +CONFIG_HISAX_ELSA=y +# CONFIG_HISAX_IX1MICROR2 is not set +# CONFIG_HISAX_DIEHLDIVA is not set +# CONFIG_HISAX_ASUSCOM is not set +# CONFIG_HISAX_TELEINT is not set +# CONFIG_HISAX_HFCS is not set +# CONFIG_HISAX_SEDLBAUER is not set +# CONFIG_HISAX_SPORTSTER is not set +# CONFIG_HISAX_MIC is not set +# CONFIG_HISAX_NETJET is not set +# CONFIG_HISAX_NICCY is not set +# CONFIG_HISAX_ISURF is not set +# CONFIG_HISAX_HSTSAPHIR is not set +# CONFIG_HISAX_BKM_A4T is not set +# CONFIG_HISAX_SCT_QUADRO is not set +# CONFIG_HISAX_GAZEL is not set +# CONFIG_HISAX_HFC_PCI is not set +# CONFIG_HISAX_W6692 is not set +# CONFIG_HISAX_HFC_SX is not set + +# +# Active ISDN cards +# +# CONFIG_ISDN_DRV_ICN is not set +# CONFIG_ISDN_DRV_PCBIT is not set +# CONFIG_ISDN_DRV_SC is not set +# CONFIG_ISDN_DRV_ACT2000 is not set +# CONFIG_ISDN_DRV_EICON is not set +# CONFIG_ISDN_CAPI is not set +# CONFIG_ISDN_CAPI_MIDDLEWARE is not set +# CONFIG_HYSDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_DRM is not set +# CONFIG_DRM_TDFX is not set +# CONFIG_AGP is not set + +# +# File systems +# +CONFIG_QUOTA=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=m +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set +CONFIG_ISO9660_FS=m +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +# CONFIG_DEVPTS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +CONFIG_SMB_FS=m +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_ISO8859_9=m +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +CONFIG_NLS_KOI8_R=m + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Kernel hacking +# +# CONFIG_CROSSCOMPILE is not set +# CONFIG_MIPS_FPE_MODULE is not set +# CONFIG_MAGIC_SYSRQ is not set diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/defconfig-decstation linux/arch/mips/defconfig-decstation --- v2.4.0-test2/linux/arch/mips/defconfig-decstation Tue May 23 15:31:33 2000 +++ linux/arch/mips/defconfig-decstation Sun Jul 9 22:18:15 2000 @@ -13,6 +13,7 @@ # CONFIG_ACER_PICA_61 is not set # CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set +# CONFIG_COBALT_MICRO_SERVER is not set CONFIG_DECSTATION=y # CONFIG_DDB5074 is not set # CONFIG_MIPS_MAGNUM_4000 is not set @@ -63,6 +64,11 @@ # CONFIG_PCMCIA is not set # +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set @@ -70,17 +76,14 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_RAID0 is not set -# CONFIG_RAID15_DANGEROUS is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set @@ -119,9 +122,9 @@ # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_BRIDGE is not set # CONFIG_LLC is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -212,8 +215,6 @@ CONFIG_ZS=y CONFIG_SERIAL_CONSOLE=y # CONFIG_UNIX98_PTYS is not set -# CONFIG_KEYBOARD is not set -# CONFIG_MOUSE is not set # CONFIG_RTC is not set # @@ -232,6 +233,7 @@ # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set # CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/defconfig-ip22 linux/arch/mips/defconfig-ip22 --- v2.4.0-test2/linux/arch/mips/defconfig-ip22 Tue May 23 15:31:33 2000 +++ linux/arch/mips/defconfig-ip22 Sun Jul 9 22:18:15 2000 @@ -13,6 +13,7 @@ # CONFIG_ACER_PICA_61 is not set # CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set +# CONFIG_COBALT_MICRO_SERVER is not set # CONFIG_DECSTATION is not set # CONFIG_DDB5074 is not set # CONFIG_MIPS_MAGNUM_4000 is not set @@ -21,6 +22,8 @@ # CONFIG_SNI_RM200_PCI is not set # CONFIG_SBUS is not set CONFIG_ARC32=y +CONFIG_PC_KEYB=y +CONFIG_SGI=y # CONFIG_ISA is not set # CONFIG_PCI is not set @@ -65,6 +68,11 @@ # CONFIG_PCMCIA is not set # +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set @@ -72,17 +80,14 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_RAID0 is not set -# CONFIG_RAID15_DANGEROUS is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set @@ -121,9 +126,9 @@ # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_BRIDGE is not set # CONFIG_LLC is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -232,6 +237,7 @@ # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set # CONFIG_RAMFS is not set CONFIG_ISO9660_FS=y diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/defconfig-rm200 linux/arch/mips/defconfig-rm200 --- v2.4.0-test2/linux/arch/mips/defconfig-rm200 Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/defconfig-rm200 Sun Jul 9 22:18:15 2000 @@ -0,0 +1,348 @@ +# +# Automatically generated make config: don't edit +# + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_ALGOR_P4032 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_COBALT_MICRO_SERVER is not set +# CONFIG_DECSTATION is not set +# CONFIG_DDB5074 is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +CONFIG_SNI_RM200_PCI=y +# CONFIG_SBUS is not set +CONFIG_ARC32=y +CONFIG_PCI=y +CONFIG_ISA=y +CONFIG_PC_KEYB=y + +# +# CPU selection +# +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +# CONFIG_CPU_HAS_WB is not set + +# +# General setup +# +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_KCORE_ELF=y +CONFIG_ELF_KERNEL=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_NET=y +# CONFIG_PCI_NAMES is not set +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set +# CONFIG_PCMCIA is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set +# CONFIG_SYN_COOKIES is not set + +# +# (it is safe to leave these untouched) +# +# CONFIG_SKB_LARGE is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Network device support +# +# CONFIG_NETDEVICES is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_DRM is not set +# CONFIG_DRM_TDFX is not set +# CONFIG_AGP is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +# CONFIG_DEVPTS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_NFS_FS is not set +# CONFIG_NFS_V3 is not set +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +# CONFIG_SUNRPC is not set +# CONFIG_LOCKD is not set +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_NLS is not set + +# +# Console drivers +# +CONFIG_VGA_CONSOLE=y +# CONFIG_FB is not set + +# +# Frame-buffer support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_MIPS_FPE_MODULE is not set +# CONFIG_MAGIC_SYSRQ is not set diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/Makefile linux/arch/mips/kernel/Makefile --- v2.4.0-test2/linux/arch/mips/kernel/Makefile Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/Makefile Sun Jul 9 22:18:15 2000 @@ -1,4 +1,3 @@ -# $Id: Makefile,v 1.14 1999/10/09 00:00:58 ralf Exp $ # # Makefile for the Linux/MIPS kernel. # @@ -36,10 +35,10 @@ # # SGIs have very different interrupt/timer hardware. # -ifndef CONFIG_SGI_IP22 - ifndef CONFIG_DECSTATION - ifndef CONFIG_BAGET_MIPS - O_OBJS += time.o +ifndef CONFIG_DECSTATION + ifndef CONFIG_BAGET_MIPS + O_OBJS += time.o + ifndef CONFIG_SGI_IP22 OX_OBJS += irq.o endif endif diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/fpe.c linux/arch/mips/kernel/fpe.c --- v2.4.0-test2/linux/arch/mips/kernel/fpe.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/fpe.c Sun Jul 9 22:18:15 2000 @@ -4,9 +4,7 @@ * in the kernel space a lot easier. So far this handler in the released * kernel source is just a dummy. * - * Copyright (C) 1997 Ralf Baechle - * - * $Id: fpe.c,v 1.3 1998/04/05 11:23:50 ralf Exp $ + * Copyright (C) 1997, 2000 Ralf Baechle */ #include #include @@ -24,7 +22,6 @@ static void do_fpe(struct pt_regs *regs, unsigned int fcr31) { - lock_kernel(); #ifdef CONF_DEBUG_EXCEPTIONS show_regs(regs); #endif @@ -34,7 +31,6 @@ goto out; force_sig(SIGFPE, current); out: - unlock_kernel(); } /* diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S --- v2.4.0-test2/linux/arch/mips/kernel/head.S Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/head.S Sun Jul 9 22:18:15 2000 @@ -101,6 +101,15 @@ END(except_vec0_r4600) /* TLB refill, EXL == 0, R52x0 "Nevada" version */ + /* + * This version has a bug workaround for the Nevada. It seems + * as if under certain circumstances the move from cp0_context + * might produce a bogus result when the mfc0 instruction and + * it's consumer are in a different cacheline or a load instruction, + * probably any memory reference, is between them. This is + * potencially slower than the R4000 version, so we use this + * special version. + */ .set noreorder .set noat LEAF(except_vec0_nevada) diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c --- v2.4.0-test2/linux/arch/mips/kernel/irixelf.c Fri Jun 23 21:55:07 2000 +++ linux/arch/mips/kernel/irixelf.c Sun Jul 9 22:18:15 2000 @@ -1,5 +1,4 @@ -/* $Id: irixelf.c,v 1.28 2000/03/23 02:25:42 ralf Exp $ - * +/* * irixelf.c: Code to load IRIX ELF executables which conform to * the MIPS ABI. * @@ -467,7 +466,6 @@ return 0; dput_and_out: - allow_write_access(file); fput(file); out: kfree(*name); @@ -771,7 +769,7 @@ #endif start_thread(regs, elf_entry, bprm->p); - if (current->flags & PF_PTRACED) + if (current->ptrace & PT_PTRACED) send_sig(SIGTRAP, current, 0); return 0; out: @@ -1284,7 +1282,7 @@ return register_binfmt(&irix_format); } -static void __exit cleanup_module(void) +static void __exit exit_irix_binfmt(void) { /* Remove the IRIX ELF loaders. */ unregister_binfmt(&irix_format); diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/irixioctl.c linux/arch/mips/kernel/irixioctl.c --- v2.4.0-test2/linux/arch/mips/kernel/irixioctl.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/irixioctl.c Sun Jul 9 22:18:15 2000 @@ -1,4 +1,4 @@ -/* $Id: irixioctl.c,v 1.6 1999/02/06 05:12:56 adevries Exp $ +/* * irixioctl.c: A fucking mess... * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -48,7 +48,7 @@ static struct tty_struct *get_real_tty(struct tty_struct *tp) { - if(tp->driver.type == TTY_DRIVER_TYPE_PTY && + if (tp->driver.type == TTY_DRIVER_TYPE_PTY && tp->driver.subtype == PTY_TYPE_MASTER) return tp->link; else @@ -61,7 +61,6 @@ mm_segment_t old_fs; int error = 0; - lock_kernel(); #ifdef DEBUG_IOCTLS printk("[%s:%d] irix_ioctl(%d, ", current->comm, current->pid, fd); #endif @@ -87,7 +86,7 @@ old_fs = get_fs(); set_fs(get_ds()); error = sys_ioctl(fd, TCGETS, (unsigned long) &kt); set_fs(old_fs); - if(error) + if (error) break; __put_user(kt.c_iflag, &it->c_iflag); __put_user(kt.c_oflag, &it->c_oflag); @@ -106,7 +105,7 @@ #ifdef DEBUG_IOCTLS printk("TCSETS, %08lx) ", arg); #endif - if(!access_ok(VERIFY_READ, it, sizeof(*it))) { + if (!access_ok(VERIFY_READ, it, sizeof(*it))) { error = -EFAULT; break; } @@ -259,6 +258,5 @@ #ifdef DEBUG_IOCTLS printk("error=%d\n", error); #endif - unlock_kernel(); return error; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c --- v2.4.0-test2/linux/arch/mips/kernel/irixsig.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/irixsig.c Sun Jul 9 22:18:15 2000 @@ -2,10 +2,9 @@ * irixsig.c: WHEEE, IRIX signals! YOW, am I compatable or what?!?! * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: irixsig.c,v 1.13 1999/10/09 00:00:58 ralf Exp $ + * Copyright (C) 1997 - 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 2000 Silicon Graphics, Inc. */ - #include #include #include @@ -19,6 +18,7 @@ asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, int options, unsigned long *ru); +extern asmlinkage void syscall_trace(void); #undef DEBUG_SIG @@ -131,10 +131,8 @@ setup_irix_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *oldmask, siginfo_t *info) { - lock_kernel(); printk("Aiee: setup_tr_frame wants to be written"); do_exit(SIGSEGV); - unlock_kernel(); } static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, @@ -193,7 +191,7 @@ if (!signr) break; - if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; @@ -266,8 +264,8 @@ /* FALLTHRU */ default: - lock_kernel(); sigaddset(¤t->signal, signr); + recalc_sigpending(current); current->flags |= PF_SIGNALED; do_exit(exit_code); /* NOTREACHED */ @@ -354,6 +352,8 @@ /* * Don't let your children do this ... */ + if (current->ptrace & PT_TRACESYS) + syscall_trace(); __asm__ __volatile__( "move\t$29,%0\n\t" "j\tret_from_sys_call" @@ -429,23 +429,24 @@ asmlinkage int irix_sigpending(irix_sigset_t *set) { - lock_kernel(); + int err; + if (verify_area(VERIFY_WRITE, set, sizeof(*set)) < 0) return -EFAULT; /* fill in "set" with signals pending but blocked. */ spin_lock_irq(¤t->sigmask_lock); - __put_user(current->blocked.sig[0] & current->signal.sig[0], - &set->sig[0]); - __put_user(current->blocked.sig[1] & current->signal.sig[1], - &set->sig[1]); - __put_user(current->blocked.sig[2] & current->signal.sig[2], - &set->sig[2]); - __put_user(current->blocked.sig[3] & current->signal.sig[3], - &set->sig[3]); + err = __put_user(current->blocked.sig[0] & current->signal.sig[0], + &set->sig[0]); + err |= __put_user(current->blocked.sig[1] & current->signal.sig[1], + &set->sig[1]); + err |= __put_user(current->blocked.sig[2] & current->signal.sig[2], + &set->sig[2]); + err |= __put_user(current->blocked.sig[3] & current->signal.sig[3], + &set->sig[3]); spin_unlock_irq(¤t->sigmask_lock); - return 0; + return err; } asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old) @@ -453,10 +454,9 @@ sigset_t oldbits, newbits; int error; - - if(new) { + if (new) { error = verify_area(VERIFY_READ, new, sizeof(*new)); - if(error) + if (error) return error; __copy_from_user(&newbits, new, sizeof(unsigned long)*4); sigdelsetmask(&newbits, ~_BLOCKABLE); @@ -565,7 +565,6 @@ sigset_t kset; int i, sig, error, timeo = 0; - lock_kernel(); #ifdef DEBUG_SIG printk("[%s:%d] irix_sigpoll_sys(%p,%p,%p)\n", current->comm, current->pid, set, info, tp); @@ -636,7 +635,6 @@ error = -EINTR; out: - unlock_kernel(); return error; } @@ -662,44 +660,45 @@ DECLARE_WAITQUEUE(wait, current); struct task_struct *p; - lock_kernel(); - if(!info) { + if (!info) { retval = -EINVAL; goto out; } retval = verify_area(VERIFY_WRITE, info, sizeof(*info)); if(retval) goto out; - if(ru) { + if (ru) { retval = verify_area(VERIFY_WRITE, ru, sizeof(*ru)); if(retval) goto out; } - if(options & ~(W_MASK)) { + if (options & ~(W_MASK)) { retval = -EINVAL; goto out; } - if(type != P_PID && type != P_PGID && type != P_ALL) { + if (type != P_PID && type != P_PGID && type != P_ALL) { retval = -EINVAL; goto out; } add_wait_queue(¤t->wait_chldexit, &wait); repeat: flag = 0; - for(p = current->p_cptr; p; p = p->p_osptr) { - if((type == P_PID) && p->pid != pid) + current->state = TASK_INTERRUPTIBLE; + read_lock(&tasklist_lock); + for (p = current->p_cptr; p; p = p->p_osptr) { + if ((type == P_PID) && p->pid != pid) continue; - if((type == P_PGID) && p->pgrp != pid) + if ((type == P_PGID) && p->pgrp != pid) continue; - if((p->exit_signal != SIGCHLD)) + if ((p->exit_signal != SIGCHLD)) continue; flag = 1; - switch(p->state) { + switch (p->state) { case TASK_STOPPED: if (!p->exit_code) continue; if (!(options & (W_TRAPPED|W_STOPPED)) && - !(p->flags & PF_PTRACED)) + !(p->ptrace & PT_PTRACED)) continue; if (ru != NULL) getrusage(p, RUSAGE_BOTH, ru); @@ -740,12 +739,13 @@ continue; } } - if(flag) { + read_unlock(&tasklist_lock); + if (flag) { retval = 0; - if(options & W_NOHANG) + if (options & W_NOHANG) goto end_waitsys; retval = -ERESTARTSYS; - if(signal_pending(current)) + if (signal_pending(current)) goto end_waitsys; current->state = TASK_INTERRUPTIBLE; schedule(); @@ -753,10 +753,10 @@ } retval = -ECHILD; end_waitsys: + current->state = TASK_RUNNING; remove_wait_queue(¤t->wait_chldexit, &wait); out: - unlock_kernel(); return retval; } @@ -779,8 +779,7 @@ struct irix5_context *ctx; unsigned long flags; - lock_kernel(); - if(regs->regs[2] == 1000) + if (regs->regs[2] == 1000) base = 1; ctx = (struct irix5_context *) regs->regs[base + 4]; @@ -803,7 +802,7 @@ __put_user(0, &ctx->weird_graphics_thing); __put_user(0, &ctx->regs[0]); - for(i = 1; i < 32; i++) + for (i = 1; i < 32; i++) __put_user(regs->regs[i], &ctx->regs[i]); __put_user(regs->lo, &ctx->regs[32]); __put_user(regs->hi, &ctx->regs[33]); @@ -821,7 +820,6 @@ error = 0; out: - unlock_kernel(); return error; } @@ -830,7 +828,6 @@ int error, base = 0; struct irix5_context *ctx; - lock_kernel(); if(regs->regs[2] == 1000) base = 1; ctx = (struct irix5_context *) regs->regs[base + 4]; @@ -841,15 +838,15 @@ #endif error = verify_area(VERIFY_READ, ctx, sizeof(*ctx)); - if(error) + if (error) goto out; - if(ctx->flags & 0x02) { + if (ctx->flags & 0x02) { /* XXX sigstack garbage, todo... */ printk("Wheee, cannot do sigstack stuff in setcontext\n"); } - if(ctx->flags & 0x04) { + if (ctx->flags & 0x04) { int i; /* XXX extra control block stuff... todo... */ @@ -860,7 +857,7 @@ regs->cp0_epc = ctx->regs[35]; } - if(ctx->flags & 0x08) { + if (ctx->flags & 0x08) { /* XXX fpu context, blah... */ printk("Wheee, cannot restore FPU context yet...\n"); } @@ -868,7 +865,6 @@ error = regs->regs[2]; out: - unlock_kernel(); return error; } @@ -878,7 +874,6 @@ { int error; - lock_kernel(); #ifdef DEBUG_SIG printk("[%s:%d] irix_sigstack(%p,%p)\n", current->comm, current->pid, new, old); @@ -895,8 +890,8 @@ goto out; } error = 0; + out: - unlock_kernel(); return error; } @@ -907,18 +902,17 @@ { int error; - lock_kernel(); #ifdef DEBUG_SIG printk("[%s:%d] irix_sigaltstack(%p,%p)\n", current->comm, current->pid, new, old); #endif - if(new) { + if (new) { error = verify_area(VERIFY_READ, new, sizeof(*new)); if(error) goto out; } - if(old) { + if (old) { error = verify_area(VERIFY_WRITE, old, sizeof(*old)); if(error) goto out; @@ -927,7 +921,6 @@ out: error = 0; - unlock_kernel(); return error; } @@ -940,7 +933,6 @@ { int error; - lock_kernel(); error = verify_area(VERIFY_READ, pset, sizeof(*pset)); if(error) goto out; @@ -950,10 +942,8 @@ pset->cmd, pset->ltype, pset->lid, pset->rtype, pset->rid, sig); #endif - error = -EINVAL; out: - unlock_kernel(); return error; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c --- v2.4.0-test2/linux/arch/mips/kernel/irq.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/irq.c Sun Jul 9 22:18:15 2000 @@ -1,5 +1,4 @@ -/* $Id: irq.c,v 1.20 2000/02/23 00:41:00 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -7,7 +6,7 @@ * Code to handle x86 style IRQs plus some generic interrupt stuff. * * Copyright (C) 1992 Linus Torvalds - * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle + * Copyright (C) 1994 - 2000 Ralf Baechle */ #include #include @@ -267,8 +266,10 @@ if (!shared) { if (is_i8259_irq(irq)) unmask_irq(irq); +#if CONFIG_DDB5074 /* This has no business here */ else nile4_enable_irq(irq_to_nile4(irq)); +#endif } restore_flags(flags); return 0; @@ -343,7 +344,7 @@ /* first, enable any unassigned (E)ISA irqs */ for (i = 15; i > 0; i--) { if (!irq_action[i]) { - enable_irq(i); + i8259_enable_irq(i); irqs |= (1 << i); } } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c --- v2.4.0-test2/linux/arch/mips/kernel/mips_ksyms.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/mips_ksyms.c Sun Jul 9 22:18:15 2000 @@ -1,12 +1,11 @@ -/* $Id: mips_ksyms.c,v 1.25 2000/02/24 00:12:40 ralf Exp $ - * +/* * Export MIPS-specific functions needed for loadable modules. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 1997, 1998 by Ralf Baechle + * Copyright (C) 1996, 1997, 1998, 2000 by Ralf Baechle */ #include #include @@ -16,10 +15,10 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -27,6 +26,9 @@ #include #include #include +#ifdef CONFIG_BLK_DEV_FD +#include +#endif extern void *__bzero(void *__s, size_t __count); extern long __strncpy_from_user_nocheck_asm(char *__to, @@ -50,11 +52,12 @@ EXPORT_SYMBOL_NOVERS(strcat); EXPORT_SYMBOL_NOVERS(strchr); EXPORT_SYMBOL_NOVERS(strlen); +EXPORT_SYMBOL_NOVERS(strpbrk); EXPORT_SYMBOL_NOVERS(strncat); EXPORT_SYMBOL_NOVERS(strnlen); EXPORT_SYMBOL_NOVERS(strrchr); +EXPORT_SYMBOL_NOVERS(strstr); EXPORT_SYMBOL_NOVERS(strtok); -EXPORT_SYMBOL_NOVERS(strpbrk); EXPORT_SYMBOL(_clear_page); EXPORT_SYMBOL(enable_irq); @@ -131,4 +134,9 @@ EXPORT_SYMBOL(screen_info); #endif +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) +EXPORT_SYMBOL(ide_ops); +#endif + EXPORT_SYMBOL(get_wchan); +EXPORT_SYMBOL(irq_stat); diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c --- v2.4.0-test2/linux/arch/mips/kernel/process.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/process.c Mon Jul 10 13:16:56 2000 @@ -34,7 +34,7 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ - current->priority = 0; + current->nice = 20; current->counter = -100; init_idle(); diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c --- v2.4.0-test2/linux/arch/mips/kernel/ptrace.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/ptrace.c Sun Jul 9 22:18:15 2000 @@ -39,12 +39,12 @@ #endif if (request == PTRACE_TRACEME) { /* are we already being traced? */ - if (current->flags & PF_PTRACED) { + if (current->ptrace & PT_PTRACED) { res = -EPERM; goto out; } /* set the ptrace bit in the process flags. */ - current->flags |= PF_PTRACED; + current->ptrace |= PT_PTRACED; res = 0; goto out; } @@ -76,9 +76,9 @@ (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) goto out_tsk; /* the same process cannot be attached many times */ - if (child->flags & PF_PTRACED) + if (child->ptrace & PT_PTRACED) goto out_tsk; - child->flags |= PF_PTRACED; + child->ptrace |= PT_PTRACED; write_lock_irq(&tasklist_lock); if (child->p_pptr != current) { @@ -93,7 +93,7 @@ goto out_tsk; } res = -ESRCH; - if (!(child->flags & PF_PTRACED)) + if (!(child->ptrace & PT_PTRACED)) goto out_tsk; if (child->state != TASK_STOPPED) { if (request != PTRACE_KILL) @@ -243,9 +243,9 @@ if ((unsigned long) data > _NSIG) break; if (request == PTRACE_SYSCALL) - child->flags |= PF_TRACESYS; + child->ptrace |= PT_TRACESYS; else - child->flags &= ~PF_TRACESYS; + child->ptrace &= ~PT_TRACESYS; child->exit_code = data; wake_up_process(child); res = 0; @@ -269,7 +269,7 @@ res = -EIO; if ((unsigned long) data > _NSIG) break; - child->flags &= ~(PF_PTRACED|PF_TRACESYS); + child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); child->exit_code = data; write_lock_irq(&tasklist_lock); REMOVE_LINKS(child); @@ -293,8 +293,8 @@ asmlinkage void syscall_trace(void) { - if ((current->flags & (PF_PTRACED|PF_TRACESYS)) - != (PF_PTRACED|PF_TRACESYS)) + if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) + != (PT_PTRACED|PT_TRACESYS)) return; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/scall_o32.S linux/arch/mips/kernel/scall_o32.S --- v2.4.0-test2/linux/arch/mips/kernel/scall_o32.S Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/scall_o32.S Sun Jul 9 22:18:15 2000 @@ -171,6 +171,7 @@ /* * The stackpointer for a call with more than 4 arguments is bad. + * We probably should handle this case a bit more drastic. */ bad_stack: negu v0 # error diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c --- v2.4.0-test2/linux/arch/mips/kernel/setup.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/setup.c Sun Jul 9 22:18:15 2000 @@ -76,7 +76,7 @@ struct fd_ops *fd_ops; #endif -#ifdef CONFIG_BLK_DEV_IDE +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) extern struct ide_ops no_ide_ops; struct ide_ops *ide_ops; #endif @@ -84,8 +84,10 @@ extern struct rtc_ops no_rtc_ops; struct rtc_ops *rtc_ops; +#ifdef CONFIG_PC_KEYB extern struct kbd_ops no_kbd_ops; struct kbd_ops *kbd_ops; +#endif /* * Setup information @@ -272,8 +274,11 @@ ide_ops = &no_ide_ops; #endif - rtc_ops = &no_rtc_ops; +#ifdef CONFIG_PC_KEYB kbd_ops = &no_kbd_ops; +#endif + + rtc_ops = &no_rtc_ops; switch(mips_machgroup) { diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c --- v2.4.0-test2/linux/arch/mips/kernel/signal.c Mon Jun 19 16:31:57 2000 +++ linux/arch/mips/kernel/signal.c Sun Jul 9 22:18:15 2000 @@ -1,5 +1,4 @@ -/* $Id: signal.c,v 1.24 2000/02/04 07:40:23 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -37,6 +36,8 @@ extern asmlinkage int save_fp_context(struct sigcontext *sc); extern asmlinkage int restore_fp_context(struct sigcontext *sc); +extern asmlinkage void syscall_trace(void); + int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from) { if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t))) @@ -265,6 +266,8 @@ /* * Don't let your children do this ... */ + if (current->ptrace & PT_TRACESYS) + syscall_trace(); __asm__ __volatile__( "move\t$29, %0\n\t" "j\tret_from_sys_call" @@ -585,7 +588,7 @@ if (!signr) break; - if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; @@ -659,7 +662,6 @@ /* FALLTHRU */ default: - lock_kernel(); sigaddset(¤t->signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/softfp.S linux/arch/mips/kernel/softfp.S --- v2.4.0-test2/linux/arch/mips/kernel/softfp.S Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/softfp.S Sun Jul 9 22:18:15 2000 @@ -1,10 +1,9 @@ -/* $Id: softfp.S,v 1.1 1998/07/16 19:10:02 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1998 by Ralf Baechle + * Copyright (C) 1998, 2000 by Ralf Baechle * * For now it's just a crude hack good enough to run certain fp programs like * Mozilla. @@ -190,15 +189,15 @@ #define FMT_switch(insn,opc,temp0,temp1) \ insn: srl temp0, opc, 19; \ andi temp0, 0x1c; \ - la temp1, insn ## .tab; \ + la temp1, insn##.tab; \ addu temp0, temp1; \ lw temp0, (temp0); \ jr temp0; \ \ .data; \ -insn ## .tab: \ - .word insn ## .s, insn ## .d, unimp, unimp; \ - .word insn ## .w, insn ## .l, unimp, unimp; \ +insn##.tab: \ + .word insn##.s, insn##.d, unimp, unimp; \ + .word insn##.w, insn##.l, unimp, unimp; \ .previous BITCH(add) diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c --- v2.4.0-test2/linux/arch/mips/kernel/syscall.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/syscall.c Sun Jul 9 22:18:15 2000 @@ -1,10 +1,10 @@ -/* $Id: syscall.c,v 1.13 2000/02/04 07:40:23 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995 - 1999 by Ralf Baechle + * Copyright (C) 1995 - 2000 by Ralf Baechle + * Copyright (C) 2000 Silicon Graphics, Inc. * * TODO: Implement the compatibility syscalls. * Don't waste that much memory for empty entries in the syscall @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -42,7 +43,6 @@ int fd[2]; int error, res; - lock_kernel(); error = do_pipe(fd); if (error) { res = error; @@ -51,7 +51,6 @@ regs.regs[3] = fd[1]; res = fd[0]; out: - unlock_kernel(); return res; } @@ -71,11 +70,7 @@ } down(¤t->mm->mmap_sem); - lock_kernel(); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - - unlock_kernel(); up(¤t->mm->mmap_sem); if (file) diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c --- v2.4.0-test2/linux/arch/mips/kernel/sysirix.c Fri Jun 23 21:55:07 2000 +++ linux/arch/mips/kernel/sysirix.c Sun Jul 9 22:18:15 2000 @@ -1,12 +1,10 @@ -/* $Id: sysirix.c,v 1.26 2000/03/12 23:15:33 ralf Exp $ - * +/* * sysirix.c: IRIX system call emulation. * * Copyright (C) 1996 David S. Miller * Copyright (C) 1997 Miguel de Icaza * Copyright (C) 1997, 1998 Ralf Baechle */ - #include #include #include @@ -32,7 +30,7 @@ #include #include -/* 2,526 lines of complete and utter shit coming up... */ +/* 2,191 lines of complete and utter shit coming up... */ extern int max_threads; @@ -59,7 +57,7 @@ error = smp_num_cpus; break; default: - printk("SYSMP[%s:%ld]: Unsupported opcode %d\n", + printk("SYSMP[%s:%d]: Unsupported opcode %d\n", current->comm, current->pid, (int)cmd); error = -EINVAL; break; @@ -91,13 +89,12 @@ unsigned long cmd; int error = 0, base = 0; - lock_kernel(); - if(regs->regs[2] == 1000) + if (regs->regs[2] == 1000) base = 1; cmd = regs->regs[base + 4]; - switch(cmd) { + switch (cmd) { case PR_MAXPROCS: - printk("irix_prctl[%s:%ld]: Wants PR_MAXPROCS\n", + printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n", current->comm, current->pid); error = max_threads; break; @@ -105,14 +102,14 @@ case PR_ISBLOCKED: { struct task_struct *task; - printk("irix_prctl[%s:%ld]: Wants PR_ISBLOCKED\n", + printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n", current->comm, current->pid); + read_lock(&tasklist_lock); task = find_task_by_pid(regs->regs[base + 5]); - if(!task) { - error = -ESRCH; - break; - } - error = (task->run_list.next != NULL); + error = -ESRCH; + if (error) + error = (task->run_list.next != NULL); + read_unlock(&tasklist_lock); /* Can _your_ OS find this out that fast? */ break; } @@ -120,17 +117,17 @@ case PR_SETSTACKSIZE: { long value = regs->regs[base + 5]; - printk("irix_prctl[%s:%ld]: Wants PR_SETSTACKSIZE<%08lx>\n", + printk("irix_prctl[%s:%d]: Wants PR_SETSTACKSIZE<%08lx>\n", current->comm, current->pid, (unsigned long) value); - if(value > RLIM_INFINITY) + if (value > RLIM_INFINITY) value = RLIM_INFINITY; - if(capable(CAP_SYS_ADMIN)) { + if (capable(CAP_SYS_ADMIN)) { current->rlim[RLIMIT_STACK].rlim_max = current->rlim[RLIMIT_STACK].rlim_cur = value; error = value; break; } - if(value > current->rlim[RLIMIT_STACK].rlim_max) { + if (value > current->rlim[RLIMIT_STACK].rlim_max) { error = -EINVAL; break; } @@ -140,25 +137,25 @@ } case PR_GETSTACKSIZE: - printk("irix_prctl[%s:%ld]: Wants PR_GETSTACKSIZE\n", + printk("irix_prctl[%s:%d]: Wants PR_GETSTACKSIZE\n", current->comm, current->pid); error = current->rlim[RLIMIT_STACK].rlim_cur; break; case PR_MAXPPROCS: - printk("irix_prctl[%s:%ld]: Wants PR_MAXPROCS\n", + printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n", current->comm, current->pid); error = 1; break; case PR_UNBLKONEXEC: - printk("irix_prctl[%s:%ld]: Wants PR_UNBLKONEXEC\n", + printk("irix_prctl[%s:%d]: Wants PR_UNBLKONEXEC\n", current->comm, current->pid); error = -EINVAL; break; case PR_SETEXITSIG: - printk("irix_prctl[%s:%ld]: Wants PR_SETEXITSIG\n", + printk("irix_prctl[%s:%d]: Wants PR_SETEXITSIG\n", current->comm, current->pid); /* We can probably play some game where we set the task @@ -169,31 +166,31 @@ break; case PR_RESIDENT: - printk("irix_prctl[%s:%ld]: Wants PR_RESIDENT\n", + printk("irix_prctl[%s:%d]: Wants PR_RESIDENT\n", current->comm, current->pid); error = 0; /* Compatibility indeed. */ break; case PR_ATTACHADDR: - printk("irix_prctl[%s:%ld]: Wants PR_ATTACHADDR\n", + printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDR\n", current->comm, current->pid); error = -EINVAL; break; case PR_DETACHADDR: - printk("irix_prctl[%s:%ld]: Wants PR_DETACHADDR\n", + printk("irix_prctl[%s:%d]: Wants PR_DETACHADDR\n", current->comm, current->pid); error = -EINVAL; break; case PR_TERMCHILD: - printk("irix_prctl[%s:%ld]: Wants PR_TERMCHILD\n", + printk("irix_prctl[%s:%d]: Wants PR_TERMCHILD\n", current->comm, current->pid); error = -EINVAL; break; case PR_GETSHMASK: - printk("irix_prctl[%s:%ld]: Wants PR_GETSHMASK\n", + printk("irix_prctl[%s:%d]: Wants PR_GETSHMASK\n", current->comm, current->pid); error = -EINVAL; /* Until I have the sproc() stuff in. */ break; @@ -203,30 +200,29 @@ break; case PR_COREPID: - printk("irix_prctl[%s:%ld]: Wants PR_COREPID\n", + printk("irix_prctl[%s:%d]: Wants PR_COREPID\n", current->comm, current->pid); error = -EINVAL; break; case PR_ATTACHADDRPERM: - printk("irix_prctl[%s:%ld]: Wants PR_ATTACHADDRPERM\n", + printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDRPERM\n", current->comm, current->pid); error = -EINVAL; break; case PR_PTHREADEXIT: - printk("irix_prctl[%s:%ld]: Wants PR_PTHREADEXIT\n", + printk("irix_prctl[%s:%d]: Wants PR_PTHREADEXIT\n", current->comm, current->pid); do_exit(regs->regs[base + 5]); default: - printk("irix_prctl[%s:%ld]: Non-existant opcode %d\n", + printk("irix_prctl[%s:%d]: Non-existant opcode %d\n", current->comm, current->pid, (int)cmd); error = -EINVAL; break; } - unlock_kernel(); return error; } @@ -267,81 +263,83 @@ asmlinkage int irix_syssgi(struct pt_regs *regs) { - unsigned long cmd; - int retval, base = 0; + unsigned long cmd; + int retval, base = 0; + + if (regs->regs[2] == 1000) + base = 1; - lock_kernel(); - if(regs->regs[2] == 1000) - base = 1; - - cmd = regs->regs[base + 4]; - switch(cmd) { - case SGI_SYSID: { - char *buf = (char *) regs->regs[base + 5]; - - /* XXX Use ethernet addr.... */ - retval = clear_user(buf, 64); - break; - } + cmd = regs->regs[base + 4]; + switch(cmd) { + case SGI_SYSID: { + char *buf = (char *) regs->regs[base + 5]; + + /* XXX Use ethernet addr.... */ + retval = clear_user(buf, 64); + break; + } #if 0 - case SGI_RDNAME: { - int pid = (int) regs->regs[base + 5]; - char *buf = (char *) regs->regs[base + 6]; - struct task_struct *p; - - retval = verify_area(VERIFY_WRITE, buf, 16); - if(retval) - break; - for_each_task(p) { - if(p->pid == pid) - goto found0; - } - retval = -ESRCH; - - found0: - /* XXX Need to check sizes. */ - copy_to_user(buf, p->comm, 16); - retval = 0; - break; - } - - case SGI_GETNVRAM: { - char *name = (char *) regs->regs[base+5]; - char *buf = (char *) regs->regs[base+6]; - char *value; + case SGI_RDNAME: { + int pid = (int) regs->regs[base + 5]; + char *buf = (char *) regs->regs[base + 6]; + struct task_struct *p; + char comm[16]; + + retval = verify_area(VERIFY_WRITE, buf, 16); + if (retval) + break; + read_lock(&tasklist_lock); + p = find_task_by_pid(pid); + if (!p) { + read_unlock(&tasklist_lock); + retval = -ESRCH; + break; + } + memcpy(comm, p->comm, 16); + read_unlock(&tasklist_lock); + + /* XXX Need to check sizes. */ + copy_to_user(buf, p->comm, 16); + retval = 0; + break; + } + + case SGI_GETNVRAM: { + char *name = (char *) regs->regs[base+5]; + char *buf = (char *) regs->regs[base+6]; + char *value; return -EINVAL; /* til I fix it */ - retval = verify_area(VERIFY_WRITE, buf, 128); - if (retval) - break; - value = prom_getenv(name); - if (!value) { - retval = -EINVAL; - break; - } - /* Do I strlen() for the length? */ - copy_to_user(buf, value, 128); - retval = 0; - break; - } - - case SGI_SETNVRAM: { - char *name = (char *) regs->regs[base+5]; - char *value = (char *) regs->regs[base+6]; + retval = verify_area(VERIFY_WRITE, buf, 128); + if (retval) + break; + value = prom_getenv(name); /* PROM lock? */ + if (!value) { + retval = -EINVAL; + break; + } + /* Do I strlen() for the length? */ + copy_to_user(buf, value, 128); + retval = 0; + break; + } + + case SGI_SETNVRAM: { + char *name = (char *) regs->regs[base+5]; + char *value = (char *) regs->regs[base+6]; return -EINVAL; /* til I fix it */ - retval = prom_setenv(name, value); + retval = prom_setenv(name, value); /* XXX make sure retval conforms to syssgi(2) */ printk("[%s:%d] setnvram(\"%s\", \"%s\"): retval %d", - current->comm, current->pid, - name, value, retval); + current->comm, current->pid, name, value, retval); /* if (retval == PROM_ENOENT) retval = -ENOENT; */ break; } #endif - + case SGI_SETPGID: { #ifdef DEBUG_PROCGRPS - printk("[%s:%ld] setpgid(%d, %d) ", + printk("[%s:%d] setpgid(%d, %d) ", current->comm, current->pid, (int) regs->regs[base + 5], (int)regs->regs[base + 6]); #endif @@ -438,7 +436,7 @@ case SGI_GETSID: #ifdef DEBUG_PROCGRPS - printk("[%s:%ld] getsid(%d) ", current->comm, current->pid, + printk("[%s:%d] getsid(%d) ", current->comm, current->pid, (int) regs->regs[base + 5]); #endif retval = sys_getsid(regs->regs[base + 5]); @@ -463,25 +461,31 @@ break; case SGI_PHYSP: { + unsigned long addr = regs->regs[base + 5]; + int *pageno = (int *) (regs->regs[base + 6]); + struct mm_struct *mm = current->mm; pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; - unsigned long addr = regs->regs[base + 5]; - int *pageno = (int *) (regs->regs[base + 6]); retval = verify_area(VERIFY_WRITE, pageno, sizeof(int)); - if(retval) + if (retval) return retval; - pgdp = pgd_offset(current->mm, addr); + + down(&mm->mmap_sem); + pgdp = pgd_offset(mm, addr); pmdp = pmd_offset(pgdp, addr); ptep = pte_offset(pmdp, addr); - if(ptep) { - if(pte_val(*ptep) & (_PAGE_VALID | _PAGE_PRESENT)) { - return put_user((pte_val(*ptep) & PAGE_MASK)>>PAGE_SHIFT, pageno); - return 0; + retval = -EINVAL; + if (ptep) { + pte_t pte = *ptep; + + if (pte_val(pte) & (_PAGE_VALID | _PAGE_PRESENT)) { + retval = put_user((pte_val(pte) & PAGE_MASK) >> + PAGE_SHIFT, pageno); } } - retval = -EINVAL; + up(&mm->mmap_sem); break; } @@ -490,7 +494,7 @@ void *buffer = (void *) regs->regs [base + 6]; int count = (int) regs->regs [base + 7]; - switch (arg1){ + switch (arg1) { case SGI_INV_SIZEOF: retval = sizeof (inventory_t); break; @@ -510,7 +514,6 @@ }; out: - unlock_kernel(); return retval; } @@ -532,7 +535,7 @@ struct mm_struct *mm = current->mm; int ret; - lock_kernel(); + down(&mm->mmap_sem); if (brk < mm->end_code) { ret = -ENOMEM; goto out; @@ -590,7 +593,7 @@ ret = 0; out: - unlock_kernel(); + up(&mm->mmap_sem); return ret; } @@ -612,26 +615,21 @@ return current->gid; } +extern rwlock_t xtime_lock; + asmlinkage int irix_stime(int value) { - int ret; + if (!capable(CAP_SYS_TIME)) + return -EPERM; - lock_kernel(); - if(!capable(CAP_SYS_TIME)) { - ret = -EPERM; - goto out; - } - cli(); + write_lock_irq(&xtime_lock); xtime.tv_sec = value; xtime.tv_usec = 0; time_maxerror = MAXPHASE; time_esterror = MAXPHASE; - sti(); - ret = 0; + write_unlock_irq(&xtime_lock); -out: - unlock_kernel(); - return ret; + return 0; } extern int do_setitimer(int which, struct itimerval *value, @@ -641,7 +639,6 @@ { value->tv_usec = (jiffies % HZ) * (1000000 / HZ); value->tv_sec = jiffies / HZ; - return; } static inline void getitimer_real(struct itimerval *value) @@ -668,8 +665,7 @@ struct itimerval it_new, it_old; unsigned int oldalarm; - lock_kernel(); - if(!seconds) { + if (!seconds) { getitimer_real(&it_old); del_timer(¤t->real_timer); } else { @@ -679,20 +675,21 @@ do_setitimer(ITIMER_REAL, &it_new, &it_old); } oldalarm = it_old.it_value.tv_sec; - /* ehhh.. We can't return 0 if we have an alarm pending.. */ - /* And we'd better return too much than too little anyway */ + /* + * ehhh.. We can't return 0 if we have an alarm pending ... + * And we'd better return too much than too little anyway + */ if (it_old.it_value.tv_usec) oldalarm++; - unlock_kernel(); + return oldalarm; } asmlinkage int irix_pause(void) { - lock_kernel(); current->state = TASK_INTERRUPTIBLE; schedule(); - unlock_kernel(); + return -EINTR; } @@ -703,16 +700,11 @@ asmlinkage int irix_mount(char *dev_name, char *dir_name, unsigned long flags, char *type, void *data, int datalen) { - int ret; - - lock_kernel(); - printk("[%s:%ld] irix_mount(%p,%p,%08lx,%p,%p,%d)\n", + printk("[%s:%d] irix_mount(%p,%p,%08lx,%p,%p,%d)\n", current->comm, current->pid, dev_name, dir_name, flags, type, data, datalen); - ret = sys_mount(dev_name, dir_name, type, flags, data); - unlock_kernel(); - return ret; + return sys_mount(dev_name, dir_name, type, flags, data); } struct irix_statfs { @@ -728,10 +720,8 @@ struct statfs kbuf; int error, i; - lock_kernel(); - /* We don't support this feature yet. */ - if(fs_type) { + if (fs_type) { error = -EINVAL; goto out; } @@ -753,7 +743,7 @@ __put_user(kbuf.f_bfree, &buf->f_bfree); __put_user(kbuf.f_files, &buf->f_files); __put_user(kbuf.f_ffree, &buf->f_ffree); - for(i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) { __put_user(0, &buf->f_fname[i]); __put_user(0, &buf->f_fpack[i]); } @@ -762,7 +752,6 @@ dput_and_out: path_release(&nd); out: - unlock_kernel(); return error; } @@ -772,7 +761,6 @@ struct file *file; int error, i; - lock_kernel(); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs)); if (error) goto out; @@ -800,7 +788,6 @@ out_f: fput(file); out: - unlock_kernel(); return error; } @@ -811,9 +798,8 @@ { int error; - lock_kernel(); #ifdef DEBUG_PROCGRPS - printk("[%s:%ld] setpgrp(%d) ", current->comm, current->pid, flags); + printk("[%s:%d] setpgrp(%d) ", current->comm, current->pid, flags); #endif if(!flags) error = current->pgrp; @@ -823,29 +809,24 @@ printk("returning %d\n", current->pgrp); #endif - unlock_kernel(); return error; } asmlinkage int irix_times(struct tms * tbuf) { - int error; + int err = 0; - lock_kernel(); if (tbuf) { - error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf); - if (error) - goto out; - __put_user(current->times.tms_utime,&tbuf->tms_utime); - __put_user(current->times.tms_stime,&tbuf->tms_stime); - __put_user(current->times.tms_cutime,&tbuf->tms_cutime); - __put_user(current->times.tms_cstime,&tbuf->tms_cstime); + err = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf); + if (err) + return err; + err |= __put_user(current->times.tms_utime,&tbuf->tms_utime); + err |= __put_user(current->times.tms_stime,&tbuf->tms_stime); + err |= __put_user(current->times.tms_cutime,&tbuf->tms_cutime); + err |= __put_user(current->times.tms_cstime,&tbuf->tms_cstime); } - error = 0; -out: - unlock_kernel(); - return error; + return err; } asmlinkage int irix_exec(struct pt_regs *regs) @@ -858,12 +839,12 @@ filename = getname((char *) (long)regs->regs[base + 4]); error = PTR_ERR(filename); if (IS_ERR(filename)) - goto out; + return error; + error = do_execve(filename, (char **) (long)regs->regs[base + 5], (char **) 0, regs); putname(filename); -out: return error; } @@ -872,37 +853,32 @@ int error, base = 0; char *filename; - lock_kernel(); - if(regs->regs[2] == 1000) + if (regs->regs[2] == 1000) base = 1; filename = getname((char *) (long)regs->regs[base + 4]); error = PTR_ERR(filename); if (IS_ERR(filename)) - goto out; + return error; error = do_execve(filename, (char **) (long)regs->regs[base + 5], (char **) (long)regs->regs[base + 6], regs); putname(filename); -out: - unlock_kernel(); return error; } asmlinkage unsigned long irix_gethostid(void) { - lock_kernel(); - printk("[%s:%ld]: irix_gethostid() called...\n", + printk("[%s:%d]: irix_gethostid() called...\n", current->comm, current->pid); - unlock_kernel(); + return -EINVAL; } asmlinkage unsigned long irix_sethostid(unsigned long val) { - lock_kernel(); - printk("[%s:%ld]: irix_sethostid(%08lx) called...\n", + printk("[%s:%d]: irix_sethostid(%08lx) called...\n", current->comm, current->pid, val); - unlock_kernel(); + return -EINVAL; } @@ -946,20 +922,18 @@ { int error; - lock_kernel(); + error = verify_area(VERIFY_WRITE, name, len); + if (error) + return error; + + down_read(&uts_sem); if(len > (__NEW_UTS_LEN - 1)) len = __NEW_UTS_LEN - 1; - error = verify_area(VERIFY_WRITE, name, len); - if(error) - goto out; - if(copy_to_user(name, system_utsname.domainname, len)) { - error = -EFAULT; - goto out; - } error = 0; + if (copy_to_user(name, system_utsname.domainname, len)) + error = -EFAULT; + up_read(&uts_sem); -out: - unlock_kernel(); return error; } @@ -972,7 +946,7 @@ unsigned long arg2, unsigned long arg3, unsigned long arg4) { - switch(opcode) { + switch (opcode) { case 0: return sys_msgget((key_t) arg0, (int) arg1); case 1: @@ -991,7 +965,7 @@ asmlinkage int irix_shmsys(int opcode, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3) { - switch(opcode) { + switch (opcode) { case 0: return sys_shmat((int) arg0, (char *)arg1, (int) arg2, (unsigned long *) arg3); @@ -1009,7 +983,7 @@ asmlinkage int irix_semsys(int opcode, unsigned long arg0, unsigned long arg1, unsigned long arg2, int arg3) { - switch(opcode) { + switch (opcode) { case 0: return sys_semctl((int) arg0, (int) arg1, (int) arg2, (union semun) arg3); @@ -1023,27 +997,42 @@ } } -extern asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high, - unsigned long offset_low, loff_t * result, - unsigned int origin); - -asmlinkage int irix_lseek64(int fd, int _unused, int offhi, int offlow, int base) +static inline loff_t llseek(struct file *file, loff_t offset, int origin) { - mm_segment_t old_fs; - loff_t junk; - int error; + loff_t (*fn)(struct file *, loff_t, int); + loff_t retval; + fn = default_llseek; + if (file->f_op && file->f_op->llseek) + fn = file->f_op->llseek; lock_kernel(); - old_fs = get_fs(); set_fs(get_ds()); - error = sys_llseek(fd, offhi, offlow, &junk, base); - set_fs(old_fs); - - if(error) - goto out; - error = (int) junk; -out: + retval = fn(file, offset, origin); unlock_kernel(); - return error; + return retval; +} + +asmlinkage int irix_lseek64(int fd, int _unused, int offhi, int offlow, + int origin) +{ + int retval; + struct file * file; + loff_t offset; + + retval = -EBADF; + file = fget(fd); + if (!file) + goto bad; + retval = -EINVAL; + if (origin > 2) + goto out_putf; + + offset = llseek(file, ((loff_t) offhi << 32) | offlow, origin); + retval = (int) offset; + +out_putf: + fput(file); +bad: + return retval; } asmlinkage int irix_sginap(int ticks) @@ -1062,9 +1051,7 @@ { int retval; - lock_kernel(); retval = copy_to_user(tv, &xtime, sizeof(*tv)) ? -EFAULT : 0; - unlock_kernel(); return retval; } @@ -1076,12 +1063,9 @@ struct file *file = NULL; unsigned long retval; - lock_kernel(); if (!(flags & MAP_ANONYMOUS)) { - if (!(file = fget(fd))) { - retval = -EBADF; - goto out; - } + if (!(file = fget(fd))) + return -EBADF; /* Ok, bad taste hack follows, try to think in something else * when reading this. */ @@ -1105,36 +1089,30 @@ if (file) fput(file); -out: - unlock_kernel(); - return retval; } asmlinkage int irix_madvise(unsigned long addr, int len, int behavior) { - lock_kernel(); - printk("[%s:%ld] Wheee.. irix_madvise(%08lx,%d,%d)\n", + printk("[%s:%d] Wheee.. irix_madvise(%08lx,%d,%d)\n", current->comm, current->pid, addr, len, behavior); - unlock_kernel(); + return -EINVAL; } asmlinkage int irix_pagelock(char *addr, int len, int op) { - lock_kernel(); - printk("[%s:%ld] Wheee.. irix_pagelock(%p,%d,%d)\n", + printk("[%s:%d] Wheee.. irix_pagelock(%p,%d,%d)\n", current->comm, current->pid, addr, len, op); - unlock_kernel(); + return -EINVAL; } asmlinkage int irix_quotactl(struct pt_regs *regs) { - lock_kernel(); - printk("[%s:%ld] Wheee.. irix_quotactl()\n", + printk("[%s:%d] Wheee.. irix_quotactl()\n", current->comm, current->pid); - unlock_kernel(); + return -EINVAL; } @@ -1142,16 +1120,15 @@ { int error; - lock_kernel(); #ifdef DEBUG_PROCGRPS - printk("[%s:%ld] BSDsetpgrp(%d, %d) ", current->comm, current->pid, + printk("[%s:%d] BSDsetpgrp(%d, %d) ", current->comm, current->pid, pid, pgrp); #endif if(!pid) pid = current->pid; /* Wheee, weird sysv thing... */ - if((pgrp == 0) && (pid == current->pid)) + if ((pgrp == 0) && (pid == current->pid)) error = sys_setsid(); else error = sys_setpgid(pid, pgrp); @@ -1160,16 +1137,14 @@ printk("error = %d\n", error); #endif - unlock_kernel(); return error; } asmlinkage int irix_systeminfo(int cmd, char *buf, int cnt) { - lock_kernel(); - printk("[%s:%ld] Wheee.. irix_systeminfo(%d,%p,%d)\n", + printk("[%s:%d] Wheee.. irix_systeminfo(%d,%p,%d)\n", current->comm, current->pid, cmd, buf, cnt); - unlock_kernel(); + return -EINVAL; } @@ -1183,22 +1158,17 @@ asmlinkage int irix_uname(struct iuname *buf) { - int retval; - - lock_kernel(); - if(copy_to_user(system_utsname.sysname, buf->sysname, 65) - || copy_to_user(system_utsname.nodename, buf->nodename, 65) - || copy_to_user(system_utsname.release, buf->release, 65) - || copy_to_user(system_utsname.version, buf->version, 65) - || copy_to_user(system_utsname.machine, buf->machine, 65)) { - retval = -EFAULT; - goto out; + down_read(&uts_sem); + if (copy_to_user(system_utsname.sysname, buf->sysname, 65) + || copy_to_user(system_utsname.nodename, buf->nodename, 65) + || copy_to_user(system_utsname.release, buf->release, 65) + || copy_to_user(system_utsname.version, buf->version, 65) + || copy_to_user(system_utsname.machine, buf->machine, 65)) { + return -EFAULT; } - retval = 1; + up_read(&uts_sem); -out: - unlock_kernel(); - return retval; + return 1; } #undef DEBUG_XSTAT @@ -1293,9 +1263,8 @@ { int retval; - lock_kernel(); #ifdef DEBUG_XSTAT - printk("[%s:%ld] Wheee.. irix_xstat(%d,%s,%p) ", + printk("[%s:%d] Wheee.. irix_xstat(%d,%s,%p) ", current->comm, current->pid, version, filename, statbuf); #endif switch(version) { @@ -1334,7 +1303,6 @@ } out: - unlock_kernel(); return retval; } @@ -1344,9 +1312,8 @@ { int error; - lock_kernel(); #ifdef DEBUG_XSTAT - printk("[%s:%ld] Wheee.. irix_lxstat(%d,%s,%p) ", + printk("[%s:%d] Wheee.. irix_lxstat(%d,%s,%p) ", current->comm, current->pid, version, filename, statbuf); #endif switch(version) { @@ -1385,7 +1352,6 @@ } out: - unlock_kernel(); return error; } @@ -1395,9 +1361,8 @@ { int error; - lock_kernel(); #ifdef DEBUG_XSTAT - printk("[%s:%ld] Wheee.. irix_fxstat(%d,%d,%p) ", + printk("[%s:%d] Wheee.. irix_fxstat(%d,%d,%p) ", current->comm, current->pid, version, fd, statbuf); #endif switch(version) { @@ -1436,7 +1401,6 @@ } out: - unlock_kernel(); return error; } @@ -1446,30 +1410,27 @@ { int retval; - lock_kernel(); - printk("[%s:%ld] Wheee.. irix_xmknod(%d,%s,%x,%x)\n", + printk("[%s:%d] Wheee.. irix_xmknod(%d,%s,%x,%x)\n", current->comm, current->pid, ver, filename, mode, (int) dev); + switch(ver) { case 2: retval = sys_mknod(filename, mode, dev); - goto out; + break; default: retval = -EINVAL; - goto out; + break; }; -out: - unlock_kernel(); return retval; } asmlinkage int irix_swapctl(int cmd, char *arg) { - lock_kernel(); - printk("[%s:%ld] Wheee.. irix_swapctl(%d,%p)\n", + printk("[%s:%d] Wheee.. irix_swapctl(%d,%p)\n", current->comm, current->pid, cmd, arg); - unlock_kernel(); + return -EINVAL; } @@ -1487,8 +1448,7 @@ struct statfs kbuf; int error, i; - lock_kernel(); - printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n", + printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n", current->comm, current->pid, fname, buf); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); if (error) @@ -1513,11 +1473,11 @@ #else __put_user(kbuf.f_fsid.val[0], &buf->f_fsid); #endif - for(i = 0; i < 16; i++) + for (i = 0; i < 16; i++) __put_user(0, &buf->f_basetype[i]); __put_user(0, &buf->f_flag); __put_user(kbuf.f_namelen, &buf->f_namemax); - for(i = 0; i < 32; i++) + for (i = 0; i < 32; i++) __put_user(0, &buf->f_fstr[i]); error = 0; @@ -1525,7 +1485,6 @@ dput_and_out: path_release(&nd); out: - unlock_kernel(); return error; } @@ -1535,8 +1494,7 @@ struct file *file; int error, i; - lock_kernel(); - printk("[%s:%ld] Wheee.. irix_fstatvfs(%d,%p)\n", + printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n", current->comm, current->pid, fd, buf); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); @@ -1572,25 +1530,22 @@ out_f: fput(file); out: - unlock_kernel(); return error; } asmlinkage int irix_priocntl(struct pt_regs *regs) { - lock_kernel(); - printk("[%s:%ld] Wheee.. irix_priocntl()\n", + printk("[%s:%d] Wheee.. irix_priocntl()\n", current->comm, current->pid); - unlock_kernel(); + return -EINVAL; } asmlinkage int irix_sigqueue(int pid, int sig, int code, int val) { - lock_kernel(); - printk("[%s:%ld] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n", + printk("[%s:%d] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n", current->comm, current->pid, pid, sig, code, val); - unlock_kernel(); + return -EINVAL; } @@ -1601,15 +1556,13 @@ { int retval; - lock_kernel(); - if(size1) { + if (size1) { retval = -EINVAL; goto out; } retval = sys_truncate(name, size2); out: - unlock_kernel(); return retval; } @@ -1617,15 +1570,13 @@ { int retval; - lock_kernel(); - if(size1) { + if (size1) { retval = -EINVAL; goto out; } retval = sys_ftruncate(fd, size2); out: - unlock_kernel(); return retval; } @@ -1639,7 +1590,6 @@ unsigned long addr, pgoff, *sp; struct file *file = NULL; - lock_kernel(); if (regs->regs[2] == 1000) base = 1; sp = (unsigned long *) (regs->regs[29] + 16); @@ -1701,14 +1651,12 @@ fput(file); out: - unlock_kernel(); - return error; } asmlinkage int irix_dmi(struct pt_regs *regs) { - printk("[%s:%ld] Wheee.. irix_dmi()\n", + printk("[%s:%d] Wheee.. irix_dmi()\n", current->comm, current->pid); return -EINVAL; @@ -1717,7 +1665,7 @@ asmlinkage int irix_pread(int fd, char *buf, int cnt, int off64, int off1, int off2) { - printk("[%s:%ld] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n", + printk("[%s:%d] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n", current->comm, current->pid, fd, buf, cnt, off64, off1, off2); return -EINVAL; @@ -1726,7 +1674,7 @@ asmlinkage int irix_pwrite(int fd, char *buf, int cnt, int off64, int off1, int off2) { - printk("[%s:%ld] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n", + printk("[%s:%d] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n", current->comm, current->pid, fd, buf, cnt, off64, off1, off2); return -EINVAL; @@ -1736,7 +1684,7 @@ unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { - printk("[%s:%ld] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx," + printk("[%s:%d] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx," "%08lx,%08lx)\n", current->comm, current->pid, cmd, arg0, arg1, arg2, arg3, arg4, arg5); @@ -1761,8 +1709,7 @@ struct statfs kbuf; int error, i; - lock_kernel(); - printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n", + printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n", current->comm, current->pid, fname, buf); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); if(error) @@ -1799,7 +1746,6 @@ dput_and_out: path_release(&nd); out: - unlock_kernel(); return error; } @@ -1809,8 +1755,7 @@ struct file *file; int error, i; - lock_kernel(); - printk("[%s:%ld] Wheee.. irix_fstatvfs(%d,%p)\n", + printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n", current->comm, current->pid, fd, buf); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); @@ -1846,20 +1791,18 @@ out_f: fput(file); out: - unlock_kernel(); return error; } asmlinkage int irix_getmountid(char *fname, unsigned long *midbuf) { - int error; + int err; - lock_kernel(); - printk("[%s:%ld] irix_getmountid(%s, %p)\n", + printk("[%s:%d] irix_getmountid(%s, %p)\n", current->comm, current->pid, fname, midbuf); - error = verify_area(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4)); - if(error) - goto out; + err = verify_area(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4)); + if (err) + return err; /* * The idea with this system call is that when trying to determine @@ -1867,24 +1810,20 @@ * fsid of the filesystem to try and make the right decision, but * we don't have this so for now. XXX */ - __put_user(0, &midbuf[0]); - __put_user(0, &midbuf[1]); - __put_user(0, &midbuf[2]); - __put_user(0, &midbuf[3]); - error = 0; + err |= __put_user(0, &midbuf[0]); + err |= __put_user(0, &midbuf[1]); + err |= __put_user(0, &midbuf[2]); + err |= __put_user(0, &midbuf[3]); -out: - unlock_kernel(); - return error; + return err; } asmlinkage int irix_nsproc(unsigned long entry, unsigned long mask, unsigned long arg, unsigned long sp, int slen) { - lock_kernel(); - printk("[%s:%ld] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n", + printk("[%s:%d] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n", current->comm, current->pid, entry, mask, arg, sp, slen); - unlock_kernel(); + return -EINVAL; } @@ -1946,7 +1885,7 @@ int error; #ifdef DEBUG_GETDENTS - printk("[%s:%ld] ngetdents(%d, %p, %d, %p) ", current->comm, + printk("[%s:%d] ngetdents(%d, %p, %d, %p) ", current->comm, current->pid, fd, dirent, count, eob); #endif error = -EBADF; @@ -1954,8 +1893,6 @@ if (!file) goto out; - lock_kernel(); - buf.current_dir = (struct irix_dirent32 *) dirent; buf.previous = NULL; buf.count = count; @@ -1983,7 +1920,6 @@ error = count - buf.count; out_putf: - unlock_kernel(); fput(file); out: return error; @@ -2048,14 +1984,12 @@ if (!(file = fget(fd))) goto out; - lock_kernel(); - error = -EFAULT; - if(!access_ok(VERIFY_WRITE, dirent, cnt)) + if (!access_ok(VERIFY_WRITE, dirent, cnt)) goto out_f; error = -EINVAL; - if(cnt < (sizeof(struct irix_dirent64) + 255)) + if (cnt < (sizeof(struct irix_dirent64) + 255)) goto out_f; buf.curr = (struct irix_dirent64 *) dirent; @@ -2077,7 +2011,6 @@ error = cnt - buf.count; out_f: - unlock_kernel(); fput(file); out: return error; @@ -2098,15 +2031,13 @@ if (!(file = fget(fd))) goto out; - lock_kernel(); - error = -EFAULT; - if(!access_ok(VERIFY_WRITE, dirent, cnt) || - !access_ok(VERIFY_WRITE, eob, sizeof(*eob))) + if (!access_ok(VERIFY_WRITE, dirent, cnt) || + !access_ok(VERIFY_WRITE, eob, sizeof(*eob))) goto out_f; error = -EINVAL; - if(cnt < (sizeof(struct irix_dirent64) + 255)) + if (cnt < (sizeof(struct irix_dirent64) + 255)) goto out_f; *eob = 0; @@ -2129,7 +2060,6 @@ error = cnt - buf.count; out_f: - unlock_kernel(); fput(file); out: return error; @@ -2139,52 +2069,50 @@ { int retval; - lock_kernel(); - switch(op) { + switch (op) { case 1: /* Reboot */ - printk("[%s:%ld] irix_uadmin: Wants to reboot...\n", + printk("[%s:%d] irix_uadmin: Wants to reboot...\n", current->comm, current->pid); retval = -EINVAL; goto out; case 2: /* Shutdown */ - printk("[%s:%ld] irix_uadmin: Wants to shutdown...\n", + printk("[%s:%d] irix_uadmin: Wants to shutdown...\n", current->comm, current->pid); retval = -EINVAL; goto out; case 4: /* Remount-root */ - printk("[%s:%ld] irix_uadmin: Wants to remount root...\n", + printk("[%s:%d] irix_uadmin: Wants to remount root...\n", current->comm, current->pid); retval = -EINVAL; goto out; case 8: /* Kill all tasks. */ - printk("[%s:%ld] irix_uadmin: Wants to kill all tasks...\n", + printk("[%s:%d] irix_uadmin: Wants to kill all tasks...\n", current->comm, current->pid); retval = -EINVAL; goto out; case 256: /* Set magic mushrooms... */ - printk("[%s:%ld] irix_uadmin: Wants to set magic mushroom[%d]...\n", + printk("[%s:%d] irix_uadmin: Wants to set magic mushroom[%d]...\n", current->comm, current->pid, (int) func); retval = -EINVAL; goto out; default: - printk("[%s:%ld] irix_uadmin: Unknown operation [%d]...\n", + printk("[%s:%d] irix_uadmin: Unknown operation [%d]...\n", current->comm, current->pid, (int) op); retval = -EINVAL; goto out; }; out: - unlock_kernel(); return retval; } @@ -2192,7 +2120,6 @@ { int retval; - lock_kernel(); switch(type) { case 0: /* uname() */ @@ -2201,27 +2128,26 @@ case 2: /* ustat() */ - printk("[%s:%ld] irix_utssys: Wants to do ustat()\n", + printk("[%s:%d] irix_utssys: Wants to do ustat()\n", current->comm, current->pid); retval = -EINVAL; goto out; case 3: /* fusers() */ - printk("[%s:%ld] irix_utssys: Wants to do fusers()\n", + printk("[%s:%d] irix_utssys: Wants to do fusers()\n", current->comm, current->pid); retval = -EINVAL; goto out; default: - printk("[%s:%ld] irix_utssys: Wants to do unknown type[%d]\n", + printk("[%s:%d] irix_utssys: Wants to do unknown type[%d]\n", current->comm, current->pid, (int) type); retval = -EINVAL; goto out; } out: - unlock_kernel(); return retval; } @@ -2236,9 +2162,8 @@ { int retval; - lock_kernel(); #ifdef DEBUG_FCNTL - printk("[%s:%ld] irix_fcntl(%d, %d, %d) ", current->comm, + printk("[%s:%d] irix_fcntl(%d, %d, %d) ", current->comm, current->pid, fd, cmd, arg); #endif if (cmd == IRIX_F_ALLOCSP){ @@ -2248,7 +2173,6 @@ #ifdef DEBUG_FCNTL printk("%d\n", retval); #endif - unlock_kernel(); return retval; } @@ -2256,29 +2180,28 @@ { int retval; - lock_kernel(); switch(cmd) { case 1: - printk("[%s:%ld] irix_ulimit: Wants to get file size limit.\n", + printk("[%s:%d] irix_ulimit: Wants to get file size limit.\n", current->comm, current->pid); retval = -EINVAL; goto out; case 2: - printk("[%s:%ld] irix_ulimit: Wants to set file size limit.\n", + printk("[%s:%d] irix_ulimit: Wants to set file size limit.\n", current->comm, current->pid); retval = -EINVAL; goto out; case 3: - printk("[%s:%ld] irix_ulimit: Wants to get brk limit.\n", + printk("[%s:%d] irix_ulimit: Wants to get brk limit.\n", current->comm, current->pid); retval = -EINVAL; goto out; case 4: #if 0 - printk("[%s:%ld] irix_ulimit: Wants to get fd limit.\n", + printk("[%s:%d] irix_ulimit: Wants to get fd limit.\n", current->comm, current->pid); retval = -EINVAL; goto out; @@ -2287,25 +2210,24 @@ goto out; case 5: - printk("[%s:%ld] irix_ulimit: Wants to get txt offset.\n", + printk("[%s:%d] irix_ulimit: Wants to get txt offset.\n", current->comm, current->pid); retval = -EINVAL; goto out; default: - printk("[%s:%ld] irix_ulimit: Unknown command [%d].\n", + printk("[%s:%d] irix_ulimit: Unknown command [%d].\n", current->comm, current->pid, cmd); retval = -EINVAL; goto out; } out: - unlock_kernel(); return retval; } asmlinkage int irix_unimp(struct pt_regs *regs) { - printk("irix_unimp [%s:%ld] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx " + printk("irix_unimp [%s:%d] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx " "a3=%08lx\n", current->comm, current->pid, (int) regs->regs[2], (int) regs->regs[3], regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c --- v2.4.0-test2/linux/arch/mips/kernel/sysmips.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/sysmips.c Sun Jul 9 22:18:15 2000 @@ -5,9 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996, 1997 by Ralf Baechle - * - * $Id: sysmips.c,v 1.8 2000/02/05 06:47:08 ralf Exp $ + * Copyright (C) 1995, 1996, 1997, 2000 by Ralf Baechle */ #include #include @@ -51,45 +49,48 @@ { int *p; char *name; - int flags, tmp, len, retval; + int flags, tmp, len, retval, errno; + + switch(cmd) { + case SETNAME: { + char nodename[__NEW_UTS_LEN + 1]; - lock_kernel(); - switch(cmd) - { - case SETNAME: - retval = -EPERM; if (!capable(CAP_SYS_ADMIN)) - goto out; + return -EPERM; name = (char *) arg1; - len = strlen_user(name); - - retval = len; - if (len < 0) - goto out; - - retval = -EINVAL; - if (len == 0 || len > __NEW_UTS_LEN) - goto out; - /* Fiiiixmeeee... */ - copy_from_user(system_utsname.nodename, name, len); - system_utsname.nodename[len] = '\0'; - retval = 0; - goto out; + len = strncpy_from_user(nodename, name, sizeof(nodename)); + if (len < 0) + return -EFAULT; + + down_write(&uts_sem); + strncpy(system_utsname.nodename, name, len); + up_write(&uts_sem); + system_utsname.nodename[len] = '\0'; + return 0; + } - case MIPS_ATOMIC_SET: + case MIPS_ATOMIC_SET: { /* This is broken in case of page faults and SMP ... - Risc/OS fauls after maximum 20 tries with EAGAIN. */ + Risc/OS faults after maximum 20 tries with EAGAIN. */ + unsigned int tmp; + p = (int *) arg1; - retval = verify_area(VERIFY_WRITE, p, sizeof(*p)); - if (retval) - goto out; + errno = verify_area(VERIFY_WRITE, p, sizeof(*p)); + if (errno) + return errno; + errno = 0; save_and_cli(flags); - retval = *p; - *p = arg2; + errno |= __get_user(tmp, p); + errno |= __put_user(arg2, p); restore_flags(flags); - goto out; + + if (errno) + return tmp; + + return tmp; /* This is broken ... */ + } case MIPS_FIXADE: tmp = current->thread.mflags & ~3; @@ -112,7 +113,6 @@ } out: - unlock_kernel(); return retval; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c --- v2.4.0-test2/linux/arch/mips/kernel/time.c Thu Mar 2 14:36:22 2000 +++ linux/arch/mips/kernel/time.c Sun Jul 9 22:18:15 2000 @@ -1,7 +1,6 @@ -/* $Id: time.c,v 1.14 2000/01/26 00:07:44 ralf Exp $ - * - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - * Copyright (C) 1996, 1997, 1998 Ralf Baechle +/* + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * Copyright (C) 1996 - 2000 Ralf Baechle * * This file contains the time handling details for PC-style clocks as * found in some MIPS systems. @@ -15,6 +14,7 @@ #include #include #include +#include #include #include @@ -26,6 +26,8 @@ #include extern volatile unsigned long lost_ticks; +unsigned long r4k_interval = 0; +extern rwlock_t xtime_lock; /* * Change this if you have some constant time drift @@ -219,7 +221,7 @@ { unsigned long flags; - save_and_cli(flags); + read_lock_irqsave (&xtime_lock, flags); *tv = xtime; tv->tv_usec += do_gettimeoffset(); @@ -230,7 +232,7 @@ if (lost_ticks) tv->tv_usec += USECS_PER_JIFFY; - restore_flags(flags); + read_unlock_irqrestore (&xtime_lock, flags); if (tv->tv_usec >= 1000000) { tv->tv_usec -= 1000000; @@ -240,7 +242,7 @@ void do_settimeofday(struct timeval *tv) { - cli(); + write_lock_irq (&xtime_lock); /* This is revolting. We need to set the xtime.tv_usec * correctly. However, the value in this location is * is value at the last tick. @@ -259,7 +261,7 @@ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; - sti(); + write_unlock_irq (&xtime_lock); } /* @@ -355,7 +357,6 @@ dist = period / 4; } #endif -#ifdef CONFIG_PROFILE if(!user_mode(regs)) { if (prof_buffer && current->pid) { extern int _stext; @@ -373,7 +374,6 @@ atomic_inc((atomic_t *)&prof_buffer[pc]); } } -#endif do_timer(regs); /* @@ -381,22 +381,26 @@ * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be * called as close as possible to 500 ms before the new second starts. */ + read_lock (&xtime_lock); if ((time_status & STA_UNSYNC) == 0 && xtime.tv_sec > last_rtc_update + 660 && xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 && - xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) + xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) { if (set_rtc_mmss(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; else last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + } /* As we return to user mode fire off the other CPU schedulers.. this is basically because we don't yet share IRQ's around. This message is rigged to be safe on the 386 - basically it's a hack, so don't look closely for now.. */ /*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */ + read_unlock (&xtime_lock); } -static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) +static inline void +r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) { unsigned int count; @@ -408,6 +412,18 @@ timerhi += (count < timerlo); /* Wrap around */ timerlo = count; +#ifdef CONFIG_SGI_IP22 + /* Since we don't get anything but r4k timer interrupts, we need to + * set this up so that we'll get one next time. Fortunately since we + * have timerhi/timerlo, we don't care so much if we miss one. So + * we need only ask for the next in r4k_interval counts. On other + * archs we have a real timer, so we don't want this. + */ + write_32bit_cp0_register (CP0_COMPARE, + (unsigned long) (count + r4k_interval)); + kstat.irqs[0][irq]++; +#endif + timer_interrupt(irq, dev_id, regs); if (!jiffies) @@ -421,6 +437,12 @@ } } +void indy_r4k_timer_interrupt (struct pt_regs *regs) +{ + static const int INDY_R4K_TIMER_IRQ = 7; + r4k_timer_interrupt (INDY_R4K_TIMER_IRQ, NULL, regs); +} + /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. @@ -500,7 +522,7 @@ void __init time_init(void) { - unsigned int epoch, year, mon, day, hour, min, sec; + unsigned int epoch = 0, year, mon, day, hour, min, sec; int i; /* The Linux interpretation of the CMOS clock register contents: @@ -543,8 +565,10 @@ } year += epoch; + write_lock_irq (&xtime_lock); xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_usec = 0; + write_unlock_irq (&xtime_lock); init_cycle_counter(); diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c --- v2.4.0-test2/linux/arch/mips/kernel/traps.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/traps.c Sun Jul 9 22:18:15 2000 @@ -1,5 +1,4 @@ -/* $Id: traps.c,v 1.28 2000/03/13 10:33:02 raiko Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -209,7 +208,7 @@ printk(" in %s, line %ld", where, line); printk(":\n"); show_regs(regs); - printk("Process %s (pid: %ld, stackpage=%08lx)\n", + printk("Process %s (pid: %d, stackpage=%08lx)\n", current->comm, current->pid, (unsigned long) current); show_stack((unsigned int *) regs->regs[29]); show_trace((unsigned int *) regs->regs[29]); @@ -230,7 +229,7 @@ extern const struct exception_table_entry __start___dbe_table[]; extern const struct exception_table_entry __stop___dbe_table[]; -static void __declare_dbe_table(void) +void __declare_dbe_table(void) { __asm__ __volatile__( ".section\t__dbe_table,\"a\"\n\t" @@ -332,7 +331,6 @@ return; } #endif - lock_kernel(); if (fcr31 & 0x20000) { /* Retry instruction with flush to zero ... */ if (!(fcr31 & (1<<24))) { @@ -344,7 +342,7 @@ "ctc1\t%0,$31" : /* No outputs */ : "r" (fcr31)); - goto out; + return; } pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0); if (get_user(insn, (unsigned int *)pc)) { @@ -358,12 +356,9 @@ } if (compute_return_epc(regs)) - goto out; + return; //force_sig(SIGFPE, current); printk(KERN_DEBUG "Should send SIGFPE to %s\n", current->comm); - -out: - unlock_kernel(); } static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode) @@ -430,17 +425,15 @@ { unsigned int opcode; - lock_kernel(); if (!get_insn_opcode(regs, &opcode)) { if ((opcode & OPCODE) == LL) simulate_ll(regs, opcode); if ((opcode & OPCODE) == SC) simulate_sc(regs, opcode); } else { - printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n", + printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n", current->comm, current->pid, regs->cp0_epc, regs->regs[31]); } - unlock_kernel(); if (compute_return_epc(regs)) return; force_sig(SIGILL, current); @@ -526,10 +519,8 @@ void do_ri(struct pt_regs *regs) { - lock_kernel(); - printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n", + printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n", current->comm, current->pid, regs->cp0_epc, regs->regs[31]); - unlock_kernel(); if (compute_return_epc(regs)) return; force_sig(SIGILL, current); diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile --- v2.4.0-test2/linux/arch/mips/lib/Makefile Tue May 23 15:31:33 2000 +++ linux/arch/mips/lib/Makefile Sun Jul 9 22:18:15 2000 @@ -9,15 +9,27 @@ $(CC) $(CFLAGS) -c $< -o $*.o L_TARGET = lib.a -L_OBJS = csum_partial.o csum_partial_copy.o floppy-std.o \ - floppy-no.o ide-std.o ide-no.o kbd-std.o kbd-no.o rtc-std.o \ - rtc-no.o memcpy.o memset.o strlen_user.o strncpy_user.o \ - strnlen_user.o watch.o + +L_OBJS = csum_partial.o csum_partial_copy.o \ + rtc-std.o rtc-no.o memcpy.o memset.o watch.o\ + strlen_user.o strncpy_user.o strnlen_user.o ifdef CONFIG_CPU_R3000 L_OBJS += r3k_dump_tlb.o else L_OBJS += dump_tlb.o +endif + +ifdef CONFIG_BLK_DEV_FD + L_OBJS += floppy-no.o floppy-std.o +endif + +ifdef CONFIG_IDE + L_OBJS += ide-std.o ide-no.o +endif + +ifdef CONFIG_PC_KEYB + L_OBJS += kbd-std.o kbd-no.o endif include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/lib/r3k_dump_tlb.c linux/arch/mips/lib/r3k_dump_tlb.c --- v2.4.0-test2/linux/arch/mips/lib/r3k_dump_tlb.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/lib/r3k_dump_tlb.c Sun Jul 9 22:18:15 2000 @@ -47,7 +47,7 @@ printk("Index: %2d ", i); printk("va=%08lx asid=%08lx" - " [pa=%06lx n=%d d=%d v=%d g=%ld]", + " [pa=%06lx n=%d d=%d v=%d g=%d]", (entryhi & 0xffffe000), entryhi & 0xfc0, entrylo0 & PAGE_MASK, diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/mm/fault.c linux/arch/mips/mm/fault.c --- v2.4.0-test2/linux/arch/mips/mm/fault.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/mm/fault.c Sun Jul 9 22:18:15 2000 @@ -1,10 +1,9 @@ -/* $Id: fault.c,v 1.15 2000/02/04 07:40:23 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle + * Copyright (C) 1995 - 2000 by Ralf Baechle */ #include #include @@ -47,9 +46,10 @@ struct vm_area_struct * vma; struct task_struct *tsk = current; struct mm_struct *mm = tsk->mm; - int si_code = SEGV_MAPERR; unsigned long fixup; + siginfo_t info; + info.si_code = SEGV_MAPERR; /* * If we're in an interrupt or have no user * context, we must not take the fault.. @@ -75,7 +75,7 @@ * we can handle it.. */ good_area: - si_code = SEGV_ACCERR; + info.si_code = SEGV_ACCERR; if (write) { if (!(vma->vm_flags & VM_WRITE)) @@ -114,7 +114,6 @@ up(&mm->mmap_sem); if (user_mode(regs)) { - struct siginfo si; tsk->thread.cp0_badvaddr = address; tsk->thread.error_code = write; #if 0 @@ -126,10 +125,11 @@ (unsigned long) regs->cp0_epc, (unsigned long) regs->regs[31]); #endif - si.si_signo = SIGSEGV; - si.si_code = si_code; - si.si_addr = (void *) address; - force_sig_info(SIGSEGV, &si, tsk); + info.si_signo = SIGSEGV; + info.si_errno = 0; + /* info.si_code has been set above */ + info.si_addr = (void *) address; + force_sig_info(SIGSEGV, &info, tsk); return; } @@ -177,7 +177,11 @@ * or user mode. */ tsk->thread.cp0_badvaddr = address; - force_sig(SIGBUS, tsk); + info.si_code = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void *) address; + force_sig_info(SIGBUS, &info, tsk); /* Kernel mode? Handle exceptions or die */ if (!user_mode(regs)) diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/mm/init.c linux/arch/mips/mm/init.c --- v2.4.0-test2/linux/arch/mips/mm/init.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/mm/init.c Sun Jul 9 22:18:15 2000 @@ -256,12 +256,16 @@ max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; low = max_low_pfn; +#if defined(CONFIG_PCI) || defined(CONFIG_ISA) if (low < max_dma) zones_size[ZONE_DMA] = low; else { zones_size[ZONE_DMA] = max_dma; zones_size[ZONE_NORMAL] = low - max_dma; } +#else + zones_size[ZONE_DMA] = low; +#endif free_area_init(zones_size); } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/mm/r2300.c linux/arch/mips/mm/r2300.c --- v2.4.0-test2/linux/arch/mips/mm/r2300.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/mm/r2300.c Sun Jul 9 22:18:15 2000 @@ -151,15 +151,15 @@ static void __init probe_dcache(void) { - dcache_size = r3k_cache_size(ST0_DE); + dcache_size = r3k_cache_size(ST0_ISC); printk("Primary data cache %dkb, linesize 4 bytes\n", dcache_size >> 10); } static void __init probe_icache(void) { - icache_size = r3k_cache_size(ST0_DE|ST0_CE); - printk("Primary instruction cache %dkb, linesize 8 bytes\n", + icache_size = r3k_cache_size(ST0_ISC|ST0_SWC); + printk("Primary instruction cache %dkb, linesize 4 bytes\n", icache_size >> 10); } @@ -174,43 +174,43 @@ save_and_cli(flags); /* isolate cache space */ - write_32bit_cp0_register(CP0_STATUS, (ST0_DE|ST0_CE|flags)&~ST0_IEC); + write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|ST0_SWC|flags)&~ST0_IEC); - for (i = 0; i < size; i += 0x100) { + for (i = 0; i < size; i += 0x080) { asm ( "sb\t$0,0x000(%0)\n\t" + "sb\t$0,0x004(%0)\n\t" "sb\t$0,0x008(%0)\n\t" + "sb\t$0,0x00c(%0)\n\t" "sb\t$0,0x010(%0)\n\t" + "sb\t$0,0x014(%0)\n\t" "sb\t$0,0x018(%0)\n\t" - "sb\t$0,0x020(%0)\n\t" + "sb\t$0,0x01c(%0)\n\t" + "sb\t$0,0x020(%0)\n\t" + "sb\t$0,0x024(%0)\n\t" "sb\t$0,0x028(%0)\n\t" + "sb\t$0,0x02c(%0)\n\t" "sb\t$0,0x030(%0)\n\t" + "sb\t$0,0x034(%0)\n\t" "sb\t$0,0x038(%0)\n\t" - "sb\t$0,0x040(%0)\n\t" + "sb\t$0,0x03c(%0)\n\t" + "sb\t$0,0x040(%0)\n\t" + "sb\t$0,0x044(%0)\n\t" "sb\t$0,0x048(%0)\n\t" + "sb\t$0,0x04c(%0)\n\t" "sb\t$0,0x050(%0)\n\t" + "sb\t$0,0x054(%0)\n\t" "sb\t$0,0x058(%0)\n\t" - "sb\t$0,0x060(%0)\n\t" + "sb\t$0,0x05c(%0)\n\t" + "sb\t$0,0x060(%0)\n\t" + "sb\t$0,0x064(%0)\n\t" "sb\t$0,0x068(%0)\n\t" + "sb\t$0,0x06c(%0)\n\t" "sb\t$0,0x070(%0)\n\t" + "sb\t$0,0x074(%0)\n\t" "sb\t$0,0x078(%0)\n\t" - "sb\t$0,0x080(%0)\n\t" - "sb\t$0,0x088(%0)\n\t" - "sb\t$0,0x090(%0)\n\t" - "sb\t$0,0x098(%0)\n\t" - "sb\t$0,0x0a0(%0)\n\t" - "sb\t$0,0x0a8(%0)\n\t" - "sb\t$0,0x0b0(%0)\n\t" - "sb\t$0,0x0b8(%0)\n\t" - "sb\t$0,0x0c0(%0)\n\t" - "sb\t$0,0x0c8(%0)\n\t" - "sb\t$0,0x0d0(%0)\n\t" - "sb\t$0,0x0d8(%0)\n\t" - "sb\t$0,0x0e0(%0)\n\t" - "sb\t$0,0x0e8(%0)\n\t" - "sb\t$0,0x0f0(%0)\n\t" - "sb\t$0,0x0f8(%0)\n\t" + "sb\t$0,0x07c(%0)\n\t" : : "r" (p) ); - p += 0x100; + p += 0x080; } restore_flags(flags); @@ -221,13 +221,13 @@ unsigned long i, flags; volatile unsigned char *p = (char *)start; - if (size > icache_size) - size = icache_size; + if (size > dcache_size) + size = dcache_size; save_and_cli(flags); /* isolate cache space */ - write_32bit_cp0_register(CP0_STATUS, (ST0_DE|flags)&~ST0_IEC); + write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|flags)&~ST0_IEC); for (i = 0; i < size; i += 0x080) { asm ( "sb\t$0,0x000(%0)\n\t" @@ -376,7 +376,7 @@ save_and_cli(flags); - write_32bit_cp0_register(CP0_STATUS, (ST0_DE|ST0_CE|flags)&~ST0_IEC); + write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|ST0_SWC|flags)&~ST0_IEC); asm ( "sb\t$0,0x000(%0)\n\t" "sb\t$0,0x008(%0)\n\t" diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/mm/umap.c linux/arch/mips/mm/umap.c --- v2.4.0-test2/linux/arch/mips/mm/umap.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/mm/umap.c Sun Jul 9 22:18:15 2000 @@ -108,7 +108,8 @@ void *vmalloc_uncached (unsigned long size) { - return vmalloc_prot (size, PAGE_KERNEL_UNCACHED); + return __vmalloc (size, GFP_KERNEL | __GFP_HIGHMEM, + PAGE_KERNEL_UNCACHED); } static inline void free_pte(pte_t page) diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/sgi/kernel/Makefile linux/arch/mips/sgi/kernel/Makefile --- v2.4.0-test2/linux/arch/mips/sgi/kernel/Makefile Tue May 23 15:31:33 2000 +++ linux/arch/mips/sgi/kernel/Makefile Sun Jul 9 22:18:15 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.7 1999/05/07 18:00:16 ulfc Exp $ +# # Makefile for the SGI specific kernel interface routines # under Linux. # @@ -14,7 +14,7 @@ $(CC) $(CFLAGS) -c $< -o $*.o OBJS = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o \ - system.o indy_timer.o indyIRQ.o reset.o setup.o time.o + system.o indyIRQ.o reset.o setup.o time.o ifdef CONFIG_SGI_PROM_CONSOLE OBJS += promcon.o endif diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/sgi/kernel/indyIRQ.S linux/arch/mips/sgi/kernel/indyIRQ.S --- v2.4.0-test2/linux/arch/mips/sgi/kernel/indyIRQ.S Tue May 23 15:31:33 2000 +++ linux/arch/mips/sgi/kernel/indyIRQ.S Sun Jul 9 22:18:15 2000 @@ -1,4 +1,4 @@ -/* $Id: indyIRQ.S,v 1.3 1998/03/22 23:27:17 ralf Exp $ +/* * indyIRQ.S: Interrupt exception dispatch code for FullHouse and * Guiness. * @@ -67,7 +67,7 @@ /* Wheee, a timer interrupt. */ move a0, sp - jal indy_timer_interrupt + jal indy_r4k_timer_interrupt nop # delay slot j ret_from_irq diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/sgi/kernel/setup.c linux/arch/mips/sgi/kernel/setup.c --- v2.4.0-test2/linux/arch/mips/sgi/kernel/setup.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/sgi/kernel/setup.c Sun Jul 9 22:18:15 2000 @@ -1,5 +1,4 @@ -/* $Id: setup.c,v 1.29 2000/01/27 01:05:23 ralf Exp $ - * +/* * setup.c: SGI specific setup, including init of the feature struct. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -37,6 +36,8 @@ extern void console_setup(char *); #endif +extern unsigned long r4k_interval; /* Cycle counter ticks per 1/HZ seconds */ + extern struct rtc_ops indy_rtc_ops; void indy_reboot_setup(void); void sgi_volume_set(unsigned char); @@ -136,6 +137,98 @@ return 0; } +void (*board_time_init)(struct irqaction *irq); + +static unsigned long dosample(volatile unsigned char *tcwp, + volatile unsigned char *tc2p) +{ + unsigned long ct0, ct1; + unsigned char msb, lsb; + + /* Start the counter. */ + *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MRGEN); + *tc2p = (SGINT_TCSAMP_COUNTER & 0xff); + *tc2p = (SGINT_TCSAMP_COUNTER >> 8); + + /* Get initial counter invariant */ + ct0 = read_32bit_cp0_register(CP0_COUNT); + + /* Latch and spin until top byte of counter2 is zero */ + do { + *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT); + lsb = *tc2p; + msb = *tc2p; + ct1 = read_32bit_cp0_register(CP0_COUNT); + } while(msb); + + /* Stop the counter. */ + *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MSWST); + + /* Return the difference, this is how far the r4k counter increments + * for every 1/HZ seconds. We round off the the nearest 1 MHz of + * master clock (= 1000000 / 100 / 2 = 5000 count). + */ + return ((ct1 - ct0) / 5000) * 5000; +} + +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) + +void sgi_time_init (struct irqaction *irq) { + /* Here we need to calibrate the cycle counter to at least be close. + * We don't need to actually register the irq handler because that's + * all done in indyIRQ.S. + */ + struct sgi_ioc_timers *p; + volatile unsigned char *tcwp, *tc2p; + unsigned long r4k_ticks[3]; + unsigned long r4k_next; + + /* Figure out the r4k offset, the algorithm is very simple + * and works in _all_ cases as long as the 8254 counter + * register itself works ok (as an interrupt driving timer + * it does not because of bug, this is why we are using + * the onchip r4k counter/compare register to serve this + * purpose, but for r4k_offset calculation it will work + * ok for us). There are other very complicated ways + * of performing this calculation but this one works just + * fine so I am not going to futz around. ;-) + */ + p = ioc_timers; + tcwp = &p->tcword; + tc2p = &p->tcnt2; + + printk("Calibrating system timer... "); + dosample(tcwp, tc2p); /* First sample. */ + dosample(tcwp, tc2p); /* Eat one. */ + r4k_ticks[0] = dosample(tcwp, tc2p); /* Second sample. */ + dosample(tcwp, tc2p); /* Eat another. */ + r4k_ticks[1] += dosample (tcwp, tc2p); /* Third sample. */ + + if (r4k_ticks[0] != r4k_ticks[1]) { + printk ("warning: timer counts differ, retrying..."); + dosample (tcwp, tc2p); + r4k_ticks[2] = dosample (tcwp, tc2p); + if (r4k_ticks[2] == r4k_ticks[0] + || r4k_ticks[2] == r4k_ticks[1]) + r4k_interval = r4k_ticks[2]; + else { + printk ("disagreement, using average..."); + r4k_interval = (r4k_ticks[0] + r4k_ticks[1] + + r4k_ticks[2]) / 3; + } + } else + r4k_interval = r4k_ticks[0]; + + printk("%d [%d.%02d MHz CPU]\n", (int) r4k_interval, + (int) (r4k_interval / 5000), (int) (r4k_interval % 5000) / 50); + + /* Set ourselves up for future interrupts */ + r4k_next = (read_32bit_cp0_register(CP0_COUNT) + r4k_interval); + write_32bit_cp0_register(CP0_COMPARE, r4k_next); + set_cp0_status(ST0_IM, ALLINTS); + sti (); +} + void __init sgi_setup(void) { #ifdef CONFIG_SERIAL_CONSOLE @@ -147,6 +240,7 @@ irq_setup = sgi_irq_setup; + board_time_init = sgi_time_init; /* Init the INDY HPC I/O controller. Need to call this before * fucking with the memory controller because it needs to know the @@ -229,5 +323,5 @@ #ifdef CONFIG_VIDEO_VINO init_vino(); #endif + } -__initcall(rs_init); diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/sgi/kernel/time.c linux/arch/mips/sgi/kernel/time.c --- v2.4.0-test2/linux/arch/mips/sgi/kernel/time.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/sgi/kernel/time.c Sun Jul 9 22:18:15 2000 @@ -1,15 +1,21 @@ -/* $Id: time.c,v 1.2 1998/04/05 11:24:00 ralf Exp $ - * time.c: Generic SGI time_init() code, this will dispatch to the - * appropriate per-architecture time/counter init code. +/* + * time.c: Generic SGI handler for (spurious) 8254 interrupts * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) */ -#include +#include +#include +#include -extern void indy_timer_init(void); - -void __init time_init(void) +void indy_8254timer_irq(void) { - /* XXX assume INDY for now XXX */ - indy_timer_init(); + int cpu = smp_processor_id(); + int irq = 4; + + irq_enter(cpu); + kstat.irqs[0][irq]++; + printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n"); + prom_getchar(); + prom_imode(); + irq_exit(cpu); } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/sni/pci.c linux/arch/mips/sni/pci.c --- v2.4.0-test2/linux/arch/mips/sni/pci.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/sni/pci.c Sun Jul 9 22:18:15 2000 @@ -1,15 +1,15 @@ -/* $Id: pci.c,v 1.9 1999/12/04 03:59:00 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * SNI specific PCI support for RM200/RM300. * - * Copyright (C) 1997, 1998, 1999 Ralf Baechle + * Copyright (C) 1997 - 2000 Ralf Baechle */ #include #include +#include #include #include #include @@ -23,10 +23,11 @@ return -1; \ *(volatile u32 *)PCIMT_CONFIG_ADDRESS = \ ((dev->bus->number & 0xff) << 0x10) | \ - ((dev->dev_fn & 0xff) << 0x08) | \ + ((dev->devfn & 0xff) << 0x08) | \ (where & 0xfc); \ } while(0); +#if 0 /* To do: Bring this uptodate ... */ static void pcimt_pcibios_fixup (void) { @@ -62,6 +63,7 @@ } } } +#endif /* * We can't address 8 and 16 bit words directly. Instead we have to @@ -148,6 +150,69 @@ pcimt_write_config_byte, pcimt_write_config_word, pcimt_write_config_dword +}; + +void __init +pcibios_fixup_bus(struct pci_bus *b) +{ +} + +void +pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + u32 new, check; + int reg; + + new = res->start | (res->flags & PCI_REGION_FLAG_MASK); + if (resource < 6) { + reg = PCI_BASE_ADDRESS_0 + 4*resource; + } else if (resource == PCI_ROM_RESOURCE) { + res->flags |= PCI_ROM_ADDRESS_ENABLE; + new |= PCI_ROM_ADDRESS_ENABLE; + reg = dev->rom_base_reg; + } else { + /* Somebody might have asked allocation of a non-standard resource */ + return; + } + + pci_write_config_dword(dev, reg, new); + pci_read_config_dword(dev, reg, &check); + if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { + printk(KERN_ERR "PCI: Error while updating region " + "%s/%d (%08x != %08x)\n", dev->slot_name, resource, + new, check); + } +} + +void __init pcibios_init(void) +{ + struct pci_ops *ops = &sni_pci_ops; + + pci_scan_bus(0, ops, NULL); +} + +int __init pcibios_enable_device(struct pci_dev *dev) +{ + /* Not needed, since we enable all devices at startup. */ + return 0; +} + +void __init +pcibios_align_resource(void *data, struct resource *res, unsigned long size) +{ +} + +char * __init +pcibios_setup(char *str) +{ + /* Nothing to do for now. */ + + return str; +} + +struct pci_fixup pcibios_fixups[] = { + { 0 } }; #endif /* CONFIG_PCI */ diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/sni/setup.c linux/arch/mips/sni/setup.c --- v2.4.0-test2/linux/arch/mips/sni/setup.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/sni/setup.c Sun Jul 9 22:18:15 2000 @@ -1,12 +1,11 @@ -/* $Id: setup.c,v 1.13 1999/12/04 03:59:00 ralf Exp $ - * +/* * Setup pointers to hardware-dependent routines. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 1997, 1998 by Ralf Baechle + * Copyright (C) 1996, 1997, 1998, 2000 by Ralf Baechle */ #include #include @@ -21,11 +20,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -78,7 +77,6 @@ } unsigned char aux_device_present; -extern struct pci_ops sni_pci_ops; extern unsigned char sni_map_isa_cache; /* @@ -110,6 +108,7 @@ void __init sni_rm200_pci_setup(void) { +#if 0 /* XXX Tag me deeper */ tag *atag; /* @@ -135,6 +134,7 @@ ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->lines; } } +#endif sni_pcimt_detect(); sni_pcimt_sc_init(); @@ -168,7 +168,6 @@ * the I/O port space ... */ request_region(0xcfc,0x04,"PCI config data"); - pci_ops = &sni_pci_ops; #ifdef CONFIG_BLK_DEV_IDE ide_ops = &std_ide_ops; diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips/tools/Makefile linux/arch/mips/tools/Makefile --- v2.4.0-test2/linux/arch/mips/tools/Makefile Tue May 23 15:31:33 2000 +++ linux/arch/mips/tools/Makefile Sun Jul 9 22:18:15 2000 @@ -12,17 +12,19 @@ .S.o: $(CC) $(CFLAGS) -c $< -o $*.o -all: $(TARGET) - $(TARGET): offset.h cmp -s $^ $@ || (cp $^ $(TARGET).new && mv $(TARGET).new $(TARGET)) offset.h: offset.s sed -n '/^@@@/s///p' $^ >$@ -offset.s: offset.c +offset.s: offset.c $(TOPDIR)/include/linux/autoconf.h clean: rm -f offset.[hs] $(TARGET).new + +mrproper: + rm -f offset.[hs] $(TARGET).new + rm -f $(TARGET) include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/Makefile linux/arch/mips64/Makefile --- v2.4.0-test2/linux/arch/mips64/Makefile Tue May 23 15:31:33 2000 +++ linux/arch/mips64/Makefile Sun Jul 9 22:18:15 2000 @@ -86,8 +86,12 @@ # must be 16kb aligned or the handling of the current variable will break. # #LOADADDR += 0xa80000000001c000 +ifdef CONFIG_MAPPED_KERNEL +LOADADDR += 0xc001c000 +else LOADADDR += 0x8001c000 endif +endif # # Some machines like the Indy need 32-bit ELF binaries for booting purposes. @@ -126,8 +130,13 @@ 64bit-bfd = elf64-bigmips endif +ifdef CONFIG_MAPPED_KERNEL +vmlinux.64: vmlinux + $(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xbfffffff40000000 $< $@ +else vmlinux.64: vmlinux $(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xa7ffffff80000000 $< $@ +endif zImage: vmlinux @$(MAKEBOOT) zImage @@ -144,6 +153,11 @@ rm -f vmlinux.64 archmrproper: + @$(MAKEBOOT) mrproper + $(MAKE) -C arch/$(ARCH)/tools mrproper archdep: + if [ ! -f $(TOPDIR)/include/asm-$(ARCH)/offset.h ]; then \ + touch $(TOPDIR)/include/asm-$(ARCH)/offset.h; \ + fi; @$(MAKEBOOT) dep diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/arc/identify.c linux/arch/mips64/arc/identify.c --- v2.4.0-test2/linux/arch/mips64/arc/identify.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/arc/identify.c Sun Jul 9 22:18:15 2000 @@ -1,5 +1,4 @@ -/* $Id: identify.c,v 1.5 1999/11/19 20:35:21 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -39,7 +38,7 @@ int prom_flags; static struct smatch * __init -string_to_mach(char *s) +string_to_mach(const char *s) { int i; diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/arc/memory.c linux/arch/mips64/arc/memory.c --- v2.4.0-test2/linux/arch/mips64/arc/memory.c Thu Mar 2 14:36:22 2000 +++ linux/arch/mips64/arc/memory.c Sun Jul 9 22:18:15 2000 @@ -28,8 +28,6 @@ #undef DEBUG -extern char _end; - struct linux_mdesc * __init ArcGetMemoryDescriptor(struct linux_mdesc *Current) { diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/boot/Makefile linux/arch/mips64/boot/Makefile --- v2.4.0-test2/linux/arch/mips64/boot/Makefile Tue May 23 15:31:33 2000 +++ linux/arch/mips64/boot/Makefile Sun Jul 9 22:18:16 2000 @@ -38,6 +38,9 @@ clean: rm -f vmlinux.ecoff +mrproper: + rm -f vmlinux.ecoff addinitrd elf2ecoff + dummy: include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/config.in linux/arch/mips64/config.in --- v2.4.0-test2/linux/arch/mips64/config.in Fri Jun 23 21:55:07 2000 +++ linux/arch/mips64/config.in Sun Jul 9 22:18:16 2000 @@ -17,6 +17,10 @@ if [ "$CONFIG_SGI_IP27" = "y" ]; then bool ' IP27 N-Mode' CONFIG_SGI_SN0_N_MODE bool ' Discontiguous Memory Support' CONFIG_DISCONTIGMEM + bool ' NUMA support' CONFIG_NUMA + bool ' Mapped kernel support' CONFIG_MAPPED_KERNEL + bool ' Kernel text replication support' CONFIG_REPLICATE_KTEXT + bool ' Exception handler replication support' CONFIG_REPLICATE_EXHANDLERS bool ' Multi-Processing support (Experimental)' CONFIG_SMP #bool ' IP27 XXL' CONFIG_SGI_SN0_XXL fi @@ -40,6 +44,7 @@ define_bool CONFIG_ARC32 y define_bool CONFIG_BOARD_SCACHE y define_bool CONFIG_ARC_MEMORY y + define_bool CONFIG_SGI y fi if [ "$CONFIG_SGI_IP27" = "y" ]; then @@ -119,6 +124,8 @@ fi endmenu + +source drivers/mtd/Config.in source drivers/block/Config.in diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/defconfig linux/arch/mips64/defconfig --- v2.4.0-test2/linux/arch/mips64/defconfig Tue May 23 15:31:33 2000 +++ linux/arch/mips64/defconfig Sun Jul 9 22:18:16 2000 @@ -14,6 +14,10 @@ CONFIG_SGI_IP27=y # CONFIG_SGI_SN0_N_MODE is not set # CONFIG_DISCONTIGMEM is not set +# CONFIG_NUMA is not set +# CONFIG_MAPPED_KERNEL is not set +# CONFIG_REPLICATE_KTEXT is not set +# CONFIG_REPLICATE_EXHANDLERS is not set # CONFIG_SMP is not set CONFIG_BOOT_ELF64=y CONFIG_ARC64=y @@ -53,12 +57,15 @@ # # Loadable module support # -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y +# CONFIG_MODULES is not set CONFIG_PCI_NAMES=y # +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set @@ -66,16 +73,14 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set @@ -110,6 +115,7 @@ # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set # # Telephony Support @@ -308,6 +314,7 @@ # Watchdog Cards # # CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set @@ -342,6 +349,7 @@ # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set # CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set @@ -420,6 +428,5 @@ # Kernel hacking # CONFIG_CROSSCOMPILE=y -# CONFIG_MIPS_FPE_MODULE is not set # CONFIG_REMOTE_DEBUG is not set # CONFIG_MAGIC_SYSRQ is not set diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/defconfig-ip22 linux/arch/mips64/defconfig-ip22 --- v2.4.0-test2/linux/arch/mips64/defconfig-ip22 Tue May 23 15:31:33 2000 +++ linux/arch/mips64/defconfig-ip22 Sun Jul 9 22:18:16 2000 @@ -16,6 +16,7 @@ CONFIG_ARC32=y CONFIG_BOARD_SCACHE=y CONFIG_ARC_MEMORY=y +CONFIG_SGI=y # CONFIG_ISA is not set # CONFIG_PCI is not set # CONFIG_SBUS is not set @@ -50,6 +51,11 @@ # CONFIG_MODULES is not set # +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set @@ -57,16 +63,14 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set @@ -101,6 +105,7 @@ # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set # # Telephony Support @@ -228,6 +233,7 @@ # Watchdog Cards # # CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set @@ -262,6 +268,7 @@ # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set # CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/defconfig-ip27 linux/arch/mips64/defconfig-ip27 --- v2.4.0-test2/linux/arch/mips64/defconfig-ip27 Tue May 23 15:31:33 2000 +++ linux/arch/mips64/defconfig-ip27 Sun Jul 9 22:18:16 2000 @@ -14,6 +14,10 @@ CONFIG_SGI_IP27=y # CONFIG_SGI_SN0_N_MODE is not set # CONFIG_DISCONTIGMEM is not set +# CONFIG_NUMA is not set +# CONFIG_MAPPED_KERNEL is not set +# CONFIG_REPLICATE_KTEXT is not set +# CONFIG_REPLICATE_EXHANDLERS is not set # CONFIG_SMP is not set CONFIG_BOOT_ELF64=y CONFIG_ARC64=y @@ -53,12 +57,15 @@ # # Loadable module support # -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y +# CONFIG_MODULES is not set CONFIG_PCI_NAMES=y # +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set @@ -66,16 +73,14 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set @@ -110,6 +115,7 @@ # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set # # Telephony Support @@ -308,6 +314,7 @@ # Watchdog Cards # # CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set @@ -342,6 +349,7 @@ # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set # CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set @@ -420,6 +428,5 @@ # Kernel hacking # CONFIG_CROSSCOMPILE=y -# CONFIG_MIPS_FPE_MODULE is not set # CONFIG_REMOTE_DEBUG is not set # CONFIG_MAGIC_SYSRQ is not set diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/Makefile linux/arch/mips64/kernel/Makefile --- v2.4.0-test2/linux/arch/mips64/kernel/Makefile Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/Makefile Sun Jul 9 22:18:16 2000 @@ -7,14 +7,15 @@ # .S.o: - $(CC) $(CFLAGS) -c $< -o $*.o + $(CC) $(CFLAGS) $(CFLAGS_$@) -c $< -o $*.o all: kernel.o head.o init_task.o O_TARGET := kernel.o O_OBJS := branch.o entry.o proc.o process.o ptrace.o r4k_cache.o r4k_fpu.o \ - r4k_genex.o r4k_switch.o r4k_tlb_debug.o r4k_tlb_glue.o scall_64.o \ - semaphore.o setup.o signal.o softfp.o syscall.o traps.o unaligned.o + r4k_genex.o r4k_switch.o r4k_tlb.o r4k_tlb_debug.o r4k_tlb_glue.o \ + scall_64.o semaphore.o setup.o signal.o softfp.o syscall.o \ + traps.o unaligned.o OX_OBJS := mips64_ksyms.o ifdef CONFIG_MIPS32_COMPAT @@ -28,6 +29,9 @@ ifdef CONFIG_SMP O_OBJS += smp.o endif + +CFLAGS_r4k_genex.o := -P +CFLAGS_r4k_tlb_glue.o := -P clean: diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/head.S linux/arch/mips64/kernel/head.S --- v2.4.0-test2/linux/arch/mips64/kernel/head.S Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/head.S Sun Jul 9 22:18:16 2000 @@ -1,5 +1,4 @@ -/* $Id: head.S,v 1.6 2000/03/27 21:05:04 ulfc Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -19,15 +18,69 @@ #include #include #include +#include +#include +#include +#include + + .macro ARC64_TWIDDLE_PC +#if defined(CONFIG_ARC64) || defined(CONFIG_MAPPED_KERNEL) + /* We get launched at a XKPHYS address but the kernel is linked to + run at a KSEG0 address, so jump there. */ + la t0, \@f + jr t0 +\@: +#endif + .endm -#define ARC64_TWIDDLE_PC \ -#ifdef CONFIG_ARC64 \ - /* We get launched at a XKPHYS address but the kernel is linked to \ - run at a KSEG0 address, so jump there. */ \ - la t0, 1f \ - jr t0 \ -1: \ + /* + * outputs the local nasid into t1. + */ + .macro GET_NASID_ASM + dli t1, LOCAL_HUB_ADDR(NI_STATUS_REV_ID) + ld t1, (t1) + and t1, NSRI_NODEID_MASK + dsrl t1, NSRI_NODEID_SHFT + .endm + + /* + * inputs are the text nasid in t1, data nasid in t2. + */ + .macro MAPPED_KERNEL_SETUP_TLB +#ifdef CONFIG_MAPPED_KERNEL + /* + * This needs to read the nasid - assume 0 for now. + * Drop in 0xffffffffc0000000 in tlbhi, 0+VG in tlblo_0, + * 0+DVG in tlblo_1. + */ + dli t0, 0xffffffffc0000000 + dmtc0 t0, CP0_ENTRYHI + li t0, 0x1c000 # Offset of text into node memory + dsll t1, NASID_SHFT # Shift text nasid into place + dsll t2, NASID_SHFT # Same for data nasid + or t1, t1, t0 # Physical load address of kernel text + or t2, t2, t0 # Physical load address of kernel data + dsrl t1, 12 # 4K pfn + dsrl t2, 12 # 4K pfn + dsll t1, 6 # Get pfn into place + dsll t2, 6 # Get pfn into place + li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _CACHE_CACHABLE_COW) >> 6) + or t0, t0, t1 + mtc0 t0, CP0_ENTRYLO0 # physaddr, VG, cach exlwr + li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _PAGE_DIRTY|_CACHE_CACHABLE_COW) >> 6) + or t0, t0, t2 + mtc0 t0, CP0_ENTRYLO1 # physaddr, DVG, cach exlwr + li t0, 0x1ffe000 # MAPPED_KERN_TLBMASK, TLBPGMASK_16M + mtc0 t0, CP0_PAGEMASK + li t0, 0 # KMAP_INX + mtc0 t0, CP0_INDEX + li t0, 1 + mtc0 t0, CP0_WIRED + tlbwi +#else + mtc0 zero, CP0_WIRED #endif + .endm .text @@ -38,11 +91,15 @@ NESTED(kernel_entry, 16, sp) # kernel entry point - ARC64_TWIDDLE_PC - ori sp, 0xf # align stack on 16 byte. xori sp, 0xf + GET_NASID_ASM + move t2, t1 # text and data are here + MAPPED_KERNEL_SETUP_TLB + + ARC64_TWIDDLE_PC + /* Note that all firmware passed argument registers still have their values. */ jal prom_init # initialize firmware @@ -75,6 +132,14 @@ END(kernel_entry) NESTED(bootstrap, 16, sp) + GET_NASID_ASM + li t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + KLDIR_OFF_POINTER + K0BASE + dsll t1, NASID_SHFT + or t0, t0, t1 + ld t0, 0(t0) # t0 points to kern_vars struct + lh t1, KV_RO_NASID_OFFSET(t0) + lh t2, KV_RW_NASID_OFFSET(t0) + MAPPED_KERNEL_SETUP_TLB ARC64_TWIDDLE_PC CLI mfc0 t0, CP0_STATUS @@ -89,20 +154,25 @@ .comm kernelsp, 8, 8 # current stackpointer +#undef PAGE_SIZE #define PAGE_SIZE 0x1000 .macro page name, order=0 .globl \name - .org . + (PAGE_SIZE << \order) \name: .size \name, (PAGE_SIZE << \order) + .org . + (PAGE_SIZE << \order) .type \name, @object .endm - .align 12 .data + .align 12 page swapper_pg_dir, 1 - page invalid_pte_table, 1 + page invalid_pte_table, 0 page invalid_pmd_table, 1 - page empty_bad_page_table, 1 - page empty_bad_page + page empty_bad_page_table, 0 + page empty_bad_pmd_table, 1 + page kptbl, KPTBL_PAGE_ORDER + .globl ekptbl + page kpmdtbl, 0 +ekptbl: diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/ioctl32.c linux/arch/mips64/kernel/ioctl32.c --- v2.4.0-test2/linux/arch/mips64/kernel/ioctl32.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/ioctl32.c Sun Jul 9 22:18:16 2000 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.1 2000/04/05 00:43:25 ulfc Exp $ +/* * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 2000 Silicon Graphics, Inc. @@ -34,23 +34,6 @@ #define EXT2_IOC32_SETFLAGS _IOW('f', 2, int) #define EXT2_IOC32_GETVERSION _IOR('v', 1, int) #define EXT2_IOC32_SETVERSION _IOW('v', 2, int) - -static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct timeval32 *up = (struct timeval32 *)arg; - struct timeval ktv; - mm_segment_t old_fs = get_fs(); - int err; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&ktv); - set_fs(old_fs); - if(!err) { - err = put_user(ktv.tv_sec, &up->tv_sec); - err |= __put_user(ktv.tv_usec, &up->tv_usec); - } - return err; -} struct ifmap32 { unsigned int mem_start; diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/linux32.c linux/arch/mips64/kernel/linux32.c --- v2.4.0-test2/linux/arch/mips64/kernel/linux32.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/linux32.c Sun Jul 9 22:18:16 2000 @@ -1,5 +1,4 @@ -/* $Id: linux32.c,v 1.14 2000/03/23 00:30:53 ulfc Exp $ - * +/* * Conversion between 32-bit and 64-bit native system calls. * * Copyright (C) 2000 Silicon Graphics, Inc. @@ -18,6 +17,8 @@ #include #include #include +#include +#include #include #include @@ -25,79 +26,6 @@ #define A(__x) ((unsigned long)(__x)) -#if 1 -static inline int -putstat(struct stat32 *ubuf, struct stat *kbuf) -{ - int err; - - err = put_user (kbuf->st_dev, &ubuf->st_dev); - err |= __put_user (kbuf->st_ino, &ubuf->st_ino); - err |= __put_user (kbuf->st_mode, &ubuf->st_mode); - err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink); - err |= __put_user (kbuf->st_uid, &ubuf->st_uid); - err |= __put_user (kbuf->st_gid, &ubuf->st_gid); - err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev); - err |= __put_user (kbuf->st_size, &ubuf->st_size); - err |= __put_user (kbuf->st_atime, &ubuf->st_atime); - err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime); - err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime); - err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize); - err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks); - return err; -} - -extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf); - -asmlinkage int -sys32_newstat(char * filename, struct stat32 *statbuf) -{ - int ret; - struct stat s; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_newstat(filename, &s); - set_fs (old_fs); - if (putstat (statbuf, &s)) - return -EFAULT; - return ret; -} - -extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf); - -asmlinkage int -sys32_newlstat(char * filename, struct stat32 *statbuf) -{ - int ret; - struct stat s; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_newlstat(filename, &s); - set_fs (old_fs); - if (putstat (statbuf, &s)) - return -EFAULT; - return ret; -} - -extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf); - -asmlinkage int -sys32_newfstat(unsigned int fd, struct stat32 *statbuf) -{ - int ret; - struct stat s; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_newfstat(fd, &s); - set_fs (old_fs); - if (putstat (statbuf, &s)) - return -EFAULT; - return ret; -} -#else /* * Revalidate the inode. This is required for proper NFS attribute caching. */ @@ -105,8 +33,10 @@ do_revalidate(struct dentry *dentry) { struct inode * inode = dentry->d_inode; + if (inode->i_op && inode->i_op->revalidate) return inode->i_op->revalidate(dentry); + return 0; } @@ -127,21 +57,22 @@ tmp.st_atime = inode->i_atime; tmp.st_mtime = inode->i_mtime; tmp.st_ctime = inode->i_ctime; -/* - * st_blocks and st_blksize are approximated with a simple algorithm if - * they aren't supported directly by the filesystem. The minix and msdos - * filesystems don't keep track of blocks, so they would either have to - * be counted explicitly (by delving into the file itself), or by using - * this simple algorithm to get a reasonable (although not 100% accurate) - * value. - */ -/* - * Use minix fs values for the number of direct and indirect blocks. The - * count is now exact for the minix fs except that it counts zero blocks. - * Everything is in units of BLOCK_SIZE until the assignment to - * tmp.st_blksize. - */ + /* + * st_blocks and st_blksize are approximated with a simple algorithm if + * they aren't supported directly by the filesystem. The minix and msdos + * filesystems don't keep track of blocks, so they would either have to + * be counted explicitly (by delving into the file itself), or by using + * this simple algorithm to get a reasonable (although not 100% + * accurate) value. + */ + + /* + * Use minix fs values for the number of direct and indirect blocks. + * The count is now exact for the minix fs except that it counts zero + * blocks. Everything is in units of BLOCK_SIZE until the assignment + * to tmp.st_blksize. + */ #define D_B 7 #define I_B (BLOCK_SIZE / sizeof(unsigned short)) @@ -163,53 +94,49 @@ tmp.st_blocks = inode->i_blocks; tmp.st_blksize = inode->i_blksize; } + return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; } + asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf) { - struct dentry * dentry; + struct nameidata nd; int error; - lock_kernel(); - dentry = namei(filename); - - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = do_revalidate(dentry); + error = user_path_walk(filename, &nd); + if (!error) { + error = do_revalidate(nd.dentry); if (!error) - error = cp_new_stat32(dentry->d_inode, statbuf); + error = cp_new_stat32(nd.dentry->d_inode, statbuf); - dput(dentry); + path_release(&nd); } - unlock_kernel(); + return error; } -asmlinkage int sys32_newlstat(char *filename, struct stat32 * statbuf) + +asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf) { - struct dentry * dentry; + struct nameidata nd; int error; - lock_kernel(); - dentry = lnamei(filename); - - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = do_revalidate(dentry); + error = user_path_walk_link(filename, &nd); + if (!error) { + error = do_revalidate(nd.dentry); if (!error) - error = cp_new_stat32(dentry->d_inode, statbuf); + error = cp_new_stat32(nd.dentry->d_inode, statbuf); - dput(dentry); + path_release(&nd); } - unlock_kernel(); + return error; } -asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 * statbuf) +asmlinkage long sys32_newfstat(unsigned int fd, struct stat32 * statbuf) { struct file * f; int err = -EBADF; - lock_kernel(); f = fget(fd); if (f) { struct dentry * dentry = f->f_dentry; @@ -219,10 +146,10 @@ err = cp_new_stat32(dentry->d_inode, statbuf); fput(f); } - unlock_kernel(); + return err; } -#endif + asmlinkage int sys_mmap2(void) {return 0;} asmlinkage long sys_truncate(const char * path, unsigned long length); @@ -232,7 +159,7 @@ { if ((int)high < 0) return -EINVAL; - return sys_truncate(path, (high << 32) | low); + return sys_truncate(path, ((long) high << 32) | low); } asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); @@ -242,28 +169,7 @@ { if ((int)high < 0) return -EINVAL; - return sys_ftruncate(fd, (high << 32) | low); -} - -asmlinkage long sys_newstat(char * filename, struct stat * statbuf); - -asmlinkage int sys_stat64(char * filename, struct stat *statbuf) -{ - return sys_newstat(filename, statbuf); -} - -asmlinkage long sys_newlstat(char * filename, struct stat * statbuf); - -asmlinkage int sys_lstat64(char * filename, struct stat *statbuf) -{ - return sys_newlstat(filename, statbuf); -} - -asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf); - -asmlinkage int sys_fstat64(unsigned int fd, struct stat *statbuf) -{ - return sys_newfstat(fd, statbuf); + return sys_ftruncate(fd, ((long) high << 32) | low); } #if 0 @@ -304,7 +210,8 @@ int len; unsigned long pos; - if (get_user(str, argv+argc) || !str || !(len = strnlen_user((char *)A(str), bprm->p))) + if (get_user(str, argv+argc) || !str || + !(len = strnlen_user((char *)A(str), bprm->p))) return -EFAULT; if (bprm->p < len) return -E2BIG; @@ -338,9 +245,11 @@ if (bytes_to_copy > len) { bytes_to_copy = len; if (new) - memset(kaddr+offset+len, 0, PAGE_SIZE-offset-len); + memset(kaddr+offset+len, 0, + PAGE_SIZE-offset-len); } - err = copy_from_user(kaddr + offset, (char *)A(str), bytes_to_copy); + err = copy_from_user(kaddr + offset, (char *)A(str), + bytes_to_copy); flush_page_to_ram(page); kunmap(page); @@ -489,12 +398,8 @@ * `munmap' if the `execve' failes. */ down(¤t->mm->mmap_sem); - lock_kernel(); - av = (char **) do_mmap_pgoff(0, 0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0); - - unlock_kernel(); up(¤t->mm->mmap_sem); if (IS_ERR(av)) @@ -974,7 +879,7 @@ tot_len = 0; i = count; ivp = iov; - while(i > 0) { + while (i > 0) { u32 len; u32 buf; @@ -1042,6 +947,7 @@ } if (iov != iovstack) kfree(iov); + return retval; } @@ -1049,22 +955,19 @@ sys32_readv(int fd, struct iovec32 *vector, u32 count) { struct file *file; - long ret = -EBADF; + ssize_t ret; - lock_kernel(); + ret = -EBADF; file = fget(fd); - if(!file) + if (!file) goto bad_file; + if (file->f_op && (file->f_mode & FMODE_READ) && + (file->f_op->readv || file->f_op->read)) + ret = do_readv_writev32(VERIFY_WRITE, file, vector, count); - if(!(file->f_mode & 1)) - goto out; - - ret = do_readv_writev32(VERIFY_WRITE, file, - vector, count); -out: fput(file); + bad_file: - unlock_kernel(); return ret; } @@ -1072,22 +975,18 @@ sys32_writev(int fd, struct iovec32 *vector, u32 count) { struct file *file; - int ret = -EBADF; + ssize_t ret; - lock_kernel(); + ret = -EBADF; file = fget(fd); if(!file) goto bad_file; - - if(!(file->f_mode & 2)) - goto out; - - ret = do_readv_writev32(VERIFY_READ, file, - vector, count); -out: + if (file->f_op && (file->f_mode & FMODE_WRITE) && + (file->f_op->writev || file->f_op->write)) + ret = do_readv_writev32(VERIFY_READ, file, vector, count); fput(file); + bad_file: - unlock_kernel(); return ret; } @@ -1306,4 +1205,135 @@ return -EFAULT; } return ret; +} + +struct tms32 { + int tms_utime; + int tms_stime; + int tms_cutime; + int tms_cstime; +}; + +extern asmlinkage long sys_times(struct tms * tbuf); +asmlinkage long sys32_times(struct tms32 *tbuf) +{ + struct tms t; + long ret; + mm_segment_t old_fs = get_fs(); + int err; + + set_fs(KERNEL_DS); + ret = sys_times(tbuf ? &t : NULL); + set_fs(old_fs); + if (tbuf) { + err = put_user (t.tms_utime, &tbuf->tms_utime); + err |= __put_user (t.tms_stime, &tbuf->tms_stime); + err |= __put_user (t.tms_cutime, &tbuf->tms_cutime); + err |= __put_user (t.tms_cstime, &tbuf->tms_cstime); + if (err) + ret = -EFAULT; + } + return ret; +} + +extern asmlinkage int sys_setsockopt(int fd, int level, int optname, + char *optval, int optlen); + +asmlinkage int sys32_setsockopt(int fd, int level, int optname, + char *optval, int optlen) +{ + if (optname == SO_ATTACH_FILTER) { + struct sock_fprog32 { + __u16 len; + __u32 filter; + } *fprog32 = (struct sock_fprog32 *)optval; + struct sock_fprog kfprog; + struct sock_filter *kfilter; + unsigned int fsize; + mm_segment_t old_fs; + __u32 uptr; + int ret; + + if (get_user(kfprog.len, &fprog32->len) || + __get_user(uptr, &fprog32->filter)) + return -EFAULT; + kfprog.filter = (struct sock_filter *)A(uptr); + fsize = kfprog.len * sizeof(struct sock_filter); + kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); + if (kfilter == NULL) + return -ENOMEM; + if (copy_from_user(kfilter, kfprog.filter, fsize)) { + kfree(kfilter); + return -EFAULT; + } + kfprog.filter = kfilter; + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_setsockopt(fd, level, optname, + (char *)&kfprog, sizeof(kfprog)); + set_fs(old_fs); + kfree(kfilter); + return ret; + } + return sys_setsockopt(fd, level, optname, optval, optlen); +} + +struct flock32 { + short l_type; + short l_whence; + __kernel_off_t32 l_start; + __kernel_off_t32 l_len; + __kernel_pid_t32 l_pid; + short __unused; +}; + +static inline int get_flock(struct flock *kfl, struct flock32 *ufl) +{ + int err; + + err = get_user(kfl->l_type, &ufl->l_type); + err |= __get_user(kfl->l_whence, &ufl->l_whence); + err |= __get_user(kfl->l_start, &ufl->l_start); + err |= __get_user(kfl->l_len, &ufl->l_len); + err |= __get_user(kfl->l_pid, &ufl->l_pid); + return err; +} + +static inline int put_flock(struct flock *kfl, struct flock32 *ufl) +{ + int err; + + err = __put_user(kfl->l_type, &ufl->l_type); + err |= __put_user(kfl->l_whence, &ufl->l_whence); + err |= __put_user(kfl->l_start, &ufl->l_start); + err |= __put_user(kfl->l_len, &ufl->l_len); + err |= __put_user(kfl->l_pid, &ufl->l_pid); + return err; +} + +extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); + +asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case F_GETLK: + case F_SETLK: + case F_SETLKW: + { + struct flock f; + mm_segment_t old_fs; + long ret; + + if(get_flock(&f, (struct flock32 *)arg)) + return -EFAULT; + old_fs = get_fs(); set_fs (KERNEL_DS); + ret = sys_fcntl(fd, cmd, (unsigned long)&f); + set_fs (old_fs); + if(put_flock(&f, (struct flock32 *)arg)) + return -EFAULT; + return ret; + } + default: + return sys_fcntl(fd, cmd, (unsigned long)arg); + } } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/mips64_ksyms.c linux/arch/mips64/kernel/mips64_ksyms.c --- v2.4.0-test2/linux/arch/mips64/kernel/mips64_ksyms.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/mips64_ksyms.c Sun Jul 9 22:18:16 2000 @@ -1,13 +1,12 @@ -/* $Id: mips64_ksyms.c,v 1.8 2000/02/24 00:12:41 ralf Exp $ - * +/* * Export MIPS64-specific functions needed for loadable modules. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 1997, 1998, 1999 by Ralf Baechle - * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include #include @@ -18,7 +17,6 @@ #include #include -#include #include #include #include @@ -27,6 +25,7 @@ #include #include #include +#include extern void *__bzero(void *__s, size_t __count); extern long __strncpy_from_user_nocheck_asm(char *__to, diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/process.c linux/arch/mips64/kernel/process.c --- v2.4.0-test2/linux/arch/mips64/kernel/process.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/process.c Mon Jul 10 13:16:56 2000 @@ -7,6 +7,7 @@ * Copyright (C) 1994 - 1999 by Ralf Baechle and others. * Copyright (C) 1999 Silicon Graphics, Inc. */ +#include #include #include #include @@ -34,7 +35,7 @@ { /* endless idle loop with no priority at all */ init_idle(); - current->priority = 0; + current->nice = 20; current->counter = -100; while (1) { while (!current->need_resched) diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/ptrace.c linux/arch/mips64/kernel/ptrace.c --- v2.4.0-test2/linux/arch/mips64/kernel/ptrace.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/ptrace.c Sun Jul 9 22:18:16 2000 @@ -1,5 +1,4 @@ -/* $Id: ptrace.c,v 1.1 1999/12/04 03:59:00 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -29,27 +28,23 @@ #include #include -/* Tracing a 32-bit process with a 64-bit strace and vice verca will not - work. I don't know how to fix this. */ - +/* + * Tracing a 32-bit process with a 64-bit strace and vice versa will not + * work. I don't know how to fix this. + */ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) { struct task_struct *child; int ret; lock_kernel(); -#if 0 - printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", - (int) request, (int) pid, (unsigned long) addr, - (unsigned long) data); -#endif ret = -EPERM; if (request == PTRACE_TRACEME) { /* are we already being traced? */ - if (current->flags & PF_PTRACED) + if (current->ptrace & PT_PTRACED) goto out; /* set the ptrace bit in the process flags. */ - current->flags |= PF_PTRACED; + current->ptrace |= PT_PTRACED; ret = 0; goto out; } @@ -79,9 +74,9 @@ (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) goto out_tsk; /* the same process cannot be attached many times */ - if (child->flags & PF_PTRACED) + if (child->ptrace & PT_PTRACED) goto out_tsk; - child->flags |= PF_PTRACED; + child->ptrace |= PT_PTRACED; write_lock_irq(&tasklist_lock); if (child->p_pptr != current) { @@ -96,7 +91,7 @@ goto out_tsk; } ret = -ESRCH; - if (!(child->flags & PF_PTRACED)) + if (!(child->ptrace & PT_PTRACED)) goto out_tsk; if (child->state != TASK_STOPPED) { if (request != PTRACE_KILL) @@ -104,7 +99,6 @@ } if (child->p_pptr != current) goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -116,7 +110,7 @@ ret = -EIO; if (copied != sizeof(tmp)) break; - ret = put_user(tmp, (unsigned int *) data); + ret = put_user(tmp, (unsigned int *) (unsigned long) data); break; } @@ -179,7 +173,7 @@ ret = -EIO; goto out_tsk; } - ret = put_user(tmp, (unsigned *) data); + ret = put_user(tmp, (unsigned *) (unsigned long) data); break; } /* when I and D space are separate, this will have to be fixed. */ @@ -248,9 +242,9 @@ if ((unsigned int) data > _NSIG) break; if (request == PTRACE_SYSCALL) - child->flags |= PF_TRACESYS; + child->ptrace |= PT_TRACESYS; else - child->flags &= ~PF_TRACESYS; + child->ptrace &= ~PT_TRACESYS; child->exit_code = data; wake_up_process(child); ret = 0; @@ -274,7 +268,7 @@ ret = -EIO; if ((unsigned long) data > _NSIG) break; - child->flags &= ~(PF_PTRACED|PF_TRACESYS); + child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); child->exit_code = data; write_lock_irq(&tasklist_lock); REMOVE_LINKS(child); @@ -312,10 +306,10 @@ ret = -EPERM; if (request == PTRACE_TRACEME) { /* are we already being traced? */ - if (current->flags & PF_PTRACED) + if (current->ptrace & PT_PTRACED) goto out; /* set the ptrace bit in the process flags. */ - current->flags |= PF_PTRACED; + current->ptrace |= PT_PTRACED; ret = 0; goto out; } @@ -345,9 +339,9 @@ (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) goto out_tsk; /* the same process cannot be attached many times */ - if (child->flags & PF_PTRACED) + if (child->ptrace & PT_PTRACED) goto out_tsk; - child->flags |= PF_PTRACED; + child->ptrace |= PT_PTRACED; write_lock_irq(&tasklist_lock); if (child->p_pptr != current) { @@ -362,7 +356,7 @@ goto out_tsk; } ret = -ESRCH; - if (!(child->flags & PF_PTRACED)) + if (!(child->ptrace & PT_PTRACED)) goto out_tsk; if (child->state != TASK_STOPPED) { if (request != PTRACE_KILL) @@ -514,9 +508,9 @@ if ((unsigned long) data > _NSIG) break; if (request == PTRACE_SYSCALL) - child->flags |= PF_TRACESYS; + child->ptrace |= PT_TRACESYS; else - child->flags &= ~PF_TRACESYS; + child->ptrace &= ~PT_TRACESYS; child->exit_code = data; wake_up_process(child); ret = 0; @@ -540,7 +534,7 @@ ret = -EIO; if ((unsigned long) data > _NSIG) break; - child->flags &= ~(PF_PTRACED|PF_TRACESYS); + child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); child->exit_code = data; write_lock_irq(&tasklist_lock); REMOVE_LINKS(child); @@ -566,9 +560,10 @@ asmlinkage void syscall_trace(void) { - if ((current->flags & (PF_PTRACED|PF_TRACESYS)) - != (PF_PTRACED|PF_TRACESYS)) + if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) + != (PT_PTRACED|PT_TRACESYS)) return; + current->exit_code = SIGTRAP; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/r4k_tlb.S linux/arch/mips64/kernel/r4k_tlb.S --- v2.4.0-test2/linux/arch/mips64/kernel/r4k_tlb.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/kernel/r4k_tlb.S Sun Jul 9 22:18:16 2000 @@ -0,0 +1,133 @@ +/* $Id: r4k_tlb.S,v 1.3 2000/06/30 00:48:29 kanoj Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Written by Ulf Carlsson (ulfc@engr.sgi.com) + */ +#include +#include +#include +#include +#include +#include + + .data + .comm pgd_current, NR_CPUS * 8, 8 + + /* + * After this macro runs we have a pointer to the pte of the address + * that caused the fault in in PTR. + */ + + .macro LOAD_PTE2, ptr, tmp +#ifdef CONFIG_SMP + mfc0 \tmp, CP0_CONTEXT + dla \ptr, pgd_current + dsrl \tmp, 23 + daddu \ptr, \tmp +#else + dla \ptr, pgd_current +#endif + dmfc0 \tmp, CP0_BADVADDR + ld \ptr, (\ptr) + bltz \tmp, kaddr + dsrl \tmp, (PGDIR_SHIFT-3) # get pgd offset in bytes + andi \tmp, ((PTRS_PER_PGD - 1)<<3) + daddu \ptr, \tmp # add in pgd offset + dmfc0 \tmp, CP0_BADVADDR + ld \ptr, (\ptr) # get pmd pointer + dsrl \tmp, (PMD_SHIFT-3) # get pmd offset in bytes + andi \tmp, ((PTRS_PER_PMD - 1)<<3) + daddu \ptr, \tmp # add in pmd offset + dmfc0 \tmp, CP0_XCONTEXT + ld \ptr, (\ptr) # get pte pointer + andi \tmp, 0xff0 # get pte offset + daddu \ptr, \tmp + .endm + + /* + * This places the even/odd pte pair in the page table at the pte + * entry pointed to by PTE into ENTRYLO0 and ENTRYLO1. + */ + .macro PTE_RELOAD, pte0, pte1 + dsrl \pte0, 6 # convert to entrylo0 + dmtc0 \pte0, CP0_ENTRYLO0 # load it + dsrl \pte1, 6 # convert to entrylo1 + dmtc0 \pte1, CP0_ENTRYLO1 # load it + .endm + + .text + .set noreorder + .set mips3 + + .align 5 +FEXPORT(except_vec0) + .set noat +1: b 1b + nop + + /* TLB refill handler for the R10000. + * Attention: We may only use 32 instructions. + */ + + .align 5 +FEXPORT(except_vec1_r10k) + .set noat + LOAD_PTE2 k1 k0 + ld k0, 0(k1) # get even pte + ld k1, 8(k1) # get odd pte + PTE_RELOAD k0 k1 + nop + tlbwr + eret +kaddr: + dla k0, handle_vmalloc_address # MAPPED kernel needs this + jr k0 + nop + + .align 5 +FEXPORT(handle_vmalloc_address) + .set noat + /* + * First, determine that the address is in/above vmalloc range. + */ + dmfc0 k0, CP0_BADVADDR + dli k1, VMALLOC_START + sltu k1, k0, k1 + bne k1, zero, not_vmalloc + dli k1, VMALLOC_START + + /* + * Now find offset into kptbl. + */ + dsubu k0, k0, k1 + dla k1, kptbl + dsrl k0, (PAGE_SHIFT+1) # get vpn2 + dsll k0, 4 # byte offset of pte + daddu k1, k1, k0 + + /* + * Determine that fault address is within vmalloc range. + */ + dla k0, ekptbl + sltu k0, k1, k0 + beq k0, zero, not_vmalloc + + /* + * Load cp0 registers. + */ + ld k0, 0(k1) # get even pte + ld k1, 8(k1) # get odd pte +1: + PTE_RELOAD k0 k1 + nop + tlbwr + eret +not_vmalloc: + daddu k0, zero, zero + daddu k1, zero, zero + j 1b + nop diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/r4k_tlb_glue.S linux/arch/mips64/kernel/r4k_tlb_glue.S --- v2.4.0-test2/linux/arch/mips64/kernel/r4k_tlb_glue.S Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/r4k_tlb_glue.S Sun Jul 9 22:18:16 2000 @@ -13,16 +13,6 @@ #include #include - __INIT -NESTED(__xtlb_refill_debug_tramp, PT_SIZE, sp) - j __xtlb_refill_debug - END(__xtlb_refill_debug_tramp) - -NESTED(__tlb_refill_debug_tramp, PT_SIZE, sp) - j __tlb_refill_debug - END(__tlb_refill_debug_tramp) - __FINIT - .macro __BUILD_cli CLI .endm @@ -31,7 +21,7 @@ STI .endm - .macro tlb_handler name interruptible + .macro tlb_handler name interruptible writebit NESTED(__\name, PT_SIZE, sp) SAVE_ALL #if DEBUG_MIPS64 @@ -42,17 +32,17 @@ ld $7, PT_R7(sp) ld $2, PT_R2(sp) #endif - __BUILD_\interruptible - dmfc0 t0, CP0_BADVADDR - sd t0, PT_BVADDR(sp) + dmfc0 a2, CP0_BADVADDR + li a1, \writebit + sd a2, PT_BVADDR(sp) move a0, sp - jal \name - j return + __BUILD_\interruptible + jal do_page_fault END(__\name) + RESTORE_ALL + eret .endm - tlb_handler tlb_refill_debug cli - tlb_handler xtlb_refill_debug cli - tlb_handler xtlb_mod_debug sti - tlb_handler xtlb_tlbl_debug sti - tlb_handler xtlb_tlbs_debug sti + tlb_handler xtlb_mod sti 1 + tlb_handler xtlb_tlbl sti 0 + tlb_handler xtlb_tlbs sti 1 diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/scall_o32.S linux/arch/mips64/kernel/scall_o32.S --- v2.4.0-test2/linux/arch/mips64/kernel/scall_o32.S Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/scall_o32.S Sun Jul 9 22:18:16 2000 @@ -1,11 +1,10 @@ -/* $Id: scall_o32.S,v 1.18 2000/03/27 21:04:13 ulfc Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996, 1997, 1998, 1999 by Ralf Baechle - * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1995 - 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. * * Hairy, the userspace application uses a different argument passing * convention than the kernel, so we have to translate things from o32 @@ -245,7 +244,7 @@ sys sys_rmdir 1 /* 4040 */ sys sys_dup 1 sys sys_pipe 0 - sys sys_times 1 + sys sys32_times 1 sys sys_ni_syscall 0 sys sys_brk 1 /* 4045 */ sys sys_setgid 1 @@ -257,7 +256,7 @@ sys sys_umount 2 sys sys_ni_syscall 0 sys sys32_ioctl 3 - sys sys_fcntl 3 /* 4055 */ + sys sys32_fcntl 3 /* 4055 */ sys sys_ni_syscall 2 sys sys_setpgid 2 sys sys_ni_syscall, 0 @@ -383,7 +382,7 @@ sys sys_send 4 sys sys_sendmsg 3 sys sys_sendto 6 /* 4180 */ - sys sys_setsockopt 5 + sys sys32_setsockopt 5 sys sys_shutdown 2 sys sys_socket 3 sys sys_socketpair 4 @@ -415,9 +414,9 @@ sys sys_mmap2 6 /* 4210 */ sys sys_truncate64 2 sys sys_ftruncate64 2 - sys sys_stat64 3 - sys sys_lstat64 3 - sys sys_fstat64 3 /* 4210 */ + sys sys_newstat 3 + sys sys_newlstat 3 + sys sys_newfstat 3 /* 4210 */ sys sys_pivot_root 2 sys sys_mincore 3 sys sys_madvise 3 diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/setup.c linux/arch/mips64/kernel/setup.c --- v2.4.0-test2/linux/arch/mips64/kernel/setup.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/setup.c Sun Jul 9 22:18:16 2000 @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef CONFIG_SGI_IP27 /* XXX Origin garbage has no business in this file */ @@ -153,6 +154,9 @@ unsigned long tmp; unsigned long *initrd_header; #endif + int i; + pmd_t *pmd = kpmdtbl; + pte_t *pte = kptbl; cpu_probe(); load_mmu(); @@ -191,4 +195,10 @@ #endif paging_init(); + + memset((void *)kptbl, 0, PAGE_SIZE << KPTBL_PAGE_ORDER); + memset((void *)kpmdtbl, 0, PAGE_SIZE); + pgd_set(swapper_pg_dir, kpmdtbl); + for (i = 0; i < (1 << KPTBL_PAGE_ORDER); pmd++,i++,pte+=PTRS_PER_PTE) + pmd_val(*pmd) = (unsigned long)pte; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/signal.c linux/arch/mips64/kernel/signal.c --- v2.4.0-test2/linux/arch/mips64/kernel/signal.c Mon Jun 19 16:31:57 2000 +++ linux/arch/mips64/kernel/signal.c Sun Jul 9 22:18:16 2000 @@ -1,12 +1,11 @@ -/* $Id: signal.c,v 1.4 2000/01/17 23:32:46 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1994 - 1999 Ralf Baechle - * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1994 - 2000 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include #include @@ -38,6 +37,8 @@ extern asmlinkage int save_fp_context(struct sigcontext *sc); extern asmlinkage int restore_fp_context(struct sigcontext *sc); +extern asmlinkage void syscall_trace(void); + int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from) { if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t))) @@ -197,8 +198,6 @@ err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler); err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig); err |= __put_user(0, &oact->sa_mask.sig[1]); - err |= __put_user(0, &oact->sa_mask.sig[2]); - err |= __put_user(0, &oact->sa_mask.sig[3]); err |= __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer); if (err) return -EFAULT; @@ -294,6 +293,8 @@ /* * Don't let your children do this ... */ + if (current->ptrace & PT_TRACESYS) + syscall_trace(); __asm__ __volatile__( "move\t$29, %0\n\t" "j\tret_from_sys_call" @@ -354,7 +355,7 @@ err |= __put_user(regs->cp0_epc, &sc->sc_pc); -#define save_gp_reg(i) { \ +#define save_gp_reg(i) do { \ err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \ } while(0) __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2); @@ -620,7 +621,7 @@ if (!signr) break; - if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; @@ -694,7 +695,6 @@ /* FALLTHRU */ default: - lock_kernel(); sigaddset(¤t->signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/signal32.c linux/arch/mips64/kernel/signal32.c --- v2.4.0-test2/linux/arch/mips64/kernel/signal32.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/signal32.c Sun Jul 9 22:18:16 2000 @@ -1,5 +1,4 @@ -/* $Id: signal32.c,v 1.4 2000/03/15 22:46:55 kanoj Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -8,6 +7,7 @@ * Copyright (C) 1994 - 1999 Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. */ +#include #include #include #include @@ -37,6 +37,8 @@ extern asmlinkage int save_fp_context(struct sigcontext *sc); extern asmlinkage int restore_fp_context(struct sigcontext *sc); +extern asmlinkage void syscall_trace(void); + /* 32-bit compatibility types */ #define _NSIG32_BPW 32 @@ -60,7 +62,7 @@ /* IRIX compatible stack_t */ typedef struct sigaltstack32 { void *ss_sp; - size_t ss_size; + __kernel_size_t32 ss_size; int ss_flags; } stack32_t; @@ -94,18 +96,72 @@ return err; } +extern void __put_sigset_unknown_nsig(void); +extern void __get_sigset_unknown_nsig(void); + +static inline int +put_sigset(const sigset_t *kbuf, sigset32_t *ubuf) +{ + int err = 0; + + if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf))) + return -EFAULT; + + switch (_NSIG_WORDS) { + default: + __put_sigset_unknown_nsig(); + case 2: + err |= __put_user (kbuf->sig[1] >> 32, &ubuf->sig[3]); + err |= __put_user (kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]); + case 1: + err |= __put_user (kbuf->sig[0] >> 32, &ubuf->sig[1]); + err |= __put_user (kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]); + } + + return err; +} + +static inline int +get_sigset(sigset_t *kbuf, const sigset32_t *ubuf) +{ + int err = 0; + unsigned long sig[4]; + + if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf))) + return -EFAULT; + + switch (_NSIG_WORDS) { + default: + __get_sigset_unknown_nsig(); + case 2: + err |= __get_user (sig[3], &ubuf->sig[3]); + err |= __get_user (sig[2], &ubuf->sig[2]); + kbuf->sig[1] = sig[2] | (sig[3] << 32); + case 1: + err |= __get_user (sig[1], &ubuf->sig[1]); + err |= __get_user (sig[0], &ubuf->sig[0]); + kbuf->sig[0] = sig[0] | (sig[1] << 32); + } + + return err; +} + /* * Atomically swap in the new signal mask, and wait for a signal. */ asmlinkage inline int sys32_sigsuspend(abi64_no_regargs, struct pt_regs regs) { - sigset_t *uset, saveset, newset; + sigset32_t *uset; + sigset_t newset, saveset; - save_static(®s); +#if DEBUG_MIPS64 printk("%s called.\n", __FUNCTION__); - uset = (sigset_t *) regs.regs[4]; - if (copy_from_user(&newset, uset, sizeof(sigset_t))) +#endif + + save_static(®s); + uset = (sigset32_t *) regs.regs[4]; + if (get_sigset(&newset, uset)) return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); @@ -128,19 +184,22 @@ asmlinkage int sys32_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs) { - sigset_t *unewset, saveset, newset; + sigset32_t *uset; + sigset_t newset, saveset; size_t sigsetsize; - save_static(®s); +#if DEBUG_MIPS64 printk("%s called.\n", __FUNCTION__); +#endif + save_static(®s); /* XXX Don't preclude handling different sized sigset_t's. */ sigsetsize = regs.regs[5]; - if (sigsetsize != sizeof(sigset_t)) + if (sigsetsize != sizeof(sigset32_t)) return -EINVAL; - unewset = (sigset_t *) regs.regs[4]; - if (copy_from_user(&newset, unewset, sizeof(newset))) + uset = (sigset32_t *) regs.regs[4]; + if (get_sigset(&newset, uset)) return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); @@ -172,10 +231,12 @@ if (!access_ok(VERIFY_READ, act, sizeof(*act))) return -EFAULT; - err |= __get_user(new_ka.sa.sa_handler, &act->sa_handler); + err |= __get_user((u32)(u64)new_ka.sa.sa_handler, + &act->sa_handler); err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); err |= __get_user(mask, &act->sa_mask.sig[0]); - err |= __get_user(new_ka.sa.sa_restorer, &act->sa_restorer); + err |= __get_user((u32)(u64)new_ka.sa.sa_restorer, + &act->sa_restorer); if (err) return -EFAULT; @@ -188,12 +249,14 @@ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact))) return -EFAULT; err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler); + err |= __put_user((u32)(u64)old_ka.sa.sa_handler, + &oact->sa_handler); err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig); err |= __put_user(0, &oact->sa_mask.sig[1]); err |= __put_user(0, &oact->sa_mask.sig[2]); err |= __put_user(0, &oact->sa_mask.sig[3]); - err |= __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer); + err |= __put_user((u32)(u64)old_ka.sa.sa_restorer, + &oact->sa_restorer); if (err) return -EFAULT; } @@ -204,12 +267,37 @@ asmlinkage int sys32_sigaltstack(abi64_no_regargs, struct pt_regs regs) { - const stack_t *uss = (const stack_t *) regs.regs[4]; - stack_t *uoss = (stack_t *) regs.regs[5]; + const stack32_t *uss = (const stack32_t *) regs.regs[4]; + stack32_t *uoss = (stack32_t *) regs.regs[5]; unsigned long usp = regs.regs[29]; -printk("%s called.\n", __FUNCTION__); + stack_t kss, koss; + int ret, err = 0; + mm_segment_t old_fs = get_fs(); - return do_sigaltstack(uss, uoss, usp); + if (uss) { + if (!access_ok(VERIFY_READ, uss, sizeof(*uss))) + return -EFAULT; + err |= __get_user(kss.ss_sp, &uss->ss_sp); + err |= __get_user(kss.ss_size, &uss->ss_size); + err |= __get_user(kss.ss_flags, &uss->ss_flags); + if (err) + return -EFAULT; + } + + set_fs (KERNEL_DS); + ret = do_sigaltstack(uss ? &kss : NULL , uoss ? &koss : NULL, usp); + set_fs (old_fs); + + if (!ret && uoss) { + if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))) + return -EFAULT; + err |= __put_user(koss.ss_sp, &uoss->ss_sp); + err |= __put_user(koss.ss_size, &uoss->ss_size); + err |= __put_user(koss.ss_flags, &uoss->ss_flags); + if (err) + return -EFAULT; + } + return ret; } static asmlinkage int @@ -293,6 +381,8 @@ /* * Don't let your children do this ... */ + if (current->ptrace & PT_TRACESYS) + syscall_trace(); __asm__ __volatile__( "move\t$29, %0\n\t" "j\tret_from_sys_call" @@ -610,7 +700,7 @@ if (!signr) break; - if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; @@ -684,7 +774,6 @@ /* FALLTHRU */ default: - lock_kernel(); sigaddset(¤t->signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; @@ -723,26 +812,128 @@ old_sigset_t *oset); asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set, - old_sigset_t32 *oset) + old_sigset_t32 *oset) { old_sigset_t s; int ret; mm_segment_t old_fs = get_fs(); - if (set && get_user (s, set)) return -EFAULT; + if (set && get_user (s, set)) + return -EFAULT; set_fs (KERNEL_DS); ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL); set_fs (old_fs); - if (ret) return ret; - if (oset && put_user (s, oset)) return -EFAULT; - return 0; + if (!ret && oset && put_user (s, oset)) + return -EFAULT; + return ret; } -/* Dummies ... */ +asmlinkage long sys_sigpending(old_sigset_t *set); + +asmlinkage int sys32_sigpending(old_sigset_t32 *set) +{ + old_sigset_t pending; + int ret; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_sigpending(&pending); + set_fs (old_fs); + + if (put_user(pending, set)) + return -EFAULT; + + return ret; +} + +asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act, + struct sigaction32 *oact, + unsigned int sigsetsize) +{ + struct k_sigaction new_sa, old_sa; + int ret = -EINVAL; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + goto out; + + if (act) { + int err = 0; + + if (!access_ok(VERIFY_READ, act, sizeof(*act))) + return -EFAULT; + err |= __get_user((u32)(u64)new_sa.sa.sa_handler, + &act->sa_handler); + err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags); + err |= __get_user((u32)(u64)new_sa.sa.sa_restorer, + &act->sa_restorer); + err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask); + if (err) + return -EFAULT; + } + + ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL); + + if (!ret && oact) { + int err = 0; + + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact))) + return -EFAULT; + + err |= __put_user((u32)(u64)new_sa.sa.sa_handler, + &oact->sa_handler); + err |= __put_user(new_sa.sa.sa_flags, &oact->sa_flags); + err |= __put_user((u32)(u64)new_sa.sa.sa_restorer, + &oact->sa_restorer); + err |= put_sigset(&new_sa.sa.sa_mask, &oact->sa_mask); + if (err) + return -EFAULT; + } +out: + return ret; +} + +asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, + size_t sigsetsize); + +asmlinkage int sys32_rt_sigprocmask(int how, sigset32_t *set, sigset32_t *oset, + unsigned int sigsetsize) +{ + sigset_t old_set, new_set; + int ret; + mm_segment_t old_fs = get_fs(); + + if (set && get_sigset(&new_set, set)) + return -EFAULT; + + set_fs (KERNEL_DS); + ret = sys_rt_sigprocmask(how, set ? &new_set : NULL, + oset ? &old_set : NULL, sigsetsize); + set_fs (old_fs); + + if (!ret && oset && put_sigset(&old_set, oset)) + return -EFAULT; + + return ret; +} + +asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize); + +asmlinkage int sys32_rt_sigpending(sigset32_t *uset, unsigned int sigsetsize) +{ + int ret; + sigset_t set; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_rt_sigpending(&set, sigsetsize); + set_fs (old_fs); + + if (!ret && put_sigset(&set, uset)) + return -EFAULT; + + return ret; +} -asmlinkage void sys32_sigpending(void) { panic(__FUNCTION__ " called."); } -asmlinkage void sys32_rt_sigaction(void) { panic(__FUNCTION__ " called."); } -asmlinkage void sys32_rt_sigprocmask(void) { panic(__FUNCTION__ " called."); } -asmlinkage void sys32_rt_sigpending(void) { panic(__FUNCTION__ " called."); } asmlinkage void sys32_rt_sigtimedwait(void) { panic(__FUNCTION__ " called."); } asmlinkage void sys32_rt_sigqueueinfo(void) { panic(__FUNCTION__ " called."); } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/smp.c linux/arch/mips64/kernel/smp.c --- v2.4.0-test2/linux/arch/mips64/kernel/smp.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/smp.c Sun Jul 9 22:18:16 2000 @@ -69,14 +69,12 @@ void __init smp_boot_cpus(void) { extern void allowboot(void); - extern int maxcpus; init_new_context(current, &init_mm); global_irq_holder = 0; current->processor = 0; init_idle(); smp_tune_scheduling(); - smp_num_cpus = maxcpus; allowboot(); } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/softfp.S linux/arch/mips64/kernel/softfp.S --- v2.4.0-test2/linux/arch/mips64/kernel/softfp.S Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/softfp.S Sun Jul 9 22:18:16 2000 @@ -1,11 +1,10 @@ -/* $Id: softfp.S,v 1.2 2000/03/21 23:50:42 ulfc Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1998, 1999 by Ralf Baechle - * Copyright (C) 1999 by Silicon Graphics, Inc. + * Copyright (C) 1998, 1999, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 by Silicon Graphics, Inc. * * For now it's just a crude hack good enough to run certain fp programs like * Mozilla. @@ -192,15 +191,15 @@ #define FMT_switch(insn,opc,temp0,temp1) \ insn: srl temp0, opc, 18; \ andi temp0, 0x1c; \ - la temp1, insn ## .tab; \ + la temp1, insn##.tab; \ daddu temp0, temp1; \ ld temp0, (temp0); \ jr temp0; \ \ .data; \ -insn ## .tab: \ - .dword insn ## .s, insn ## .d, unimp, unimp; \ - .dword insn ## .w, insn ## .l, unimp, unimp; \ +insn##.tab: \ + .dword insn##.s, insn##.d, unimp, unimp; \ + .dword insn##.w, insn##.l, unimp, unimp; \ .previous BITCH(add) diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/syscall.c linux/arch/mips64/kernel/syscall.c --- v2.4.0-test2/linux/arch/mips64/kernel/syscall.c Fri Jun 23 21:55:07 2000 +++ linux/arch/mips64/kernel/syscall.c Sun Jul 9 22:18:16 2000 @@ -1,11 +1,10 @@ -/* $Id: syscall.c,v 1.3 2000/02/04 07:40:24 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995 - 1999 by Ralf Baechle - * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1995 - 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include #include @@ -21,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +36,6 @@ int fd[2]; int error, res; - lock_kernel(); error = do_pipe(fd); if (error) { res = error; @@ -45,7 +44,6 @@ regs.regs[3] = fd[1]; res = fd[0]; out: - unlock_kernel(); return res; } @@ -56,7 +54,6 @@ struct file * file = NULL; unsigned long error = -EFAULT; - lock_kernel(); if (!(flags & MAP_ANONYMOUS)) { error = -EBADF; file = fget(fd); @@ -71,7 +68,6 @@ if (file) fput(file); out: - unlock_kernel(); return error; } @@ -174,39 +170,46 @@ char *name; int flags, tmp, len, errno; - switch(cmd) - { - case SETNAME: + switch(cmd) { + case SETNAME: { + char nodename[__NEW_UTS_LEN + 1]; + if (!capable(CAP_SYS_ADMIN)) return -EPERM; name = (char *) arg1; - len = strlen_user(name); - if (len == 0 || len > __NEW_UTS_LEN) - return -EINVAL; - down(&uts_sem); - errno = -EFAULT; - if (!copy_from_user(system_utsname.nodename, name, len)) { - system_utsname.nodename[len] = '\0'; - errno = 0; - } - up(&uts_sem); - return errno; + len = strncpy_from_user(nodename, name, sizeof(nodename)); + if (len < 0) + return -EFAULT; + + down_write(&uts_sem); + strncpy(system_utsname.nodename, name, len); + up_write(&uts_sem); + system_utsname.nodename[len] = '\0'; + return 0; + } - case MIPS_ATOMIC_SET: + case MIPS_ATOMIC_SET: { /* This is broken in case of page faults and SMP ... - Risc/OS fauls after maximum 20 tries with EAGAIN. */ + Risc/OS faults after maximum 20 tries with EAGAIN. */ + unsigned int tmp; + p = (int *) arg1; errno = verify_area(VERIFY_WRITE, p, sizeof(*p)); if (errno) return errno; + errno = 0; save_and_cli(flags); - errno = *p; - *p = arg2; + errno |= __get_user(tmp, p); + errno |= __put_user(arg2, p); restore_flags(flags); - return errno; /* This is broken ... */ + if (errno) + return tmp; + + return tmp; /* This is broken ... */ + } case MIPS_FIXADE: tmp = current->thread.mflags & ~3; @@ -230,7 +233,7 @@ * This is really horribly ugly. */ asmlinkage int sys_ipc (uint call, int first, int second, - int third, void *ptr, long fifth) + unsigned long third, void *ptr, long fifth) { int version, ret; diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/traps.c linux/arch/mips64/kernel/traps.c --- v2.4.0-test2/linux/arch/mips64/kernel/traps.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/traps.c Sun Jul 9 22:18:16 2000 @@ -1,5 +1,4 @@ -/* $Id: traps.c,v 1.4 2000/01/20 23:50:27 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -41,9 +40,9 @@ console_loglevel = 15; } -extern asmlinkage void __xtlb_mod_debug(void); -extern asmlinkage void __xtlb_tlbl_debug(void); -extern asmlinkage void __xtlb_tlbs_debug(void); +extern asmlinkage void __xtlb_mod(void); +extern asmlinkage void __xtlb_tlbl(void); +extern asmlinkage void __xtlb_tlbs(void); extern asmlinkage void handle_adel(void); extern asmlinkage void handle_ades(void); extern asmlinkage void handle_ibe(void); @@ -77,10 +76,10 @@ * This routine abuses get_user()/put_user() to reference pointers * with at least a bit of error checking ... */ -void show_stack(unsigned int *sp) +void show_stack(unsigned long *sp) { int i; - unsigned int *stack; + unsigned long *stack; stack = sp; i = 0; @@ -94,22 +93,22 @@ break; } - printk(" %08lx", stackdata); + printk(" %016lx", stackdata); if (++i > 40) { printk(" ..."); break; } - if (i % 8 == 0) + if (i % 4 == 0) printk("\n "); } } -void show_trace(unsigned int *sp) +void show_trace(unsigned long *sp) { int i; - unsigned int *stack; + unsigned long *stack; unsigned long kernel_start, kernel_end; unsigned long module_start, module_end; extern char _stext, _etext; @@ -144,7 +143,11 @@ if ((addr >= kernel_start && addr < kernel_end) || (addr >= module_start && addr < module_end)) { - printk(" [<%08lx>]", addr); + /* Since our kernel is still at KSEG0, + * truncate the address so that ksymoops + * understands it. + */ + printk(" [<%08x>]", (unsigned int) addr); if (++i > 40) { printk(" ..."); break; @@ -160,12 +163,12 @@ printk("\nCode:"); for(i = -3 ; i < 6 ; i++) { - unsigned long insn; + unsigned int insn; if (__get_user(insn, pc + i)) { printk(" (Bad address in epc)\n"); break; } - printk("%c%08lx%c",(i?' ':'<'),insn,(i?' ':'>')); + printk("%c%08x%c",(i?' ':'<'),insn,(i?' ':'>')); } } @@ -180,10 +183,10 @@ spin_lock_irq(&die_lock); printk("%s: %04lx\n", str, err & 0xffff); show_regs(regs); - printk("Process %s (pid: %ld, stackpage=%08lx)\n", + printk("Process %s (pid: %d, stackpage=%08lx)\n", current->comm, current->pid, (unsigned long) current); - show_stack((unsigned int *) regs->regs[29]); - show_trace((unsigned int *) regs->regs[29]); + show_stack((unsigned long *) regs->regs[29]); + show_trace((unsigned long *) regs->regs[29]); show_code((unsigned int *) regs->cp0_epc); printk("\n"); spin_unlock_irq(&die_lock); @@ -230,6 +233,7 @@ { unsigned long pc; unsigned int insn; + extern void simfp(unsigned int); #ifdef CONFIG_MIPS_FPE_MODULE if (fpe_handler != NULL) { @@ -237,7 +241,6 @@ return; } #endif - lock_kernel(); if (fcr31 & 0x20000) { /* Retry instruction with flush to zero ... */ if (!(fcr31 & (1<<24))) { @@ -249,7 +252,7 @@ "ctc1\t%0,$31" : /* No outputs */ : "r" (fcr31)); - goto out; + return; } pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0); if (get_user(insn, (unsigned int *)pc)) { @@ -263,12 +266,9 @@ } if (compute_return_epc(regs)) - goto out; + return; //force_sig(SIGFPE, current); printk(KERN_DEBUG "Should send SIGFPE to %s\n", current->comm); - -out: - unlock_kernel(); } static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode) @@ -327,11 +327,9 @@ void do_ri(struct pt_regs *regs) { - lock_kernel(); - printk("Cpu%d[%s:%ld] Illegal instruction at %08lx ra=%08lx\n", + printk("Cpu%d[%s:%d] Illegal instruction at %08lx ra=%08lx\n", smp_processor_id(), current->comm, current->pid, regs->cp0_epc, regs->regs[31]); - unlock_kernel(); if (compute_return_epc(regs)) return; force_sig(SIGILL, current); @@ -390,7 +388,7 @@ * caused by a new unknown cpu type or after another deadly * hard/software error. */ - panic("Caught reserved exception %d - should not happen.", + panic("Caught reserved exception %ld - should not happen.", (regs->cp0_cause & 0x1f) >> 2); } @@ -471,8 +469,8 @@ void __init trap_init(void) { - extern char __tlb_refill_debug_tramp; - extern char __xtlb_refill_debug_tramp; + extern char except_vec0; + extern char except_vec1_r10k; extern char except_vec2_generic; extern char except_vec3_generic, except_vec3_r4000; extern void bus_error_init(void); @@ -528,8 +526,8 @@ case CPU_NEVADA: r4k: /* Debug TLB refill handler. */ - memcpy((void *)KSEG0, &__tlb_refill_debug_tramp, 0x80); - memcpy((void *)KSEG0 + 0x080, &__xtlb_refill_debug_tramp, 0x80); + memcpy((void *)KSEG0, &except_vec0, 0x80); + memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80); /* Cache error vector */ memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80); @@ -542,9 +540,9 @@ 0x100); } - set_except_vector(1, __xtlb_mod_debug); - set_except_vector(2, __xtlb_tlbl_debug); - set_except_vector(3, __xtlb_tlbs_debug); + set_except_vector(1, __xtlb_mod); + set_except_vector(2, __xtlb_tlbl); + set_except_vector(3, __xtlb_tlbs); set_except_vector(4, handle_adel); set_except_vector(5, handle_ades); diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/ld.script.elf32 linux/arch/mips64/ld.script.elf32 --- v2.4.0-test2/linux/arch/mips64/ld.script.elf32 Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/ld.script.elf32 Sun Jul 9 22:18:16 2000 @@ -3,11 +3,9 @@ SECTIONS { /* Read-only sections, merged into text segment: */ - . = 0x80000000; .init : { *(.init) } =0 .text : { - _ftext = . ; *(.text) *(.rodata) *(.rodata1) @@ -15,9 +13,9 @@ *(.gnu.warning) } =0 _etext = .; - PROVIDE (etext = .); . = ALIGN(16384); + /* This for CONFIG_MAPPED_KERNEL . = . + 16777216; */ .data.init_task : { *(.data.init_task) } /* Startup code */ @@ -65,7 +63,6 @@ CONSTRUCTORS } .data1 : { *(.data1) } - _gp = . + 0x8000; .lit8 : { *(.lit8) } .lit4 : { *(.lit4) } .ctors : { *(.ctors) } @@ -77,10 +74,7 @@ we can shorten the on-disk segment size. */ .sdata : { *(.sdata) } _edata = .; - PROVIDE (edata = .); - __bss_start = .; - _fbss = .; .sbss : { *(.sbss) *(.scommon) } .bss : { @@ -88,7 +82,6 @@ *(.bss) *(COMMON) _end = . ; - PROVIDE (end = .); } /* These are needed for ELF backends which have not yet been converted to the new style linker. */ diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/ld.script.elf64 linux/arch/mips64/ld.script.elf64 --- v2.4.0-test2/linux/arch/mips64/ld.script.elf64 Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/ld.script.elf64 Sun Jul 9 22:18:16 2000 @@ -16,7 +16,6 @@ /* . = 0xa800000000300000; */ . = 0xffffffff80300000; .text : { - _ftext = . ; *(.text) *(.rodata) *(.rodata1) @@ -24,7 +23,6 @@ *(.gnu.warning) } = 0 _etext = .; - PROVIDE (etext = .); . = ALIGN(16384); .data.init_task : { *(.data.init_task) } @@ -74,7 +72,6 @@ CONSTRUCTORS } .data1 : { *(.data1) } - _gp = . + 0x8000; .lit8 : { *(.lit8) } .lit4 : { *(.lit4) } .ctors : { *(.ctors) } @@ -86,10 +83,7 @@ we can shorten the on-disk segment size. */ .sdata : { *(.sdata) } _edata = .; - PROVIDE (edata = .); - __bss_start = .; - _fbss = .; .sbss : { *(.sbss) *(.scommon) } .bss : { @@ -97,7 +91,6 @@ *(.bss) *(COMMON) _end = . ; - PROVIDE (end = .); } /* These are needed for ELF backends which have not yet been converted to the new style linker. */ diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/lib/dump_tlb.c linux/arch/mips64/lib/dump_tlb.c --- v2.4.0-test2/linux/arch/mips64/lib/dump_tlb.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/dump_tlb.c Sun Jul 9 22:18:16 2000 @@ -133,28 +133,28 @@ pgd_t *page_dir, *pgd; pmd_t *pmd; pte_t *pte, page; - unsigned int addr; + unsigned long addr; unsigned long val; - addr = (unsigned int) address; + addr = (unsigned long) address; - printk("Addr == %08x\n", addr); - printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd); + printk("Addr == %08lx\n", addr); + printk("tasks->mm.pgd == %08lx\n", (unsigned long) t->mm->pgd); page_dir = pgd_offset(t->mm, 0); - printk("page_dir == %08x\n", (unsigned int) page_dir); + printk("page_dir == %08lx\n", (unsigned long) page_dir); pgd = pgd_offset(t->mm, addr); - printk("pgd == %08x, ", (unsigned int) pgd); + printk("pgd == %08lx, ", (unsigned long) pgd); pmd = pmd_offset(pgd, addr); - printk("pmd == %08x, ", (unsigned int) pmd); + printk("pmd == %08lx, ", (unsigned long) pmd); pte = pte_offset(pmd, addr); - printk("pte == %08x, ", (unsigned int) pte); + printk("pte == %08lx, ", (unsigned long) pte); page = *pte; - printk("page == %08x\n", (unsigned int) pte_val(page)); + printk("page == %08lx\n", (unsigned long) pte_val(page)); val = pte_val(page); if (val & _PAGE_PRESENT) printk("present "); diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/lib/floppy-std.c linux/arch/mips64/lib/floppy-std.c --- v2.4.0-test2/linux/arch/mips64/lib/floppy-std.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/lib/floppy-std.c Sun Jul 9 22:18:16 2000 @@ -1,5 +1,4 @@ -/* $Id: floppy-std.c,v 1.1 1999/08/21 21:43:00 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -23,7 +22,6 @@ #include #include #include -#include #include /* diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/mm/andes.c linux/arch/mips64/mm/andes.c --- v2.4.0-test2/linux/arch/mips64/mm/andes.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/mm/andes.c Sun Jul 9 22:18:16 2000 @@ -458,7 +458,6 @@ _user_mode = andes_user_mode; flush_cache_all(); - write_32bit_cp0_register(CP0_WIRED, 0); /* * You should never change this register: diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/mm/fault.c linux/arch/mips64/mm/fault.c --- v2.4.0-test2/linux/arch/mips64/mm/fault.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/mm/fault.c Sun Jul 9 22:18:16 2000 @@ -1,11 +1,10 @@ -/* $Id: fault.c,v 1.7 2000/03/13 22:43:25 kanoj Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996, 1997, 1998, 1999 by Ralf Baechle - * Copyright (C) 1999 by Silicon Graphics + * Copyright (C) 1995 - 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 by Silicon Graphics, Inc. */ #include #include @@ -41,7 +40,8 @@ asmlinkage void dodebug(abi64_no_regargs, struct pt_regs regs) { - printk("Got syscall %d, cpu %d proc %s:%d epc 0x%lx\n", regs.regs[2], smp_processor_id(), current->comm, current->pid, regs.cp0_epc); + printk("Got syscall %ld, cpu %d proc %s:%d epc 0x%lx\n", regs.regs[2], + smp_processor_id(), current->comm, current->pid, regs.cp0_epc); } asmlinkage void @@ -68,9 +68,10 @@ struct vm_area_struct * vma; struct task_struct *tsk = current; struct mm_struct *mm = tsk->mm; - int si_code = SEGV_MAPERR; unsigned long fixup; + siginfo_t info; + info.si_code = SEGV_MAPERR; /* * If we're in an interrupt or have no user * context, we must not take the fault.. @@ -96,7 +97,7 @@ * we can handle it.. */ good_area: - si_code = SEGV_ACCERR; + info.si_code = SEGV_ACCERR; if (write) { if (!(vma->vm_flags & VM_WRITE)) @@ -134,8 +135,14 @@ bad_area: up(&mm->mmap_sem); + /* + * Quickly check for vmalloc range faults. + */ + if ((!vma) && (address >= VMALLOC_START) && (address < VMALLOC_END)) { + printk("Fix vmalloc invalidate fault\n"); + while(1); + } if (user_mode(regs)) { - struct siginfo si; tsk->thread.cp0_badvaddr = address; tsk->thread.error_code = write; #if 0 @@ -147,10 +154,11 @@ (unsigned long) regs->cp0_epc, (unsigned long) regs->regs[31]); #endif - si.si_signo = SIGSEGV; - si.si_code = si_code; - si.si_addr = (void *) address; - force_sig_info(SIGSEGV, &si, tsk); + info.si_signo = SIGSEGV; + info.si_errno = 0; + /* info.si_code has been set above */ + info.si_addr = (void *) address; + force_sig_info(SIGSEGV, &info, tsk); return; } @@ -174,8 +182,9 @@ * terminate things with extreme prejudice. */ printk(KERN_ALERT "Cpu %d Unable to handle kernel paging request at " - "address %08lx, epc == %08lx, ra == %08lx\n", - smp_processor_id(), address, regs->cp0_epc, regs->regs[31]); + "address %08lx, epc == %08x, ra == %08x\n", + smp_processor_id(), address, (unsigned int) regs->cp0_epc, + (unsigned int) regs->regs[31]); die("Oops", regs, write); do_exit(SIGKILL); @@ -198,7 +207,11 @@ * or user mode. */ tsk->thread.cp0_badvaddr = address; - force_sig(SIGBUS, tsk); + info.si_code = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void *) address; + force_sig_info(SIGBUS, &info, tsk); /* Kernel mode? Handle exceptions or die */ if (!user_mode(regs)) diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/mm/init.c linux/arch/mips64/mm/init.c --- v2.4.0-test2/linux/arch/mips64/mm/init.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/mm/init.c Sun Jul 9 22:18:16 2000 @@ -56,7 +56,7 @@ void __bad_pmd(pgd_t *pgd) { printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); - pgd_set(pgd, (pmd_t *) BAD_PAGETABLE); + pgd_set(pgd, empty_bad_pmd_table); } void pgd_init(unsigned long page) @@ -93,7 +93,7 @@ return ret; } -void pmd_init(unsigned long addr) +void pmd_init(unsigned long addr, unsigned long pagetable) { unsigned long *p, *end; @@ -101,14 +101,14 @@ end = p + PTRS_PER_PMD; while (p < end) { - p[0] = (unsigned long) invalid_pte_table; - p[1] = (unsigned long) invalid_pte_table; - p[2] = (unsigned long) invalid_pte_table; - p[3] = (unsigned long) invalid_pte_table; - p[4] = (unsigned long) invalid_pte_table; - p[5] = (unsigned long) invalid_pte_table; - p[6] = (unsigned long) invalid_pte_table; - p[7] = (unsigned long) invalid_pte_table; + p[0] = (unsigned long)pagetable; + p[1] = (unsigned long)pagetable; + p[2] = (unsigned long)pagetable; + p[3] = (unsigned long)pagetable; + p[4] = (unsigned long)pagetable; + p[5] = (unsigned long)pagetable; + p[6] = (unsigned long)pagetable; + p[7] = (unsigned long)pagetable; p += 8; } } @@ -120,7 +120,7 @@ pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, 1); if (pgd_none(*pgd)) { if (pmd) { - pmd_init((unsigned long)pmd); + pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table); pgd_set(pgd, pmd); return pmd + offset; } @@ -161,7 +161,7 @@ { pte_t *page; - page = (pte_t *) __get_free_pages(GFP_KERNEL, 1); + page = (pte_t *) __get_free_pages(GFP_KERNEL, 0); if (pmd_none(*pmd)) { if (page) { clear_page(page); @@ -171,7 +171,7 @@ pmd_set(pmd, BAD_PAGETABLE); return NULL; } - free_pages((unsigned long)page, 1); + free_pages((unsigned long)page, 0); if (pmd_bad(*pmd)) { __bad_pte(pmd); return NULL; @@ -246,21 +246,6 @@ return 1UL << order; } -extern inline void pte_init(unsigned long page) -{ - unsigned long *p, *end, bp; - - bp = pte_val(BAD_PAGE); - p = (unsigned long *) page; - end = p + (2 * PTRS_PER_PTE); - - while (p < end) { - p[0] = p[1] = p[2] = p[3] = - p[4] = p[5] = p[6] = p[7] = bp; - p += 8; - } -} - /* * BAD_PAGE is the page that is used for page faults when linux * is out-of-memory. Older versions of linux just did a @@ -276,33 +261,17 @@ */ pmd_t * __bad_pmd_table(void) { - extern pmd_t invalid_pmd_table[PTRS_PER_PMD]; - unsigned long page; - - page = (unsigned long) invalid_pmd_table; - pmd_init(page); - - return (pmd_t *) page; + return empty_bad_pmd_table; } pte_t * __bad_pagetable(void) { - extern char empty_bad_page_table[PAGE_SIZE]; - unsigned long page; - - page = (unsigned long) empty_bad_page_table; - pte_init(page); - - return (pte_t *) page; + return empty_bad_page_table; } pte_t __bad_page(void) { - extern char empty_bad_page[PAGE_SIZE]; - unsigned long page = (unsigned long) empty_bad_page; - - clear_page((void *)page); - return pte_mkdirty(mk_pte_phys(__pa(page), PAGE_SHARED)); + return __pte(0); } void show_mem(void) @@ -337,7 +306,7 @@ #ifndef CONFIG_DISCONTIGMEM /* References to section boundaries */ -extern char _ftext, _etext, _fdata, _edata; +extern char _stext, _etext, _fdata, _edata; extern char __init_begin, __init_end; void __init paging_init(void) @@ -347,8 +316,10 @@ /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); - pmd_init((unsigned long)invalid_pmd_table); - memset((void *)invalid_pte_table, 0, sizeof(pte_t) * 2 * PTRS_PER_PTE); + pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); + memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE); + pmd_init((unsigned long)empty_bad_pmd_table, (unsigned long)empty_bad_page_table); + memset((void *)empty_bad_page_table, 0, sizeof(pte_t) * PTRS_PER_PTE); max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; low = max_low_pfn; @@ -384,7 +355,7 @@ reservedpages++; } - codesize = (unsigned long) &_etext - (unsigned long) &_ftext; + codesize = (unsigned long) &_etext - (unsigned long) &_stext; datasize = (unsigned long) &_edata - (unsigned long) &_fdata; initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/mm/r4xx0.c linux/arch/mips64/mm/r4xx0.c --- v2.4.0-test2/linux/arch/mips64/mm/r4xx0.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/mm/r4xx0.c Sun Jul 9 22:18:16 2000 @@ -2545,7 +2545,6 @@ _user_mode = r4k_user_mode; flush_cache_all(); - write_32bit_cp0_register(CP0_WIRED, 0); /* * You should never change this register: diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip22/ip22-setup.c linux/arch/mips64/sgi-ip22/ip22-setup.c --- v2.4.0-test2/linux/arch/mips64/sgi-ip22/ip22-setup.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/sgi-ip22/ip22-setup.c Sun Jul 9 22:18:16 2000 @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -125,6 +126,7 @@ #ifdef CONFIG_SERIAL_CONSOLE char *ctype; #endif + TLBMISS_HANDLER_SETUP(); /* Init the INDY HPC I/O controller. Need to call this before * fucking with the memory controller because it needs to know the diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip27/Makefile linux/arch/mips64/sgi-ip27/Makefile --- v2.4.0-test2/linux/arch/mips64/sgi-ip27/Makefile Tue May 23 15:31:33 2000 +++ linux/arch/mips64/sgi-ip27/Makefile Sun Jul 9 22:18:16 2000 @@ -11,6 +11,6 @@ L_TARGET = ip27.a L_OBJS = ip27-berr.o ip27-irq.o ip27-irq-glue.o ip27-klconfig.o \ ip27-memory.o ip27-pci.o ip27-pci-dma.o ip27-reset.o ip27-setup.o \ - ip27-timer.o ip27-init.o ip27-nmi.o + ip27-timer.o ip27-init.o ip27-nmi.o ip27-klnuma.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-berr.c linux/arch/mips64/sgi-ip27/ip27-berr.c --- v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-berr.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/sgi-ip27/ip27-berr.c Sun Jul 9 22:18:16 2000 @@ -1,5 +1,4 @@ -/* $Id: ip27-berr.c,v 1.1 2000/01/20 22:50:29 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -13,6 +12,9 @@ #include #include #include + +extern void dump_tlb_addr(unsigned long addr); +extern void dump_tlb_all(void); extern asmlinkage void handle_ibe(void); extern asmlinkage void handle_dbe(void); diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-init.c linux/arch/mips64/sgi-ip27/ip27-init.c --- v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-init.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/sgi-ip27/ip27-init.c Sun Jul 9 22:18:16 2000 @@ -1,4 +1,3 @@ -#include #include #include #include @@ -22,6 +21,7 @@ #include #include #include +#include #define CPU_NONE (cpuid_t)-1 @@ -35,12 +35,13 @@ #define CNODEMASK_SETB(p, bit) ((p) |= 1ULL << (bit)) cpumask_t boot_cpumask; -static volatile cpumask_t boot_barrier; hubreg_t region_mask = 0; static int fine_mode = 0; int maxcpus; static spinlock_t hub_mask_lock = SPIN_LOCK_UNLOCKED; static cnodemask_t hub_init_mask; +static atomic_t numstarted = ATOMIC_INIT(1); +nasid_t master_nasid = INVALID_NASID; cnodeid_t nasid_to_compact_node[MAX_NASIDS]; nasid_t compact_to_nasid_node[MAX_COMPACT_NODES]; @@ -160,19 +161,6 @@ return(highest + 1); } -void alloc_cpupda(int i) -{ - cnodeid_t node; - nasid_t nasid; - - node = get_cpu_cnode(i); - nasid = COMPACT_TO_NASID_NODEID(node); - - cputonasid(i) = nasid; - cputocnode(i) = node; - cputoslice(i) = get_cpu_slice(i); -} - int cpu_enabled(cpuid_t cpu) { if (cpu == CPU_NONE) @@ -180,19 +168,11 @@ return (CPUMASK_TSTB(boot_cpumask, cpu) != 0); } -void initpdas(void) -{ - cpuid_t i; - - for (i = 0; i < maxcpus; i++) - if (cpu_enabled(i)) - alloc_cpupda(i); -} - void mlreset (void) { int i; + master_nasid = get_nasid(); fine_mode = is_fine_dirmode(); /* @@ -202,11 +182,12 @@ CPUMASK_CLRALL(boot_cpumask); maxcpus = cpu_node_probe(&boot_cpumask, &numnodes); printk("Discovered %d cpus on %d nodes\n", maxcpus, numnodes); - initpdas(); gen_region_mask(®ion_mask, numnodes); CNODEMASK_CLRALL(hub_init_mask); + setup_replication_mask(numnodes); + /* * Set all nodes' calias sizes to 8k */ @@ -221,7 +202,11 @@ * thinks it is a node 0 address. */ REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1)); +#ifdef CONFIG_REPLICATE_EXHANDLERS + REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K); +#else REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0); +#endif #ifdef LATER /* @@ -283,6 +268,7 @@ void per_hub_init(cnodeid_t cnode) { + extern void pcibr_setup(cnodeid_t); cnodemask_t done; spin_lock(&hub_mask_lock); @@ -290,16 +276,35 @@ if (!(done = CNODEMASK_TSTB(hub_init_mask, cnode))) { /* Turn our bit on in the mask. */ CNODEMASK_SETB(hub_init_mask, cnode); - } - spin_unlock(&hub_mask_lock); - - /* - * Do the actual initialization if it hasn't been done yet. - * We don't need to hold a lock for this work. - */ - if (!done) { + /* + * Do the actual initialization if it hasn't been done yet. + * We don't need to hold a lock for this work. + */ hub_rtc_init(cnode); + pcibr_setup(cnode); +#ifdef CONFIG_REPLICATE_EXHANDLERS + /* + * If this is not a headless node initialization, + * copy over the caliased exception handlers. + */ + if (get_compact_nodeid() == cnode) { + extern char except_vec0, except_vec1_r10k; + extern char except_vec2_generic, except_vec3_generic; + + memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, + 0x80); + memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, + 0x80); + memcpy((void *)KSEG0, &except_vec0, 0x80); + memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80); + memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80); + memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, + 0x100); + flush_cache_all(); + } +#endif } + spin_unlock(&hub_mask_lock); } /* @@ -318,10 +323,11 @@ extern void install_cpu_nmi_handler(int slice); extern void load_mmu(void); static int is_slave = 0; - cpuid_t cpu = getcpuid(); + int cpu = smp_processor_id(); cnodeid_t cnode = get_compact_nodeid(); current_cpu_data.asid_cache = ASID_FIRST_VERSION; + TLBMISS_HANDLER_SETUP(); #if 0 intr_init(); #endif @@ -331,7 +337,7 @@ if (smp_processor_id()) /* master can't do this early, no kmalloc */ install_cpuintr(cpu); /* Install our NMI handler if symmon hasn't installed one. */ - install_cpu_nmi_handler(cputoslice(smp_processor_id())); + install_cpu_nmi_handler(cputoslice(cpu)); #if 0 install_tlbintr(cpu); #endif @@ -343,9 +349,10 @@ set_cp0_status(ST0_KX|ST0_SX|ST0_UX, ST0_KX|ST0_SX|ST0_UX); sti(); load_mmu(); - } - if (is_slave == 0) + atomic_inc(&numstarted); + } else { is_slave = 1; + } } cnodeid_t get_compact_nodeid(void) @@ -362,6 +369,24 @@ #ifdef CONFIG_SMP +/* + * Takes as first input the PROM assigned cpu id, and the kernel + * assigned cpu id as the second. + */ +static void alloc_cpupda(cpuid_t cpu, int cpunum) +{ + cnodeid_t node; + nasid_t nasid; + + node = get_cpu_cnode(cpu); + nasid = COMPACT_TO_NASID_NODEID(node); + + cputonasid(cpunum) = nasid; + cputocnode(cpunum) = node; + cputoslice(cpunum) = get_cpu_slice(cpu); + cpu_data[cpunum].p_cpuid = cpu; +} + void __init smp_callin(void) { #if 0 @@ -380,10 +405,10 @@ return cpu_idle(); } -static atomic_t numstarted = ATOMIC_INIT(0); +static volatile cpumask_t boot_barrier; + void cboot(void) { - atomic_inc(&numstarted); CPUMASK_CLRB(boot_barrier, getcpuid()); /* needs atomicity */ per_cpu_init(); #if 0 @@ -399,22 +424,24 @@ void allowboot(void) { int num_cpus = 0; - cpuid_t cpu; + cpuid_t cpu, mycpuid = getcpuid(); cnodeid_t cnode; extern void bootstrap(void); sn_mp_setup(); /* Master has already done per_cpu_init() */ - install_cpuintr(getcpuid()); + install_cpuintr(smp_processor_id()); #if 0 bte_lateinit(); ecc_init(); #endif + replicate_kernel_text(numnodes); boot_barrier = boot_cpumask; /* Launch slaves. */ for (cpu = 0; cpu < maxcpus; cpu++) { - if (cpu == smp_processor_id()) { + if (cpu == mycpuid) { + alloc_cpupda(cpu, num_cpus); num_cpus++; /* We're already started, clear our bit */ CPUMASK_CLRB(boot_barrier, cpu); @@ -433,6 +460,7 @@ p = init_task.prev_task; sprintf(p->comm, "%s%d", "Idle", num_cpus); init_tasks[num_cpus] = p; + alloc_cpupda(cpu, num_cpus); p->processor = num_cpus; p->has_cpu = 1; /* we schedule the first task manually */ del_from_runqueue(p); @@ -448,10 +476,10 @@ * created idle process, gp to the proc struct * (so that current-> works). */ - LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu), - (launch_proc_t)bootstrap, 0, - (void *)((unsigned long)p+KERNEL_STACK_SIZE - 32), - (void *)p); + LAUNCH_SLAVE(cputonasid(num_cpus),cputoslice(num_cpus), + (launch_proc_t)MAPPED_KERN_RW_TO_K0(bootstrap), + 0, (void *)((unsigned long)p + + KERNEL_STACK_SIZE - 32), (void *)p); /* * Now optimistically set the mapping arrays. We @@ -461,13 +489,18 @@ __cpu_number_map[cpu] = num_cpus; __cpu_logical_map[num_cpus] = cpu; num_cpus++; - /* smp_num_cpus++; Do after smp_send_reschedule works */ + /* + * Wait this cpu to start up and initialize its hub, + * and discover the io devices it will control. + * + * XXX: We really want to fire up launch all the CPUs + * at once. We have to preserve the order of the + * devices on the bridges first though. + */ + while(atomic_read(&numstarted) != num_cpus); } } - /* while(atomic_read(&numstarted) != (maxcpus - num_cpus)) */ - if (maxcpus > 1) while(atomic_read(&numstarted) == 0); - printk("Holding %d cpus slave\n", atomic_read(&numstarted)); #ifdef LATER Wait logic goes here. @@ -484,6 +517,7 @@ cpu_io_setup(); init_mfhi_war(); #endif + smp_num_cpus = num_cpus; } #else /* CONFIG_SMP */ diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-irq.c linux/arch/mips64/sgi-ip27/ip27-irq.c --- v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-irq.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/sgi-ip27/ip27-irq.c Sun Jul 9 22:18:16 2000 @@ -1,11 +1,9 @@ -/* $Id: ip27-irq.c,v 1.9 2000/03/14 01:39:27 ralf Exp $ - * +/* * ip27-irq.c: Highlevel interrupt handling for IP27 architecture. * - * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ -#include #include #include @@ -20,11 +18,11 @@ #include #include #include +#include #include #include #include -#include #include #include @@ -64,9 +62,10 @@ irq_cpustat_t irq_stat [NR_CPUS]; extern asmlinkage void ip27_irq(void); +extern int irq_to_bus[], irq_to_slot[], bus_to_cpu[]; int (*irq_cannonicalize)(int irq); -int intr_connect_level(cpuid_t cpu, int bit); -int intr_disconnect_level(cpuid_t cpu, int bit); +int intr_connect_level(int cpu, int bit); +int intr_disconnect_level(int cpu, int bit); unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; @@ -76,15 +75,17 @@ * we need to map irq's up to at least bit 7 of the INT_MASK0_A register * since bits 0-6 are pre-allocated for other purposes. */ -#define IRQ_TO_SWLEVEL(i) i + 7 -#define SWLEVEL_TO_IRQ(s) s - 7 +#define IRQ_TO_SWLEVEL(cpu, i) i + 7 +#define SWLEVEL_TO_IRQ(cpu, s) s - 7 /* - * use these macros to get the encoded nasid, widget id, and real irq + * use these macros to get the encoded nasid and widget id * from the irq value */ -#define NASID_FROM_IRQ(i) ((i >> 16)&(0xff)) -#define WID_FROM_IRQ(i) ((i >> 8)&(0xff)) -#define IRQ_FROM_IRQ(i) ((i)&(0xff)) +#define IRQ_TO_BUS(i) irq_to_bus[(i)] +#define IRQ_TO_CPU(i) bus_to_cpu[IRQ_TO_BUS(i)] +#define NASID_FROM_PCI_IRQ(i) bus_to_nid[IRQ_TO_BUS(i)] +#define WID_FROM_PCI_IRQ(i) bus_to_wid[IRQ_TO_BUS(i)] +#define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i] void disable_irq(unsigned int irq_nr) { @@ -104,7 +105,7 @@ int i, len = 0; struct irqaction * action; - for (i = 0 ; i < 32 ; i++) { + for (i = 0 ; i < NR_IRQS ; i++) { action = irq_action[i]; if (!action) continue; @@ -126,20 +127,18 @@ * do_IRQ handles all normal device IRQ's (the special SMP cross-CPU interrupts * have their own specific handlers). */ -asmlinkage void do_IRQ(int irq, struct pt_regs * regs) +static void do_IRQ(cpuid_t thiscpu, int irq, struct pt_regs * regs) { struct irqaction *action; - int do_random, cpu; + int do_random; - cpu = smp_processor_id(); - irq_enter(cpu, irq); - kstat.irqs[cpu][irq]++; + irq_enter(thiscpu, irq); + kstat.irqs[thiscpu][irq]++; action = *(irq + irq_action); if (action) { if (!(action->flags & SA_INTERRUPT)) __sti(); - action = *(irq + irq_action); do_random = 0; do { do_random |= action->flags; @@ -150,7 +149,7 @@ add_interrupt_randomness(irq); __cli(); } - irq_exit(cpu, irq); + irq_exit(thiscpu, irq); /* unmasking and bottom half handling is done magically for us. */ } @@ -171,31 +170,46 @@ return b + (int) (x >> 1); } - -/* For now ... */ + +/* + * This code is unnecessarily complex, because we do SA_INTERRUPT + * intr enabling. Basically, once we grab the set of intrs we need + * to service, we must mask _all_ these interrupts; firstly, to make + * sure the same intr does not intr again, causing recursion that + * can lead to stack overflow. Secondly, we can not just mask the + * one intr we are do_IRQing, because the non-masked intrs in the + * first set might intr again, causing multiple servicings of the + * same intr. This effect is mostly seen for intercpu intrs. + * Kanoj 05.13.00 + */ void ip27_do_irq(struct pt_regs *regs) { int irq, swlevel; hubreg_t pend0, mask0; - int pi_int_mask0 = ((cputoslice(smp_processor_id()) == 0) ? + cpuid_t thiscpu = smp_processor_id(); + int pi_int_mask0 = ((cputoslice(thiscpu) == 0) ? PI_INT_MASK0_A : PI_INT_MASK0_B); /* copied from Irix intpend0() */ while (((pend0 = LOCAL_HUB_L(PI_INT_PEND0)) & (mask0 = LOCAL_HUB_L(pi_int_mask0))) != 0) { - pend0 &= mask0; - do { - swlevel = ms1bit(pend0); - LOCAL_HUB_S(pi_int_mask0, mask0 & ~(1 << swlevel)); - LOCAL_HUB_CLR_INTR(swlevel); - /* "map" swlevel to irq */ - irq = SWLEVEL_TO_IRQ(swlevel); - do_IRQ(irq, regs); - /* reset INT_MASK0 register */ + pend0 &= mask0; /* Pick intrs we should look at */ + if (pend0) { + /* Prevent any of the picked intrs from recursing */ + LOCAL_HUB_S(pi_int_mask0, mask0 & ~(pend0)); + do { + swlevel = ms1bit(pend0); + LOCAL_HUB_CLR_INTR(swlevel); + /* "map" swlevel to irq */ + irq = SWLEVEL_TO_IRQ(thiscpu, swlevel); + do_IRQ(thiscpu, irq, regs); + /* clear bit in pend0 */ + pend0 ^= 1ULL << swlevel; + } while(pend0); + /* Now allow the set of serviced intrs again */ LOCAL_HUB_S(pi_int_mask0, mask0); - /* clear bit in pend0 */ - pend0 ^= 1ULL << swlevel; - } while (pend0); + LOCAL_HUB_L(PI_INT_PEND0); + } } } @@ -203,69 +217,38 @@ /* Startup one of the (PCI ...) IRQs routes over a bridge. */ static unsigned int bridge_startup(unsigned int irq) { - bridge_t *bridge; - int pin, swlevel; - int real_irq = IRQ_FROM_IRQ(irq); - - DBG("bridge_startup(): irq= 0x%x real_irq= %d\n", irq, real_irq); - bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_IRQ(irq), WID_FROM_IRQ(irq)); - - /* FIIIIIXME ... Temporary kludge. This knows how interrupts are - setup in _my_ Origin. */ - - if (irq != real_irq) /* pci device interrupt */ - switch (real_irq) { - case IRQ_FROM_IRQ(IOC3_ETH_INT): pin = 2; break; - default: pin = real_irq; break; - } - else - switch (real_irq) { - case CPU_RESCHED_A_IRQ: - case CPU_RESCHED_B_IRQ: - case CPU_CALL_A_IRQ: - case CPU_CALL_B_IRQ: - return 0; - default: panic("bridge_startup: whoops? %d\n", irq); - } - - /* - * "map" irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - swlevel = IRQ_TO_SWLEVEL(real_irq); - intr_connect_level(smp_processor_id(), swlevel); - - bridge->b_int_addr[pin].addr = 0x20000 | swlevel; - bridge->b_int_enable |= (1 << pin); - /* set more stuff in int_enable reg */ + bridgereg_t device; + bridge_t *bridge; + int pin, swlevel; + cpuid_t cpu; + nasid_t master = NASID_FROM_PCI_IRQ(irq); + + bridge = (bridge_t *) NODE_SWIN_BASE(master, WID_FROM_PCI_IRQ(irq)); + pin = SLOT_FROM_PCI_IRQ(irq); + cpu = IRQ_TO_CPU(irq); + + DBG("bridge_startup(): irq= 0x%x pin=%d\n", irq, pin); + /* + * "map" irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken + */ + swlevel = IRQ_TO_SWLEVEL(cpu, irq); + intr_connect_level(cpu, swlevel); + + bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (master << 8)); + bridge->b_int_enable |= (1 << pin); + /* more stuff in int_enable reg */ bridge->b_int_enable |= 0x7ffffe00; - if (real_irq < 2 || real_irq==4 || real_irq==5) { - bridgereg_t device; -#if 0 - /* - * Allocate enough RRBs on the bridge for the DMAs. - * Right now allocating 2 RRBs on the normal channel - * and 2 on the virtual channel for slot 0 on the bus. - * And same for slot 1, to get ioc3 eth working. - */ - Not touching b_even_resp /* boot doesn't go far */ - bridge->b_even_resp = 0xdd99cc88; /* boot doesn't go far */ - bridge->b_even_resp = 0xcccc8888; /* breaks eth0 */ - bridge->b_even_resp = 0xcc88; /* breaks eth0 */ -#endif - /* Turn on bridge swapping */ - device = bridge->b_device[real_irq].reg; - device |= BRIDGE_DEV_SWAP_DIR; - bridge->b_device[real_irq].reg = device; - /* - * Associate interrupt pin with device - * XXX This only works if b_int_device is initialized to 0! - */ - device = bridge->b_int_device; - device |= (pin << (real_irq*3)); - bridge->b_int_device = device; - } + /* + * XXX This only works if b_int_device is initialized to 0! + * We program the bridge to have a 1:1 mapping between devices + * (slots) and intr pins. + */ + device = bridge->b_int_device; + device |= (pin << (pin*3)); + bridge->b_int_device = device; + bridge->b_widget.w_tflush; /* Flush */ return 0; /* Never anything pending. */ @@ -274,70 +257,25 @@ /* Shutdown one of the (PCI ...) IRQs routes over a bridge. */ static unsigned int bridge_shutdown(unsigned int irq) { - bridge_t *bridge; - int pin, swlevel; - int real_irq = IRQ_FROM_IRQ(irq); - struct irqaction **p; + bridge_t *bridge; + int pin, swlevel; - bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_IRQ(irq), WID_FROM_IRQ(irq)); + bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_PCI_IRQ(irq), + WID_FROM_PCI_IRQ(irq)); DBG("bridge_shutdown: irq 0x%x\n", irq); - /* FIIIIIXME ... Temporary kludge. This knows how interrupts are - setup in _my_ Origin. */ + pin = SLOT_FROM_PCI_IRQ(irq); - if (irq != real_irq) /* pci device interrupt */ - switch (real_irq) { - case IRQ_FROM_IRQ(IOC3_ETH_INT): pin = 2; break; - default: pin = real_irq; break; - } - else - switch (real_irq) { - case CPU_RESCHED_A_IRQ: - case CPU_RESCHED_B_IRQ: - case CPU_CALL_A_IRQ: - case CPU_CALL_B_IRQ: - return 0; - default: panic("bridge_startup: whoops?"); - } - - /* - * map irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - swlevel = IRQ_TO_SWLEVEL(real_irq); - intr_disconnect_level(smp_processor_id(), swlevel); + /* + * map irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken + */ + swlevel = IRQ_TO_SWLEVEL(cpu, irq); + intr_disconnect_level(smp_processor_id(), swlevel); - bridge->b_int_enable &= ~(1 << pin); - bridge->b_widget.w_tflush; /* Flush */ + bridge->b_int_enable &= ~(1 << pin); + bridge->b_widget.w_tflush; /* Flush */ - return 0; /* Never anything pending. */ -} - -static void bridge_init(void) -{ - bridge_t *bridge; - nasid_t nasid; - char wid; - int bus; - - nasid = get_nasid(); - - for (bus=0; busb_int_mode = 0x0; /* Don't clear ints */ -#if 0 - bridge->b_wid_int_upper = 0x000a8000; /* Ints to node 0 */ - bridge->b_wid_int_lower = 0x01000090; - bridge->b_dir_map = 0xa00000; /* DMA */ -#endif /* shouldn't lower= 0x01800090 ??? */ - bridge->b_wid_int_upper = 0x000a8000; /* Ints to widget A */ - bridge->b_wid_int_lower = 0x01800090; - bridge->b_dir_map = 0xa00000; /* DMA */ - - bridge->b_int_enable = 0; - bridge->b_widget.w_tflush; /* Flush */ - } + return 0; /* Never anything pending. */ } void irq_debug(void) @@ -346,8 +284,8 @@ printk("bridge->b_int_status = 0x%x\n", bridge->b_int_status); printk("bridge->b_int_enable = 0x%x\n", bridge->b_int_enable); - printk("PI_INT_PEND0 = 0x%x\n", LOCAL_HUB_L(PI_INT_PEND0)); - printk("PI_INT_MASK0_A = 0x%x\n", LOCAL_HUB_L(PI_INT_MASK0_A)); + printk("PI_INT_PEND0 = 0x%lx\n", LOCAL_HUB_L(PI_INT_PEND0)); + printk("PI_INT_MASK0_A = 0x%lx\n", LOCAL_HUB_L(PI_INT_MASK0_A)); } int setup_irq(unsigned int irq, struct irqaction *new) @@ -357,11 +295,15 @@ unsigned long flags; DBG("setup_irq: 0x%x\n", irq); + if (irq >= NR_IRQS) { + printk("IRQ array overflow %d\n", irq); + while(1); + } if (new->flags & SA_SAMPLE_RANDOM) rand_initialize_irq(irq); save_and_cli(flags); - p = irq_action + IRQ_FROM_IRQ(irq); + p = irq_action + irq; if ((old = *p) != NULL) { /* Can't share interrupts unless both agree to */ if (!(old->flags & new->flags & SA_SHIRQ)) { @@ -379,7 +321,7 @@ *p = new; - if (!shared) { + if ((!shared) && (irq >= BASE_PCI_IRQ)) { bridge_startup(irq); } restore_flags(flags); @@ -395,8 +337,6 @@ struct irqaction *action; DBG("request_irq(): irq= 0x%x\n", irq); - if (IRQ_FROM_IRQ(irq) > 9) - return -EINVAL; if (!handler) return -EINVAL; @@ -424,18 +364,18 @@ struct irqaction * action, **p; unsigned long flags; - if (IRQ_FROM_IRQ(irq) > 9) { + if (irq >= NR_IRQS) { printk("Trying to free IRQ%d\n", irq); return; } - for (p = IRQ_FROM_IRQ(irq) + irq_action; (action = *p) != NULL; p = &action->next) { + for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { if (action->dev_id != dev_id) continue; /* Found it - now free it */ save_and_cli(flags); *p = action->next; - if (!irq[irq_action]) + if (irq >= BASE_PCI_IRQ) bridge_shutdown(irq); restore_flags(flags); kfree(action); @@ -465,7 +405,6 @@ { irq_cannonicalize = indy_irq_cannonicalize; - bridge_init(); set_except_vector(0, ip27_irq); } @@ -675,7 +614,7 @@ return hub_intmasks; } -int intr_connect_level(cpuid_t cpu, int bit) +int intr_connect_level(int cpu, int bit) { int ip; int slice = cputoslice(cpu); @@ -701,7 +640,7 @@ return(0); } -int intr_disconnect_level(cpuid_t cpu, int bit) +int intr_disconnect_level(int cpu, int bit) { int ip; int slice = cputoslice(cpu); @@ -728,11 +667,14 @@ /* Nothing, the return from intr will work for us */ } -void install_cpuintr(cpuid_t cpu) +extern void smp_call_function_interrupt(void); + +void install_cpuintr(int cpu) { - int irq; - extern void smp_call_function_interrupt(void); +#ifdef CONFIG_SMP +#if (CPUS_PER_NODE == 2) static int done = 0; + int irq; /* * This is a hack till we have a pernode irqlist. Currently, @@ -740,15 +682,13 @@ * cpu irqs. */ -#ifdef CONFIG_SMP -#if (CPUS_PER_NODE == 2) irq = CPU_RESCHED_A_IRQ + cputoslice(cpu); - intr_connect_level(cpu, IRQ_TO_SWLEVEL(irq)); + intr_connect_level(cpu, IRQ_TO_SWLEVEL(cpu, irq)); if (done == 0) if (request_irq(irq, handle_resched_intr, 0, "resched", 0)) panic("intercpu intr unconnectible\n"); irq = CPU_CALL_A_IRQ + cputoslice(cpu); - intr_connect_level(cpu, IRQ_TO_SWLEVEL(irq)); + intr_connect_level(cpu, IRQ_TO_SWLEVEL(cpu, irq)); if (done == 0) if (request_irq(irq, smp_call_function_interrupt, 0, "callfunc", 0)) @@ -766,12 +706,12 @@ done = 1; /* HACK ENDS */ #else /* CPUS_PER_NODE */ - << Bomb! Must redefine this for more than 2 CPUS. >> +#error Must redefine this for more than 2 CPUS. #endif /* CPUS_PER_NODE */ #endif /* CONFIG_SMP */ } -void install_tlbintr(cpuid_t cpu) +void install_tlbintr(int cpu) { int intr_bit = N_INTPEND_BITS + TLB_INTR_A + cputoslice(cpu); diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-klconfig.c linux/arch/mips64/sgi-ip27/ip27-klconfig.c --- v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-klconfig.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/sgi-ip27/ip27-klconfig.c Sun Jul 9 22:18:16 2000 @@ -61,7 +61,7 @@ return (lboard_t *)NULL; } -cnodeid_t get_cpu_cnode(int cpu) +cnodeid_t get_cpu_cnode(cpuid_t cpu) { return CPUID_TO_COMPACT_NODEID(cpu); } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-klnuma.c linux/arch/mips64/sgi-ip27/ip27-klnuma.c --- v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-klnuma.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/sgi-ip27/ip27-klnuma.c Sun Jul 9 22:18:16 2000 @@ -0,0 +1,147 @@ +/* + * Ported from IRIX to Linux by Kanoj Sarcar, 06/08/00. + * Copyright 2000 Silicon Graphics, Inc. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define CPUMASK_CLRALL(p) (p) = 0 +#define CPUMASK_SETB(p, bit) (p) |= 1 << (bit) +#define CPUMASK_TSTB(p, bit) ((p) & (1ULL << (bit))) + +extern char _end; +static cpumask_t ktext_repmask; + +/* + * XXX - This needs to be much smarter about where it puts copies of the + * kernel. For example, we should never put a copy on a headless node, + * and we should respect the topology of the machine. + */ +void __init setup_replication_mask(int maxnodes) +{ + static int numa_kernel_replication_ratio; + cnodeid_t cnode; + + /* Set only the master cnode's bit. The master cnode is always 0. */ + CPUMASK_CLRALL(ktext_repmask); + CPUMASK_SETB(ktext_repmask, 0); + + numa_kernel_replication_ratio = 0; +#ifdef CONFIG_REPLICATE_KTEXT +#ifndef CONFIG_MAPPED_KERNEL +#error Kernel replication works with mapped kernel support. No calias support. +#endif + numa_kernel_replication_ratio = 1; +#endif + + for (cnode = 1; cnode < numnodes; cnode++) { + /* See if this node should get a copy of the kernel */ + if (numa_kernel_replication_ratio && + !(cnode % numa_kernel_replication_ratio)) { + + /* Advertise that we have a copy of the kernel */ + CPUMASK_SETB(ktext_repmask, cnode); + } + } + + /* Set up a GDA pointer to the replication mask. */ + GDA->g_ktext_repmask = &ktext_repmask; +} + + +static __init void set_ktext_source(nasid_t client_nasid, nasid_t server_nasid) +{ + kern_vars_t *kvp; + cnodeid_t client_cnode; + + client_cnode = NASID_TO_COMPACT_NODEID(client_nasid); + + kvp = &(PLAT_NODE_DATA(client_cnode)->kern_vars); + + KERN_VARS_ADDR(client_nasid) = (unsigned long)kvp; + + kvp->kv_magic = KV_MAGIC; + + kvp->kv_ro_nasid = server_nasid; + kvp->kv_rw_nasid = master_nasid; + kvp->kv_ro_baseaddr = NODE_CAC_BASE(server_nasid); + kvp->kv_rw_baseaddr = NODE_CAC_BASE(master_nasid); + printk("REPLICATION: ON nasid %d, ktext from nasid %d, kdata from nasid %d\n", client_nasid, server_nasid, master_nasid); +} + +/* XXX - When the BTE works, we should use it instead of this. */ +static __init void copy_kernel(nasid_t dest_nasid) +{ + extern char _stext, _etext; + unsigned long dest_kern_start, source_start, source_end, kern_size; + + source_start = (unsigned long)&_stext; + source_end = (unsigned long)&_etext; + kern_size = source_end - source_start; + + dest_kern_start = CHANGE_ADDR_NASID(MAPPED_KERN_RO_TO_K0(source_start), + dest_nasid); + memcpy((void *)dest_kern_start, (void *)source_start, kern_size); +} + +void __init replicate_kernel_text(int maxnodes) +{ + cnodeid_t cnode; + nasid_t client_nasid; + nasid_t server_nasid; + + server_nasid = master_nasid; + + /* Record where the master node should get its kernel text */ + set_ktext_source(master_nasid, master_nasid); + + for (cnode = 1; cnode < maxnodes; cnode++) { + client_nasid = COMPACT_TO_NASID_NODEID(cnode); + + /* Check if this node should get a copy of the kernel */ + if (CPUMASK_TSTB(ktext_repmask, cnode)) { + server_nasid = client_nasid; + copy_kernel(server_nasid); + } + + /* Record where this node should get its kernel text */ + set_ktext_source(client_nasid, server_nasid); + } +} + +/* + * Return pfn of first free page of memory on a node. PROM may allocate + * data structures on the first couple of pages of the first slot of each + * node. If this is the case, getfirstfree(node) > getslotstart(node, 0). + */ +pfn_t node_getfirstfree(cnodeid_t cnode) +{ + unsigned long loadbase = CKSEG0; + nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); + unsigned long offset; + +#ifdef CONFIG_MAPPED_KERNEL + loadbase = CKSSEG + 16777216; +#endif + offset = PAGE_ALIGN((unsigned long)(&_end)) - loadbase; + if (cnode == 0) + return (offset >> PAGE_SHIFT); + else if (CPUMASK_TSTB(ktext_repmask, cnode)) + return (TO_NODE(nasid, offset) >> PAGE_SHIFT); + else + return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> + PAGE_SHIFT); +} + diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-memory.c linux/arch/mips64/sgi-ip27/ip27-memory.c --- v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-memory.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/sgi-ip27/ip27-memory.c Sun Jul 9 22:18:16 2000 @@ -1,5 +1,4 @@ -/* $Id: ip27-memory.c,v 1.2 2000/01/27 01:05:24 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -27,10 +26,8 @@ #include #include -typedef unsigned long pfn_t; /* into */ -#define KDM_TO_PHYS(x) ((x) & TO_PHYS_MASK) /* into asm/addrspace.h */ - -extern char _end; +/* ip27-klnuma.c */ +extern pfn_t node_getfirstfree(cnodeid_t cnode); #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) #define SLOT_IGNORED 0xffff @@ -38,7 +35,6 @@ short slot_lastfilled_cache[MAX_COMPACT_NODES]; unsigned short slot_psize_cache[MAX_COMPACT_NODES][MAX_MEM_SLOTS]; static pfn_t numpages; -static pfn_t pagenr = 0; plat_pg_data_t *plat_node_data[MAX_COMPACT_NODES]; bootmem_data_t plat_node_bdata[MAX_COMPACT_NODES]; @@ -46,26 +42,11 @@ int numa_debug(void) { printk("NUMA debug\n"); - BUG(); + *(int *)0 = 0; return(0); } /* - * Return pfn of first free page of memory on a node. PROM may allocate - * data structures on the first couple of pages of the first slot of each - * node. If this is the case, getfirstfree(node) > getslotstart(node, 0). - */ -pfn_t node_getfirstfree(cnodeid_t cnode) -{ - nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); - - if (cnode == 0) - return (KDM_TO_PHYS(PAGE_ALIGN((unsigned long)(&_end)) - - (CKSEG0 - K0BASE)) >> PAGE_SHIFT); - return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> PAGE_SHIFT); -} - -/* * Return the number of pages of memory provided by the given slot * on the specified node. */ @@ -261,6 +242,8 @@ #ifdef CONFIG_DISCONTIGMEM +static pfn_t pagenr = 0; + void __init paging_init(void) { cnodeid_t node; @@ -268,8 +251,10 @@ /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); - pmd_init((unsigned long)invalid_pmd_table); - memset((void *)invalid_pte_table, 0, sizeof(pte_t) * 2 * PTRS_PER_PTE); + pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); + memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE); + pmd_init((unsigned long)empty_bad_pmd_table, (unsigned long)empty_bad_page_table); + memset((void *)empty_bad_page_table, 0, sizeof(pte_t) * PTRS_PER_PTE); for (node = 0; node < numnodes; node++) { pfn_t start_pfn = slot_getbasepfn(node, 0); @@ -287,7 +272,7 @@ void __init mem_init(void) { - extern char _ftext, _etext, _fdata, _edata; + extern char _stext, _etext, _fdata, _edata; extern char __init_begin, __init_end; extern unsigned long totalram_pages; extern unsigned long setup_zero_pages(void); @@ -367,7 +352,7 @@ } } - codesize = (unsigned long) &_etext - (unsigned long) &_ftext; + codesize = (unsigned long) &_etext - (unsigned long) &_stext; datasize = (unsigned long) &_edata - (unsigned long) &_fdata; initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-nmi.c linux/arch/mips64/sgi-ip27/ip27-nmi.c --- v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-nmi.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/sgi-ip27/ip27-nmi.c Sun Jul 9 22:18:16 2000 @@ -145,6 +145,10 @@ cpu = CNODE_TO_CPU_BASE(node); for (n=0; n < CNODE_NUM_CPUS(node); cpu++, n++) { CPUMASK_SETB(nmied_cpus, cpu); + /* + * cputonasid, cputoslice + * needs kernel cpuid + */ SEND_NMI((cputonasid(cpu)), (cputoslice(cpu))); } } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-pci.c linux/arch/mips64/sgi-ip27/ip27-pci.c --- v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-pci.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/sgi-ip27/ip27-pci.c Sun Jul 9 22:18:16 2000 @@ -1,5 +1,4 @@ -/* $Id: ip27-pci.c,v 1.8 2000/02/16 01:07:30 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -17,6 +16,28 @@ #include /* + * Max #PCI busses we can handle; ie, max #PCI bridges. + */ +#define MAX_PCI_BUSSES 20 + +/* + * Max #PCI devices (like scsi controllers) we handle on a bus. + */ +#define MAX_DEVICES_PER_PCIBUS 8 + +/* + * No locking needed until PCI initialization is done parallely. + */ +int irqstore[MAX_PCI_BUSSES][MAX_DEVICES_PER_PCIBUS]; +int lastirq = BASE_PCI_IRQ; + +/* + * Translate from irq to software PCI bus number and PCI slot. + */ +int irq_to_bus[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; +int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; + +/* * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is * not really documented, so right now I can't write code which uses it. * Therefore we use type 0 accesses for now even though they won't work @@ -123,13 +144,12 @@ void __init pcibios_init(void) { struct pci_ops *ops = &bridge_pci_ops; - nasid_t nid = get_nasid(); int i; ioport_resource.end = ~0UL; for (i=0; idevfn); } -/* XXX This should include the node ID into the final interrupt number. */ +/* + * All observed requests have pin == 1. We could have a global here, that + * gets incremented and returned every time - unfortunately, pci_map_irq + * may be called on the same device over and over, and need to return the + * same value. On o2000, pin can be 0 or 1, and PCI slots can be [0..7]. + * + * A given PCI device, in general, should be able to intr any of the cpus + * on any one of the hubs connected to its xbow. + */ static int __init pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - int rv; - rv = (slot + (((pin-1) & 1) << 2)) & 7; - rv |= (bus_to_wid[dev->bus->number] << 8); - rv |= (bus_to_nid[dev->bus->number] << 16); - return rv; + if ((dev->bus->number >= MAX_PCI_BUSSES) || (pin != 1) || \ + (slot >= MAX_DEVICES_PER_PCIBUS)) { + printk("Increase supported PCI busses %d,%d,%d\n", \ + dev->bus->number, slot, pin); + while(1); + } + + /* + * Already assigned? Then return previously assigned value ... + */ + if (irqstore[dev->bus->number][slot]) + return(irqstore[dev->bus->number][slot]); + else { + lastirq++; /* IOC3_ETH_INT hack */ + irq_to_bus[lastirq] = dev->bus->number; + irq_to_slot[lastirq] = slot; + return(irqstore[dev->bus->number][slot] = lastirq); + } } void __init @@ -222,8 +263,41 @@ } static void __init +pci_disable_swapping(struct pci_dev *dev) +{ + unsigned int bus_id = (unsigned) dev->bus->number; + bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], + bus_to_wid[bus_id]); + int slot = PCI_SLOT(dev->devfn); + bridgereg_t devreg; + + devreg = bridge->b_device[slot].reg; + devreg &= ~BRIDGE_DEV_SWAP_DIR; /* turn off byte swapping */ + bridge->b_device[slot].reg = devreg; + + bridge->b_widget.w_tflush; /* Flush */ +} + +static void __init +pci_enable_swapping(struct pci_dev *dev) +{ + unsigned int bus_id = (unsigned) dev->bus->number; + bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], + bus_to_wid[bus_id]); + int slot = PCI_SLOT(dev->devfn); + bridgereg_t devreg; + + devreg = bridge->b_device[slot].reg; + devreg |= BRIDGE_DEV_SWAP_DIR; /* turn on byte swapping */ + bridge->b_device[slot].reg = devreg; + + bridge->b_widget.w_tflush; /* Flush */ +} + +static void __init pci_fixup_ioc3(struct pci_dev *d) { + unsigned int bus_id = (unsigned) d->bus->number; int i; /* IOC3 only decodes 0x20 bytes of the config space, so we end up @@ -232,6 +306,9 @@ use INTA. */ printk("PCI: Fixing base addresses for IOC3 device %s\n", d->slot_name); + d->resource[0].start |= NODE_OFFSET(bus_to_nid[bus_id]); + d->resource[0].end |= NODE_OFFSET(bus_to_nid[bus_id]); + for (i = 1; i <= PCI_ROM_RESOURCE; i++) { d->resource[i].start = 0UL; d->resource[i].end = 0UL; @@ -240,6 +317,8 @@ d->subsystem_vendor = 0; d->subsystem_device = 0; d->irq = 1; + + pci_disable_swapping(d); } static void __init @@ -247,24 +326,25 @@ { unsigned short command; + d->resource[0].start |= ((unsigned long)(bus_to_nid[d->bus->number])<<32); printk("PCI: Fixing isp1020 in [bus:slot.fn] %s\n", d->slot_name); /* Configure device to allow bus mastering, i/o and memory mapping. * Older qlogicisp driver expects to have the IO space enable - * bit set. Things stop working if we program the controllers as not having - * PCI_COMMAND_MEMORY, so we have to fudge the mem_flags. + * bit set. Things stop working if we program the controllers as not + * having PCI_COMMAND_MEMORY, so we have to fudge the mem_flags. */ - /* only turn on scsi's on main bus */ - if (d->bus->number == 0) { - pci_set_master(d); - pci_read_config_word(d, PCI_COMMAND, &command); - command |= PCI_COMMAND_MEMORY; - command |= PCI_COMMAND_IO; - pci_write_config_word(d, PCI_COMMAND, command); - d->resource[1].flags |= 1; - } + pci_set_master(d); + pci_read_config_word(d, PCI_COMMAND, &command); + command |= PCI_COMMAND_MEMORY; + command |= PCI_COMMAND_IO; + pci_write_config_word(d, PCI_COMMAND, command); + d->resource[1].flags |= 1; + + pci_enable_swapping(d); } + static void __init pci_fixup_isp2x00(struct pci_dev *d) { @@ -280,7 +360,7 @@ printk("PCI: Fixing isp2x00 in [bus:slot.fn] %s\n", d->slot_name); /* set the resource struct for this device */ - start = (u32) bridge; /* yes, we want to lose the upper 32 bits here */ + start = (u32) (u64)bridge; /* yes, we want to lose the upper 32 bits here */ start |= BRIDGE_DEVIO(slot); d->resource[0].start = start; @@ -298,12 +378,10 @@ /* point device(x) to it appropriate small window */ devreg &= ~BRIDGE_DEV_OFF_MASK; devreg |= (start >> 20) & BRIDGE_DEV_OFF_MASK; - - /* turn on byte swapping in direct map mode (how we currently run dma's) */ - devreg |= BRIDGE_DEV_SWAP_DIR; /* turn on byte swapping */ - bridge->b_device[slot].reg = devreg; + pci_enable_swapping(d); + /* set card's base addr reg */ //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x500001); //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, 0x8b00000); @@ -317,7 +395,6 @@ pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, start); //pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, (start | 0x20000)); - /* set cache line size */ pci_conf0_write_config_dword(d, PCI_CACHE_LINE_SIZE, 0xf080); @@ -329,7 +406,7 @@ /* set host error field */ bridge->b_int_host_err = 0x44; bridge->b_wid_tflush; - + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ for (i=0; i<8; i++) printk("PCI: device(%d)= 0x%x\n",i,bridge->b_device[i].reg); diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-reset.c linux/arch/mips64/sgi-ip27/ip27-reset.c --- v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-reset.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/sgi-ip27/ip27-reset.c Sun Jul 9 22:18:16 2000 @@ -1,13 +1,12 @@ -/* $Id$ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Reset an IP27. * - * Copyright (C) 1997, 1998, 1999 by Ralf Baechle - * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1997, 1998, 1999, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include #include @@ -19,8 +18,6 @@ #include #include #include -#include -#include #include #include #include @@ -30,10 +27,14 @@ void machine_halt(void) __attribute__((noreturn)); void machine_power_off(void) __attribute__((noreturn)); +#define noreturn while(1); /* Silence gcc. */ + /* XXX How to pass the reboot command to the firmware??? */ void machine_restart(char *command) { +#if 0 int i; +#endif printk("Reboot started from CPU %d\n", smp_processor_id()); #ifdef CONFIG_SMP @@ -42,20 +43,31 @@ #if 0 for (i = 0; i < numnodes; i++) REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG, - PROMOP_RESTART); + PROMOP_REBOOT); #else LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET); #endif + noreturn; } void machine_halt(void) { - ArcEnterInteractiveMode(); + int i; + +#ifdef CONFIG_SMP + smp_send_stop(); +#endif + for (i = 0; i < numnodes; i++) + REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG, + PROMOP_RESTART); + LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET); + noreturn; } void machine_power_off(void) { /* To do ... */ + noreturn; } void ip27_reboot_setup(void) diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-setup.c linux/arch/mips64/sgi-ip27/ip27-setup.c --- v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-setup.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/sgi-ip27/ip27-setup.c Sun Jul 9 22:18:16 2000 @@ -1,17 +1,19 @@ -/* $Id: ip27-setup.c,v 1.7 2000/03/07 15:45:29 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * SGI IP27 specific setup. * - * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999 Silcon Graphics, Inc. + * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000 Silcon Graphics, Inc. */ #include #include #include +#include +#include +#include #include #include #include @@ -24,6 +26,7 @@ #include #include #include +#include /* Check against user dumbness. */ #ifdef CONFIG_VT @@ -101,27 +104,32 @@ #define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */ #define BASE_XBOW_PORT 8 /* Lowest external port */ -static void __init pcibr_setup(void) +unsigned int bus_to_cpu[256]; + +void __init pcibr_setup(cnodeid_t nid) { - int i; + int i, start, num, masterwid; bridge_t *bridge; volatile u64 hubreg; - nasid_t nasid; + nasid_t nasid, masternasid; xwidget_part_num_t partnum; widgetreg_t widget_id; + static spinlock_t pcibr_setup_lock = SPIN_LOCK_UNLOCKED; - num_bridges = 0; /* * find what's on our local node */ - nasid = 0; - hubreg = LOCAL_HUB_L(IIO_LLP_CSR); + spin_lock(&pcibr_setup_lock); + start = num_bridges; /* Remember where we start from */ + nasid = COMPACT_TO_NASID_NODEID(nid); + hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR); if (hubreg & IIO_LLP_CSR_IS_UP) { /* link is up */ widget_id = *(volatile widgetreg_t *) (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); partnum = XWIDGET_PART_NUM(widget_id); - printk("pcibr_setup(): found partnum= 0x%x ", partnum); + printk("Cpu %d, Nasid 0x%x, pcibr_setup(): found partnum= 0x%x", + smp_processor_id(), nasid, partnum); if (partnum == BRIDGE_WIDGET_PART_NUM) { /* * found direct connected bridge so must be Origin200 @@ -130,8 +138,7 @@ num_bridges = 1; bus_to_wid[0] = 0x8; bus_to_nid[0] = 0; - } - if (partnum == XBOW_WIDGET_PART_NUM) { + } else if (partnum == XBOW_WIDGET_PART_NUM) { lboard_t *brd; klxbow_t *xbow_p; /* @@ -144,11 +151,32 @@ KLTYPE_MIDPLANE8)) == NULL) printk("argh\n"); else - printk("brd= 0x%x\n", brd); + printk("brd = 0x%lx\n", (unsigned long) brd); if ((xbow_p = (klxbow_t *) find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL) printk("argh\n"); else { + /* + * Okay, here's a xbow. Lets arbitrate and find + * out if we should initialize it. Set hub connected + * at highest or lowest widget as master. + * This algo needs to change a little for headless + * nodes. + */ +#ifdef WIDGET_A + i = HUB_WIDGET_ID_MAX + 1; + do { + i--; + } while (!XBOW_PORT_TYPE_HUB(xbow_p, i)); +#else + i = HUB_WIDGET_ID_MIN - 1; + do { + i++; + } while (!XBOW_PORT_TYPE_HUB(xbow_p, i)); +#endif + masterwid = i; + masternasid = XBOW_PORT_NASID(xbow_p, i); + if (nasid == masternasid) for (i=HUB_WIDGET_ID_MIN; i<=HUB_WIDGET_ID_MAX; i++) { if (!XBOW_PORT_IS_ENABLED(xbow_p, i)) continue; @@ -165,8 +193,7 @@ } } } - } - if (partnum == XXBOW_WIDGET_PART_NUM) { + } else if (partnum == XXBOW_WIDGET_PART_NUM) { /* * found xbridge, assume ibrick for now */ @@ -182,13 +209,17 @@ num_bridges = 3; } } + num = num_bridges - start; + spin_unlock(&pcibr_setup_lock); /* * set bridge registers */ - for (i=0; ib_wid_control |= BRIDGE_CTRL_IO_SWAP; bridge->b_wid_control |= BRIDGE_CTRL_MEM_SWAP; + /* + * Hmm... IRIX sets additional bits in the address which + * are documented as reserved in the bridge docs. + * We waste time programming b_wid_int_upper/b_wid_int_lower, + * since bridge_startup will set up the widget->nasid intr + * path anyway. + */ + bridge->b_int_mode = 0x0; /* Don't clear ints */ + bridge->b_wid_int_upper = 0x000a8000; /* Ints to widget A */ + bridge->b_wid_int_lower = 0x01800090; + bridge->b_dir_map = 0xa00000; /* DMA */ + bridge->b_int_enable = 0; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ } } @@ -216,11 +260,11 @@ nasid_t nid; hubreg_t p, e; + num_bridges = 0; /* * hub_rtc init and cpu clock intr enabled for later calibrate_delay. */ DBG("ip27_setup(): Entered.\n"); - per_cpu_init(); nid = get_nasid(); printk("IP27: Running on node %d.\n", nid); @@ -239,9 +283,5 @@ verify_mode(); ioc3_sio_init(); ioc3_eth_init(); - - DBG("ip27_setup(): calling pcibr_setup\n"); - /* set some bridge registers */ - pcibr_setup(); - DBG("ip27_setup(): Exit.\n"); + per_cpu_init(); } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-timer.c linux/arch/mips64/sgi-ip27/ip27-timer.c --- v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-timer.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/sgi-ip27/ip27-timer.c Mon Jul 10 14:22:00 2000 @@ -1,9 +1,7 @@ -/* $Id: ip27-timer.c,v 1.3 2000/02/18 09:54:40 ulfc Exp $ - * - * Copytight (C) 1999 Ralf Baechle (ralf@gnu.org) - * Copytight (C) 1999 Silicon Graphics, Inc. +/* + * Copytight (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copytight (C) 1999, 2000 Silicon Graphics, Inc. */ -#include #include #include #include @@ -36,10 +34,11 @@ #define CYCLES_PER_SEC (NSEC_PER_SEC/NSEC_PER_CYCLE) #define CYCLES_PER_JIFFY (CYCLES_PER_SEC/HZ) -static unsigned long ct_cur; /* What counter should be at next timer irq */ +static unsigned long ct_cur[NR_CPUS]; /* What counter should be at next timer irq */ static long last_rtc_update = 0; /* Last time the rtc clock got updated */ extern rwlock_t xtime_lock; +extern volatile unsigned long lost_ticks; static int set_rtc_mmss(unsigned long nowtime) @@ -91,26 +90,28 @@ void rt_timer_interrupt(struct pt_regs *regs) { int cpu = smp_processor_id(); - int cpuA = ((cputoslice(smp_processor_id())) == 0); - int user = user_mode(regs); + int cpuA = ((cputoslice(cpu)) == 0); int irq = 7; /* XXX Assign number */ write_lock(&xtime_lock); again: LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */ - ct_cur += CYCLES_PER_JIFFY; - LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur); + ct_cur[cpu] += CYCLES_PER_JIFFY; + LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur[cpu]); - if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur) + if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu]) goto again; - kstat.irqs[cpu][irq]++; /* kstat+do_timer only for bootcpu? */ - do_timer(regs); + kstat.irqs[cpu][irq]++; /* kstat only for bootcpu? */ + + if (cpu == 0) + do_timer(regs); #ifdef CONFIG_SMP if (current->pid) { unsigned int *inc, *inc2; + int user = user_mode(regs); update_one_process(current, 1, user, !user, cpu); if (--current->counter <= 0) { @@ -119,7 +120,7 @@ } if (user) { - if (current->priority < DEF_PRIORITY) { + if (current->nice > 0) { inc = &kstat.cpu_nice; inc2 = &kstat.per_cpu_nice[cpu]; } else { @@ -159,19 +160,51 @@ write_unlock(&xtime_lock); } +unsigned long inline do_gettimeoffset(void) +{ + unsigned long ct_cur1; + ct_cur1 = REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT) + CYCLES_PER_JIFFY; + return (ct_cur1 - ct_cur[0]) * NSEC_PER_CYCLE / 1000; +} + void do_gettimeofday(struct timeval *tv) { unsigned long flags; + unsigned long usec, sec; read_lock_irqsave(&xtime_lock, flags); - *tv = xtime; + usec = do_gettimeoffset(); + { + unsigned long lost = lost_ticks; + if (lost) + usec += lost * (1000000 / HZ); + } + sec = xtime.tv_sec; + usec += xtime.tv_usec; read_unlock_irqrestore(&xtime_lock, flags); + + while (usec >= 1000000) { + usec -= 1000000; + sec++; + } + + tv->tv_sec = sec; + tv->tv_usec = usec; } void do_settimeofday(struct timeval *tv) { write_lock_irq(&xtime_lock); + tv->tv_usec -= do_gettimeoffset(); + tv->tv_usec -= lost_ticks * (1000000 / HZ); + + while (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + xtime = *tv; + time_adjust = 0; /* stop active adjtime() */ time_state = TIME_BAD; time_maxerror = MAXPHASE; time_esterror = MAXPHASE; @@ -286,15 +319,16 @@ * node and timeouts will not happen there. */ if (get_compact_nodeid() == cnode) { + int cpu = smp_processor_id(); LOCAL_HUB_S(PI_RT_EN_A, 1); LOCAL_HUB_S(PI_RT_EN_B, 1); LOCAL_HUB_S(PI_PROF_EN_A, 0); LOCAL_HUB_S(PI_PROF_EN_B, 0); - ct_cur = CYCLES_PER_JIFFY; - LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur); + ct_cur[cpu] = CYCLES_PER_JIFFY; + LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur[cpu]); LOCAL_HUB_S(PI_RT_COUNT, 0); LOCAL_HUB_S(PI_RT_PEND_A, 0); - LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur); + LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur[cpu]); LOCAL_HUB_S(PI_RT_COUNT, 0); LOCAL_HUB_S(PI_RT_PEND_B, 0); } diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/tools/Makefile linux/arch/mips64/tools/Makefile --- v2.4.0-test2/linux/arch/mips64/tools/Makefile Tue May 23 15:31:33 2000 +++ linux/arch/mips64/tools/Makefile Sun Jul 9 22:18:16 2000 @@ -13,17 +13,19 @@ .S.o: $(CC) $(CFLAGS) -c $< -o $*.o -all: $(TARGET) - $(TARGET): offset.h cmp -s $^ $@ || (cp $^ $(TARGET).new && mv $(TARGET).new $(TARGET)) offset.h: offset.s sed -n '/^@@@/s///p' $^ >$@ -offset.s: offset.c +offset.s: offset.c $(TOPDIR)/include/linux/autoconf.h clean: rm -f offset.[hs] $(TARGET).new + +mrproper: + rm -f offset.[hs] $(TARGET).new + rm -f $(TARGET) include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test2/linux/arch/ppc/8260_io/uart.c linux/arch/ppc/8260_io/uart.c --- v2.4.0-test2/linux/arch/ppc/8260_io/uart.c Fri Jun 23 21:55:07 2000 +++ linux/arch/ppc/8260_io/uart.c Wed Jul 5 11:24:40 2000 @@ -2318,10 +2318,6 @@ volatile iop8260_t *io; init_bh(SERIAL_BH, do_serial_bh); -#if 0 - timer_table[RS_TIMER].fn = rs_8xx_timer; - timer_table[RS_TIMER].expires = 0; -#endif show_serial_version(); diff -u --recursive --new-file v2.4.0-test2/linux/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c --- v2.4.0-test2/linux/arch/ppc/8xx_io/uart.c Fri Jun 23 21:55:07 2000 +++ linux/arch/ppc/8xx_io/uart.c Wed Jul 5 11:24:40 2000 @@ -2437,10 +2437,6 @@ volatile immap_t *immap; init_bh(SERIAL_BH, do_serial_bh); -#if 0 - timer_table[RS_TIMER].fn = rs_8xx_timer; - timer_table[RS_TIMER].expires = 0; -#endif show_serial_version(); diff -u --recursive --new-file v2.4.0-test2/linux/arch/ppc/amiga/chipram.c linux/arch/ppc/amiga/chipram.c --- v2.4.0-test2/linux/arch/ppc/amiga/chipram.c Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/amiga/chipram.c Sat Jul 8 19:44:08 2000 @@ -1,15 +1,14 @@ /* ** linux/amiga/chipram.c ** -** Modified 03-May-94 by Geert Uytterhoeven -** (Geert.Uytterhoeven@cs.kuleuven.ac.be) +** Modified 03-May-94 by Geert Uytterhoeven ** - 64-bit aligned allocations for full AGA compatibility */ -#include #include #include #include +#include #include struct chip_desc { @@ -25,6 +24,8 @@ u_long amiga_chip_size; static unsigned long chipavail; +static struct resource chipram = { "Chip RAM", 0 }; + unsigned long amiga_chip_avail( void ) { #ifdef DEBUG @@ -34,8 +35,7 @@ } -__init -void amiga_chip_init (void) +void __init amiga_chip_init (void) { struct chip_desc *dp; @@ -49,6 +49,8 @@ */ amiga_chip_size -= 0x4000; #endif + chipram.end = amiga_chip_size-1; + request_resource(&iomem_resource, &chipram); /* initialize start boundary */ @@ -72,7 +74,7 @@ #endif } -void *amiga_chip_alloc (long size) +void *amiga_chip_alloc(long size, const char *name) { /* last chunk */ struct chip_desc *dp; @@ -82,7 +84,7 @@ size = (size + 7) & ~7; #ifdef DEBUG - printk("chip_alloc: allocate %ld bytes\n", size); + printk("amiga_chip_alloc: allocate %ld bytes\n", size); #endif /* @@ -108,14 +110,14 @@ dp = DP((unsigned long)ptr + dp->length); dp->alloced = 1; #ifdef DEBUG - printk ("chip_alloc: no split\n"); + printk ("amiga_chip_alloc: no split\n"); #endif } else { /* split the extent; use the end part */ long newsize = dp->length - (2*sizeof(*dp) + size); #ifdef DEBUG - printk ("chip_alloc: splitting %d to %ld\n", dp->length, + printk ("amiga_chip_alloc: splitting %d to %ld\n", dp->length, newsize); #endif dp->length = newsize; @@ -134,14 +136,18 @@ } #ifdef DEBUG - printk ("chip_alloc: returning %p\n", ptr); + printk ("amiga_chip_alloc: returning %p\n", ptr); #endif if ((unsigned long)ptr & 7) - panic("chip_alloc: alignment violation\n"); + panic("amiga_chip_alloc: alignment violation\n"); chipavail -= size + (2*sizeof(*dp)); /*MILAN*/ + if (!request_mem_region(ZTWO_PADDR(ptr), size, name)) + printk(KERN_WARNING "amiga_chip_alloc: region of size %ld at 0x%08lx " + "is busy\n", size, ZTWO_PADDR(ptr)); + return ptr; } @@ -156,6 +162,7 @@ #endif /* deallocate the chunk */ sdp->alloced = edp->alloced = 0; + release_mem_region(ZTWO_PADDR(ptr), sdp->length); /* check if we should merge with the previous chunk */ if (!sdp->first && !sdp[-1].alloced) { diff -u --recursive --new-file v2.4.0-test2/linux/arch/ppc/config.in linux/arch/ppc/config.in --- v2.4.0-test2/linux/arch/ppc/config.in Fri Jun 23 21:55:07 2000 +++ linux/arch/ppc/config.in Wed Jul 5 13:10:35 2000 @@ -183,7 +183,7 @@ fi endmenu - +source drivers/mtd/Config.in source drivers/pnp/Config.in source drivers/block/Config.in #source drivers.new/Config.in diff -u --recursive --new-file v2.4.0-test2/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c --- v2.4.0-test2/linux/arch/ppc/kernel/smp.c Fri Jun 23 21:55:07 2000 +++ linux/arch/ppc/kernel/smp.c Mon Jul 10 14:22:00 2000 @@ -95,7 +95,7 @@ p->counter = 0; current->need_resched = 1; } - if (p->priority < DEF_PRIORITY) { + if (p->nice > 0) { kstat.cpu_nice += user; kstat.per_cpu_nice[cpu] += user; } else { diff -u --recursive --new-file v2.4.0-test2/linux/arch/ppc/kernel/syscalls.c linux/arch/ppc/kernel/syscalls.c --- v2.4.0-test2/linux/arch/ppc/kernel/syscalls.c Sun Feb 13 19:29:03 2000 +++ linux/arch/ppc/kernel/syscalls.c Sat Jul 8 19:26:12 2000 @@ -52,25 +52,19 @@ int sys_iopl(int a1, int a2, int a3, int a4) { - lock_kernel(); printk(KERN_ERR "sys_iopl(%x, %x, %x, %x)!\n", a1, a2, a3, a4); - unlock_kernel(); return (-ENOSYS); } int sys_vm86(int a1, int a2, int a3, int a4) { - lock_kernel(); printk(KERN_ERR "sys_vm86(%x, %x, %x, %x)!\n", a1, a2, a3, a4); - unlock_kernel(); return (-ENOSYS); } int sys_modify_ldt(int a1, int a2, int a3, int a4) { - lock_kernel(); printk(KERN_ERR "sys_modify_ldt(%x, %x, %x, %x)!\n", a1, a2, a3, a4); - unlock_kernel(); return (-ENOSYS); } @@ -84,7 +78,6 @@ { int version, ret; - lock_kernel(); version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; @@ -171,7 +164,6 @@ break; } - unlock_kernel(); return ret; } @@ -184,9 +176,7 @@ int fd[2]; int error; - lock_kernel(); error = do_pipe(fd); - unlock_kernel(); if (!error) { if (copy_to_user(fildes, fd, 2*sizeof(int))) error = -EFAULT; @@ -201,7 +191,6 @@ struct file * file = NULL; int ret = -EBADF; - lock_kernel(); if (!(flags & MAP_ANONYMOUS)) { if (!(file = fget(fd))) goto out; @@ -214,7 +203,6 @@ if (file) fput(file); out: - unlock_kernel(); return ret; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/s390/config.in linux/arch/s390/config.in --- v2.4.0-test2/linux/arch/s390/config.in Fri Jun 23 21:55:08 2000 +++ linux/arch/s390/config.in Wed Jul 5 13:10:35 2000 @@ -57,6 +57,9 @@ source fs/Config.in +# Not sure about this one. dwmw2 +# source drivers/mtd/Config.in + # source drivers/char/Config.in mainmenu_option next_comment diff -u --recursive --new-file v2.4.0-test2/linux/arch/s390/kernel/process.c linux/arch/s390/kernel/process.c --- v2.4.0-test2/linux/arch/s390/kernel/process.c Fri May 12 14:18:55 2000 +++ linux/arch/s390/kernel/process.c Mon Jul 10 13:16:56 2000 @@ -59,7 +59,7 @@ { /* endless idle loop with no priority at all */ init_idle(); - current->priority = 0; + current->nice = 20; current->counter = -100; wait_psw.mask = _WAIT_PSW_MASK; wait_psw.addr = (unsigned long) &&idle_wakeup | 0x80000000L; diff -u --recursive --new-file v2.4.0-test2/linux/arch/s390/kernel/smp.c linux/arch/s390/kernel/smp.c --- v2.4.0-test2/linux/arch/s390/kernel/smp.c Fri May 12 14:18:55 2000 +++ linux/arch/s390/kernel/smp.c Mon Jul 10 14:22:00 2000 @@ -712,7 +712,7 @@ p->counter = 0; p->need_resched = 1; } - if (p->priority < DEF_PRIORITY) { + if (p->nice > 0) { kstat.cpu_nice += user; kstat.per_cpu_nice[cpu] += user; } else { diff -u --recursive --new-file v2.4.0-test2/linux/arch/s390/kernel/sys_s390.c linux/arch/s390/kernel/sys_s390.c --- v2.4.0-test2/linux/arch/s390/kernel/sys_s390.c Fri May 12 14:18:55 2000 +++ linux/arch/s390/kernel/sys_s390.c Wed Jul 5 11:31:01 2000 @@ -37,9 +37,7 @@ int fd[2]; int error; - lock_kernel(); error = do_pipe(fd); - unlock_kernel(); if (!error) { if (copy_to_user(fildes, fd, 2*sizeof(int))) error = -EFAULT; @@ -64,11 +62,7 @@ } down(¤t->mm->mmap_sem); - lock_kernel(); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - - unlock_kernel(); up(¤t->mm->mmap_sem); if (file) diff -u --recursive --new-file v2.4.0-test2/linux/arch/sh/config.in linux/arch/sh/config.in --- v2.4.0-test2/linux/arch/sh/config.in Fri Jun 23 21:55:08 2000 +++ linux/arch/sh/config.in Wed Jul 5 13:10:35 2000 @@ -113,6 +113,8 @@ endmenu +source drivers/mtd/Config.in + source drivers/block/Config.in if [ "$CONFIG_NET" = "y" ]; then diff -u --recursive --new-file v2.4.0-test2/linux/arch/sh/kernel/process.c linux/arch/sh/kernel/process.c --- v2.4.0-test2/linux/arch/sh/kernel/process.c Fri Jun 23 21:55:08 2000 +++ linux/arch/sh/kernel/process.c Mon Jul 10 13:16:56 2000 @@ -63,7 +63,7 @@ { /* endless idle loop with no priority at all */ init_idle(); - current->priority = 0; + current->nice = 20; current->counter = -100; while (1) { diff -u --recursive --new-file v2.4.0-test2/linux/arch/sh/kernel/sys_sh.c linux/arch/sh/kernel/sys_sh.c --- v2.4.0-test2/linux/arch/sh/kernel/sys_sh.c Tue Mar 7 14:32:25 2000 +++ linux/arch/sh/kernel/sys_sh.c Wed Jul 5 11:31:01 2000 @@ -35,9 +35,7 @@ int fd[2]; int error; - lock_kernel(); error = do_pipe(fd); - unlock_kernel(); if (!error) { regs.regs[1] = fd[1]; return fd[0]; @@ -60,10 +58,7 @@ } down(¤t->mm->mmap_sem); - lock_kernel(); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - unlock_kernel(); up(¤t->mm->mmap_sem); if (file) diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc/config.in linux/arch/sparc/config.in --- v2.4.0-test2/linux/arch/sparc/config.in Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc/config.in Wed Jul 5 22:15:24 2000 @@ -1,6 +1,6 @@ -# $Id: config.in,v 1.96 2000/06/20 01:10:00 anton Exp $ +# $Id: config.in,v 1.98 2000/07/06 01:41:29 davem Exp $ # For a description of the syntax of this configuration file, -# see the Configure script. +# see Documentation/kbuild/config-language.txt. # mainmenu_name "Linux/SPARC Kernel Configuration" @@ -72,6 +72,8 @@ bool 'PROM console' CONFIG_PROM_CONSOLE source drivers/video/Config.in endmenu + +source drivers/mtd/Config.in if [ "$CONFIG_SUN4" != "y" ]; then source drivers/sbus/char/Config.in diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc/defconfig linux/arch/sparc/defconfig --- v2.4.0-test2/linux/arch/sparc/defconfig Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc/defconfig Sun Jul 9 22:30:36 2000 @@ -80,6 +80,11 @@ # CONFIG_FBCON_FONTS is not set # +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# # Misc Linux/SPARC drivers # CONFIG_SUN_OPENPROMIO=m @@ -107,6 +112,7 @@ CONFIG_MD_LINEAR=m CONFIG_MD_STRIPED=m CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_NBD=m @@ -128,12 +134,8 @@ # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_IP_ALIAS is not set +# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set - -# -# (it is safe to leave these untouched) -# -CONFIG_SKB_LARGE=y CONFIG_IPV6=m # CONFIG_IPV6_EUI64 is not set # CONFIG_KHTTPD is not set @@ -261,6 +263,7 @@ # CONFIG_UMSDOS_FS is not set CONFIG_VFAT_FS=m CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set # CONFIG_RAMFS is not set CONFIG_ISO9660_FS=m @@ -294,7 +297,6 @@ # CONFIG_ROOT_NFS is not set CONFIG_NFSD=m # CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_SMB_FS=m diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile --- v2.4.0-test2/linux/arch/sparc/kernel/Makefile Mon Jun 19 16:31:58 2000 +++ linux/arch/sparc/kernel/Makefile Wed Jul 5 22:15:24 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.55 2000/05/23 23:09:08 davem Exp $ +# $Id: Makefile,v 1.56 2000/07/06 01:41:29 davem Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -69,6 +69,7 @@ @echo 'struct task_struct _task;' >> check_asm.c @echo 'struct mm_struct _mm;' >> check_asm.c @echo 'struct thread_struct _thread;' >> check_asm.c + @echo 'extern int printf(const char *fmt, ...);' >>check_asm.c @echo 'int main(void) {' >> check_asm.c $(SH) ./check_asm.sh task tmp.i check_asm.c $(SH) ./check_asm.sh mm tmp.i check_asm.c @@ -94,6 +95,7 @@ @echo 'struct task_struct _task;' >> check_asm.c @echo 'struct mm_struct _mm;' >> check_asm.c @echo 'struct thread_struct _thread;' >> check_asm.c + @echo 'extern int printf(const char *fmt, ...);' >>check_asm.c @echo 'int main(void) {' >> check_asm.c $(SH) ./check_asm.sh task tmp.i check_asm.c $(SH) ./check_asm.sh mm tmp.i check_asm.c diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c --- v2.4.0-test2/linux/arch/sparc/kernel/irq.c Tue May 23 15:31:34 2000 +++ linux/arch/sparc/kernel/irq.c Wed Jul 5 22:15:24 2000 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.103 2000/05/09 17:40:13 davem Exp $ +/* $Id: irq.c,v 1.104 2000/06/30 10:18:38 davem Exp $ * arch/sparc/kernel/irq.c: Interrupt request handling routines. On the * Sparc the IRQ's are basically 'cast in stone' * and you are supposed to probe the prom's device @@ -196,14 +196,14 @@ } #ifndef CONFIG_SMP -unsigned int local_bh_count; -unsigned int local_irq_count; +unsigned int __local_bh_count; +unsigned int __local_irq_count; #else /* SMP interrupt locking on Sparc. */ -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; +unsigned int __local_bh_count[NR_CPUS]; +unsigned int __local_irq_count[NR_CPUS]; /* Who has global_irq_lock. */ unsigned char global_irq_holder = NO_PROC_ID; @@ -229,14 +229,14 @@ printk("irq: %d [ ", atomic_read(&global_irq_count)); for (i = 0; i < NR_CPUS; i++) { - printk("%d ", local_irq_count[i]); + printk("%d ", __local_irq_count[i]); } printk("]\n"); printk("bh: %d [ ", (spin_is_locked(&global_bh_lock) ? 1 : 0)); for (i = 0; i < NR_CPUS; i++) { - printk("%d ", local_bh_count[cpu]); + printk("%d ", __local_bh_count[cpu]); } printk("]\n"); @@ -263,7 +263,7 @@ * already executing in one.. */ if (!atomic_read(&global_irq_count)) { - if (local_bh_count[cpu] || !spin_is_locked(&global_bh_lock)) + if (__local_bh_count[cpu] || !spin_is_locked(&global_bh_lock)) break; } @@ -282,7 +282,7 @@ continue; if (spin_is_locked (&global_irq_lock)) continue; - if (!local_bh_count[cpu] && spin_is_locked(&global_bh_lock)) + if (!__local_bh_count[cpu] && spin_is_locked(&global_bh_lock)) continue; if (spin_trylock(&global_irq_lock)) break; @@ -358,7 +358,7 @@ if ((flags & PSR_PIL) != PSR_PIL) { int cpu = smp_processor_id(); __cli(); - if (!local_irq_count[cpu]) + if (!__local_irq_count[cpu]) get_irqlock(cpu); } } @@ -367,7 +367,7 @@ { int cpu = smp_processor_id(); - if (!local_irq_count[cpu]) + if (!__local_irq_count[cpu]) release_irqlock(cpu); __sti(); } @@ -394,7 +394,7 @@ retval = 2 + local_enabled; /* check for global flags if we're not in an interrupt */ - if (!local_irq_count[smp_processor_id()]) { + if (!__local_irq_count[smp_processor_id()]) { if (local_enabled) retval = 1; if (global_irq_holder == (unsigned char) smp_processor_id()) diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c --- v2.4.0-test2/linux/arch/sparc/kernel/process.c Tue May 23 15:31:34 2000 +++ linux/arch/sparc/kernel/process.c Mon Jul 10 13:16:56 2000 @@ -60,7 +60,7 @@ goto out; /* endless idle loop with no priority at all */ - current->priority = 0; + current->nice = 20; current->counter = -100; init_idle(); diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c --- v2.4.0-test2/linux/arch/sparc/kernel/signal.c Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc/kernel/signal.c Thu Jul 6 21:36:21 2000 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.105 2000/06/19 06:24:37 davem Exp $ +/* $Id: signal.c,v 1.106 2000/07/07 04:25:17 davem Exp $ * linux/arch/sparc/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -1282,7 +1282,6 @@ #endif /* fall through */ default: - lock_kernel(); sigaddset(¤t->signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c --- v2.4.0-test2/linux/arch/sparc/kernel/sparc_ksyms.c Tue May 23 15:31:34 2000 +++ linux/arch/sparc/kernel/sparc_ksyms.c Wed Jul 5 22:15:24 2000 @@ -1,4 +1,4 @@ -/* $Id: sparc_ksyms.c,v 1.97 2000/05/09 17:40:13 davem Exp $ +/* $Id: sparc_ksyms.c,v 1.99 2000/06/30 10:18:38 davem Exp $ * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -42,6 +42,9 @@ #include #include #endif +#ifdef CONFIG_PCI +#include +#endif #include #include @@ -143,8 +146,8 @@ EXPORT_SYMBOL(global_irq_count); EXPORT_SYMBOL(synchronize_irq); #endif -EXPORT_SYMBOL(local_irq_count); -EXPORT_SYMBOL(local_bh_count); +EXPORT_SYMBOL(__local_irq_count); +EXPORT_SYMBOL(__local_bh_count); EXPORT_SYMBOL(udelay); EXPORT_SYMBOL(mstk48t02_regs); @@ -189,7 +192,17 @@ EXPORT_SYMBOL(sbus_ioremap); #endif #if CONFIG_PCI -/* We do not have modular drivers for PCI devices yet. */ +/* Actually, ioremap/iounmap are not PCI specific. But it is ok for drivers. */ +EXPORT_SYMBOL(ioremap); +EXPORT_SYMBOL(iounmap); + +EXPORT_SYMBOL(insl); +EXPORT_SYMBOL(outsl); +EXPORT_SYMBOL(pci_alloc_consistent); +EXPORT_SYMBOL(pci_free_consistent); +EXPORT_SYMBOL(pci_map_single); +EXPORT_SYMBOL(pci_unmap_single); +EXPORT_SYMBOL(pci_dma_sync_single); #endif /* Solaris/SunOS binary compatibility */ @@ -228,7 +241,7 @@ /* sparc library symbols */ EXPORT_SYMBOL(bcopy); EXPORT_SYMBOL_NOVERS(memscan); -EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL_NOVERS(strlen); EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strcpy); EXPORT_SYMBOL(strncpy); diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc/kernel/sun4d_smp.c linux/arch/sparc/kernel/sun4d_smp.c --- v2.4.0-test2/linux/arch/sparc/kernel/sun4d_smp.c Wed Apr 26 16:34:07 2000 +++ linux/arch/sparc/kernel/sun4d_smp.c Mon Jul 10 14:22:00 2000 @@ -484,7 +484,7 @@ } if(user) { - if(current->priority < DEF_PRIORITY) { + if(current->nice > 0) { kstat.cpu_nice++; kstat.per_cpu_nice[cpu]++; } else { diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc/kernel/sun4m_smp.c linux/arch/sparc/kernel/sun4m_smp.c --- v2.4.0-test2/linux/arch/sparc/kernel/sun4m_smp.c Wed Apr 26 16:34:07 2000 +++ linux/arch/sparc/kernel/sun4m_smp.c Mon Jul 10 14:22:00 2000 @@ -471,7 +471,7 @@ } if(user) { - if(current->priority < DEF_PRIORITY) { + if(current->nice > 0) { kstat.cpu_nice++; kstat.per_cpu_nice[cpu]++; } else { diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c --- v2.4.0-test2/linux/arch/sparc/kernel/sys_sparc.c Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc/kernel/sys_sparc.c Sat Jul 8 19:26:12 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.63 2000/06/22 11:42:25 davem Exp $ +/* $Id: sys_sparc.c,v 1.65 2000/07/06 01:41:29 davem Exp $ * linux/arch/sparc/kernel/sys_sparc.c * * This file contains various random system calls that @@ -81,14 +81,12 @@ int fd[2]; int error; - lock_kernel(); error = do_pipe(fd); if (error) goto out; regs->u_regs[UREG_I1] = fd[1]; error = fd[0]; out: - unlock_kernel(); return error; } @@ -102,7 +100,6 @@ { int version, err; - lock_kernel(); version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; @@ -197,7 +194,6 @@ else err = -EINVAL; out: - unlock_kernel(); return err; } @@ -215,8 +211,6 @@ goto out; } - down(¤t->mm->mmap_sem); - lock_kernel(); retval = -EINVAL; len = PAGE_ALIGN(len); if (ARCH_SUN4C_SUN4 && @@ -230,11 +224,11 @@ goto out_putf; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + down(¤t->mm->mmap_sem); retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + up(¤t->mm->mmap_sem); out_putf: - unlock_kernel(); - up(¤t->mm->mmap_sem); if (file) fput(file); out: diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c --- v2.4.0-test2/linux/arch/sparc/kernel/sys_sunos.c Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc/kernel/sys_sunos.c Sat Jul 8 19:26:12 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.125 2000/06/22 11:42:25 davem Exp $ +/* $Id: sys_sunos.c,v 1.128 2000/07/06 01:41:29 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -68,8 +68,6 @@ struct file * file = NULL; unsigned long retval, ret_type; - down(¤t->mm->mmap_sem); - lock_kernel(); if(flags & MAP_NORESERVE) { static int cnt; if (cnt++ < 10) @@ -118,7 +116,9 @@ } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + down(¤t->mm->mmap_sem); retval = do_mmap(file, addr, len, prot, flags, off); + up(¤t->mm->mmap_sem); if(!ret_type) retval = ((retval < PAGE_OFFSET) ? 0 : retval); @@ -126,8 +126,6 @@ if (file) fput(file); out: - unlock_kernel(); - up(¤t->mm->mmap_sem); return retval; } @@ -363,7 +361,6 @@ if (!file) goto out; - lock_kernel(); error = -EINVAL; if (cnt < (sizeof(struct sunos_dirent) + 255)) goto out_putf; @@ -385,7 +382,6 @@ } out_putf: - unlock_kernel(); fput(file); out: return error; @@ -444,7 +440,6 @@ if (!file) goto out; - lock_kernel(); error = -EINVAL; if(cnt < (sizeof(struct sunos_direntry) + 255)) goto out_putf; @@ -466,7 +461,6 @@ } out_putf: - unlock_kernel(); fput(file); out: return error; @@ -527,7 +521,6 @@ { int ret; - lock_kernel(); switch(name) { case _PCONF_LINK: ret = LINK_MAX; @@ -558,7 +551,6 @@ ret = -EINVAL; break; } - unlock_kernel(); return ret; } @@ -566,9 +558,7 @@ { int ret; - lock_kernel(); ret = sunos_fpathconf(0, name); /* XXX cheese XXX */ - unlock_kernel(); return ret; } @@ -581,7 +571,6 @@ int ret; /* SunOS binaries expect that select won't change the tvp contents */ - lock_kernel(); ret = sys_select (width, inp, outp, exp, tvp); if (ret == -EINTR && tvp) { time_t sec, usec; @@ -592,7 +581,6 @@ if (sec == 0 && usec == 0) ret = 0; } - unlock_kernel(); return ret; } @@ -658,6 +646,8 @@ if (!file) goto out; + inode = file->f_dentry->d_inode; + socket = &inode->u.socket_i; local.sin_family = AF_INET; local.sin_addr.s_addr = INADDR_ANY; @@ -833,7 +823,6 @@ int ret; /* So stupid... */ - lock_kernel(); if((!pid || pid == current->pid) && !pgid) { sys_setsid(); @@ -841,7 +830,6 @@ } else { ret = sys_setpgid(pid, pgid); } - unlock_kernel(); return ret; } @@ -851,9 +839,7 @@ { int ret; - lock_kernel(); ret = sys_wait4((pid ? pid : -1), stat_addr, options, ru); - unlock_kernel(); return ret; } @@ -901,7 +887,6 @@ { long ret; - lock_kernel(); switch (name){ case _SC_ARG_MAX: ret = ARG_MAX; @@ -934,7 +919,6 @@ ret = -1; break; }; - unlock_kernel(); return ret; } @@ -944,7 +928,6 @@ union semun arg4; int ret; - lock_kernel(); switch (op) { case 0: /* Most arguments match on a 1:1 basis but cmd doesn't */ @@ -980,7 +963,6 @@ ret = -EINVAL; break; }; - unlock_kernel(); return ret; } @@ -991,7 +973,6 @@ unsigned long arg5; int rval; - lock_kernel(); switch(op) { case 0: rval = sys_msgget((key_t)arg1, (int)arg2); @@ -1001,8 +982,10 @@ (struct msqid_ds *)arg3); break; case 2: + lock_kernel(); sp = (struct sparc_stackf *)current->thread.kregs->u_regs[UREG_FP]; arg5 = sp->xxargs[0]; + unlock_kernel(); rval = sys_msgrcv((int)arg1, (struct msgbuf *)arg2, (size_t)arg3, (long)arg4, (int)arg5); break; @@ -1014,7 +997,6 @@ rval = -EINVAL; break; } - unlock_kernel(); return rval; } @@ -1024,7 +1006,6 @@ unsigned long raddr; int rval; - lock_kernel(); switch(op) { case 0: /* sys_shmat(): attach a shared memory area */ @@ -1048,7 +1029,6 @@ rval = -EINVAL; break; }; - unlock_kernel(); return rval; } @@ -1062,9 +1042,12 @@ static inline int check_nonblock(int ret, int fd) { if (ret == -EAGAIN) { - struct file * file = fcheck(fd); - if (file && (file->f_flags & O_NDELAY)) - ret = -SUNOS_EWOULDBLOCK; + struct file * file = fget(fd); + if (file) { + if (file->f_flags & O_NDELAY) + ret = -SUNOS_EWOULDBLOCK; + fput(file); + } } return ret; } @@ -1082,9 +1065,7 @@ { int ret; - lock_kernel(); ret = check_nonblock(sys_read(fd,buf,count),fd); - unlock_kernel(); return ret; } @@ -1092,9 +1073,7 @@ { int ret; - lock_kernel(); ret = check_nonblock(sys_readv(fd,vector,count),fd); - unlock_kernel(); return ret; } @@ -1102,9 +1081,7 @@ { int ret; - lock_kernel(); ret = check_nonblock(sys_write(fd,buf,count),fd); - unlock_kernel(); return ret; } @@ -1112,9 +1089,7 @@ { int ret; - lock_kernel(); ret = check_nonblock(sys_writev(fd,vector,count),fd); - unlock_kernel(); return ret; } @@ -1122,9 +1097,7 @@ { int ret; - lock_kernel(); ret = check_nonblock(sys_recv(fd,ubuf,size,flags),fd); - unlock_kernel(); return ret; } @@ -1132,9 +1105,7 @@ { int ret; - lock_kernel(); ret = check_nonblock(sys_send(fd,buff,len,flags),fd); - unlock_kernel(); return ret; } @@ -1145,7 +1116,6 @@ { int ret, one = 1; - lock_kernel(); ret = sys_socket(family, type, protocol); if (ret < 0) goto out; @@ -1153,7 +1123,6 @@ sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, (char *)&one, sizeof(one)); out: - unlock_kernel(); return ret; } @@ -1161,7 +1130,6 @@ { int ret, one = 1; - lock_kernel(); while (1) { ret = check_nonblock(sys_accept(fd,sa,addrlen),fd); if (ret != -ENETUNREACH && ret != -EHOSTUNREACH) @@ -1173,7 +1141,6 @@ sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, (char *)&one, sizeof(one)); out: - unlock_kernel(); return ret; } @@ -1230,14 +1197,12 @@ int tr_opt = optname; int ret; - lock_kernel(); if (level == SOL_IP) { /* Multicast socketopts (ttl, membership) */ if (tr_opt >=2 && tr_opt <= 6) tr_opt += 30; } ret = sys_setsockopt(fd, level, tr_opt, optval, optlen); - unlock_kernel(); return ret; } @@ -1247,13 +1212,11 @@ int tr_opt = optname; int ret; - lock_kernel(); if (level == SOL_IP) { /* Multicast socketopts (ttl, membership) */ if (tr_opt >=2 && tr_opt <= 6) tr_opt += 30; } ret = sys_getsockopt(fd, level, tr_opt, optval, optlen); - unlock_kernel(); return ret; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c --- v2.4.0-test2/linux/arch/sparc/mm/srmmu.c Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc/mm/srmmu.c Wed Jul 5 22:15:24 2000 @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.214 2000/06/22 01:28:44 anton Exp $ +/* $Id: srmmu.c,v 1.215 2000/06/30 13:25:28 anton Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -1127,8 +1127,6 @@ } } -static unsigned long end_of_phys_memory __initdata = 0; - #define KERNEL_PTE(page_shifted) ((page_shifted)|SRMMU_CACHE|SRMMU_PRIV|SRMMU_VALID) /* Create a third-level SRMMU 16MB page mapping. */ @@ -1268,7 +1266,7 @@ return sprintf(buf, "MMU type\t: %s\n" "contexts\t: %d\n" - "nocache total\t: %d\n" + "nocache total\t: %ld\n" "nocache used\t: %d\n" , srmmu_name, num_contexts, diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c --- v2.4.0-test2/linux/arch/sparc/mm/sun4c.c Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc/mm/sun4c.c Wed Jul 5 22:15:24 2000 @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.194 2000/06/05 06:08:45 anton Exp $ +/* $Id: sun4c.c,v 1.195 2000/06/30 13:25:28 anton Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -2360,8 +2360,11 @@ do { if (pgd_quicklist) sun4c_free_pgd_slow(sun4c_get_pgd_fast()), freed++; + /* Only two level page tables at the moment, sun4 3 level mmu is not supported - Anton */ +#if 0 if (pmd_quicklist) sun4c_free_pmd_slow(sun4c_get_pmd_fast()), freed++; +#endif if (pte_quicklist) sun4c_free_pte_slow(sun4c_get_pte_fast()), freed++; } while (pgtable_cache_size > low); diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc/vmlinux.lds linux/arch/sparc/vmlinux.lds --- v2.4.0-test2/linux/arch/sparc/vmlinux.lds Thu Feb 10 17:11:05 2000 +++ linux/arch/sparc/vmlinux.lds Wed Jul 5 22:15:24 2000 @@ -73,5 +73,5 @@ .debug_pubnames 0 : { *(.debug_pubnames) } .debug_sfnames 0 : { *(.debug_sfnames) } .line 0 : { *(.line) } - /DISCARD/ : { *(.text.exit) *(.data.exit) } + /DISCARD/ : { *(.text.exit) *(.data.exit) *(.exitcall.exit) } } diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.4.0-test2/linux/arch/sparc64/config.in Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc64/config.in Sun Jul 9 22:30:36 2000 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.115 2000/06/20 04:36:22 ecd Exp $ +# $Id: config.in,v 1.116 2000/07/06 01:41:29 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -27,6 +27,7 @@ bool 'Symmetric multi-processing support' CONFIG_SMP # Global things across all Sun machines. +define_bool CONFIG_HAVE_DEC_LOCK y define_bool CONFIG_ISA n define_bool CONFIG_PCMCIA n define_bool CONFIG_SBUS y @@ -78,7 +79,7 @@ source drivers/sbus/char/Config.in source drivers/sbus/audio/Config.in - +source drivers/mtd/Config.in mainmenu_option next_comment comment 'Block devices' diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.4.0-test2/linux/arch/sparc64/defconfig Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc64/defconfig Sun Jul 9 22:30:36 2000 @@ -20,6 +20,7 @@ CONFIG_VT=y CONFIG_VT_CONSOLE=y # CONFIG_SMP is not set +CONFIG_HAVE_DEC_LOCK=y # CONFIG_ISA is not set # CONFIG_PCMCIA is not set CONFIG_SBUS=y @@ -85,6 +86,7 @@ CONFIG_FB_ATY=y # CONFIG_FB_ATY128 is not set # CONFIG_FB_3DFX is not set +# CONFIG_FB_SIS is not set CONFIG_FB_SBUS=y CONFIG_FB_CREATOR=y CONFIG_FB_CGSIX=y @@ -124,6 +126,11 @@ # CONFIG_SPARCAUDIO_DUMMY is not set # +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# # Block devices # CONFIG_BLK_DEV_FD=y @@ -149,12 +156,8 @@ # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_IP_ALIAS is not set +# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set - -# -# (it is safe to leave these untouched) -# -CONFIG_SKB_LARGE=y CONFIG_IPV6=m # CONFIG_IPV6_EUI64 is not set # CONFIG_KHTTPD is not set @@ -396,6 +399,7 @@ # CONFIG_UMSDOS_FS is not set CONFIG_VFAT_FS=m CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set CONFIG_CRAMFS=m CONFIG_RAMFS=m CONFIG_ISO9660_FS=m @@ -429,7 +433,6 @@ # CONFIG_ROOT_NFS is not set CONFIG_NFSD=m CONFIG_NFSD_V3=y -# CONFIG_NFSD_TCP is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile --- v2.4.0-test2/linux/arch/sparc64/kernel/Makefile Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc64/kernel/Makefile Wed Jul 5 22:15:24 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.55 2000/05/27 00:49:35 davem Exp $ +# $Id: Makefile,v 1.56 2000/07/06 01:41:29 davem Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -91,6 +91,7 @@ @echo 'struct task_struct _task;' >> check_asm.c @echo 'struct mm_struct _mm;' >> check_asm.c @echo 'struct thread_struct _thread;' >> check_asm.c + @echo 'extern int printf(const char *fmt, ...);' >>check_asm.c @echo 'int main(void) {' >> check_asm.c $(SH) ./check_asm.sh task tmp.i check_asm.c $(SH) ./check_asm.sh mm tmp.i check_asm.c @@ -120,6 +121,7 @@ @echo 'struct task_struct _task;' >> check_asm.c @echo 'struct mm_struct _mm;' >> check_asm.c @echo 'struct thread_struct _thread;' >> check_asm.c + @echo 'extern int printf(const char *fmt, ...);' >>check_asm.c @echo 'int main(void) {' >> check_asm.c $(SH) ./check_asm.sh task tmp.i check_asm.c $(SH) ./check_asm.sh mm tmp.i check_asm.c @@ -145,6 +147,7 @@ @echo 'struct task_struct _task;' >> check_asm.c @echo 'struct mm_struct _mm;' >> check_asm.c @echo 'struct thread_struct _thread;' >> check_asm.c + @echo 'extern int printf(const char *fmt, ...);' >>check_asm.c @echo 'int main(void) {' >> check_asm.c $(SH) ./check_asm.sh task tmp.i check_asm.c $(SH) ./check_asm.sh mm tmp.i check_asm.c diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/kernel/binfmt_aout32.c linux/arch/sparc64/kernel/binfmt_aout32.c --- v2.4.0-test2/linux/arch/sparc64/kernel/binfmt_aout32.c Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc64/kernel/binfmt_aout32.c Sun Jul 9 22:30:37 2000 @@ -325,7 +325,7 @@ current->thread.flags |= SPARC_FLAG_32BIT; } start_thread32(regs, ex.a_entry, current->mm->start_stack); - if (current->flags & PF_PTRACED) + if (current->ptrace & PT_PTRACED) send_sig(SIGTRAP, current, 0); return 0; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c --- v2.4.0-test2/linux/arch/sparc64/kernel/irq.c Tue May 23 15:31:34 2000 +++ linux/arch/sparc64/kernel/irq.c Wed Jul 5 22:15:25 2000 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.87 2000/05/09 17:40:13 davem Exp $ +/* $Id: irq.c,v 1.89 2000/06/30 10:18:38 davem Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -62,6 +62,19 @@ #define irq_work(__cpu, __pil) &(cpu_data[(__cpu)].irq_worklists[(__pil)]) #endif +#ifdef CONFIG_PCI +/* This is a table of physical addresses used to deal with SA_DMA_SYNC. + * It is used for PCI only to synchronize DMA transfers with IRQ delivery + * for devices behind busses other than APB on Sabre systems. + * + * Currently these physical addresses are just config space accesses + * to the command register for that device. + */ +unsigned long pci_dma_wsync; +unsigned long dma_sync_reg_table[256]; +unsigned char dma_sync_reg_table_entry = 0; +#endif + /* This is based upon code in the 32-bit Sparc kernel written mostly by * David Redman (djhr@tadpole.co.uk). */ @@ -280,8 +293,6 @@ /* * Check wether we _should_ use DMA Write Sync * (for devices behind bridges behind APB). - * - * XXX: Not implemented, yet. */ if (bucket->flags & IBF_DMA_SYNC) irqflags |= SA_DMA_SYNC; @@ -541,8 +552,8 @@ * lives in the brlock table for cache reasons. */ #ifndef CONFIG_SMP -unsigned int local_irq_count; -unsigned int local_bh_count; +unsigned int __local_irq_count; +unsigned int __local_bh_count; #else /* Who has global_irq_lock. */ @@ -594,14 +605,14 @@ spinlock_t *lock; if (!irqs_running() && - (local_bh_count || !spin_is_locked(&global_bh_lock))) + (local_bh_count(smp_processor_id()) || !spin_is_locked(&global_bh_lock))) break; br_write_unlock(BR_GLOBALIRQ_LOCK); lock = &__br_write_locks[BR_GLOBALIRQ_LOCK].lock; while (irqs_running() || spin_is_locked(lock) || - (!local_bh_count && spin_is_locked(&global_bh_lock))) { + (!local_bh_count(smp_processor_id()) && spin_is_locked(&global_bh_lock))) { if (!--count) { show("wait_on_irq"); count = (~0 >> 1); @@ -624,7 +635,7 @@ if(flags == 0) { int cpu = smp_processor_id(); __cli(); - if (! local_irq_count) + if (! local_irq_count(cpu)) get_irqlock(cpu); } } @@ -633,7 +644,7 @@ { int cpu = smp_processor_id(); - if (! local_irq_count) + if (! local_irq_count(cpu)) release_irqlock(cpu); __sti(); } @@ -645,7 +656,7 @@ __save_flags(flags); local_enabled = ((flags == 0) ? 1 : 0); retval = 2 + local_enabled; - if (! local_irq_count) { + if (! local_irq_count(smp_processor_id())) { if (local_enabled) retval = 1; if (global_irq_holder == (unsigned char) smp_processor_id()) @@ -719,14 +730,14 @@ /* 'cpu' is the MID (ie. UPAID), calculate the MID * of our buddy. */ - if(should_forward != 0) { + if (should_forward != 0) { buddy = cpu_number_map(cpu) + 1; if (buddy >= NR_CPUS || (buddy = cpu_logical_map(buddy)) == -1) buddy = cpu_logical_map(0); /* Voo-doo programming. */ - if(cpu_data[buddy].idle_volume < FORWARD_VOLUME) + if (cpu_data[buddy].idle_volume < FORWARD_VOLUME) should_forward = 0; buddy <<= 26; } @@ -752,25 +763,29 @@ #else bp = __bucket(xchg32(irq_work(cpu, irq), 0)); #endif - for( ; bp != NULL; bp = nbp) { + for ( ; bp != NULL; bp = nbp) { unsigned char flags = bp->flags; nbp = __bucket(bp->irq_chain); - if((flags & IBF_ACTIVE) != 0) { - if((flags & IBF_MULTI) == 0) { + if ((flags & IBF_ACTIVE) != 0) { + if ((flags & IBF_DMA_SYNC) != 0) { + upa_readl(dma_sync_reg_table[bp->synctab_ent]); + upa_readq(pci_dma_wsync); + } + if ((flags & IBF_MULTI) == 0) { struct irqaction *ap = bp->irq_info; ap->handler(__irq(bp), ap->dev_id, regs); } else { void **vector = (void **)bp->irq_info; int ent; - for(ent = 0; ent < 4; ent++) { + for (ent = 0; ent < 4; ent++) { struct irqaction *ap = vector[ent]; - if(ap != NULL) + if (ap != NULL) ap->handler(__irq(bp), ap->dev_id, regs); } } /* Only the dummy bucket lacks IMAP/ICLR. */ - if(bp->pil != 0) { + if (bp->pil != 0) { #ifdef CONFIG_SMP /* Ok, here is what is going on: * 1) Retargeting IRQs on Starfire is very diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c --- v2.4.0-test2/linux/arch/sparc64/kernel/pci_sabre.c Wed Apr 26 16:34:07 2000 +++ linux/arch/sparc64/kernel/pci_sabre.c Wed Jul 5 12:14:54 2000 @@ -1,4 +1,4 @@ -/* $Id: pci_sabre.c,v 1.19 2000/04/15 13:07:51 davem Exp $ +/* $Id: pci_sabre.c,v 1.20 2000/06/26 19:40:27 davem Exp $ * pci_sabre.c: Sabre specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -641,14 +641,28 @@ bucket = __bucket(build_irq(pil, inofixup, iclr, imap)); bucket->flags |= IBF_PCI; - /* XXX We still need to code up support for this in irq.c - * XXX It's easy to code up since only one SIMBA can exist - * XXX in a machine and this is where the sync register is. -DaveM - */ if (pdev) { struct pcidev_cookie *pcp = pdev->sysdata; - if (pdev->bus->number != pcp->pbm->pci_first_busno) + + /* When a device lives behind a bridge deeper in the + * PCI bus topology than APB, a special sequence must + * run to make sure all pending DMA transfers at the + * time of IRQ delivery are visible in the coherency + * domain by the cpu. This sequence is to perform + * a read on the far side of the non-APB bridge, then + * perform a read of Sabre's DMA write-sync register. + * + * Currently, the PCI_CONFIG register for the device + * is used for this read from the far side of the bridge. + */ + if (pdev->bus->number != pcp->pbm->pci_first_busno) { bucket->flags |= IBF_DMA_SYNC; + bucket->synctab_ent = dma_sync_reg_table_entry++; + dma_sync_reg_table[bucket->synctab_ent] = + (unsigned long) sabre_pci_config_mkaddr( + pcp->pbm, + pdev->bus->number, pdev->devfn, PCI_COMMAND); + } } return __irq(bucket); } @@ -1399,7 +1413,10 @@ * First REG in property is base of entire SABRE register space. */ p->controller_regs = pr_regs[0].phys_addr; - printk("PCI: Found SABRE, main regs at %016lx\n", p->controller_regs); + pci_dma_wsync = p->controller_regs + SABRE_WRSYNC; + + printk("PCI: Found SABRE, main regs at %016lx, wsync at %016lx\n", + p->controller_regs, pci_dma_wsync); /* Error interrupts are enabled later after the bus scan. */ sabre_write(p->controller_regs + SABRE_PCICTRL, diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- v2.4.0-test2/linux/arch/sparc64/kernel/process.c Tue May 23 15:31:34 2000 +++ linux/arch/sparc64/kernel/process.c Mon Jul 10 13:16:56 2000 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.107 2000/05/09 17:40:14 davem Exp $ +/* $Id: process.c,v 1.108 2000/06/30 10:18:38 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -53,7 +53,7 @@ return -EPERM; /* endless idle loop with no priority at all */ - current->priority = 0; + current->nice = 20; current->counter = -100; init_idle(); @@ -270,7 +270,9 @@ spin_lock_irqsave(®dump_lock, flags); printk("CPU[%d]: local_irq_count[%u] irqs_running[%d]\n", - smp_processor_id(), local_irq_count, irqs_running()); + smp_processor_id(), + local_irq_count(smp_processor_id()), + irqs_running()); #endif printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x\n", regs->tstate, regs->tpc, regs->tnpc, regs->y); diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c --- v2.4.0-test2/linux/arch/sparc64/kernel/signal.c Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc64/kernel/signal.c Thu Jul 6 21:36:22 2000 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.51 2000/06/19 06:24:37 davem Exp $ +/* $Id: signal.c,v 1.52 2000/07/07 04:25:17 davem Exp $ * arch/sparc64/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -788,7 +788,6 @@ #endif /* fall through */ default: - lock_kernel(); sigaddset(¤t->signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c --- v2.4.0-test2/linux/arch/sparc64/kernel/signal32.c Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc64/kernel/signal32.c Thu Jul 6 21:36:22 2000 @@ -1,4 +1,4 @@ -/* $Id: signal32.c,v 1.64 2000/06/19 06:24:37 davem Exp $ +/* $Id: signal32.c,v 1.65 2000/07/07 04:25:17 davem Exp $ * arch/sparc64/kernel/signal32.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -1420,7 +1420,6 @@ #endif /* fall through */ default: - lock_kernel(); sigaddset(¤t->signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c --- v2.4.0-test2/linux/arch/sparc64/kernel/smp.c Wed Apr 26 16:34:07 2000 +++ linux/arch/sparc64/kernel/smp.c Mon Jul 10 14:22:00 2000 @@ -386,6 +386,46 @@ } } +struct call_data_struct { + void (*func) (void *info); + void *info; + atomic_t finished; + int wait; +}; + +extern unsigned long xcall_call_function; + +int smp_call_function(void (*func)(void *info), void *info, + int nonatomic, int wait) +{ + struct call_data_struct data; + int cpus = smp_num_cpus - 1; + + if (!cpus) + return 0; + + data.func = func; + data.info = info; + atomic_set(&data.finished, 0); + data.wait = wait; + + smp_cross_call(&xcall_call_function, + 0, (u64) &data, 0); + if (wait) { + while (atomic_read(&data.finished) != cpus) + barrier(); + } + + return 0; +} + +void smp_call_function_client(struct call_data_struct *call_data) +{ + call_data->func(call_data->info); + if (call_data->wait) + atomic_inc(&call_data->finished); +} + extern unsigned long xcall_flush_tlb_page; extern unsigned long xcall_flush_tlb_mm; extern unsigned long xcall_flush_tlb_range; @@ -677,7 +717,7 @@ } if (user) { - if (current->priority < DEF_PRIORITY) { + if (current->nice > 0) { inc = &kstat.cpu_nice; inc2 = &kstat.per_cpu_nice[cpu]; } else { diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.4.0-test2/linux/arch/sparc64/kernel/sparc64_ksyms.c Mon Jun 19 16:31:58 2000 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Wed Jul 5 22:15:25 2000 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.85 2000/05/23 02:14:25 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.86 2000/06/30 10:18:38 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -85,7 +85,6 @@ extern int unregister_ioctl32_conversion(unsigned int cmd); extern int io_remap_page_range(unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space); -extern void bcopy (const char *, char *, int); extern int __ashrdi3(int, int); extern void dump_thread(struct pt_regs *, struct user *); @@ -158,8 +157,8 @@ #endif #else -EXPORT_SYMBOL(local_bh_count); -EXPORT_SYMBOL(local_irq_count); +EXPORT_SYMBOL(__local_bh_count); +EXPORT_SYMBOL(__local_irq_count); #endif /* rw semaphores */ @@ -263,7 +262,6 @@ EXPORT_SYMBOL(__prom_getsibling); /* sparc library symbols */ -EXPORT_SYMBOL(bcopy); EXPORT_SYMBOL(__strlen); #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91 EXPORT_SYMBOL(strlen); diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c --- v2.4.0-test2/linux/arch/sparc64/kernel/sys_sparc.c Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc64/kernel/sys_sparc.c Sat Jul 8 19:26:12 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.41 2000/06/22 11:42:25 davem Exp $ +/* $Id: sys_sparc.c,v 1.43 2000/07/06 01:41:29 davem Exp $ * linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that @@ -92,14 +92,12 @@ int fd[2]; int error; - lock_kernel(); error = do_pipe(fd); if (error) goto out; regs->u_regs[UREG_I1] = fd[1]; error = fd[0]; out: - unlock_kernel(); return error; } @@ -113,7 +111,6 @@ { int err; - lock_kernel(); /* No need for backward compatibility. We can start fresh... */ if (call <= SEMCTL) @@ -179,7 +176,6 @@ else err = -EINVAL; out: - unlock_kernel(); return err; } @@ -200,11 +196,9 @@ asmlinkage int sparc64_personality(unsigned long personality) { int ret; - lock_kernel(); if (current->personality == PER_LINUX32 && personality == PER_LINUX) personality = PER_LINUX32; ret = sys_personality(personality); - unlock_kernel(); if (ret == PER_LINUX32) ret = PER_LINUX; return ret; @@ -227,9 +221,6 @@ len = PAGE_ALIGN(len); retval = -EINVAL; - down(¤t->mm->mmap_sem); - lock_kernel(); - if (current->thread.flags & SPARC_FLAG_32BIT) { if (len > 0xf0000000UL || ((flags & MAP_FIXED) && addr > 0xf0000000UL - len)) @@ -241,11 +232,11 @@ goto out_putf; } + down(¤t->mm->mmap_sem); retval = do_mmap(file, addr, len, prot, flags, off); + up(¤t->mm->mmap_sem); out_putf: - unlock_kernel(); - up(¤t->mm->mmap_sem); if (file) fput(file); out: diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.4.0-test2/linux/arch/sparc64/kernel/sys_sparc32.c Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc64/kernel/sys_sparc32.c Sun Jul 9 22:30:37 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.152 2000/06/22 17:44:47 davem Exp $ +/* $Id: sys_sparc32.c,v 1.154 2000/07/06 01:41:29 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -279,7 +279,7 @@ char *tmp, *result; result = ERR_PTR(-ENOMEM); - tmp = (char *)__get_free_page(GFP_KERNEL); + tmp = __getname(); if (tmp) { int retval = do_getname32(filename, tmp); @@ -1184,8 +1184,6 @@ struct file *file; long ret = -EBADF; - lock_kernel(); - file = fget(fd); if(!file) goto bad_file; @@ -1195,7 +1193,6 @@ fput(file); bad_file: - unlock_kernel(); return ret; } @@ -1204,8 +1201,6 @@ struct file *file; int ret = -EBADF; - lock_kernel(); - file = fget(fd); if(!file) goto bad_file; @@ -1214,7 +1209,6 @@ fput(file); bad_file: - unlock_kernel(); return ret; } @@ -1266,14 +1260,12 @@ buf.count = 0; buf.dirent = dirent; - lock_kernel(); error = vfs_readdir(file, fillonedir, &buf); if (error < 0) goto out_putf; error = buf.count; out_putf: - unlock_kernel(); fput(file); out: return error; @@ -1333,7 +1325,6 @@ buf.count = count; buf.error = 0; - lock_kernel(); error = vfs_readdir(file, filldir, &buf); if (error < 0) goto out_putf; @@ -1344,7 +1335,6 @@ error = count - buf.count; } out_putf: - unlock_kernel(); fput(file); out: return error; @@ -1587,7 +1577,6 @@ struct nameidata nd; int error; - lock_kernel(); error = user_path_walk(filename, &nd); if (!error) { struct inode *inode = nd.dentry->d_inode; @@ -1602,7 +1591,6 @@ path_release(&nd); } - unlock_kernel(); return error; } @@ -1611,7 +1599,6 @@ struct nameidata nd; int error; - lock_kernel(); error = user_path_walk_link(filename, &nd); if (!error) { struct inode *inode = nd.dentry->d_inode; @@ -1626,7 +1613,6 @@ path_release(&nd); } - unlock_kernel(); return error; } @@ -1635,15 +1621,13 @@ struct file *f; int err = -EBADF; - lock_kernel(); f = fget(fd); if (f) { - struct dentry *dentry = f->f_dentry; - struct inode *inode = dentry->d_inode; + struct inode *inode = f->f_dentry->d_inode; if (inode->i_op && inode->i_op->revalidate) - err = inode->i_op->revalidate(dentry); + err = inode->i_op->revalidate(f->f_dentry); else err = 0; if (!err) @@ -1651,7 +1635,6 @@ fput(f); } - unlock_kernel(); return err; } @@ -3029,9 +3012,7 @@ bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0])); - lock_kernel(); file = open_exec(filename); - unlock_kernel(); retval = PTR_ERR(file); if (IS_ERR(file)) @@ -3043,10 +3024,12 @@ bprm.loader = 0; bprm.exec = 0; if ((bprm.argc = count32(argv)) < 0) { + allow_write_access(file); fput(file); return bprm.argc; } if ((bprm.envc = count32(envp)) < 0) { + allow_write_access(file); fput(file); return bprm.envc; } @@ -3075,6 +3058,7 @@ out: /* Something went wrong, return the inode and free the argument pages*/ + allow_write_access(bprm.file); if (bprm.file) fput(bprm.file); @@ -4142,10 +4126,7 @@ if (!IS_ERR(tmp)) { fd = get_unused_fd(); if (fd >= 0) { - struct file * f; - lock_kernel(); - f = filp_open(tmp, flags, mode); - unlock_kernel(); + struct file * f = filp_open(tmp, flags, mode); error = PTR_ERR(f); if (IS_ERR(f)) goto out_error; diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c --- v2.4.0-test2/linux/arch/sparc64/kernel/sys_sunos32.c Fri Jun 23 21:55:08 2000 +++ linux/arch/sparc64/kernel/sys_sunos32.c Sat Jul 8 19:26:12 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.49 2000/06/22 11:42:25 davem Exp $ +/* $Id: sys_sunos32.c,v 1.51 2000/07/06 01:41:29 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -68,8 +68,6 @@ struct file *file = NULL; unsigned long retval, ret_type; - down(¤t->mm->mmap_sem); - lock_kernel(); if(flags & MAP_NORESERVE) { static int cnt; if (cnt++ < 10) @@ -102,18 +100,18 @@ flags &= ~_MAP_NEW; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + down(¤t->mm->mmap_sem); retval = do_mmap(file, (unsigned long) addr, (unsigned long) len, (unsigned long) prot, (unsigned long) flags, (unsigned long) off); + up(¤t->mm->mmap_sem); if(!ret_type) retval = ((retval < 0xf0000000) ? 0 : retval); out_putf: if (file) fput(file); out: - unlock_kernel(); - up(¤t->mm->mmap_sem); return (u32) retval; } @@ -321,8 +319,6 @@ if(!file) goto out; - lock_kernel(); - error = -EINVAL; if(cnt < (sizeof(struct sunos_dirent) + 255)) goto out_putf; @@ -344,7 +340,6 @@ } out_putf: - unlock_kernel(); fput(file); out: return error; @@ -406,8 +401,6 @@ if(!file) goto out; - lock_kernel(); - error = -EINVAL; if(cnt < (sizeof(struct sunos_direntry) + 255)) goto out_putf; @@ -429,7 +422,6 @@ } out_putf: - unlock_kernel(); fput(file); out: return error; @@ -489,7 +481,6 @@ { int ret; - lock_kernel(); switch(name) { case _PCONF_LINK: ret = LINK_MAX; @@ -520,7 +511,6 @@ ret = -EINVAL; break; } - unlock_kernel(); return ret; } @@ -528,9 +518,7 @@ { int ret; - lock_kernel(); ret = sunos_fpathconf(0, name); /* XXX cheese XXX */ - unlock_kernel(); return ret; } @@ -548,7 +536,6 @@ int ret; /* SunOS binaries expect that select won't change the tvp contents */ - lock_kernel(); ret = sys32_select (width, inp, outp, exp, tvp_x); if (ret == -EINTR && tvp_x) { struct timeval32 *tvp = (struct timeval32 *)A(tvp_x); @@ -559,7 +546,6 @@ if (sec == 0 && usec == 0) ret = 0; } - unlock_kernel(); return ret; } @@ -806,7 +792,6 @@ int ret; /* So stupid... */ - lock_kernel(); if((!pid || pid == current->pid) && !pgid) { sys_setsid(); @@ -814,7 +799,6 @@ } else { ret = sys_setpgid(pid, pgid); } - unlock_kernel(); return ret; } @@ -826,10 +810,8 @@ { int ret; - lock_kernel(); ret = sys32_wait4((pid ? pid : ((__kernel_pid_t32)-1)), stat_addr, options, ru); - unlock_kernel(); return ret; } @@ -846,9 +828,7 @@ asmlinkage int sunos_audit(void) { - lock_kernel(); printk ("sys_audit\n"); - unlock_kernel(); return -1; } @@ -876,7 +856,6 @@ { s32 ret; - lock_kernel(); switch (name){ case _SC_ARG_MAX: ret = ARG_MAX; @@ -909,7 +888,6 @@ ret = -1; break; }; - unlock_kernel(); return ret; } @@ -918,7 +896,6 @@ union semun arg4; int ret; - lock_kernel(); switch (op) { case 0: /* Most arguments match on a 1:1 basis but cmd doesn't */ @@ -954,7 +931,6 @@ ret = -EINVAL; break; }; - unlock_kernel(); return ret; } @@ -1056,7 +1032,6 @@ u32 arg5; int rval; - lock_kernel(); switch(op) { case 0: rval = sys_msgget((key_t)arg1, (int)arg2); @@ -1110,7 +1085,6 @@ rval = -EINVAL; break; } - unlock_kernel(); return rval; } @@ -1170,7 +1144,6 @@ mm_segment_t old_fs = get_fs(); int rval; - lock_kernel(); switch(op) { case 0: /* sys_shmat(): attach a shared memory area */ @@ -1202,7 +1175,6 @@ rval = -EINVAL; break; }; - unlock_kernel(); return rval; } @@ -1225,9 +1197,12 @@ static inline int check_nonblock(int ret, int fd) { if (ret == -EAGAIN) { - struct file * file = fcheck(fd); - if (file && (file->f_flags & O_NDELAY)) - ret = -SUNOS_EWOULDBLOCK; + struct file * file = fget(fd); + if (file) { + if (file->f_flags & O_NDELAY) + ret = -SUNOS_EWOULDBLOCK; + fput(file); + } } return ret; } @@ -1244,9 +1219,7 @@ { int ret; - lock_kernel(); ret = check_nonblock(sys_read(fd, (char *)A(buf), count), fd); - unlock_kernel(); return ret; } @@ -1254,9 +1227,7 @@ { int ret; - lock_kernel(); ret = check_nonblock(sys32_readv(fd, vector, count), fd); - unlock_kernel(); return ret; } @@ -1264,9 +1235,7 @@ { int ret; - lock_kernel(); ret = check_nonblock(sys_write(fd, (char *)A(buf), count), fd); - unlock_kernel(); return ret; } @@ -1274,9 +1243,7 @@ { int ret; - lock_kernel(); ret = check_nonblock(sys32_writev(fd, vector, count), fd); - unlock_kernel(); return ret; } @@ -1284,9 +1251,7 @@ { int ret; - lock_kernel(); ret = check_nonblock(sys_recv(fd, (void *)A(ubuf), size, flags), fd); - unlock_kernel(); return ret; } @@ -1294,9 +1259,7 @@ { int ret; - lock_kernel(); ret = check_nonblock(sys_send(fd, (void *)A(buff), len, flags), fd); - unlock_kernel(); return ret; } @@ -1307,7 +1270,6 @@ { int ret, one = 1; - lock_kernel(); ret = sys_socket(family, type, protocol); if (ret < 0) goto out; @@ -1315,7 +1277,6 @@ sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, (char *)&one, sizeof(one)); out: - unlock_kernel(); return ret; } @@ -1323,7 +1284,6 @@ { int ret, one = 1; - lock_kernel(); while (1) { ret = check_nonblock(sys_accept(fd, (struct sockaddr *)A(sa), (int *)A(addrlen)), fd); @@ -1336,7 +1296,6 @@ sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, (char *)&one, sizeof(one)); out: - unlock_kernel(); return ret; } @@ -1384,14 +1343,12 @@ int tr_opt = optname; int ret; - lock_kernel(); if (level == SOL_IP) { /* Multicast socketopts (ttl, membership) */ if (tr_opt >=2 && tr_opt <= 6) tr_opt += 30; } ret = sys_setsockopt(fd, level, tr_opt, (char *)A(optval), optlen); - unlock_kernel(); return ret; } @@ -1401,13 +1358,11 @@ int tr_opt = optname; int ret; - lock_kernel(); if (level == SOL_IP) { /* Multicast socketopts (ttl, membership) */ if (tr_opt >=2 && tr_opt <= 6) tr_opt += 30; } ret = sys32_getsockopt(fd, level, tr_opt, optval, optlen); - unlock_kernel(); return ret; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/lib/Makefile linux/arch/sparc64/lib/Makefile --- v2.4.0-test2/linux/arch/sparc64/lib/Makefile Wed Apr 26 16:34:07 2000 +++ linux/arch/sparc64/lib/Makefile Sun Jul 9 22:30:37 2000 @@ -1,5 +1,5 @@ # $Id: Makefile,v 1.22 2000/03/31 04:06:23 davem Exp $ -# Makefile for Sparc library files.. +# Makefile for Sparc64 library files.. # CFLAGS := $(CFLAGS) @@ -7,7 +7,8 @@ OBJS = PeeCeeI.o blockops.o debuglocks.o strlen.o strncmp.o \ memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \ VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \ - VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o + VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \ + dec_and_lock.o lib.a: $(OBJS) $(AR) rcs lib.a $(OBJS) diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/lib/dec_and_lock.S linux/arch/sparc64/lib/dec_and_lock.S --- v2.4.0-test2/linux/arch/sparc64/lib/dec_and_lock.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/lib/dec_and_lock.S Sun Jul 9 22:30:37 2000 @@ -0,0 +1,61 @@ +/* $Id$ + * dec_and_lock.S: Sparc64 version of "atomic_dec_and_lock()" + * using cas and ldstub instructions. + * + * Copyright (C) 2000 David S. Miller (davem@redhat.com) + */ + + .text + .align 64 + + /* CAS basically works like this: + * + * void CAS(MEM, REG1, REG2) + * { + * START_ATOMIC(); + * if (*(MEM) == REG1) { + * TMP = *(MEM); + * *(MEM) = REG2; + * REG2 = TMP; + * } + * END_ATOMIC(); + * } + * + * All non-contention cases are handled in 2 I-cache + * lines which is 1 L2 cache line. + */ + + .globl atomic_dec_and_lock +atomic_dec_and_lock: /* %o0 = counter, %o1 = lock */ +loop1: lduw [%o0], %g5 + subcc %g5, 1, %g7 + be,pn %icc, to_zero + nop +nzero: cas [%o0], %g5, %g7 + cmp %g5, %g7 + bne,pn %icc, loop1 + mov 0, %g1 + +out: retl + mov %g1, %o0 +to_zero:ldstub [%o1], %g3 + brnz,pn %g3, spin_on_lock + membar #StoreLoad | #StoreStore +loop2: cas [%o0], %g5, %g7 /* ASSERT(g7 == 0) */ + brnz,pt %g7, out + mov 1, %g1 + + lduw [%o0], %g5 + subcc %g5, 1, %g7 + be,pn %icc, loop2 + nop + membar #StoreStore | #LoadStore + stb %g0, [%o1] + b,pt %xcc, nzero + nop + +spin_on_lock: + ldub [%o1], %g3 + brnz,pt %g3, spin_on_lock + membar #LoadLoad + b,a,pt %xcc, to_zero diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/mm/modutil.c linux/arch/sparc64/mm/modutil.c --- v2.4.0-test2/linux/arch/sparc64/mm/modutil.c Mon Jun 19 16:31:58 2000 +++ linux/arch/sparc64/mm/modutil.c Wed Jul 5 12:14:54 2000 @@ -1,4 +1,4 @@ -/* $Id: modutil.c,v 1.5 2000/05/23 23:09:08 davem Exp $ +/* $Id: modutil.c,v 1.6 2000/06/26 23:20:24 davem Exp $ * arch/sparc64/mm/modutil.c * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -58,7 +58,7 @@ area->next = *p; *p = area; - if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, GFP_KERNEL)) { + if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, GFP_KERNEL, PAGE_KERNEL)) { vfree(addr); return NULL; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S --- v2.4.0-test2/linux/arch/sparc64/mm/ultra.S Tue May 23 15:31:34 2000 +++ linux/arch/sparc64/mm/ultra.S Sun Jul 9 22:30:37 2000 @@ -432,4 +432,24 @@ nop flush %g6 retry + + .globl xcall_call_function +xcall_call_function: + mov TLB_TAG_ACCESS, %g5 ! wheee... + stxa %g1, [%g5] ASI_IMMU ! save call_data here for a bit + membar #Sync + rdpr %pstate, %g2 + wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate + mov TLB_TAG_ACCESS, %g2 + ldxa [%g2] ASI_IMMU, %g5 + rdpr %pil, %g2 + wrpr %g0, 15, %pil + sethi %hi(109f), %g7 + b,pt %xcc, etrap_irq +109: or %g7, %lo(109b), %g7 + call smp_call_function_client + mov %l5, %o0 + b,pt %xcc, rtrap + clr %l6 + #endif /* CONFIG_SMP */ diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/prom/misc.c linux/arch/sparc64/prom/misc.c --- v2.4.0-test2/linux/arch/sparc64/prom/misc.c Tue May 23 15:31:34 2000 +++ linux/arch/sparc64/prom/misc.c Wed Jul 5 22:15:25 2000 @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.18 2000/05/09 17:40:14 davem Exp $ +/* $Id: misc.c,v 1.19 2000/06/30 10:18:38 davem Exp $ * misc.c: Miscellaneous prom functions that don't belong * anywhere else. * @@ -67,7 +67,7 @@ irq_exit(smp_processor_id(), 0); smp_capture(); #else - local_irq_count--; + local_irq_count(smp_processor_id())--; #endif p1275_cmd ("enter", P1275_INOUT(0,0)); @@ -77,7 +77,7 @@ irq_enter(smp_processor_id(), 0); spin_unlock_wait(&__br_write_locks[BR_GLOBALIRQ_LOCK].lock); #else - local_irq_count++; + local_irq_count(smp_processor_id())++; #endif #ifdef CONFIG_SUN_CONSOLE diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/solaris/fs.c linux/arch/sparc64/solaris/fs.c --- v2.4.0-test2/linux/arch/sparc64/solaris/fs.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/solaris/fs.c Sun Jul 9 22:30:37 2000 @@ -1,4 +1,4 @@ -/* $Id: fs.c,v 1.19 2000/05/09 04:48:35 davem Exp $ +/* $Id: fs.c,v 1.20 2000/07/06 01:41:30 davem Exp $ * fs.c: fs related syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -480,14 +481,12 @@ struct nameidata nd; int error; - lock_kernel(); error = user_path_walk((const char *)A(path),&nd); if (!error) { struct inode * inode = nd.dentry->d_inode; error = report_statvfs(inode, buf); path_release(&nd); } - unlock_kernel(); return error; } @@ -499,9 +498,7 @@ error = -EBADF; file = fget(fd); if (file) { - lock_kernel(); error = report_statvfs(file->f_dentry->d_inode, buf); - unlock_kernel(); fput(file); } diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/solaris/misc.c linux/arch/sparc64/solaris/misc.c --- v2.4.0-test2/linux/arch/sparc64/solaris/misc.c Tue May 23 15:31:34 2000 +++ linux/arch/sparc64/solaris/misc.c Wed Jul 5 22:15:25 2000 @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.27 2000/05/09 17:40:14 davem Exp $ +/* $Id: misc.c,v 1.28 2000/07/06 01:41:30 davem Exp $ * misc.c: Miscelaneous syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -54,7 +54,6 @@ struct file *file = NULL; unsigned long retval, ret_type; - lock_kernel(); /* Do we need it here? */ set_personality(PER_SVR4); if (flags & MAP_NORESERVE) { @@ -107,7 +106,6 @@ if (file) fput(file); out: - unlock_kernel(); return (u32) retval; } diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/vmlinux.lds linux/arch/sparc64/vmlinux.lds --- v2.4.0-test2/linux/arch/sparc64/vmlinux.lds Thu Feb 10 17:11:06 2000 +++ linux/arch/sparc64/vmlinux.lds Wed Jul 5 22:15:25 2000 @@ -74,5 +74,5 @@ .debug_pubnames 0 : { *(.debug_pubnames) } .debug_sfnames 0 : { *(.debug_sfnames) } .line 0 : { *(.line) } - /DISCARD/ : { *(.text.exit) *(.data.exit) } + /DISCARD/ : { *(.text.exit) *(.data.exit) *(.exitcall.exit) } } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/Makefile linux/drivers/Makefile --- v2.4.0-test2/linux/drivers/Makefile Tue Mar 14 19:10:39 2000 +++ linux/drivers/Makefile Sun Jul 9 22:21:41 2000 @@ -11,7 +11,8 @@ MOD_SUB_DIRS := $(SUB_DIRS) ALL_SUB_DIRS := $(SUB_DIRS) pci sgi ide scsi sbus cdrom isdn pnp i2o \ ieee1394 macintosh video dio zorro fc4 \ - usb nubus tc atm pcmcia i2c telephony + usb nubus tc atm pcmcia i2c telephony \ + acpi mtd ifdef CONFIG_DIO SUB_DIRS += dio @@ -30,6 +31,11 @@ endif endif +ifdef CONFIG_MTD +SUB_DIRS += mtd +MOD_SUB_DIRS += mtd +endif + ifdef CONFIG_SBUS SUB_DIRS += sbus MOD_SUB_DIRS += sbus @@ -80,7 +86,7 @@ endif endif -ifdef CONFIG_SGI_IP22 +ifdef CONFIG_SGI SUB_DIRS += sgi MOD_SUB_DIRS += sgi endif @@ -178,6 +184,11 @@ ifeq ($(CONFIG_I2C),m) MOD_SUB_DIRS += i2c endif +endif + +ifeq ($(CONFIG_ACPI),y) +SUB_DIRS += acpi +MOD_SUB_DIRS += acpi endif include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acorn/block/fd1772.c linux/drivers/acorn/block/fd1772.c --- v2.4.0-test2/linux/drivers/acorn/block/fd1772.c Thu May 11 15:30:06 2000 +++ linux/drivers/acorn/block/fd1772.c Wed Jul 5 11:24:40 2000 @@ -289,6 +289,7 @@ #define MAX_ERRORS 8 /* After this many errors the driver * will give up. */ +static struct timer_list fd_timer; #define START_MOTOR_OFF_TIMER(delay) \ do { \ @@ -299,8 +300,7 @@ #define START_CHECK_CHANGE_TIMER(delay) \ do { \ - timer_table[FLOPPY_TIMER].expires = jiffies + (delay); \ - timer_active |= (1 << FLOPPY_TIMER); \ + mod_timer(&fd_timer, jiffies + (delay)); \ } while(0) #define START_TIMEOUT() \ @@ -340,7 +340,7 @@ static void fd_select_drive(int drive); static void fd_deselect(void); static void fd_motor_off_timer(unsigned long dummy); -static void check_change(void); +static void check_change(unsigned long dummy); static __inline__ void set_head_settle_flag(void); static __inline__ int get_head_settle_flag(void); static void floppy_irqconsequencehandler(void); @@ -501,7 +501,7 @@ * as possible) and keep track of the current state of the write protection. */ -static void check_change(void) +static void check_change(unsigned long dummy) { static int drive = 0; @@ -1093,12 +1093,12 @@ STOP_TIMEOUT(); NeedSeek = 0; - if ((timer_active & (1 << FLOPPY_TIMER)) && - time_after(jiffies + 5, timer_table[FLOPPY_TIMER].expires)) + if (timer_pending(&fd_timer) && + time_after(jiffies + 5, fd_timer.expires)) /* If the check for a disk change is done too early after this * last seek command, the WP bit still reads wrong :-(( */ - timer_table[FLOPPY_TIMER].expires = jiffies + 5; + mod_timer(&fd_timer, jiffies + 5); else { /* START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */ }; @@ -1602,9 +1602,9 @@ #endif /* initialize check_change timer */ - timer_table[FLOPPY_TIMER].fn = check_change; - timer_active &= ~(1 << FLOPPY_TIMER); - + init_timer(&fd_timer); + fd_timer.function = check_change; +} #ifdef TRACKBUFFER DMABuffer = (char *)kmalloc((MAX_SECTORS+1)*512,GFP_KERNEL); /* Atari uses 512 - I want to eventually cope with 1K sectors */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acorn/char/Makefile linux/drivers/acorn/char/Makefile --- v2.4.0-test2/linux/drivers/acorn/char/Makefile Fri Jun 23 21:55:08 2000 +++ linux/drivers/acorn/char/Makefile Mon Jun 26 12:04:42 2000 @@ -33,6 +33,7 @@ obj-$(CONFIG_RPCMOUSE) += mouse_rpc.o obj-$(CONFIG_ATOMWIDE_SERIAL) += serial-atomwide.o obj-$(CONFIG_DUALSP_SERIAL) += serial-dualsp.o +obj-$(CONFIG_ARCH_ACORN) += defkeymap-acorn.o # Do the i2c and rtc last obj-y += $(obj-$(MACHINE)) i2c.o pcf8583.o diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acorn/char/defkeymap-acorn.c linux/drivers/acorn/char/defkeymap-acorn.c --- v2.4.0-test2/linux/drivers/acorn/char/defkeymap-acorn.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acorn/char/defkeymap-acorn.c Mon Jun 26 12:04:42 2000 @@ -0,0 +1,358 @@ +/* + * linux/arch/arm/drivers/char/defkeymap.c + * + * Copyright (C) 1995, 1996 Russell King + */ + +#include +#include +#include + +/* Normal (maps 1:1 with no processing) */ +#define KTn 0xF0 +/* Function keys */ +#define KTf 0xF1 +/* Special (Performs special house-keeping funcs) */ +#define KTs 0xF2 +#define KIGNORE K(KTs, 0) /* Ignore */ +#define KENTER K(KTs, 1) /* Enter */ +#define KREGS K(KTs, 2) /* Regs */ +#define KMEM K(KTs, 3) /* Mem */ +#define KSTAT K(KTs, 4) /* State */ +#define KINTR K(KTs, 5) /* Intr */ +#define Ksl 6 /* Last console */ +#define KCAPSLK K(KTs, 7) /* Caps lock */ +#define KNUMLK K(KTs, 8) /* Num-lock */ +#define KSCRLLK K(KTs, 9) /* Scroll-lock */ +#define KSCRLFOR K(KTs,10) /* Scroll forward */ +#define KSCRLBAK K(KTs,11) /* Scroll back */ +#define KREBOOT K(KTs,12) /* Reboot */ +#define KCAPSON K(KTs,13) /* Caps on */ +#define KCOMPOSE K(KTs,14) /* Compose */ +#define KSAK K(KTs,15) /* SAK */ +#define CONS_DEC K(KTs,16) /* Dec console */ +#define CONS_INC K(KTs,17) /* Incr console */ +#define KFLOPPY K(KTs,18) /* Floppy */ +/* Key pad (0-9 = digits, 10=+, 11=-, 12=*, 13=/, 14=enter, 16=., 17=# */ +#define KTp 0xF3 +#define KPAD_0 K(KTp, 0 ) +#define KPAD_1 K(KTp, 1 ) +#define KPAD_2 K(KTp, 2 ) +#define KPAD_3 K(KTp, 3 ) +#define KPAD_4 K(KTp, 4 ) +#define KPAD_5 K(KTp, 5 ) +#define KPAD_6 K(KTp, 6 ) +#define KPAD_7 K(KTp, 7 ) +#define KPAD_8 K(KTp, 8 ) +#define KPAD_9 K(KTp, 9 ) +#define KPAD_PL K(KTp,10 ) +#define KPAD_MI K(KTp,11 ) +#define KPAD_ML K(KTp,12 ) +#define KPAD_DV K(KTp,13 ) +#define KPAD_EN K(KTp,14 ) +#define KPAD_DT K(KTp,16 ) +#define KPAD_HS K(KTp,20 ) +/* Console switching */ +#define KCn 0xF5 +/* Cursor */ +#define KTc 0xF6 +#define Kcd 0 /* Cursor down */ +#define Kcl 1 /* Cursor left */ +#define Kcr 2 /* Cursor right */ +#define Kcu 3 /* Cursor up */ +/* Shift/alt modifiers etc */ +#define KMd 0xF7 +#define KSHIFT K(KMd, 0 ) +#define KALTGR K(KMd, 1 ) +#define KCTRL K(KMd, 2 ) +#define KALT K(KMd, 3 ) +/* Meta */ +#define KMt 0xF8 +#define KAs 0xF9 +#define KPADA_0 K(KAs, 0 ) +#define KPADA_1 K(KAs, 1 ) +#define KPADA_2 K(KAs, 2 ) +#define KPADA_3 K(KAs, 3 ) +#define KPADA_4 K(KAs, 4 ) +#define KPADA_5 K(KAs, 5 ) +#define KPADA_6 K(KAs, 6 ) +#define KPADA_7 K(KAs, 7 ) +#define KPADA_8 K(KAs, 8 ) +#define KPADA_9 K(KAs, 9 ) +#define KPADB_0 K(KAs,10 ) +#define KPADB_1 K(KAs,11 ) +#define KPADB_2 K(KAs,12 ) +#define KPADB_3 K(KAs,13 ) +#define KPADB_4 K(KAs,14 ) +#define KPADB_5 K(KAs,15 ) +#define KPADB_6 K(KAs,16 ) +#define KPADB_7 K(KAs,17 ) +#define KPADB_8 K(KAs,18 ) +#define KPADB_9 K(KAs,19 ) +/* Locking keys */ +#define KLk 0xFA +/* Letters */ +#define KTl 0xFB + +u_short plain_map[NR_KEYS]= +{ + K(KTn, 27),K(KTf, 0),K(KTf, 1),K(KTf, 2 ),K(KTf, 3),K(KTf, 4),K(KTf, 5 ),K(KTf, 6), + K(KTf, 7),K(KTf, 8),K(KTf, 9),K(KTf, 10 ),K(KTf, 11),KIGNORE ,KSCRLLK ,KINTR , + K(KTn,'`'),K(KTn,'1'),K(KTn,'2'),K(KTn,'3' ),K(KTn,'4'),K(KTn,'5'),K(KTn,'6' ),K(KTn,'7'), + K(KTn,'8'),K(KTn,'9'),K(KTn,'0'),K(KTn,'-' ),K(KTn,'='),K(KTn,'£'),K(KTn,127 ),K(KTf,21 ), + K(KTf,20 ),K(KTf,24 ),KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,K(KTn, 9 ),K(KTl,'q'), + K(KTl,'w'),K(KTl,'e'),K(KTl,'r'),K(KTl,'t' ),K(KTl,'y'),K(KTl,'u'),K(KTl,'i' ),K(KTl,'o'), + K(KTl,'p'),K(KTn,'['),K(KTn,']'),K(KTn,'\\'),K(KTf,22 ),K(KTf,23 ),K(KTf,25 ),KPAD_7 , + KPAD_8 ,KPAD_9 ,KPAD_MI ,KCTRL ,K(KTl,'a'),K(KTl,'s'),K(KTl,'d' ),K(KTl,'f'), + K(KTl,'g'),K(KTl,'h'),K(KTl,'j'),K(KTl,'k' ),K(KTl,'l'),K(KTn,';'),K(KTn,'\''),KENTER , + KPAD_4 ,KPAD_5 ,KPAD_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KTl,'z' ),K(KTl,'x'), + K(KTl,'c'),K(KTl,'v'),K(KTl,'b'),K(KTl,'n' ),K(KTl,'m'),K(KTn,','),K(KTn,'.' ),K(KTn,'/'), + KSHIFT ,K(KTc,Kcu),KPAD_1 ,KPAD_2 ,KPAD_3 ,KCAPSLK ,KALT ,K(KTn,' '), + KALTGR ,KCTRL ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPAD_0 ,KPAD_DT ,KPAD_EN , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , +}; + +u_short shift_map[NR_KEYS]= +{ + K(KTn, 27),K(KTf, 10),K(KTf, 11),K(KTf, 12 ),K(KTf, 13),K(KTf, 14),K(KTf, 15 ),K(KTf, 16), + K(KTf, 17),K(KTf, 18),K(KTf, 19),K(KTf, 20 ),K(KTf, 21),KIGNORE ,KMEM ,KINTR , + K(KTn,'~'),K(KTn,'!'),K(KTn,'@'),K(KTn,'#' ),K(KTn,'$'),K(KTn,'%'),K(KTn,'^' ),K(KTn,'&'), + K(KTn,'*'),K(KTn,'('),K(KTn,')'),K(KTn,'_' ),K(KTn,'+'),K(KTn,'¤'),K(KTn,127 ),K(KTf,21 ), + K(KTf,20 ),KSCRLBAK ,KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,K(KTn, 9 ),K(KTl,'Q'), + K(KTl,'W'),K(KTl,'E'),K(KTl,'R'),K(KTl,'T' ),K(KTl,'Y'),K(KTl,'U'),K(KTl,'I' ),K(KTl,'O'), + K(KTl,'P'),K(KTn,'{'),K(KTn,'}'),K(KTn,'|' ),K(KTf,22 ),K(KTf,23 ),KSCRLFOR ,KPAD_7 , + KPAD_8 ,KPAD_9 ,KPAD_MI ,KCTRL ,K(KTl,'A'),K(KTl,'S'),K(KTl,'D' ),K(KTl,'F'), + K(KTl,'G'),K(KTl,'H'),K(KTl,'J'),K(KTl,'K' ),K(KTl,'L'),K(KTn,':'),K(KTn,'"' ),KENTER , + KPAD_4 ,KPAD_5 ,KPAD_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KTl,'Z' ),K(KTl,'X'), + K(KTl,'C'),K(KTl,'V'),K(KTl,'B'),K(KTl,'N' ),K(KTl,'M'),K(KTn,'<'),K(KTn,'>' ),K(KTn,'?'), + KSHIFT ,K(KTc,Kcu),KPAD_1 ,KPAD_2 ,KPAD_3 ,KCAPSLK ,KALT ,K(KTn,' '), + KALTGR ,KCTRL ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPAD_0 ,KPAD_DT ,KPAD_EN , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , +}; + +u_short altgr_map[NR_KEYS]= +{ + KIGNORE ,K(KCn,12 ),K(KCn,13 ),K(KCn,14 ),K(KCn,15 ),K(KCn,16 ),K(KCn,17 ),K(KCn, 18), + K(KCn, 19),K(KCn,20 ),K(KCn,21 ),K(KCn,22 ),K(KCn,23 ),KIGNORE ,KREGS ,KINTR , + KIGNORE ,KIGNORE ,K(KTn,'@'),KIGNORE ,K(KTn,'$'),KIGNORE ,KIGNORE ,K(KTn,'{'), + K(KTn,'['),K(KTn,']'),K(KTn,'}'),K(KTn,'\\'),KIGNORE ,KIGNORE ,KIGNORE ,K(KTf,21 ), + K(KTf,20 ),K(KTf,24 ),KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,KIGNORE ,K(KTl,'q'), + K(KTl,'w'),K(KTl,'e'),K(KTl,'r'),K(KTl,'t' ),K(KTl,'y'),K(KTl,'u'),K(KTl,'i' ),K(KTl,'o'), + K(KTl,'p'),KIGNORE ,K(KTn,'~'),KIGNORE ,K(KTf,22 ),K(KTf,23 ),K(KTf,25 ),KPADB_7 , + KPADB_8 ,KPADB_9 ,KPAD_MI ,KCTRL ,K(KAs,20 ),K(KTl,'s'),K(KAs,23 ),K(KAs,25 ), + K(KTl,'g'),K(KTl,'h'),K(KTl,'j'),K(KTl,'k' ),K(KTl,'l'),KIGNORE ,KIGNORE ,KENTER , + KPADB_4 ,KPADB_5 ,KPADB_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KTl,'z' ),K(KTl,'x'), + K(KAs,22 ),K(KTl,'v'),K(KTl,21 ),K(KTl,'n' ),K(KTl,'m'),KIGNORE ,KIGNORE ,KIGNORE , + KSHIFT ,K(KTc,Kcu),KPADB_1 ,KPADB_2 ,KPADB_3 ,KCAPSLK ,KALT ,KIGNORE , + KALTGR ,KCTRL ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPADB_0 ,KPAD_DT ,KPAD_EN , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , +}; + +u_short ctrl_map[NR_KEYS]= +{ + KIGNORE ,K(KTf, 0),K(KTf, 1),K(KTf, 2 ),K(KTf, 3),K(KTf, 4),K(KTf, 5 ),K(KTf, 6), + K(KTf, 7),K(KTf, 8),K(KTf, 9),K(KTf, 10 ),K(KTf, 11),KIGNORE ,KSTAT ,KINTR , + KIGNORE ,K(KTn, 1 ),K(KTn, 2 ),K(KTn, 3 ),K(KTn, 4 ),K(KTn, 5 ),K(KTn, 6 ),K(KTn, 7 ), + K(KTn, 8 ),K(KTn, 9 ),K(KTn, 0 ),K(KTn,31 ),KIGNORE ,KIGNORE ,K(KTn, 8 ),K(KTf,21 ), + K(KTf,20 ),K(KTf,24 ),KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,KIGNORE ,K(KTn,17 ), + K(KTn,23 ),K(KTn, 5 ),K(KTn,18 ),K(KTn,20 ),K(KTn,25 ),K(KTn,21 ),K(KTn, 9 ),K(KTn,15 ), + K(KTn,16 ),K(KTn,27 ),K(KTn,29 ),K(KTn,28 ),K(KTf,22 ),K(KTf,23 ),K(KTf,25 ),KPAD_7 , + KPAD_8 ,KPAD_9 ,KPAD_MI ,KCTRL ,K(KTn, 1 ),K(KTn,19 ),K(KTn, 4 ),K(KTn, 6 ), + K(KTn, 7 ),K(KTn, 8 ),K(KTn,10 ),K(KTn,11 ),K(KTn,12 ),KIGNORE ,K(KTn, 7 ),KENTER , + KPAD_4 ,KPAD_5 ,KPAD_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KTn,26 ),K(KTn,24 ), + K(KTn, 3 ),K(KTn,22 ),K(KTn, 2 ),K(KTn,14 ),K(KTn,13 ),KIGNORE ,KCOMPOSE ,K(KTn,127), + KSHIFT ,K(KTc,Kcu),KPAD_1 ,KPAD_2 ,KPAD_3 ,KCAPSLK ,KALT ,K(KTn, 0 ), + KALTGR ,KCTRL ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPAD_0 ,KPAD_DT ,KPAD_EN , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , +}; + +u_short shift_ctrl_map[NR_KEYS]= +{ + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KFLOPPY ,KINTR , + KIGNORE ,KIGNORE ,K(KTn, 0 ),KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,K(KTn,31 ),KIGNORE ,KIGNORE ,KIGNORE ,K(KTf,21 ), + K(KTf,20 ),K(KTf,24 ),KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,KIGNORE ,K(KTn,17 ), + K(KTn,23 ),K(KTn, 5 ),K(KTn,18 ),K(KTn,20 ),K(KTn,25 ),K(KTn,21 ),K(KTn, 9 ),K(KTn,15 ), + K(KTn,16 ),KIGNORE ,KIGNORE ,KIGNORE ,K(KTf,22 ),K(KTf,23 ),K(KTf,25 ),KPAD_7 , + KPAD_8 ,KPAD_9 ,KPAD_MI ,KCTRL ,K(KTn, 1 ),K(KTn,19 ),K(KTn, 4 ),K(KTn, 6 ), + K(KTn, 7 ),K(KTn, 8 ),K(KTn,10 ),K(KTn,11 ),K(KTn,12 ),KIGNORE ,K(KTn, 7 ),KENTER , + KPAD_4 ,KPAD_5 ,KPAD_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KTn,26 ),K(KTn,24 ), + K(KTn, 3 ),K(KTn,22 ),K(KTn, 2 ),K(KTn,14 ),K(KTn,13 ),KIGNORE ,KIGNORE ,KIGNORE , + KSHIFT ,K(KTc,Kcu),KPAD_1 ,KPAD_2 ,KPAD_3 ,KCAPSLK ,KALT ,K(KTn, 0 ), + KALTGR ,KCTRL ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPAD_0 ,KPAD_DT ,KPAD_EN , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , +}; + +u_short alt_map[NR_KEYS]= +{ + K(KMt,27 ),K(KCn, 0 ),K(KCn, 1 ),K(KCn, 2 ),K(KCn, 3 ),K(KCn, 4 ),K(KCn, 5 ),K(KCn, 6 ), + K(KCn, 7 ),K(KCn, 8 ),K(KCn, 9 ),K(KCn,10 ),K(KCn,11 ),KIGNORE ,KSCRLLK ,KINTR , + K(KMt,'`'),K(KMt,'1'),K(KMt,'2'),K(KMt,'3' ),K(KMt,'4'),K(KMt,'5'),K(KMt,'6' ),K(KMt,'7'), + K(KMt,'8'),K(KMt,'9'),K(KMt,'0'),K(KMt,'-' ),K(KMt,'='),K(KMt,'£'),K(KMt,127 ),K(KTf,21 ), + K(KTf,20 ),K(KTf,24 ),KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,K(KMt, 9 ),K(KMt,'q'), + K(KMt,'w'),K(KMt,'e'),K(KMt,'r'),K(KMt,'t' ),K(KMt,'y'),K(KMt,'u'),K(KMt,'i' ),K(KMt,'o'), + K(KMt,'p'),K(KMt,'['),K(KMt,']'),K(KMt,'\\'),K(KTf,22 ),K(KTf,23 ),K(KTf,25 ),KPADA_7 , + KPADA_8 ,KPADA_9 ,KPAD_MI ,KCTRL ,K(KMt,'a'),K(KMt,'s'),K(KMt,'d' ),K(KMt,'f'), + K(KMt,'g'),K(KMt,'h'),K(KMt,'j'),K(KMt,'k' ),K(KMt,'l'),K(KMt,';'),K(KMt,'\''),K(KMt,13 ), + KPADA_4 ,KPADA_5 ,KPADA_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KMt,'z' ),K(KMt,'x'), + K(KMt,'c'),K(KMt,'v'),K(KMt,'b'),K(KMt,'n' ),K(KMt,'m'),K(KMt,','),K(KMt,'.' ),KIGNORE , + KSHIFT ,K(KTc,Kcu),KPADA_1 ,KPADA_2 ,KPADA_3 ,KCAPSLK ,KALT ,K(KMt,' '), + KALTGR ,KCTRL ,CONS_DEC ,K(KTc,Kcd ),CONS_INC ,KPADA_0 ,KPAD_DT ,KPAD_EN , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , +}; + +u_short ctrl_alt_map[NR_KEYS]= +{ + KIGNORE ,K(KCn, 0 ),K(KCn, 1 ),K(KCn, 2 ),K(KCn, 3 ),K(KCn, 4 ),K(KCn, 5 ),K(KCn, 6 ), + K(KCn, 7 ),K(KCn, 8 ),K(KCn, 9 ),K(KCn,10 ),K(KCn,11 ),KIGNORE ,KIGNORE ,KINTR , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,K(KTf,21 ), + K(KTf,20 ),K(KTf,24 ),KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,KIGNORE ,K(KMt,17 ), + K(KMt,23 ),K(KMt, 5 ),K(KMt,18 ),K(KMt,20 ),K(KMt,25 ),K(KMt,21 ),K(KMt, 9 ),K(KMt,15 ), + K(KMt,16 ),KIGNORE ,KIGNORE ,KIGNORE ,KREBOOT ,K(KTf,23 ),K(KTf,25 ),KPAD_7 , + KPAD_8 ,KPAD_9 ,KPAD_MI ,KCTRL ,K(KMt, 1 ),K(KMt,19 ),K(KMt, 4 ),K(KMt, 6 ), + K(KMt, 7 ),K(KMt, 8 ),K(KMt,10 ),K(KMt,11 ),K(KMt,12 ),KIGNORE ,KIGNORE ,KENTER , + KPAD_4 ,KPAD_5 ,KPAD_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KMt,26 ),K(KMt,24 ), + K(KMt, 3 ),K(KMt,22 ),K(KMt, 2 ),K(KMt,14 ),K(KMt,13 ),KIGNORE ,KIGNORE ,KIGNORE , + KSHIFT ,K(KTc,Kcu),KPAD_1 ,KPAD_2 ,KPAD_3 ,KCAPSLK ,KALT ,KIGNORE , + KALTGR ,KCTRL ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPAD_0 ,KREBOOT ,KPAD_EN , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , + KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , +}; + +ushort *key_maps[MAX_NR_KEYMAPS] = { + plain_map, shift_map, altgr_map, 0, + ctrl_map, shift_ctrl_map, 0, 0, + alt_map, 0, 0, 0, + ctrl_alt_map, 0 +}; + +unsigned int keymap_count = 7; + +/* + * Philosophy: most people do not define more strings, but they who do + * often want quite a lot of string space. So, we statically allocate + * the default and allocate dynamically in chunks of 512 bytes. + */ + +char func_buf[] = { + '\033', '[', '[', 'A', 0, + '\033', '[', '[', 'B', 0, + '\033', '[', '[', 'C', 0, + '\033', '[', '[', 'D', 0, + '\033', '[', '[', 'E', 0, + '\033', '[', '1', '7', '~', 0, + '\033', '[', '1', '8', '~', 0, + '\033', '[', '1', '9', '~', 0, + '\033', '[', '2', '0', '~', 0, + '\033', '[', '2', '1', '~', 0, + '\033', '[', '2', '3', '~', 0, + '\033', '[', '2', '4', '~', 0, + '\033', '[', '2', '5', '~', 0, + '\033', '[', '2', '6', '~', 0, + '\033', '[', '2', '8', '~', 0, + '\033', '[', '2', '9', '~', 0, + '\033', '[', '3', '1', '~', 0, + '\033', '[', '3', '2', '~', 0, + '\033', '[', '3', '3', '~', 0, + '\033', '[', '3', '4', '~', 0, + '\033', '[', '1', '~', 0, + '\033', '[', '2', '~', 0, + '\033', '[', '3', '~', 0, + '\033', '[', '4', '~', 0, + '\033', '[', '5', '~', 0, + '\033', '[', '6', '~', 0, + '\033', '[', 'M', 0, + '\033', '[', 'P', 0, +}; + +char *funcbufptr = func_buf; +int funcbufsize = sizeof(func_buf); +int funcbufleft = 0; /* space left */ + +char *func_table[MAX_NR_FUNC] = { + func_buf + 0, + func_buf + 5, + func_buf + 10, + func_buf + 15, + func_buf + 20, + func_buf + 25, + func_buf + 31, + func_buf + 37, + func_buf + 43, + func_buf + 49, + func_buf + 55, + func_buf + 61, + func_buf + 67, + func_buf + 73, + func_buf + 79, + func_buf + 85, + func_buf + 91, + func_buf + 97, + func_buf + 103, + func_buf + 109, + func_buf + 115, + func_buf + 120, + func_buf + 125, + func_buf + 130, + func_buf + 135, + func_buf + 140, + func_buf + 145, + 0, + 0, + func_buf + 149, + 0, +}; + +struct kbdiacr accent_table[MAX_DIACR] = { + {'`', 'A', '\300'}, {'`', 'a', '\340'}, + {'\'', 'A', '\301'}, {'\'', 'a', '\341'}, + {'^', 'A', '\302'}, {'^', 'a', '\342'}, + {'~', 'A', '\303'}, {'~', 'a', '\343'}, + {'"', 'A', '\304'}, {'"', 'a', '\344'}, + {'O', 'A', '\305'}, {'o', 'a', '\345'}, + {'0', 'A', '\305'}, {'0', 'a', '\345'}, + {'A', 'A', '\305'}, {'a', 'a', '\345'}, + {'A', 'E', '\306'}, {'a', 'e', '\346'}, + {',', 'C', '\307'}, {',', 'c', '\347'}, + {'`', 'E', '\310'}, {'`', 'e', '\350'}, + {'\'', 'E', '\311'}, {'\'', 'e', '\351'}, + {'^', 'E', '\312'}, {'^', 'e', '\352'}, + {'"', 'E', '\313'}, {'"', 'e', '\353'}, + {'`', 'I', '\314'}, {'`', 'i', '\354'}, + {'\'', 'I', '\315'}, {'\'', 'i', '\355'}, + {'^', 'I', '\316'}, {'^', 'i', '\356'}, + {'"', 'I', '\317'}, {'"', 'i', '\357'}, + {'-', 'D', '\320'}, {'-', 'd', '\360'}, + {'~', 'N', '\321'}, {'~', 'n', '\361'}, + {'`', 'O', '\322'}, {'`', 'o', '\362'}, + {'\'', 'O', '\323'}, {'\'', 'o', '\363'}, + {'^', 'O', '\324'}, {'^', 'o', '\364'}, + {'~', 'O', '\325'}, {'~', 'o', '\365'}, + {'"', 'O', '\326'}, {'"', 'o', '\366'}, + {'/', 'O', '\330'}, {'/', 'o', '\370'}, + {'`', 'U', '\331'}, {'`', 'u', '\371'}, + {'\'', 'U', '\332'}, {'\'', 'u', '\372'}, + {'^', 'U', '\333'}, {'^', 'u', '\373'}, + {'"', 'U', '\334'}, {'"', 'u', '\374'}, + {'\'', 'Y', '\335'}, {'\'', 'y', '\375'}, + {'T', 'H', '\336'}, {'t', 'h', '\376'}, + {'s', 's', '\337'}, {'"', 'y', '\377'}, + {'s', 'z', '\337'}, {'i', 'j', '\377'}, +}; + +unsigned int accent_table_size = 68; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/Makefile linux/drivers/acpi/Makefile --- v2.4.0-test2/linux/drivers/acpi/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/Makefile Wed Jul 5 11:23:12 2000 @@ -0,0 +1,27 @@ +# +# Makefile for the Linux ACPI interpreter +# + +SUB_DIRS := +MOD_SUB_DIRS := $(SUB_DIRS) +MOD_IN_SUB_DIRS := +ALL_SUB_DIRS := $(SUB_DIRS) + +O_TARGET := acpi.o +O_OBJS := +M_OBJS := + +ACPI_OBJS := osd.o +ACPI_OBJS += $(patsubst %.c,%.o,$(wildcard */*.c)) + +EXTRA_CFLAGS += -I./include -D_LINUX + +# if the interpreter is used, it overrides arch/i386/kernel/acpi.c +ifeq ($(CONFIG_ACPI_INTERPRETER),y) + O_OBJS += $(ACPI_OBJS) +endif + +include $(TOPDIR)/Rules.make + +clean: + $(RM) *.o */*.o diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/common/cmalloc.c linux/drivers/acpi/common/cmalloc.c --- v2.4.0-test2/linux/drivers/acpi/common/cmalloc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/common/cmalloc.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,166 @@ +/****************************************************************************** + * + * Module Name: cmalloc - local memory allocation routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "interp.h" +#include "namesp.h" +#include "globals.h" + +#define _COMPONENT MISCELLANEOUS + MODULE_NAME ("cmalloc"); + + +/***************************************************************************** + * + * FUNCTION: _Cm_allocate + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: The subsystem's equivalent of malloc. + * + ****************************************************************************/ + +void * +_cm_allocate ( + u32 size, + u32 component, + ACPI_STRING module, + s32 line) +{ + void *address = NULL; + + /* Check for an inadvertent size of zero bytes */ + + if (!size) { + REPORT_ERROR ("Cm_allocate: Attempt to allocate zero bytes"); + size = 1; + } + + address = acpi_os_allocate (size); + if (!address) { + /* Report allocation error */ + + _REPORT_ERROR (module, line, component, + "Cm_allocate: Memory allocation failure"); + + return (NULL); + } + + + return (address); +} + + +/***************************************************************************** + * + * FUNCTION: _Cm_callocate + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of calloc. + * + ****************************************************************************/ + +void * +_cm_callocate ( + u32 size, + u32 component, + ACPI_STRING module, + s32 line) +{ + void *address = NULL; + + /* Check for an inadvertent size of zero bytes */ + + if (!size) { + REPORT_ERROR ("Cm_callocate: Attempt to allocate zero bytes"); + return (NULL); + } + + + address = acpi_os_callocate (size); + + if (!address) { + /* Report allocation error */ + + _REPORT_ERROR (module, line, component, + "Cm_callocate: Memory allocation failure"); + + return (NULL); + } + + + return (address); +} + + +/***************************************************************************** + * + * FUNCTION: _Cm_free + * + * PARAMETERS: Address - Address of the memory to deallocate + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: None + * + * DESCRIPTION: Frees the memory at Address + * + ****************************************************************************/ + +void +_cm_free ( + void *address, + u32 component, + ACPI_STRING module, + s32 line) +{ + + if (NULL == address) { + _REPORT_ERROR (module, line, component, + "_Cm_free: Trying to delete a NULL address."); + + return; + } + + + acpi_os_free (address); + + return; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/common/cmcopy.c linux/drivers/acpi/common/cmcopy.c --- v2.4.0-test2/linux/drivers/acpi/common/cmcopy.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/common/cmcopy.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,711 @@ +/****************************************************************************** + * + * Module Name: cmcopy - Internal to external object translation utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" +#include "namesp.h" + + +#define _COMPONENT MISCELLANEOUS + MODULE_NAME ("cmcopy"); + + +typedef struct search_st +{ + ACPI_OBJECT_INTERNAL *internal_obj; + u32 index; + ACPI_OBJECT *external_obj; + +} PKG_SEARCH_INFO; + + +/* Used to traverse nested packages */ + +PKG_SEARCH_INFO level[MAX_PACKAGE_DEPTH]; + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_build_external_simple_object + * + * PARAMETERS: *Internal_obj - Pointer to the object we are examining + * *Buffer - Where the object is returned + * *Space_used - Where the data length is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to place a simple object in a user + * buffer. + * + * The buffer is assumed to have sufficient space for the object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_build_external_simple_object ( + ACPI_OBJECT_INTERNAL *internal_obj, + ACPI_OBJECT *external_obj, + u8 *data_space, + u32 *buffer_space_used) +{ + u32 length = 0; + char *source_ptr = NULL; + + + /* + * Check for NULL object case (could be an uninitialized + * package element + */ + + if (!internal_obj) { + *buffer_space_used = 0; + return (AE_OK); + } + + /* Always clear the external object */ + + MEMSET (external_obj, 0, sizeof (ACPI_OBJECT)); + + /* + * In general, the external object will be the same type as + * the internal object + */ + + external_obj->type = internal_obj->common.type; + + /* However, only a limited number of external types are supported */ + + switch (external_obj->type) + { + + case ACPI_TYPE_STRING: + + length = internal_obj->string.length; + external_obj->string.length = internal_obj->string.length; + external_obj->string.pointer = (char *) data_space; + source_ptr = internal_obj->string.pointer; + break; + + + case ACPI_TYPE_BUFFER: + + length = internal_obj->buffer.length; + external_obj->buffer.length = internal_obj->buffer.length; + external_obj->buffer.pointer = data_space; + source_ptr = (char *) internal_obj->buffer.pointer; + break; + + + case ACPI_TYPE_NUMBER: + + external_obj->number.value= internal_obj->number.value; + break; + + + case INTERNAL_TYPE_REFERENCE: + + /* + * This is an object reference. We use the object type of "Any" + * to indicate a reference object containing a handle to an ACPI + * named object. + */ + + external_obj->type = ACPI_TYPE_ANY; + external_obj->reference.handle = internal_obj->reference.nte; + break; + + + case ACPI_TYPE_PROCESSOR: + + external_obj->processor.proc_id = + internal_obj->processor.proc_id; + + external_obj->processor.pblk_address = + internal_obj->processor.pblk_address; + + external_obj->processor.pblk_length = + internal_obj->processor.pblk_length; + break; + + case ACPI_TYPE_POWER: + + external_obj->power_resource.system_level = + internal_obj->power_resource.system_level; + + external_obj->power_resource.resource_order = + internal_obj->power_resource.resource_order; + break; + + default: + return (AE_CTRL_RETURN_VALUE); + break; + } + + + /* Copy data if necessary (strings or buffers) */ + + if (length) { + /* + * Copy the return data to the caller's buffer + */ + MEMCPY ((void *) data_space, (void *) source_ptr, length); + } + + + *buffer_space_used = (u32) ROUND_UP_TO_NATIVE_WORD (length); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_build_external_package_object + * + * PARAMETERS: *Internal_obj - Pointer to the object we are returning + * *Buffer - Where the object is returned + * *Space_used - Where the object length is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to place a package object in a user + * buffer. A package object by definition contains other objects. + * + * The buffer is assumed to have sufficient space for the object. + * The caller must have verified the buffer length needed using the + * Acpi_cm_get_object_size function before calling this function. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_build_external_package_object ( + ACPI_OBJECT_INTERNAL *internal_obj, + u8 *buffer, + u32 *space_used) +{ + u8 *free_space; + ACPI_OBJECT *external_obj; + u32 current_depth = 0; + ACPI_STATUS status; + u32 length = 0; + u32 this_index; + u32 object_space; + ACPI_OBJECT_INTERNAL *this_internal_obj; + ACPI_OBJECT *this_external_obj; + PKG_SEARCH_INFO *level_ptr; + + + /* + * First package at head of the buffer + */ + external_obj = (ACPI_OBJECT *) buffer; + + /* + * Free space begins right after the first package + */ + free_space = buffer + ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)); + + + /* + * Initialize the working variables + */ + + MEMSET ((void *) level, 0, sizeof (level)); + + level[0].internal_obj = internal_obj; + level[0].external_obj = external_obj; + level[0].index = 0; + level_ptr = &level[0]; + current_depth = 0; + + external_obj->type = internal_obj->common.type; + external_obj->package.count = internal_obj->package.count; + external_obj->package.elements = (ACPI_OBJECT *) free_space; + + + /* + * Build an array of ACPI_OBJECTS in the buffer + * and move the free space past it + */ + + free_space += external_obj->package.count * + ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)); + + + while (1) { + this_index = level_ptr->index; + this_internal_obj = + (ACPI_OBJECT_INTERNAL *) + level_ptr->internal_obj->package.elements[this_index]; + this_external_obj = + (ACPI_OBJECT *) + &level_ptr->external_obj->package.elements[this_index]; + + + /* + * Check for 1) Null object -- OK, this can happen if package + * element is never initialized + * 2) Not an internal object - can be an NTE instead + * 3) Any internal object other than a package. + * + * The more complex package case is handled later + */ + + if ((!this_internal_obj) || + (!VALID_DESCRIPTOR_TYPE ( + this_internal_obj, ACPI_DESC_TYPE_INTERNAL)) || + (!IS_THIS_OBJECT_TYPE ( + this_internal_obj, ACPI_TYPE_PACKAGE))) + { + /* + * This is a simple or null object -- get the size + */ + + status = + acpi_cm_build_external_simple_object (this_internal_obj, + this_external_obj, + free_space, + &object_space); + if (ACPI_FAILURE (status)) { + return (status); + } + + free_space += object_space; + length += object_space; + + level_ptr->index++; + while (level_ptr->index >= + level_ptr->internal_obj->package.count) + { + /* + * We've handled all of the objects at this + * level. This means that we have just + * completed a package. That package may + * have contained one or more packages + * itself + */ + if (current_depth == 0) { + /* + * We have handled all of the objects + * in the top level package just add + * the length of the package objects + * and get out + */ + *space_used = length; + return (AE_OK); + } + + /* + * go back up a level and move the index + * past the just completed package object. + */ + current_depth--; + level_ptr = &level[current_depth]; + level_ptr->index++; + } + } + + + else { + /* + * This object is a package + * -- we must go one level deeper + */ + if (current_depth >= MAX_PACKAGE_DEPTH-1) { + /* + * Too many nested levels of packages + * for us to handle + */ + return (AE_LIMIT); + } + + /* + * Build the package object + */ + this_external_obj->type = ACPI_TYPE_PACKAGE; + this_external_obj->package.count = + this_internal_obj->package.count; + this_external_obj->package.elements = + (ACPI_OBJECT *) free_space; + + /* + * Save space for the array of objects (Package elements) + * update the buffer length counter + */ + object_space = (u32) ROUND_UP_TO_NATIVE_WORD ( + this_external_obj->package.count * + sizeof (ACPI_OBJECT)); + + free_space += object_space; + length += object_space; + + current_depth++; + level_ptr = &level[current_depth]; + level_ptr->internal_obj = this_internal_obj; + level_ptr->external_obj = this_external_obj; + level_ptr->index = 0; + } + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_build_external_object + * + * PARAMETERS: *Internal_obj - The internal object to be converted + * *Buffer_ptr - Where the object is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to build an API object to be returned to + * the caller. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_build_external_object ( + ACPI_OBJECT_INTERNAL *internal_obj, + ACPI_BUFFER *ret_buffer) +{ + ACPI_STATUS status; + + + if (IS_THIS_OBJECT_TYPE (internal_obj, ACPI_TYPE_PACKAGE)) { + /* + * Package objects contain other objects (which can be objects) + * buildpackage does it all + */ + status = + acpi_cm_build_external_package_object (internal_obj, + ret_buffer->pointer, + &ret_buffer->length); + } + + else { + /* + * Build a simple object (no nested objects) + */ + status = + acpi_cm_build_external_simple_object (internal_obj, + (ACPI_OBJECT *) ret_buffer->pointer, + ((u8 *) ret_buffer->pointer + + ROUND_UP_TO_NATIVE_WORD ( + sizeof (ACPI_OBJECT))), + &ret_buffer->length); + /* + * build simple does not include the object size in the length + * so we add it in here + */ + ret_buffer->length += sizeof (ACPI_OBJECT); + } + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_build_internal_simple_object + * + * PARAMETERS: *External_obj - The external object to be converted + * *Internal_obj - Where the internal object is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function copies an external object to an internal one. + * NOTE: Pointers can be copied, we don't need to copy data. + * (The pointers have to be valid in our address space no matter + * what we do with them!) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_build_internal_simple_object ( + ACPI_OBJECT *external_obj, + ACPI_OBJECT_INTERNAL *internal_obj) +{ + + + internal_obj->common.type = (u8) external_obj->type; + + switch (external_obj->type) + { + + case ACPI_TYPE_STRING: + + internal_obj->string.length = external_obj->string.length; + internal_obj->string.pointer = external_obj->string.pointer; + break; + + + case ACPI_TYPE_BUFFER: + + internal_obj->buffer.length = external_obj->buffer.length; + internal_obj->buffer.pointer = external_obj->buffer.pointer; + break; + + + case ACPI_TYPE_NUMBER: + /* + * Number is included in the object itself + */ + internal_obj->number.value = external_obj->number.value; + break; + + + default: + return (AE_CTRL_RETURN_VALUE); + break; + } + + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_build_internal_package_object + * + * PARAMETERS: *Internal_obj - Pointer to the object we are returning + * *Buffer - Where the object is returned + * *Space_used - Where the length of the object is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to place a package object in a user + * buffer. A package object by definition contains other objects. + * + * The buffer is assumed to have sufficient space for the object. + * The caller must have verified the buffer length needed using the + * Acpi_cm_get_object_size function before calling this function. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_build_internal_package_object ( + ACPI_OBJECT_INTERNAL *internal_obj, + u8 *buffer, + u32 *space_used) +{ + u8 *free_space; + ACPI_OBJECT *external_obj; + u32 current_depth = 0; + ACPI_STATUS status = AE_OK; + u32 length = 0; + u32 this_index; + u32 object_space = 0; + ACPI_OBJECT_INTERNAL *this_internal_obj; + ACPI_OBJECT *this_external_obj; + PKG_SEARCH_INFO *level_ptr; + + + /* + * First package at head of the buffer + */ + external_obj = (ACPI_OBJECT *)buffer; + + /* + * Free space begins right after the first package + */ + free_space = buffer + sizeof(ACPI_OBJECT); + + + /* + * Initialize the working variables + */ + + MEMSET ((void *) level, 0, sizeof(level)); + + level[0].internal_obj = internal_obj; + level[0].external_obj = external_obj; + level_ptr = &level[0]; + current_depth = 0; + + external_obj->type = internal_obj->common.type; + external_obj->package.count = internal_obj->package.count; + external_obj->package.elements = (ACPI_OBJECT *)free_space; + + + /* + * Build an array of ACPI_OBJECTS in the buffer + * and move the free space past it + */ + + free_space += external_obj->package.count * sizeof(ACPI_OBJECT); + + + while (1) { + this_index = level_ptr->index; + + this_internal_obj = (ACPI_OBJECT_INTERNAL *) + &level_ptr->internal_obj->package.elements[this_index]; + + this_external_obj = (ACPI_OBJECT *) + &level_ptr->external_obj->package.elements[this_index]; + + if (IS_THIS_OBJECT_TYPE (this_internal_obj, ACPI_TYPE_PACKAGE)) { + /* + * If this object is a package then we go one deeper + */ + if (current_depth >= MAX_PACKAGE_DEPTH-1) { + /* + * Too many nested levels of packages for us to handle + */ + return (AE_LIMIT); + } + + /* + * Build the package object + */ + this_external_obj->type = ACPI_TYPE_PACKAGE; + this_external_obj->package.count = this_internal_obj->package.count; + this_external_obj->package.elements = (ACPI_OBJECT *) free_space; + + /* + * Save space for the array of objects (Package elements) + * update the buffer length counter + */ + object_space = this_external_obj->package.count * + sizeof (ACPI_OBJECT); + + free_space += object_space; + length += object_space; + + current_depth++; + level_ptr = &level[current_depth]; + level_ptr->internal_obj = this_internal_obj; + level_ptr->external_obj = this_external_obj; + level_ptr->index = 0; + + } /* if object is a package */ + + else { +/* Status = Acpi_cm_build_simple_object(This_internal_obj, + This_external_obj, Free_space, + &Object_space); +*/ + if (status != AE_OK) { + /* + * Failure get out + */ + return (status); + } + + free_space += object_space; + length += object_space; + + level_ptr->index++; + while (level_ptr->index >= + level_ptr->internal_obj->package.count) + { + /* + * We've handled all of the objects at + * this level, This means that we have + * just completed a package. That package + * may have contained one or more packages + * itself + */ + if (current_depth == 0) { + /* + * We have handled all of the objects + * in the top level package just add + * the length of the package objects + * and get out + */ + *space_used = length; + return (AE_OK); + } + + /* + * go back up a level and move the index + * past the just completed package object. + */ + current_depth--; + level_ptr = &level[current_depth]; + level_ptr->index++; + } + } /* else object is NOT a package */ + } /* while (1) */ + + + /* + * We'll never get here, but the compiler whines about + * return value + */ + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_build_internal_object + * + * PARAMETERS: *Internal_obj - The external object to be converted + * *Buffer_ptr - Where the internal object is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: Converts an external object to an internal object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_build_internal_object ( + ACPI_OBJECT *external_obj, + ACPI_OBJECT_INTERNAL *internal_obj) +{ + ACPI_STATUS status; + + + if (external_obj->type == ACPI_TYPE_PACKAGE) { + /* + * Package objects contain other objects (which can be objects) + * buildpackage does it all + */ +/* + Status = Acpi_cm_build_internal_package_object(Internal_obj, + Ret_buffer->Pointer, + &Ret_buffer->Length); +*/ + return (AE_NOT_IMPLEMENTED); + } + + else { + /* + * Build a simple object (no nested objects) + */ + status = acpi_cm_build_internal_simple_object (external_obj, internal_obj); + /* + * build simple does not include the object size in the length + * so we add it in here + */ + } + + return (status); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/common/cmdebug.c linux/drivers/acpi/common/cmdebug.c --- v2.4.0-test2/linux/drivers/acpi/common/cmdebug.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/common/cmdebug.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,570 @@ + +/****************************************************************************** + * + * Module Name: cmdebug - Debug print routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" + +#define _COMPONENT MISCELLANEOUS + MODULE_NAME ("cmdebug"); + + +/***************************************************************************** + * + * FUNCTION: Get/Set debug level + * + * DESCRIPTION: Get or set value of the debug flag + * + * These are used to allow user's to get/set the debug level + * + ****************************************************************************/ + + +s32 +get_debug_level (void) +{ + + return acpi_dbg_level; +} + +void +set_debug_level ( + s32 new_debug_level) +{ + + acpi_dbg_level = new_debug_level; +} + + +/***************************************************************************** + * + * FUNCTION: Function_trace + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_trace ( + char *module_name, + s32 line_number, + s32 component_id, + char *function_name) +{ + + acpi_gbl_nesting_level++; + + debug_print (module_name, line_number, component_id, + TRACE_FUNCTIONS, + " %2.2ld Entered Function: %s\n", + acpi_gbl_nesting_level, function_name); +} + + +/***************************************************************************** + * + * FUNCTION: Function_trace_ptr + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Pointer - Pointer to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_trace_ptr ( + char *module_name, + s32 line_number, + s32 component_id, + char *function_name, + void *pointer) +{ + + acpi_gbl_nesting_level++; + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Entered Function: %s, 0x%p\n", + acpi_gbl_nesting_level, function_name, pointer); +} + + +/***************************************************************************** + * + * FUNCTION: Function_trace_str + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * String - Additional string to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_trace_str ( + char *module_name, + s32 line_number, + s32 component_id, + char *function_name, + char *string) +{ + + acpi_gbl_nesting_level++; + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Entered Function: %s, %s\n", + acpi_gbl_nesting_level, function_name, string); +} + + +/***************************************************************************** + * + * FUNCTION: Function_trace_u32 + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Integer - Integer to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_trace_u32 ( + char *module_name, + s32 line_number, + s32 component_id, + char *function_name, + u32 integer) +{ + + acpi_gbl_nesting_level++; + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Entered Function: %s, 0x%l_x\n", + acpi_gbl_nesting_level, function_name, integer); +} + + +/***************************************************************************** + * + * FUNCTION: Function_exit + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_exit ( + char *module_name, + s32 line_number, + s32 component_id, + char *function_name) +{ + + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Exiting Function: %s\n", + acpi_gbl_nesting_level, function_name); + + acpi_gbl_nesting_level--; +} + + +/***************************************************************************** + * + * FUNCTION: Function_status_exit + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Status - Exit status code + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level. Prints exit status also. + * + ****************************************************************************/ + +void +function_status_exit ( + char *module_name, + s32 line_number, + s32 component_id, + char *function_name, + ACPI_STATUS status) +{ + + if (status > ACPI_MAX_STATUS) { + debug_print (module_name, line_number, component_id, + TRACE_FUNCTIONS, + " %2.2ld Exiting Function: %s, [Unknown Status] 0x%X\n", + acpi_gbl_nesting_level, + function_name, + status); + } + + else { + debug_print (module_name, line_number, component_id, + TRACE_FUNCTIONS, + " %2.2ld Exiting Function: %s, %s\n", + acpi_gbl_nesting_level, + function_name, + acpi_cm_format_exception (status)); + } + + acpi_gbl_nesting_level--; +} + + +/***************************************************************************** + * + * FUNCTION: Function_value_exit + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Value - Value to be printed with exit msg + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level. Prints exit value also. + * + ****************************************************************************/ + +void +function_value_exit ( + char *module_name, + s32 line_number, + s32 component_id, + char *function_name, + NATIVE_UINT value) +{ + + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Exiting Function: %s, 0x%X\n", + acpi_gbl_nesting_level, function_name, value); + + acpi_gbl_nesting_level--; +} + + +/***************************************************************************** + * + * FUNCTION: Function_ptr_exit + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Value - Value to be printed with exit msg + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level. Prints exit value also. + * + ****************************************************************************/ + +void +function_ptr_exit ( + char *module_name, + s32 line_number, + s32 component_id, + char *function_name, + char *ptr) +{ + + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Exiting Function: %s, 0x%p\n", + acpi_gbl_nesting_level, function_name, ptr); + + acpi_gbl_nesting_level--; +} + + +/***************************************************************************** + * + * FUNCTION: Debug_print + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Print_level - Requested debug print level + * Format - Printf format field + * ... - Optional printf arguments + * + * RETURN: None + * + * DESCRIPTION: Print error message with prefix consisting of the module name, + * line number, and component ID. + * + ****************************************************************************/ + +void +debug_print ( + char *module_name, + s32 line_number, + s32 component_id, + s32 print_level, + char *format, + ...) +{ + va_list args; + + + /* Both the level and the component must be enabled */ + + if ((print_level & acpi_dbg_level) && + (component_id & acpi_dbg_layer)) + { + va_start (args, format); + + acpi_os_printf ("%8s-%04d: ", module_name, line_number); + acpi_os_vprintf (format, args); + } +} + + +/***************************************************************************** + * + * FUNCTION: Debug_print_prefix + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * + * RETURN: None + * + * DESCRIPTION: Print the prefix part of an error message, consisting of the + * module name, and line number + * + ****************************************************************************/ + +void +debug_print_prefix ( + char *module_name, + s32 line_number) +{ + + + acpi_os_printf ("%8s-%04d: ", module_name, line_number); +} + + +/***************************************************************************** + * + * FUNCTION: Debug_print_raw + * + * PARAMETERS: Format - Printf format field + * ... - Optional printf arguments + * + * RETURN: None + * + * DESCRIPTION: Print error message -- without module/line indentifiers + * + ****************************************************************************/ + +void +debug_print_raw ( + char *format, + ...) +{ + va_list args; + + + va_start (args, format); + + acpi_os_vprintf (format, args); + + va_end (args); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_dump_buffer + * + * PARAMETERS: Buffer - Buffer to dump + * Count - Amount to dump, in bytes + * Component_iD - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ****************************************************************************/ + +void +acpi_cm_dump_buffer ( + char *buffer, + u32 count, + u32 display, + s32 component_id) +{ + u32 i = 0; + u32 j; + u32 temp32; + u8 buf_char; + + + /* Only dump the buffer if tracing is enabled */ + + if (!((TRACE_TABLES & acpi_dbg_level) && + (component_id & acpi_dbg_layer))) + { + return; + } + + + /* + * Nasty little dump buffer routine! + */ + while (i < count) { + /* Print current offset */ + + acpi_os_printf ("%05_x ", i); + + + /* Print 16 hex chars */ + + for (j = 0; j < 16;) { + if (i + j >= count) { + acpi_os_printf ("\n"); + return; + } + + /* Make sure that the char doesn't get sign-extended! */ + + switch (display) + { + /* Default is BYTE display */ + + default: + + acpi_os_printf ("%02_x ", + *((u8 *) &buffer[i + j])); + j += 1; + break; + + + case DB_WORD_DISPLAY: + + MOVE_UNALIGNED16_TO_32 (&temp32, + &buffer[i + j]); + acpi_os_printf ("%04_x ", temp32); + j += 2; + break; + + + case DB_DWORD_DISPLAY: + + MOVE_UNALIGNED32_TO_32 (&temp32, + &buffer[i + j]); + acpi_os_printf ("%08_x ", temp32); + j += 4; + break; + + + case DB_QWORD_DISPLAY: + + MOVE_UNALIGNED32_TO_32 (&temp32, + &buffer[i + j]); + acpi_os_printf ("%08_x", temp32); + + MOVE_UNALIGNED32_TO_32 (&temp32, + &buffer[i + j + 4]); + acpi_os_printf ("%08_x ", temp32); + j += 8; + break; + } + } + + + /* + * Print the ASCII equivalent characters + * But watch out for the bad unprintable ones... + */ + + for (j = 0; j < 16; j++) { + if (i + j >= count) { + acpi_os_printf ("\n"); + return; + } + + buf_char = buffer[i + j]; + if ((buf_char > 0x1F && buf_char < 0x2E) || + (buf_char > 0x2F && buf_char < 0x61) || + (buf_char > 0x60 && buf_char < 0x7F)) + { + acpi_os_printf ("%c", buf_char); + } + else { + acpi_os_printf ("."); + } + } + + /* Done with that line. */ + + acpi_os_printf ("\n"); + i += 16; + } + + return; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/common/cmdelete.c linux/drivers/acpi/common/cmdelete.c --- v2.4.0-test2/linux/drivers/acpi/common/cmdelete.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/common/cmdelete.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,584 @@ + +/****************************************************************************** + * + * Module Name: cmdelete - object deletion and reference count utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" +#include "namesp.h" +#include "tables.h" +#include "parser.h" + +#define _COMPONENT MISCELLANEOUS + MODULE_NAME ("cmdelete"); + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_delete_internal_obj + * + * PARAMETERS: *Object - Pointer to the list to be deleted + * + * RETURN: None + * + * DESCRIPTION: Low level object deletion, after reference counts have been + * updated (All reference counts, including sub-objects!) + * + ******************************************************************************/ + +void +acpi_cm_delete_internal_obj ( + ACPI_OBJECT_INTERNAL *object) +{ + void *obj_pointer = NULL; + + + if (!object) { + return; + } + + /* + * Must delete or free any pointers within the object that are not + * actual ACPI objects (for example, a raw buffer pointer). + */ + + switch (object->common.type) + { + + case ACPI_TYPE_STRING: + + /* Free the actual string buffer */ + + obj_pointer = object->string.pointer; + break; + + + case ACPI_TYPE_BUFFER: + + /* Free the actual buffer */ + + obj_pointer = object->buffer.pointer; + break; + + + case ACPI_TYPE_PACKAGE: + + /* + * Elements of the package are not handled here, they are deleted + * separately + */ + + /* Free the (variable length) element pointer array */ + + obj_pointer = object->package.elements; + break; + + + case ACPI_TYPE_MUTEX: + + acpi_os_delete_semaphore (object->mutex.semaphore); + break; + + + case ACPI_TYPE_EVENT: + + acpi_os_delete_semaphore (object->event.semaphore); + object->event.semaphore = NULL; + break; + + + case ACPI_TYPE_METHOD: + + /* Delete parse tree if it exists */ + + if (object->method.parser_op) { + acpi_ps_delete_parse_tree (object->method.parser_op); + object->method.parser_op = NULL; + } + + /* Delete semaphore if it exists */ + + if (object->method.semaphore) { + acpi_os_delete_semaphore (object->method.semaphore); + object->method.semaphore = NULL; + } + + break; + + + default: + break; + } + + + /* + * Delete any allocated memory found above + */ + + if (obj_pointer) { + if (!acpi_tb_system_table_pointer (obj_pointer)) { + acpi_cm_free (obj_pointer); + } + } + + + /* Only delete the object if it was dynamically allocated */ + + + if (!(object->common.flags & AO_STATIC_ALLOCATION)) { + acpi_cm_delete_object_desc (object); + + } + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_delete_internal_object_list + * + * PARAMETERS: *Obj_list - Pointer to the list to be deleted + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function deletes an internal object list, including both + * simple objects and package objects + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_delete_internal_object_list ( + ACPI_OBJECT_INTERNAL **obj_list) +{ + ACPI_OBJECT_INTERNAL **internal_obj; + + + /* Walk the null-terminated internal list */ + + for (internal_obj = obj_list; *internal_obj; internal_obj++) { + /* + * Check for a package + * Simple objects are simply stored in the array and do not + * need to be deleted separately. + */ + + if (IS_THIS_OBJECT_TYPE ((*internal_obj), ACPI_TYPE_PACKAGE)) { + /* Delete the package */ + + /* + * TBD: [Investigate] This might not be the right thing to do, + * depending on how the internal package object was allocated!!! + */ + acpi_cm_delete_internal_obj (*internal_obj); + } + + } + + /* Free the combined parameter pointer list and object array */ + + acpi_cm_free (obj_list); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_update_ref_count + * + * PARAMETERS: *Object - Object whose ref count is to be updated + * Count - Current ref count + * Action - What to do + * + * RETURN: New ref count + * + * DESCRIPTION: Modify the ref count and return it. + * + ******************************************************************************/ + +void +acpi_cm_update_ref_count ( + ACPI_OBJECT_INTERNAL *object, + s32 action) +{ + u16 count; + u16 new_count; + + + if (!object) { + return; + } + + + count = object->common.reference_count; + new_count = count; + + /* + * Reference count action (increment, decrement, or force delete) + */ + + switch (action) + { + + case REF_INCREMENT: + + new_count++; + object->common.reference_count = new_count; + + break; + + + case REF_DECREMENT: + + if (count < 1) { + new_count = 0; + } + + else { + new_count--; + + } + + + object->common.reference_count = new_count; + if (new_count == 0) { + acpi_cm_delete_internal_obj (object); + } + + break; + + + case REF_FORCE_DELETE: + + new_count = 0; + object->common.reference_count = new_count; + acpi_cm_delete_internal_obj (object); + break; + + + default: + + break; + } + + + /* + * Sanity check the reference count, for debug purposes only. + * (A deleted object will have a huge reference count) + */ + + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_update_object_reference + * + * PARAMETERS: *Object - Increment ref count for this object + * and all sub-objects + * Action - Either REF_INCREMENT or REF_DECREMENT or + * REF_FORCE_DELETE + * + * RETURN: Status + * + * DESCRIPTION: Increment the object reference count + * + * Object references are incremented when: + * 1) An object is added as a value in an Name Table Entry (NTE) + * 2) An object is copied (all subobjects must be incremented) + * + * Object references are decremented when: + * 1) An object is removed from an NTE + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_update_object_reference ( + ACPI_OBJECT_INTERNAL *object, + u16 action) +{ + ACPI_STATUS status; + u32 i; + ACPI_OBJECT_INTERNAL *next; + ACPI_OBJECT_INTERNAL *new; + ACPI_GENERIC_STATE *state_list = NULL; + ACPI_GENERIC_STATE *state; + + + /* Ignore a null object ptr */ + + if (!object) { + return (AE_OK); + } + + + /* + * Make sure that this isn't a namespace handle or an AML pointer + */ + + if (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_NAMED)) { + return (AE_OK); + } + + if (acpi_tb_system_table_pointer (object)) { + return (AE_OK); + } + + + state = acpi_cm_create_update_state (object, action); + + while (state) { + + object = state->update.object; + action = state->update.value; + acpi_cm_delete_generic_state (state); + + /* + * All sub-objects must have their reference count incremented also. + * Different object types have different subobjects. + */ + switch (object->common.type) + { + + case ACPI_TYPE_DEVICE: + + status = acpi_cm_create_update_state_and_push (object->device.addr_handler, + action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + + acpi_cm_update_ref_count (object->device.sys_handler, action); + acpi_cm_update_ref_count (object->device.drv_handler, action); + break; + + + case INTERNAL_TYPE_ADDRESS_HANDLER: + + /* Must walk list of address handlers */ + + next = object->addr_handler.link; + while (next) { + new = next->addr_handler.link; + acpi_cm_update_ref_count (next, action); + + next = new; + } + break; + + + case ACPI_TYPE_PACKAGE: + + /* + * We must update all the sub-objects of the package + * (Each of whom may have their own sub-objects, etc. + */ + for (i = 0; i < object->package.count; i++) { + /* + * Push each element onto the stack for later processing. + * Note: There can be null elements within the package, + * these are simply ignored + */ + + status = + acpi_cm_create_update_state_and_push (object->package.elements[i], + action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + } + break; + + + case ACPI_TYPE_FIELD_UNIT: + + status = + acpi_cm_create_update_state_and_push (object->field_unit.container, + action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + break; + + + case INTERNAL_TYPE_DEF_FIELD: + + status = + acpi_cm_create_update_state_and_push (object->field.container, + action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + break; + + + case INTERNAL_TYPE_BANK_FIELD: + + status = + acpi_cm_create_update_state_and_push (object->bank_field.bank_select, + action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = + acpi_cm_create_update_state_and_push (object->bank_field.container, + action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + break; + + + case ACPI_TYPE_REGION: + + acpi_cm_update_ref_count (object->region.method, action); + + /* TBD: [Investigate] + Acpi_cm_update_ref_count (Object->Region.Addr_handler, Action); + */ +/* + Status = + Acpi_cm_create_update_state_and_push (Object->Region.Addr_handler, + Action, &State_list); + if (ACPI_FAILURE (Status)) { + return (Status); + } +*/ + break; + + + case INTERNAL_TYPE_REFERENCE: + + break; + } + + + /* + * Now we can update the count in the main object. This can only + * happen after we update the sub-objects in case this causes the + * main object to be deleted. + */ + + acpi_cm_update_ref_count (object, action); + + + /* Move on to the next object to be updated */ + + state = acpi_cm_pop_generic_state (&state_list); + } + + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_add_reference + * + * PARAMETERS: *Object - Object whose reference count is to be + * incremented + * + * RETURN: None + * + * DESCRIPTION: Add one reference to an ACPI object + * + ******************************************************************************/ + +void +acpi_cm_add_reference ( + ACPI_OBJECT_INTERNAL *object) +{ + + + /* + * Ensure that we have a valid object + */ + + if (!acpi_cm_valid_internal_object (object)) { + return; + } + + + /* + * We have a valid ACPI internal object, now increment the reference count + */ + + acpi_cm_update_object_reference (object, REF_INCREMENT); + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_remove_reference + * + * PARAMETERS: *Object - Object whose ref count will be decremented + * + * RETURN: None + * + * DESCRIPTION: Decrement the reference count of an ACPI internal object + * + ******************************************************************************/ + +void +acpi_cm_remove_reference ( + ACPI_OBJECT_INTERNAL *object) +{ + + + /* + * Ensure that we have a valid object + */ + + if (!acpi_cm_valid_internal_object (object)) { + return; + } + + /* + * Decrement the reference count, and only actually delete the object + * if the reference count becomes 0. (Must also decrement the ref count + * of all subobjects!) + */ + + acpi_cm_update_object_reference (object, REF_DECREMENT); + + /* + * If the reference count has reached zero, + * delete the object and all sub-objects contained within it + */ +/* + if (Object->Common.Reference_count == 0) { + Acpi_cm_delete_internal_obj (Object); + } +*/ + return; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/common/cmeval.c linux/drivers/acpi/common/cmeval.c --- v2.4.0-test2/linux/drivers/acpi/common/cmeval.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/common/cmeval.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,310 @@ + +/****************************************************************************** + * + * Module Name: cmeval - Object evaluation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "namesp.h" +#include "interp.h" + + +#define _COMPONENT MISCELLANEOUS + MODULE_NAME ("cmeval"); + + +/**************************************************************************** + * + * FUNCTION: Acpi_cm_evaluate_numeric_object + * + * PARAMETERS: Acpi_device - NTE for the device + * *Address - Where the value is returned + * + * RETURN: Status + * + * DESCRIPTION: evaluates a numeric namespace object for a selected device + * and stores results in *Address. + * + * NOTE: Internal function, no parameter validation + * + ***************************************************************************/ + +ACPI_STATUS +acpi_cm_evaluate_numeric_object ( + char *object_name, + ACPI_NAMED_OBJECT *acpi_device, + u32 *address) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_STATUS status; + + + /* Execute the method */ + + status = acpi_ns_evaluate_relative (acpi_device, object_name, NULL, &obj_desc); + if (ACPI_FAILURE (status)) { + + return (status); + } + + + /* Did we get a return object? */ + + if (!obj_desc) { + return (AE_TYPE); + } + + /* Is the return object of the correct type? */ + + if (obj_desc->common.type != ACPI_TYPE_NUMBER) { + status = AE_TYPE; + } + else { + /* + * Since the structure is a union, setting any field will set all + * of the variables in the union + */ + *address = obj_desc->number.value; + } + + /* On exit, we must delete the return object */ + + acpi_cm_remove_reference (obj_desc); + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_cm_execute_HID + * + * PARAMETERS: Acpi_device - NTE for the device + * *Hid - Where the HID is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _HID control method that returns the hardware + * ID of the device. + * + * NOTE: Internal function, no parameter validation + * + ***************************************************************************/ + +ACPI_STATUS +acpi_cm_execute_HID ( + ACPI_NAMED_OBJECT *acpi_device, + DEVICE_ID *hid) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_STATUS status; + + + /* Execute the method */ + + status = acpi_ns_evaluate_relative (acpi_device, + METHOD_NAME__HID, NULL, &obj_desc); + if (ACPI_FAILURE (status)) { + + + return (status); + } + + /* Did we get a return object? */ + + if (!obj_desc) { + return (AE_TYPE); + } + + /* + * A _HID can return either a Number (32 bit compressed EISA ID) or + * a string + */ + + if ((obj_desc->common.type != ACPI_TYPE_NUMBER) && + (obj_desc->common.type != ACPI_TYPE_STRING)) + { + status = AE_TYPE; + } + + else { + if (obj_desc->common.type == ACPI_TYPE_NUMBER) { + /* Convert the Numeric HID to string */ + + acpi_aml_eisa_id_to_string (obj_desc->number.value, hid->data.buffer); + hid->type = STRING_DEVICE_ID; + } + + else { + /* Copy the String HID from the returned object */ + + hid->data.string_ptr = obj_desc->string.pointer; + hid->type = STRING_PTR_DEVICE_ID; + } + } + + + /* On exit, we must delete the return object */ + + acpi_cm_remove_reference (obj_desc); + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_cm_execute_UID + * + * PARAMETERS: Acpi_device - NTE for the device + * *Uid - Where the UID is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _UID control method that returns the hardware + * ID of the device. + * + * NOTE: Internal function, no parameter validation + * + ***************************************************************************/ + +ACPI_STATUS +acpi_cm_execute_UID ( + ACPI_NAMED_OBJECT *acpi_device, + DEVICE_ID *uid) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_STATUS status; + + + /* Execute the method */ + + status = acpi_ns_evaluate_relative (acpi_device, + METHOD_NAME__UID, NULL, &obj_desc); + if (ACPI_FAILURE (status)) { + + + return (status); + } + + /* Did we get a return object? */ + + if (!obj_desc) { + return (AE_TYPE); + } + + /* + * A _UID can return either a Number (32 bit compressed EISA ID) or + * a string + */ + + if ((obj_desc->common.type != ACPI_TYPE_NUMBER) && + (obj_desc->common.type != ACPI_TYPE_STRING)) + { + status = AE_TYPE; + } + + else { + if (obj_desc->common.type == ACPI_TYPE_NUMBER) { + /* Convert the Numeric HID to string */ + + uid->data.number = obj_desc->number.value; + } + + else { + /* Copy the String HID from the returned object */ + + uid->data.string_ptr = obj_desc->string.pointer; + uid->type = STRING_PTR_DEVICE_ID; + } + } + + + /* On exit, we must delete the return object */ + + acpi_cm_remove_reference (obj_desc); + + return (status); +} + +/**************************************************************************** + * + * FUNCTION: Acpi_cm_execute_STA + * + * PARAMETERS: Acpi_device - NTE for the device + * *Flags - Where the status flags are returned + * + * RETURN: Status + * + * DESCRIPTION: Executes _STA for selected device and stores results in + * *Flags. + * + * NOTE: Internal function, no parameter validation + * + ***************************************************************************/ + +ACPI_STATUS +acpi_cm_execute_STA ( + ACPI_NAMED_OBJECT *acpi_device, + u32 *flags) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_STATUS status; + + + /* Execute the method */ + + status = acpi_ns_evaluate_relative (acpi_device, + METHOD_NAME__STA, NULL, &obj_desc); + if (ACPI_FAILURE (status)) { + + + return (status); + } + + + /* Did we get a return object? */ + + if (!obj_desc) { + return (AE_TYPE); + } + + /* Is the return object of the correct type? */ + + if (obj_desc->common.type != ACPI_TYPE_NUMBER) { + status = AE_TYPE; + } + + else { + /* Extract the status flags */ + + *flags = obj_desc->number.value; + } + + + /* On exit, we must delete the return object */ + + acpi_cm_remove_reference (obj_desc); + + return (status); +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/common/cmglobal.c linux/drivers/acpi/common/cmglobal.c --- v2.4.0-test2/linux/drivers/acpi/common/cmglobal.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/common/cmglobal.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,441 @@ + +/****************************************************************************** + * + * Module Name: cmglobal - Global variables for the ACPI subsystem + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define DEFINE_ACPI_GLOBALS + +#include "acpi.h" +#include "events.h" +#include "namesp.h" +#include "interp.h" + + +#define _COMPONENT MISCELLANEOUS + MODULE_NAME ("cmglobal"); + + +/****************************************************************************** + * + * Static global variable initialization. + * + ******************************************************************************/ + +/* + * We want the debug switches statically initialized so they + * are already set when the debugger is entered. + */ + +/* Debug switch - level and trace mask */ + +u32 acpi_dbg_level = NORMAL_DEFAULT; + +/* Debug switch - layer (component) mask */ + +u32 acpi_dbg_layer = ALL_COMPONENTS; +u32 acpi_gbl_nesting_level = 0; + + +/* Debugger globals */ + +u8 acpi_gbl_db_terminate_threads = FALSE; +u8 acpi_gbl_method_executing = FALSE; + +/* System flags */ + +u32 acpi_gbl_system_flags = 0; +u32 acpi_gbl_startup_flags = 0; + +/* System starts unitialized! */ +u8 acpi_gbl_shutdown = TRUE; + + +/****************************************************************************** + * + * Namespace globals + * + ******************************************************************************/ + + +/* + * Names built-in to the interpreter + * + * Initial values are currently supported only for types String and Number. + * To avoid type punning, both are specified as strings in this table. + */ + +PREDEFINED_NAMES acpi_gbl_pre_defined_names[] = +{ + {"_GPE", INTERNAL_TYPE_DEF_ANY}, + {"_PR_", INTERNAL_TYPE_DEF_ANY}, + {"_SB_", INTERNAL_TYPE_DEF_ANY}, + {"_SI_", INTERNAL_TYPE_DEF_ANY}, + {"_TZ_", INTERNAL_TYPE_DEF_ANY}, + {"_REV", ACPI_TYPE_NUMBER, "2"}, + {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, + {"_GL_", ACPI_TYPE_MUTEX, "0"}, + + /* Table terminator */ + + {NULL, ACPI_TYPE_ANY} +}; + + +/* + * Properties of the ACPI Object Types, both internal and external. + * + * Elements of Acpi_ns_properties are bit significant + * and the table is indexed by values of ACPI_OBJECT_TYPE + */ + +u8 acpi_gbl_ns_properties[] = +{ + NSP_NORMAL, /* 00 Any */ + NSP_NORMAL, /* 01 Number */ + NSP_NORMAL, /* 02 String */ + NSP_NORMAL, /* 03 Buffer */ + NSP_LOCAL, /* 04 Package */ + NSP_NORMAL, /* 05 Field_unit */ + NSP_NEWSCOPE | NSP_LOCAL, /* 06 Device */ + NSP_LOCAL, /* 07 Acpi_event */ + NSP_NEWSCOPE | NSP_LOCAL, /* 08 Method */ + NSP_LOCAL, /* 09 Mutex */ + NSP_LOCAL, /* 10 Region */ + NSP_NEWSCOPE | NSP_LOCAL, /* 11 Power */ + NSP_NEWSCOPE | NSP_LOCAL, /* 12 Processor */ + NSP_NEWSCOPE | NSP_LOCAL, /* 13 Thermal */ + NSP_NORMAL, /* 14 Buffer_field */ + NSP_NORMAL, /* 15 Ddb_handle */ + NSP_NORMAL, /* 16 reserved */ + NSP_NORMAL, /* 17 reserved */ + NSP_NORMAL, /* 18 reserved */ + NSP_NORMAL, /* 19 reserved */ + NSP_NORMAL, /* 20 reserved */ + NSP_NORMAL, /* 21 reserved */ + NSP_NORMAL, /* 22 reserved */ + NSP_NORMAL, /* 23 reserved */ + NSP_NORMAL, /* 24 reserved */ + NSP_NORMAL, /* 25 Def_field */ + NSP_NORMAL, /* 26 Bank_field */ + NSP_NORMAL, /* 27 Index_field */ + NSP_NORMAL, /* 28 Def_field_defn */ + NSP_NORMAL, /* 29 Bank_field_defn */ + NSP_NORMAL, /* 30 Index_field_defn */ + NSP_NORMAL, /* 31 If */ + NSP_NORMAL, /* 32 Else */ + NSP_NORMAL, /* 33 While */ + NSP_NEWSCOPE, /* 34 Scope */ + NSP_LOCAL, /* 35 Def_any */ + NSP_NORMAL, /* 36 Reference */ + NSP_NORMAL, /* 37 Alias */ + NSP_NORMAL, /* 38 Notify */ + NSP_NORMAL, /* 39 Address Handler */ + NSP_NORMAL /* 40 Invalid */ +}; + + +/****************************************************************************** + * + * Table globals + * + ******************************************************************************/ + + +ACPI_TABLE_DESC acpi_gbl_acpi_tables[NUM_ACPI_TABLES]; + + +ACPI_TABLE_SUPPORT acpi_gbl_acpi_table_data[NUM_ACPI_TABLES] = +{ + /* Name, Signature, Signature size, How many allowed?, Supported? Global typed pointer */ + + /* RSDP 0 */ {"RSDP", RSDP_SIG, sizeof (RSDP_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, NULL}, + /* APIC 1 */ {APIC_SIG, APIC_SIG, sizeof (APIC_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_APIC}, + /* DSDT 2 */ {DSDT_SIG, DSDT_SIG, sizeof (DSDT_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_DSDT}, + /* FACP 3 */ {FACP_SIG, FACP_SIG, sizeof (FACP_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_FACP}, + /* FACS 4 */ {FACS_SIG, FACS_SIG, sizeof (FACS_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_FACS}, + /* PSDT 5 */ {PSDT_SIG, PSDT_SIG, sizeof (PSDT_SIG)-1, ACPI_TABLE_MULTIPLE, AE_OK, NULL}, + /* RSDT 6 */ {RSDT_SIG, RSDT_SIG, sizeof (RSDT_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, NULL}, + /* SSDT 7 */ {SSDT_SIG, SSDT_SIG, sizeof (SSDT_SIG)-1, ACPI_TABLE_MULTIPLE, AE_OK, NULL}, + /* SBST 8 */ {SBST_SIG, SBST_SIG, sizeof (SBST_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_SBST}, + /* BOOT 9 */ {BOOT_SIG, BOOT_SIG, sizeof (BOOT_SIG)-1, ACPI_TABLE_SINGLE, AE_SUPPORT, NULL} +}; + +ACPI_INIT_DATA acpi_gbl_acpi_init_data; + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_valid_object_type + * + * PARAMETERS: None. + * + * RETURN: TRUE if valid object type + * + * DESCRIPTION: Validate an object type + * + ****************************************************************************/ + +u8 +acpi_cm_valid_object_type ( + u32 type) +{ + + if (type > ACPI_TYPE_MAX) { + if ((type < INTERNAL_TYPE_BEGIN) || + (type > INTERNAL_TYPE_MAX)) + { + return FALSE; + } + } + + return TRUE; +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_format_exception + * + * PARAMETERS: Status - Acpi status to be formatted + * + * RETURN: Formatted status string + * + * DESCRIPTION: Convert an ACPI exception to a string + * + ****************************************************************************/ + +char * +acpi_cm_format_exception ( + ACPI_STATUS status) +{ + + if (status > ACPI_MAX_STATUS) { + return "UNKNOWN_STATUS"; + } + + return (acpi_gbl_exception_names [status]); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_cm_allocate_owner_id + * + * PARAMETERS: Id_type - Type of ID (method or table) + * + * DESCRIPTION: Allocate a table or method owner id + * + ***************************************************************************/ + +ACPI_OWNER_ID +acpi_cm_allocate_owner_id ( + u32 id_type) +{ + ACPI_OWNER_ID owner_id = 0xFFFF; + + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + + switch (id_type) + { + case OWNER_TYPE_TABLE: + + owner_id = acpi_gbl_next_table_owner_id; + acpi_gbl_next_table_owner_id++; + + if (acpi_gbl_next_table_owner_id == FIRST_METHOD_ID) { + acpi_gbl_next_table_owner_id = FIRST_TABLE_ID; + } + break; + + + case OWNER_TYPE_METHOD: + + owner_id = acpi_gbl_next_method_owner_id; + acpi_gbl_next_method_owner_id++; + + if (acpi_gbl_next_method_owner_id == FIRST_TABLE_ID) { + acpi_gbl_next_method_owner_id = FIRST_METHOD_ID; + } + break; + } + + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + + return (owner_id); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_cm_init_globals + * + * PARAMETERS: none + * + * DESCRIPTION: Init library globals. All globals that require specific + * initialization should be initialized here! + * + ***************************************************************************/ + +void +acpi_cm_init_globals (ACPI_INIT_DATA *init_data) +{ + u32 i; + + + if (init_data) { + MEMCPY (&acpi_gbl_acpi_init_data, init_data, sizeof (ACPI_INIT_DATA)); + } + + else { + MEMSET (&acpi_gbl_acpi_init_data, 0, sizeof (ACPI_INIT_DATA)); + } + + /* ACPI table structure */ + + for (i = 0; i < ACPI_TABLE_MAX; i++) { + acpi_gbl_acpi_tables[i].prev = &acpi_gbl_acpi_tables[i]; + acpi_gbl_acpi_tables[i].next = &acpi_gbl_acpi_tables[i]; + acpi_gbl_acpi_tables[i].pointer = NULL; + acpi_gbl_acpi_tables[i].length = 0; + acpi_gbl_acpi_tables[i].allocation = ACPI_MEM_NOT_ALLOCATED; + acpi_gbl_acpi_tables[i].count = 0; + } + + + /* Address Space handler array */ + + for (i = 0; i < ACPI_MAX_ADDRESS_SPACE; i++) { + acpi_gbl_address_spaces[i].handler = NULL; + acpi_gbl_address_spaces[i].context = NULL; + } + + /* Mutex locked flags */ + + for (i = 0; i < NUM_MTX; i++) { + acpi_gbl_acpi_mutex_info[i].mutex = NULL; + acpi_gbl_acpi_mutex_info[i].locked = FALSE; + acpi_gbl_acpi_mutex_info[i].use_count = 0; + } + + /* Global notify handlers */ + + acpi_gbl_sys_notify.handler = NULL; + acpi_gbl_drv_notify.handler = NULL; + + /* Global "typed" ACPI table pointers */ + + acpi_gbl_RSDP = NULL; + acpi_gbl_RSDT = NULL; + acpi_gbl_FACS = NULL; + acpi_gbl_FACP = NULL; + acpi_gbl_APIC = NULL; + acpi_gbl_DSDT = NULL; + acpi_gbl_SBST = NULL; + + + /* Global Lock support */ + + acpi_gbl_global_lock_acquired = FALSE; + acpi_gbl_global_lock_thread_count = 0; + + /* Miscellaneous variables */ + + acpi_gbl_system_flags = 0; + acpi_gbl_startup_flags = 0; + acpi_gbl_global_lock_set = FALSE; + acpi_gbl_rsdp_original_location = 0; + acpi_gbl_when_to_parse_methods = METHOD_PARSE_CONFIGURATION; + acpi_gbl_cm_single_step = FALSE; + acpi_gbl_db_terminate_threads = FALSE; + acpi_gbl_shutdown = FALSE; + acpi_gbl_ns_lookup_count = 0; + acpi_gbl_ps_find_count = 0; + acpi_gbl_acpi_hardware_present = TRUE; + acpi_gbl_next_table_owner_id = FIRST_TABLE_ID; + acpi_gbl_next_method_owner_id = FIRST_METHOD_ID; + acpi_gbl_debugger_configuration = DEBUGGER_THREADING; + + /* Cache of small "state" objects */ + + acpi_gbl_generic_state_cache = NULL; + acpi_gbl_generic_state_cache_depth = 0; + acpi_gbl_state_cache_requests = 0; + acpi_gbl_state_cache_hits = 0; + + acpi_gbl_parse_cache = NULL; + acpi_gbl_parse_cache_depth = 0; + acpi_gbl_parse_cache_requests = 0; + acpi_gbl_parse_cache_hits = 0; + + acpi_gbl_object_cache = NULL; + acpi_gbl_object_cache_depth = 0; + acpi_gbl_object_cache_requests = 0; + acpi_gbl_object_cache_hits = 0; + + acpi_gbl_walk_state_cache = NULL; + acpi_gbl_walk_state_cache_depth = 0; + acpi_gbl_walk_state_cache_requests = 0; + acpi_gbl_walk_state_cache_hits = 0; + + /* Interpreter */ + + acpi_gbl_buf_seq = 0; + acpi_gbl_named_object_err = FALSE; + + /* Parser */ + + acpi_gbl_parsed_namespace_root = NULL; + + /* Hardware oriented */ + + acpi_gbl_gpe0enable_register_save = NULL; + acpi_gbl_gpe1_enable_register_save = NULL; + acpi_gbl_original_mode = SYS_MODE_UNKNOWN; /* original ACPI/legacy mode */ + acpi_gbl_gpe_registers = NULL; + acpi_gbl_gpe_info = NULL; + + /* Namespace */ + + acpi_gbl_root_name_table.next_table = NULL; + acpi_gbl_root_name_table.parent_entry = NULL; + acpi_gbl_root_name_table.parent_table = NULL; + + acpi_gbl_root_object = acpi_gbl_root_name_table.entries; + + acpi_gbl_root_object->name = ACPI_ROOT_NAME; + acpi_gbl_root_object->data_type = ACPI_DESC_TYPE_NAMED; + acpi_gbl_root_object->type = ACPI_TYPE_ANY; + acpi_gbl_root_object->this_index = 0; + acpi_gbl_root_object->child_table = NULL; + acpi_gbl_root_object->object = NULL; + + /* Memory allocation metrics - compiled out in non-debug mode. */ + + INITIALIZE_ALLOCATION_METRICS(); + + return; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/common/cminit.c linux/drivers/acpi/common/cminit.c --- v2.4.0-test2/linux/drivers/acpi/common/cminit.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/common/cminit.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,362 @@ + +/****************************************************************************** + * + * Module Name: cminit - Common ACPI subsystem initialization + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "hardware.h" +#include "namesp.h" +#include "events.h" +#include "parser.h" +#include "dispatch.h" + +#define _COMPONENT MISCELLANEOUS + MODULE_NAME ("cminit"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_facp_register_error + * + * PARAMETERS: *Register_name - Pointer to string identifying register + * Value - Actual register contents value + * Acpi_test_spec_section - TDS section containing assertion + * Acpi_assertion - Assertion number being tested + * + * RETURN: none + * + * DESCRIPTION: Display failure message and link failure to TDS assertion + * + ******************************************************************************/ + +void +acpi_cm_facp_register_error ( + char *register_name, + u32 value) +{ + + REPORT_ERROR ("Invalid FACP register value"); + +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_hardware_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize and validate various ACPI registers + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_hardware_initialize (void) +{ + ACPI_STATUS status = AE_OK; + s32 index; + + + /* Are we running on the actual hardware */ + + if (!acpi_gbl_acpi_hardware_present) { + /* No, just return */ + + return (AE_OK); + } + + /* We must have the ACPI tables by the time we get here */ + + if (!acpi_gbl_FACP) { + acpi_gbl_restore_acpi_chipset = FALSE; + + return (AE_NO_ACPI_TABLES); + } + + /* Must support *some* mode! */ +/* + if (!(System_flags & SYS_MODES_MASK)) { + Restore_acpi_chipset = FALSE; + + return (AE_ERROR); + } + +*/ + + + switch (acpi_gbl_system_flags & SYS_MODES_MASK) + { + /* Identify current ACPI/legacy mode */ + + case (SYS_MODE_ACPI): + + acpi_gbl_original_mode = SYS_MODE_ACPI; + break; + + + case (SYS_MODE_LEGACY): + + acpi_gbl_original_mode = SYS_MODE_LEGACY; + break; + + + case (SYS_MODE_ACPI | SYS_MODE_LEGACY): + + if (acpi_hw_get_mode () == SYS_MODE_ACPI) { + acpi_gbl_original_mode = SYS_MODE_ACPI; + } + else { + acpi_gbl_original_mode = SYS_MODE_LEGACY; + } + + break; + } + + + if (acpi_gbl_system_flags & SYS_MODE_ACPI) { + /* Target system supports ACPI mode */ + + /* + * The purpose of this block of code is to save the initial state + * of the ACPI event enable registers. An exit function will be + * registered which will restore this state when the application + * exits. The exit function will also clear all of the ACPI event + * status bits prior to restoring the original mode. + * + * The location of the PM1a_evt_blk enable registers is defined as the + * base of PM1a_evt_blk + PM1a_evt_blk_length / 2. Since the spec further + * fully defines the PM1a_evt_blk to be a total of 4 bytes, the offset + * for the enable registers is always 2 from the base. It is hard + * coded here. If this changes in the spec, this code will need to + * be modified. The PM1b_evt_blk behaves as expected. + */ + + acpi_gbl_pm1_enable_register_save = + acpi_os_in16 ((acpi_gbl_FACP->pm1a_evt_blk + 2)); + if (acpi_gbl_FACP->pm1b_evt_blk) { + acpi_gbl_pm1_enable_register_save |= + acpi_os_in16 ((acpi_gbl_FACP->pm1b_evt_blk + 2)); + } + + + /* + * The GPEs behave similarly, except that the length of the register + * block is not fixed, so the buffer must be allocated with malloc + */ + + if (acpi_gbl_FACP->gpe0blk && acpi_gbl_FACP->gpe0blk_len) { + /* GPE0 specified in FACP */ + + acpi_gbl_gpe0enable_register_save = + acpi_cm_allocate (DIV_2 (acpi_gbl_FACP->gpe0blk_len)); + if (!acpi_gbl_gpe0enable_register_save) { + return (AE_NO_MEMORY); + } + + /* Save state of GPE0 enable bits */ + + for (index = 0; index < DIV_2 (acpi_gbl_FACP->gpe0blk_len); index++) { + acpi_gbl_gpe0enable_register_save[index] = + acpi_os_in8 (acpi_gbl_FACP->gpe0blk + + DIV_2 (acpi_gbl_FACP->gpe0blk_len)); + } + } + + else { + acpi_gbl_gpe0enable_register_save = NULL; + } + + if (acpi_gbl_FACP->gpe1_blk && acpi_gbl_FACP->gpe1_blk_len) { + /* GPE1 defined */ + + acpi_gbl_gpe1_enable_register_save = + acpi_cm_allocate (DIV_2 (acpi_gbl_FACP->gpe1_blk_len)); + if (!acpi_gbl_gpe1_enable_register_save) { + return (AE_NO_MEMORY); + } + + /* save state of GPE1 enable bits */ + + for (index = 0; index < DIV_2 (acpi_gbl_FACP->gpe1_blk_len); index++) { + acpi_gbl_gpe1_enable_register_save[index] = + acpi_os_in8 (acpi_gbl_FACP->gpe1_blk + + DIV_2 (acpi_gbl_FACP->gpe1_blk_len)); + } + } + + else { + acpi_gbl_gpe1_enable_register_save = NULL; + } + + + /* + * Verify Fixed ACPI Description Table fields, + * but don't abort on any problems, just display error + */ + + if (acpi_gbl_FACP->pm1_evt_len < 4) { + acpi_cm_facp_register_error ("PM1_EVT_LEN", + (u32) acpi_gbl_FACP->pm1_evt_len); + } + + if (!acpi_gbl_FACP->pm1_cnt_len) { + acpi_cm_facp_register_error ("PM1_CNT_LEN", + (u32) acpi_gbl_FACP->pm1_cnt_len); + } + + if (!acpi_gbl_FACP->pm1a_evt_blk) { + acpi_cm_facp_register_error ("PM1a_EVT_BLK", acpi_gbl_FACP->pm1a_evt_blk); + } + + if (!acpi_gbl_FACP->pm1a_cnt_blk) { + acpi_cm_facp_register_error ("PM1a_CNT_BLK", acpi_gbl_FACP->pm1a_cnt_blk); + } + + if (!acpi_gbl_FACP->pm_tmr_blk) { + acpi_cm_facp_register_error ("PM_TMR_BLK", acpi_gbl_FACP->pm_tmr_blk); + } + + if (acpi_gbl_FACP->pm2_cnt_blk && !acpi_gbl_FACP->pm2_cnt_len) { + acpi_cm_facp_register_error ("PM2_CNT_LEN", + (u32) acpi_gbl_FACP->pm2_cnt_len); + } + + if (acpi_gbl_FACP->pm_tm_len < 4) { + acpi_cm_facp_register_error ("PM_TM_LEN", + (u32) acpi_gbl_FACP->pm_tm_len); + } + + /* length not multiple of 2 */ + if (acpi_gbl_FACP->gpe0blk && (acpi_gbl_FACP->gpe0blk_len & 1)) { + acpi_cm_facp_register_error ("GPE0_BLK_LEN", + (u32) acpi_gbl_FACP->gpe0blk_len); + } + + /* length not multiple of 2 */ + if (acpi_gbl_FACP->gpe1_blk && (acpi_gbl_FACP->gpe1_blk_len & 1)) { + acpi_cm_facp_register_error ("GPE1_BLK_LEN", + (u32) acpi_gbl_FACP->gpe1_blk_len); + } + } + + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_terminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: free memory allocated for table storage. + * + ******************************************************************************/ + +void +acpi_cm_terminate (void) +{ + + + /* Free global tables, etc. */ + + if (acpi_gbl_gpe0enable_register_save) { + acpi_cm_free (acpi_gbl_gpe0enable_register_save); + } + + if (acpi_gbl_gpe1_enable_register_save) { + acpi_cm_free (acpi_gbl_gpe1_enable_register_save); + } + + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_subsystem_shutdown + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Shutdown the various subsystems. Don't delete the mutex + * objects here -- because the AML debugger may be still running. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_subsystem_shutdown (void) +{ + + /* Just exit if subsystem is already shutdown */ + + if (acpi_gbl_shutdown) { + return (AE_OK); + } + + /* Subsystem appears active, go ahead and shut it down */ + + acpi_gbl_shutdown = TRUE; + + /* Close the Namespace */ + + acpi_ns_terminate (); + + /* Close the Acpi_event Handling */ + + acpi_ev_terminate (); + + /* Close the globals */ + + acpi_cm_terminate (); + + /* Flush the local cache(s) */ + + acpi_cm_delete_generic_state_cache (); + acpi_cm_delete_object_cache (); + acpi_ds_delete_walk_state_cache (); + + /* Close the Parser */ + + /* TBD: [Restructure] Acpi_ps_terminate () */ + + acpi_ps_delete_parse_cache (); + + /* Debug only - display leftover memory allocation, if any */ + + acpi_cm_dump_current_allocations (ACPI_UINT32_MAX, NULL); + + BREAKPOINT3; + + return (AE_OK); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/common/cmobject.c linux/drivers/acpi/common/cmobject.c --- v2.4.0-test2/linux/drivers/acpi/common/cmobject.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/common/cmobject.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,648 @@ + +/****************************************************************************** + * + * Module Name: cmobject - ACPI object create/delete/size/cache routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" +#include "namesp.h" +#include "tables.h" +#include "amlcode.h" + + +#define _COMPONENT MISCELLANEOUS + MODULE_NAME ("cmobject"); + + +/****************************************************************************** + * + * FUNCTION: _Cm_create_internal_object + * + * PARAMETERS: Address - Address of the memory to deallocate + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * Type - ACPI Type of the new object + * + * RETURN: Object - The new object. Null on failure + * + * DESCRIPTION: Create and initialize a new internal object. + * + * NOTE: + * We always allocate the worst-case object descriptor because these + * objects are cached, and we want them to be one-size-satisifies-any-request. + * This in itself may not be the most memory efficient, but the efficiency + * of the object cache should more than make up for this! + * + ******************************************************************************/ + +ACPI_OBJECT_INTERNAL * +_cm_create_internal_object ( + char *module_name, + s32 line_number, + s32 component_id, + OBJECT_TYPE_INTERNAL type) +{ + ACPI_OBJECT_INTERNAL *object; + + + /* Allocate the raw object descriptor */ + + object = _cm_allocate_object_desc (module_name, line_number, component_id); + if (!object) { + /* Allocation failure */ + + return (NULL); + } + + /* Save the object type in the object descriptor */ + + object->common.type = type; + object->common.size = (u8) sizeof (ACPI_OBJECT_INTERNAL); + + /* Init the reference count */ + + object->common.reference_count = 1; + + /* Any per-type initialization should go here */ + + + /* Memory allocation metrics - compiled out in non debug mode. */ + + INCREMENT_OBJECT_METRICS (sizeof (ACPI_OBJECT_INTERNAL)); + + return (object); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_valid_internal_object + * + * PARAMETERS: Operand - Object to be validated + * + * RETURN: Validate a pointer to be an ACPI_OBJECT_INTERNAL + * + *****************************************************************************/ + +u8 +acpi_cm_valid_internal_object ( + void *object) +{ + + /* Check for a null pointer */ + + if (!object) { + return FALSE; + } + + /* Check for a pointer within one of the ACPI tables */ + + if (acpi_tb_system_table_pointer (object)) { + return FALSE; + } + + /* Check the descriptor type field */ + + if (!VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL)) { + /* Not an ACPI internal object, do some further checking */ + + + + + return FALSE; + } + + + /* The object appears to be a valid ACPI_OBJECT_INTERNAL */ + + return TRUE; +} + + +/***************************************************************************** + * + * FUNCTION: _Cm_allocate_object_desc + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Message - Error message to use on failure + * + * RETURN: Pointer to newly allocated object descriptor. Null on error + * + * DESCRIPTION: Allocate a new object descriptor. Gracefully handle + * error conditions. + * + ****************************************************************************/ + +void * +_cm_allocate_object_desc ( + char *module_name, + s32 line_number, + s32 component_id) +{ + ACPI_OBJECT_INTERNAL *object; + + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + + acpi_gbl_object_cache_requests++; + + /* Check the cache first */ + + if (acpi_gbl_object_cache) { + /* There is an object available, use it */ + + object = acpi_gbl_object_cache; + acpi_gbl_object_cache = object->common.next; + object->common.next = NULL; + + acpi_gbl_object_cache_hits++; + acpi_gbl_object_cache_depth--; + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + } + + else { + /* The cache is empty, create a new object */ + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + + /* Attempt to allocate new descriptor */ + + object = _cm_callocate (sizeof (ACPI_OBJECT_INTERNAL), component_id, + module_name, line_number); + + if (!object) { + /* Allocation failed */ + + _REPORT_ERROR (module_name, line_number, component_id, + "Could not allocate Object Descriptor"); + + return (NULL); + } + } + + /* Mark the descriptor type */ + + object->common.data_type = ACPI_DESC_TYPE_INTERNAL; + + return (object); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_delete_object_desc + * + * PARAMETERS: Object - Acpi internal object to be deleted + * + * RETURN: None. + * + * DESCRIPTION: Free an ACPI object descriptor or add it to the object cache + * + ****************************************************************************/ + +void +acpi_cm_delete_object_desc ( + ACPI_OBJECT_INTERNAL *object) +{ + + + /* Object must be an ACPI_OBJECT_INTERNAL */ + + if (object->common.data_type != ACPI_DESC_TYPE_INTERNAL) { + return; + } + + /* Make sure that the object isn't already in the cache */ + + if (object->common.next) { + return; + } + + + /* If cache is full, just free this object */ + + if (acpi_gbl_object_cache_depth >= MAX_OBJECT_CACHE_DEPTH) { + /* + * Memory allocation metrics. Call the macro here since we only + * care about dynamically allocated objects. + */ + DECREMENT_OBJECT_METRICS (acpi_gbl_object_cache->common.size); + + acpi_cm_free (object); + return; + } + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + + /* Clear the entire object. This is important! */ + + MEMSET (object, 0, sizeof (ACPI_OBJECT_INTERNAL)); + object->common.data_type = ACPI_DESC_TYPE_INTERNAL; + + /* Put the object at the head of the global cache list */ + + object->common.next = acpi_gbl_object_cache; + acpi_gbl_object_cache = object; + acpi_gbl_object_cache_depth++; + + + acpi_cm_release_mutex (ACPI_MTX_CACHES); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_delete_object_cache + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Purge the global state object cache. Used during subsystem + * termination. + * + ******************************************************************************/ + +void +acpi_cm_delete_object_cache ( + void) +{ + ACPI_OBJECT_INTERNAL *next; + + + /* Traverse the global cache list */ + + while (acpi_gbl_object_cache) { + /* Delete one cached state object */ + + next = acpi_gbl_object_cache->common.next; + acpi_gbl_object_cache->common.next = NULL; + + /* + * Memory allocation metrics. Call the macro here since we only + * care about dynamically allocated objects. + */ + DECREMENT_OBJECT_METRICS (acpi_gbl_object_cache->common.size); + + acpi_cm_free (acpi_gbl_object_cache); + acpi_gbl_object_cache = next; + } + + return; +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_init_static_object + * + * PARAMETERS: Obj_desc - Pointer to a "static" object - on stack + * or in the data segment. + * + * RETURN: None. + * + * DESCRIPTION: Initialize a static object. Sets flags to disallow dynamic + * deletion of the object. + * + ****************************************************************************/ + +void +acpi_cm_init_static_object ( + ACPI_OBJECT_INTERNAL *obj_desc) +{ + + + if (!obj_desc) { + return; + } + + + /* + * Clear the entire descriptor + */ + MEMSET ((void *) obj_desc, 0, sizeof (ACPI_OBJECT_INTERNAL)); + + + /* + * Initialize the header fields + * 1) This is an ACPI_OBJECT_INTERNAL descriptor + * 2) The size is the full object (worst case) + * 3) The flags field indicates static allocation + * 4) Reference count starts at one (not really necessary since the + * object can't be deleted, but keeps everything sane) + */ + + obj_desc->common.data_type = ACPI_DESC_TYPE_INTERNAL; + obj_desc->common.size = sizeof (ACPI_OBJECT_INTERNAL); + obj_desc->common.flags = AO_STATIC_ALLOCATION; + obj_desc->common.reference_count = 1; + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_get_simple_object_size + * + * PARAMETERS: *Internal_obj - Pointer to the object we are examining + * *Ret_length - Where the length is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to determine the space required to + * contain a simple object for return to an API user. + * + * The length includes the object structure plus any additional + * needed space. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_get_simple_object_size ( + ACPI_OBJECT_INTERNAL *internal_obj, + u32 *obj_length) +{ + u32 length; + ACPI_STATUS status = AE_OK; + + + /* Handle a null object (Could be a uninitialized package element -- which is legal) */ + + if (!internal_obj) { + *obj_length = 0; + return (AE_OK); + } + + + /* Start with the length of the Acpi object */ + + length = sizeof (ACPI_OBJECT); + + if (VALID_DESCRIPTOR_TYPE (internal_obj, ACPI_DESC_TYPE_NAMED)) { + /* Object is an NTE (reference), just return the length */ + + *obj_length = (u32) ROUND_UP_TO_NATIVE_WORD (length); + return (status); + } + + + /* + * The final length depends on the object type + * Strings and Buffers are packed right up against the parent object and + * must be accessed bytewise or there may be alignment problems. + * + * TBD:[Investigate] do strings and buffers require alignment also? + */ + + switch (internal_obj->common.type) + { + + case ACPI_TYPE_STRING: + + length += internal_obj->string.length; + break; + + + case ACPI_TYPE_BUFFER: + + length += internal_obj->buffer.length; + break; + + + case ACPI_TYPE_NUMBER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_POWER: + + /* + * No extra data for these types + */ + break; + + + case INTERNAL_TYPE_REFERENCE: + + /* + * The only type that should be here is opcode AML_NAMEPATH_OP -- since + * this means an object reference + */ + if (internal_obj->reference.op_code != AML_NAMEPATH_OP) { + status = AE_TYPE; + } + break; + + + default: + + status = AE_TYPE; + break; + } + + + /* + * Account for the space required by the object rounded up to the next + * multiple of the machine word size. This keeps each object aligned + * on a machine word boundary. (preventing alignment faults on some + * machines.) + */ + *obj_length = (u32) ROUND_UP_TO_NATIVE_WORD (length); + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_get_package_object_size + * + * PARAMETERS: *Internal_obj - Pointer to the object we are examining + * *Ret_length - Where the length is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to determine the space required to contain + * a package object for return to an API user. + * + * This is moderately complex since a package contains other objects + * including packages. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_get_package_object_size ( + ACPI_OBJECT_INTERNAL *internal_obj, + u32 *obj_length) +{ + + ACPI_OBJECT_INTERNAL *this_internal_obj; + ACPI_OBJECT_INTERNAL *parent_obj[MAX_PACKAGE_DEPTH] = { 0,0,0,0,0 }; + ACPI_OBJECT_INTERNAL *this_parent; + u32 this_index; + u32 index[MAX_PACKAGE_DEPTH] = { 0,0,0,0,0 }; + u32 length = 0; + u32 object_space; + u32 current_depth = 0; + u32 package_count = 1; + ACPI_STATUS status; + + + parent_obj[0] = internal_obj; + + while (1) { + this_parent = parent_obj[current_depth]; + this_index = index[current_depth]; + this_internal_obj = this_parent->package.elements[this_index]; + + + /* + * Check for 1) An unitialized package element. It is completely + * legal to declare a package and leave it uninitialized + * 2) Any type other than a package. Packages are handled + * below. + */ + + if ((!this_internal_obj) || + (!IS_THIS_OBJECT_TYPE (this_internal_obj, ACPI_TYPE_PACKAGE))) + { + /* + * Simple object - just get the size (Null object/entry handled + * also) + */ + + status = + acpi_cm_get_simple_object_size (this_internal_obj, &object_space); + + if (status != AE_OK) { + return (status); + } + + length += object_space; + + index[current_depth]++; + while (index[current_depth] >= + parent_obj[current_depth]->package.count) + { + /* + * We've handled all of the objects at + * this level, This means that we have + * just completed a package. That package + * may have contained one or more packages + * itself. + */ + if (current_depth == 0) { + /* + * We have handled all of the objects + * in the top level package just add the + * length of the package objects and + * get out. Round up to the next machine + * word. + */ + length += + ROUND_UP_TO_NATIVE_WORD ( + sizeof (ACPI_OBJECT)) * + package_count; + + *obj_length = length; + + return (AE_OK); + } + + /* + * Go back up a level and move the index + * past the just completed package object. + */ + current_depth--; + index[current_depth]++; + } + } + + else { + /* + * This object is a package + * -- go one level deeper + */ + package_count++; + if (current_depth < MAX_PACKAGE_DEPTH-1) { + current_depth++; + parent_obj[current_depth] = this_internal_obj; + index[current_depth] = 0; + } + + else { + /* + * Too many nested levels of packages for us + * to handle + */ + + return (AE_LIMIT); + } + } + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_get_object_size + * + * PARAMETERS: *Internal_obj - Pointer to the object we are examining + * *Ret_length - Where the length will be returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to determine the space required to + * contain an object for return to an API user. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_get_object_size( + ACPI_OBJECT_INTERNAL *internal_obj, + u32 *obj_length) +{ + ACPI_STATUS status; + + + if ((VALID_DESCRIPTOR_TYPE (internal_obj, ACPI_DESC_TYPE_INTERNAL)) && + (IS_THIS_OBJECT_TYPE (internal_obj, ACPI_TYPE_PACKAGE))) + { + status = + acpi_cm_get_package_object_size (internal_obj, obj_length); + } + + else { + status = + acpi_cm_get_simple_object_size (internal_obj, obj_length); + } + + return status; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/common/cmutils.c linux/drivers/acpi/common/cmutils.c --- v2.4.0-test2/linux/drivers/acpi/common/cmutils.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/common/cmutils.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,726 @@ +/****************************************************************************** + * + * Module Name: cmutils - common utility procedures + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "events.h" +#include "hardware.h" +#include "namesp.h" +#include "interp.h" +#include "amlcode.h" +#include "debugger.h" + + +#define _COMPONENT MISCELLANEOUS + MODULE_NAME ("cmutils"); + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_valid_acpi_name + * + * PARAMETERS: Character - The character to be examined + * + * RETURN: 1 if Character may appear in a name, else 0 + * + * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + ****************************************************************************/ + +u8 +acpi_cm_valid_acpi_name ( + u32 name) +{ + char *name_ptr = (char *) &name; + u32 i; + + + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (!((name_ptr[i] == '_') || + (name_ptr[i] >= 'A' && name_ptr[i] <= 'Z') || + (name_ptr[i] >= '0' && name_ptr[i] <= '9'))) + { + return FALSE; + } + } + + + return TRUE; +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_valid_acpi_character + * + * PARAMETERS: Character - The character to be examined + * + * RETURN: 1 if Character may appear in a name, else 0 + * + * DESCRIPTION: Check for a printable character + * + ****************************************************************************/ + +u8 +acpi_cm_valid_acpi_character ( + char character) +{ + + return ((u8) ((character == '_') || + (character >= 'A' && character <= 'Z') || + (character >= '0' && character <= '9'))); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_mutex_initialize + * + * PARAMETERS: None. + * + * RETURN: Status + * + * DESCRIPTION: Create the system mutex objects. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_cm_mutex_initialize ( + void) +{ + u32 i; + ACPI_STATUS status; + + + /* + * Create each of the predefined mutex objects + */ + for (i = 0; i < NUM_MTX; i++) { + status = acpi_cm_create_mutex (i); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_mutex_terminate + * + * PARAMETERS: None. + * + * RETURN: None. + * + * DESCRIPTION: Delete all of the system mutex objects. + * + ****************************************************************************/ + +void +acpi_cm_mutex_terminate ( + void) +{ + u32 i; + + + /* + * Delete each predefined mutex object + */ + for (i = 0; i < NUM_MTX; i++) { + acpi_cm_delete_mutex (i); + } + + return; +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_create_mutex + * + * PARAMETERS: Mutex_iD - ID of the mutex to be created + * + * RETURN: Status + * + * DESCRIPTION: Create a mutex object. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_cm_create_mutex ( + ACPI_MUTEX_HANDLE mutex_id) +{ + ACPI_STATUS status = AE_OK; + + + if (mutex_id > MAX_MTX) { + return (AE_BAD_PARAMETER); + } + + + if (!acpi_gbl_acpi_mutex_info[mutex_id].mutex) { + status = acpi_os_create_semaphore (1, 1, + &acpi_gbl_acpi_mutex_info[mutex_id].mutex); + acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE; + acpi_gbl_acpi_mutex_info[mutex_id].use_count = 0; + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_delete_mutex + * + * PARAMETERS: Mutex_iD - ID of the mutex to be deleted + * + * RETURN: Status + * + * DESCRIPTION: Delete a mutex object. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_cm_delete_mutex ( + ACPI_MUTEX_HANDLE mutex_id) +{ + ACPI_STATUS status; + + + if (mutex_id > MAX_MTX) { + return (AE_BAD_PARAMETER); + } + + + status = acpi_os_delete_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex); + + acpi_gbl_acpi_mutex_info[mutex_id].mutex = NULL; + acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE; + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_acquire_mutex + * + * PARAMETERS: Mutex_iD - ID of the mutex to be acquired + * + * RETURN: Status + * + * DESCRIPTION: Acquire a mutex object. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_cm_acquire_mutex ( + ACPI_MUTEX_HANDLE mutex_id) +{ + ACPI_STATUS status; + + + if (mutex_id > MAX_MTX) { + return (AE_BAD_PARAMETER); + } + + + status = + acpi_os_wait_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, + 1, WAIT_FOREVER); + + if (ACPI_SUCCESS (status)) { + acpi_gbl_acpi_mutex_info[mutex_id].locked = TRUE; + acpi_gbl_acpi_mutex_info[mutex_id].use_count++; + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_release_mutex + * + * PARAMETERS: Mutex_iD - ID of the mutex to be released + * + * RETURN: Status + * + * DESCRIPTION: Release a mutex object. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_cm_release_mutex ( + ACPI_MUTEX_HANDLE mutex_id) +{ + ACPI_STATUS status; + + + if (mutex_id > MAX_MTX) { + return (AE_BAD_PARAMETER); + } + + + acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE; /* Mark before unlocking */ + + status = + acpi_os_signal_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, 1); + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_create_update_state_and_push + * + * PARAMETERS: *Object - Object to be added to the new state + * Action - Increment/Decrement + * State_list - List the state will be added to + * + * RETURN: None + * + * DESCRIPTION: Create a new state and push it + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_create_update_state_and_push ( + ACPI_OBJECT_INTERNAL *object, + u16 action, + ACPI_GENERIC_STATE **state_list) +{ + ACPI_GENERIC_STATE *state; + + + /* Ignore null objects; these are expected */ + + if (!object) { + return AE_OK; + } + + state = acpi_cm_create_update_state (object, action); + if (!state) { + return AE_NO_MEMORY; + } + + + acpi_cm_push_generic_state (state_list, state); + return AE_OK; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_push_generic_state + * + * PARAMETERS: List_head - Head of the state stack + * State - State object to push + * + * RETURN: Status + * + * DESCRIPTION: Push a state object onto a state stack + * + ******************************************************************************/ + +void +acpi_cm_push_generic_state ( + ACPI_GENERIC_STATE **list_head, + ACPI_GENERIC_STATE *state) +{ + /* Push the state object onto the front of the list (stack) */ + + state->common.next = *list_head; + *list_head = state; + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_pop_generic_state + * + * PARAMETERS: List_head - Head of the state stack + * + * RETURN: Status + * + * DESCRIPTION: Pop a state object from a state stack + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +acpi_cm_pop_generic_state ( + ACPI_GENERIC_STATE **list_head) +{ + ACPI_GENERIC_STATE *state; + + + /* Remove the state object at the head of the list (stack) */ + + state = *list_head; + if (state) { + /* Update the list head */ + + *list_head = state->common.next; + } + + return (state); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_create_generic_state + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create a generic state object. Attempt to obtain one from + * the global state cache; If none available, create a new one. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +acpi_cm_create_generic_state (void) +{ + ACPI_GENERIC_STATE *state; + + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + + acpi_gbl_state_cache_requests++; + + /* Check the cache first */ + + if (acpi_gbl_generic_state_cache) { + /* There is an object available, use it */ + + state = acpi_gbl_generic_state_cache; + acpi_gbl_generic_state_cache = state->common.next; + state->common.next = NULL; + + acpi_gbl_state_cache_hits++; + acpi_gbl_generic_state_cache_depth--; + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + } + + else { + /* The cache is empty, create a new object */ + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + + state = acpi_cm_callocate (sizeof (ACPI_GENERIC_STATE)); + } + + /* Initialize */ + + if (state) { + state->common.data_type = ACPI_DESC_TYPE_STATE; + } + + return state; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_create_update_state + * + * PARAMETERS: Object - Initial Object to be installed in the state + * Action - Update action to be performed + * + * RETURN: Status + * + * DESCRIPTION: Create an "Update State" - a flavor of the generic state used + * to update reference counts and delete complex objects such + * as packages. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +acpi_cm_create_update_state ( + ACPI_OBJECT_INTERNAL *object, + u16 action) +{ + ACPI_GENERIC_STATE *state; + + + /* Create the generic state object */ + + state = acpi_cm_create_generic_state (); + if (!state) { + return NULL; + } + + /* Init fields specific to the update struct */ + + state->update.object = object; + state->update.value = action; + + return (state); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_create_control_state + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create a "Control State" - a flavor of the generic state used + * to support nested IF/WHILE constructs in the AML. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +acpi_cm_create_control_state ( + void) +{ + ACPI_GENERIC_STATE *state; + + + /* Create the generic state object */ + + state = acpi_cm_create_generic_state (); + if (!state) { + return NULL; + } + + + /* Init fields specific to the control struct */ + + state->common.state = CONTROL_CONDITIONAL_EXECUTING; + + return (state); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_delete_generic_state + * + * PARAMETERS: State - The state object to be deleted + * + * RETURN: Status + * + * DESCRIPTION: Put a state object back into the global state cache. The object + * is not actually freed at this time. + * + ******************************************************************************/ + +void +acpi_cm_delete_generic_state ( + ACPI_GENERIC_STATE *state) +{ + + /* If cache is full, just free this state object */ + + if (acpi_gbl_generic_state_cache_depth >= MAX_STATE_CACHE_DEPTH) { + acpi_cm_free (state); + } + + /* Otherwise put this object back into the cache */ + + else { + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + + /* Clear the state */ + + MEMSET (state, 0, sizeof (ACPI_GENERIC_STATE)); + state->common.data_type = ACPI_DESC_TYPE_STATE; + + /* Put the object at the head of the global cache list */ + + state->common.next = acpi_gbl_generic_state_cache; + acpi_gbl_generic_state_cache = state; + acpi_gbl_generic_state_cache_depth++; + + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + } + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_delete_generic_state_cache + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Purge the global state object cache. Used during subsystem + * termination. + * + ******************************************************************************/ + +void +acpi_cm_delete_generic_state_cache ( + void) +{ + ACPI_GENERIC_STATE *next; + + + /* Traverse the global cache list */ + + while (acpi_gbl_generic_state_cache) { + /* Delete one cached state object */ + + next = acpi_gbl_generic_state_cache->common.next; + acpi_cm_free (acpi_gbl_generic_state_cache); + acpi_gbl_generic_state_cache = next; + } + + return; +} + + +/***************************************************************************** + * + * FUNCTION: _Report_error + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Message - Error message to use on failure + * + * RETURN: None + * + * DESCRIPTION: Print error message from KD table + * + ****************************************************************************/ + +void +_report_error ( + char *module_name, + s32 line_number, + s32 component_id, + char *message) +{ + + debug_print (module_name, line_number, component_id, ACPI_ERROR, + "*** Error: %s\n", message); + +} + + +/***************************************************************************** + * + * FUNCTION: _Report_warning + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Message - Error message to use on failure + * + * RETURN: None + * + * DESCRIPTION: Print warning message from KD table + * + ****************************************************************************/ + +void +_report_warning ( + char *module_name, + s32 line_number, + s32 component_id, + char *message) +{ + + debug_print (module_name, line_number, component_id, ACPI_WARN, + "*** Warning: %s\n", message); + +} + + +/***************************************************************************** + * + * FUNCTION: _Report_success + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Message - Error message to use on failure + * + * RETURN: None + * + * DESCRIPTION: Print warning message from KD table + * + ****************************************************************************/ + +void +_report_success ( + char *module_name, + s32 line_number, + s32 component_id, + char *message) +{ + + debug_print (module_name, line_number, component_id, ACPI_OK, + "*** Success: %s\n", message); +} + + +/***************************************************************************** + * + * FUNCTION: _Report_info + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Message - Error message to use on failure + * + * RETURN: None + * + * DESCRIPTION: Print information message from KD table + * + ****************************************************************************/ + +void +_report_info ( + char *module_name, + s32 line_number, + s32 component_id, + char *message) +{ + + debug_print (module_name, line_number, component_id, ACPI_INFO, + "*** Info: %s\n", message); + +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/common/cmxface.c linux/drivers/acpi/common/cmxface.c --- v2.4.0-test2/linux/drivers/acpi/common/cmxface.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/common/cmxface.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,268 @@ +/****************************************************************************** + * + * Module Name: cmxface - External interfaces for "global" ACPI functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "events.h" +#include "hardware.h" +#include "namesp.h" +#include "interp.h" +#include "amlcode.h" +#include "debugger.h" + + +#define _COMPONENT MISCELLANEOUS + MODULE_NAME ("cmxface"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initializes all global variables. This is the first function + * called, so any early initialization belongs here. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_initialize (ACPI_INIT_DATA *init_data) +{ + ACPI_STATUS status; + + + /* Initialize all globals used by the subsystem */ + + acpi_cm_init_globals (init_data); + + /* Initialize the OS-Dependent layer */ + + status = acpi_os_initialize (); + if (ACPI_FAILURE (status)) { + REPORT_ERROR ("OSD Initialization Failure"); + return (status); + } + + /* Create the default mutex objects */ + + status = acpi_cm_mutex_initialize (); + if (ACPI_FAILURE (status)) { + REPORT_ERROR ("Global Mutex Initialization Failure"); + return (status); + } + + /* If configured, initialize the AML debugger */ + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_terminate + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Shutdown the ACPI subsystem. Release all resources. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_terminate (void) +{ + + /* Terminate the AML Debuger if present */ + + acpi_gbl_db_terminate_threads = TRUE; + acpi_cm_release_mutex (ACPI_MTX_DEBUG_CMD_READY); + + + /* Shutdown and free all resources */ + + acpi_cm_subsystem_shutdown (); + + + /* Free the mutex objects */ + + acpi_cm_mutex_terminate (); + + + /* Now we can shutdown the OS-dependent layer */ + + acpi_os_terminate (); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_system_info + * + * PARAMETERS: Out_buffer - a pointer to a buffer to receive the + * resources for the device + * Buffer_length - the number of bytes available in the buffer + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get information about the current + * state of the ACPI subsystem. It will return system information + * in the Out_buffer. + * + * If the function fails an appropriate status will be returned + * and the value of Out_buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_system_info ( + ACPI_BUFFER *out_buffer) +{ + ACPI_SYSTEM_INFO *info_ptr; + u32 i; + + + /* + * Must have a valid buffer + */ + if ((!out_buffer) || + (!out_buffer->pointer)) + { + return (AE_BAD_PARAMETER); + } + + if (out_buffer->length < sizeof (ACPI_SYSTEM_INFO)) { + /* + * Caller's buffer is too small + */ + out_buffer->length = sizeof (ACPI_SYSTEM_INFO); + + return (AE_BUFFER_OVERFLOW); + } + + + /* + * Set return length and get data + */ + out_buffer->length = sizeof (ACPI_SYSTEM_INFO); + info_ptr = (ACPI_SYSTEM_INFO *) out_buffer->pointer; + + /* TBD [Future]: need a version number, or use the version string */ + info_ptr->acpi_ca_version = 0x1234; + + /* System flags (ACPI capabilities) */ + + info_ptr->flags = acpi_gbl_system_flags; + + /* Timer resolution - 24 or 32 bits */ + + info_ptr->timer_resolution = acpi_hw_pmt_resolution (); + + /* Clear the reserved fields */ + + info_ptr->reserved1 = 0; + info_ptr->reserved2 = 0; + + /* Current debug levels */ + + info_ptr->debug_layer = acpi_dbg_layer; + info_ptr->debug_level = acpi_dbg_level; + + /* Current status of the ACPI tables, per table type */ + + info_ptr->num_table_types = NUM_ACPI_TABLES; + for (i = 0; i < NUM_ACPI_TABLES; i++); { + info_ptr->table_info[i].count = acpi_gbl_acpi_tables[i].count; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_format_exception + * + * PARAMETERS: Out_buffer - a pointer to a buffer to receive the + * exception name + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function translates an ACPI exception into an ASCII string. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_format_exception ( + ACPI_STATUS exception, + ACPI_BUFFER *out_buffer) +{ + u32 length; + char *formatted_exception; + + + /* + * Must have a valid buffer + */ + if ((!out_buffer) || + (!out_buffer->pointer)) + { + return (AE_BAD_PARAMETER); + } + + + /* Exception must be within range */ + + if (exception > ACPI_MAX_STATUS) { + return (AE_BAD_PARAMETER); + } + + + /* Convert the exception code */ + + formatted_exception = acpi_cm_format_exception (exception); + + /* + * Get length of string and check if it will fit in caller's buffer + */ + + length = STRLEN (formatted_exception); + if (out_buffer->length < length) { + out_buffer->length = length; + return (AE_BUFFER_OVERFLOW); + } + + + /* Copy the string, all done */ + + STRCPY (out_buffer->pointer, formatted_exception); + + return (AE_OK); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/dispatcher/dsfield.c linux/drivers/acpi/dispatcher/dsfield.c --- v2.4.0-test2/linux/drivers/acpi/dispatcher/dsfield.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/dispatcher/dsfield.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,414 @@ + +/****************************************************************************** + * + * Module Name: dsfield - Dispatcher field routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "dispatch.h" +#include "interp.h" +#include "namesp.h" + + +#define _COMPONENT DISPATCHER + MODULE_NAME ("dsfield"); + + +/* + * Field flags: Bits 00 - 03 : Access_type (Any_acc, Byte_acc, etc.) + * 04 : Lock_rule (1 == Lock) + * 05 - 06 : Update_rule + */ + +#define FIELD_ACCESS_TYPE_MASK 0x0F +#define FIELD_LOCK_RULE_MASK 0x10 +#define FIELD_UPDATE_RULE_MASK 0x60 + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_create_field + * + * PARAMETERS: Op - Op containing the Field definition and args + * Region - NTE for the containing Operation Region + * + * RETURN: Status + * + * DESCRIPTION: Create a new field in the specified operation region + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_create_field ( + ACPI_GENERIC_OP *op, + ACPI_HANDLE region, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_AML_ERROR; + ACPI_GENERIC_OP *arg; + ACPI_NAMED_OBJECT *entry; + u8 field_flags; + u8 access_attribute = 0; + u32 field_bit_position = 0; + + + /* First arg is the name of the parent Op_region */ + + arg = op->value.arg; + + /* Second arg is the field flags */ + + arg = arg->next; + field_flags = (u8) arg->value.integer; + + /* Each remaining arg is a Named Field */ + + arg = arg->next; + while (arg) { + switch (arg->opcode) + { + case AML_RESERVEDFIELD_OP: + + field_bit_position += arg->value.size; + break; + + + case AML_ACCESSFIELD_OP: + + /* + * Get a new Access_type and Access_attribute for all + * entries (until end or another Access_as keyword) + */ + + access_attribute = (u8) arg->value.integer; + field_flags = (u8) + ((field_flags & FIELD_ACCESS_TYPE_MASK) || + ((u8) (arg->value.integer >> 8))); + break; + + + case AML_NAMEDFIELD_OP: + + status = acpi_ns_lookup (walk_state->scope_info, + (char *) &((ACPI_NAMED_OP *)arg)->name, + INTERNAL_TYPE_DEF_FIELD, + IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &entry); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Initialize an object for the new NTE that is on + * the object stack + */ + + status = acpi_aml_prep_def_field_value (entry, region, + field_flags, + access_attribute, + field_bit_position, + arg->value.size); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Keep track of bit position for the *next* field */ + + field_bit_position += arg->value.size; + break; + } + + arg = arg->next; + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_create_bank_field + * + * PARAMETERS: Op - Op containing the Field definition and args + * Region - NTE for the containing Operation Region + * + * RETURN: Status + * + * DESCRIPTION: Create a new bank field in the specified operation region + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_create_bank_field ( + ACPI_GENERIC_OP *op, + ACPI_HANDLE region, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_AML_ERROR; + ACPI_GENERIC_OP *arg; + ACPI_NAMED_OBJECT *bank_reg; + ACPI_NAMED_OBJECT *entry; + u32 bank_value; + u8 field_flags; + u8 access_attribute = 0; + u32 field_bit_position = 0; + + + /* First arg is the name of the parent Op_region */ + + arg = op->value.arg; + + /* Socond arg is the Bank Register */ + + arg = arg->next; + + status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + INTERNAL_TYPE_BANK_FIELD_DEFN, + IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &bank_reg); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Third arg is the Bank_value */ + + arg = arg->next; + bank_value = arg->value.integer; + + + /* Next arg is the field flags */ + + arg = arg->next; + field_flags = (u8) arg->value.integer; + + /* Each remaining arg is a Named Field */ + + arg = arg->next; + while (arg) { + switch (arg->opcode) + { + case AML_RESERVEDFIELD_OP: + + field_bit_position += arg->value.size; + break; + + + case AML_ACCESSFIELD_OP: + + /* + * Get a new Access_type and Access_attribute for + * all entries (until end or another Access_as keyword) + */ + + access_attribute = (u8) arg->value.integer; + field_flags = (u8) + ((field_flags & FIELD_ACCESS_TYPE_MASK) || + ((u8) (arg->value.integer >> 8))); + break; + + + case AML_NAMEDFIELD_OP: + + status = acpi_ns_lookup (walk_state->scope_info, + (char *) &((ACPI_NAMED_OP *)arg)->name, + INTERNAL_TYPE_DEF_FIELD, + IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &entry); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Initialize an object for the new NTE that is on + * the object stack + */ + + status = acpi_aml_prep_bank_field_value (entry, region, + bank_reg, bank_value, + field_flags, + access_attribute, + field_bit_position, + arg->value.size); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Keep track of bit position for the *next* field */ + + field_bit_position += arg->value.size; + break; + + } + + arg = arg->next; + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_create_index_field + * + * PARAMETERS: Op - Op containing the Field definition and args + * Region - NTE for the containing Operation Region + * + * RETURN: Status + * + * DESCRIPTION: Create a new index field in the specified operation region + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_create_index_field ( + ACPI_GENERIC_OP *op, + ACPI_HANDLE region, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_GENERIC_OP *arg; + ACPI_NAMED_OBJECT *entry; + ACPI_NAMED_OBJECT *index_reg; + ACPI_NAMED_OBJECT *data_reg; + u8 field_flags; + u8 access_attribute = 0; + u32 field_bit_position = 0; + + + arg = op->value.arg; + + /* First arg is the name of the Index register */ + + status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + ACPI_TYPE_ANY, IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &index_reg); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Second arg is the data register */ + + arg = arg->next; + + status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + INTERNAL_TYPE_INDEX_FIELD_DEFN, + IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &data_reg); + + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* Next arg is the field flags */ + + arg = arg->next; + field_flags = (u8) arg->value.integer; + + + /* Each remaining arg is a Named Field */ + + arg = arg->next; + while (arg) { + switch (arg->opcode) + { + case AML_RESERVEDFIELD_OP: + + field_bit_position += arg->value.size; + break; + + + case AML_ACCESSFIELD_OP: + + /* + * Get a new Access_type and Access_attribute for all + * entries (until end or another Access_as keyword) + */ + + access_attribute = (u8) arg->value.integer; + field_flags = (u8) + ((field_flags & FIELD_ACCESS_TYPE_MASK) || + ((u8) (arg->value.integer >> 8))); + break; + + + case AML_NAMEDFIELD_OP: + + status = acpi_ns_lookup (walk_state->scope_info, + (char *) &((ACPI_NAMED_OP *)arg)->name, + INTERNAL_TYPE_INDEX_FIELD, + IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &entry); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Initialize an object for the new NTE that is on + * the object stack + */ + + status = acpi_aml_prep_index_field_value (entry, index_reg, + data_reg, field_flags, + access_attribute, + field_bit_position, + arg->value.size); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Keep track of bit position for the *next* field */ + + field_bit_position += arg->value.size; + break; + + + default: + + status = AE_AML_ERROR; + break; + } + + arg = arg->next; + } + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/dispatcher/dsmethod.c linux/drivers/acpi/dispatcher/dsmethod.c --- v2.4.0-test2/linux/drivers/acpi/dispatcher/dsmethod.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/dispatcher/dsmethod.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,506 @@ + +/****************************************************************************** + * + * Module Name: dsmethod - Parser/Interpreter interface - control method parsing + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "amlcode.h" +#include "dispatch.h" +#include "interp.h" +#include "namesp.h" +#include "tables.h" +#include "debugger.h" + + +#define _COMPONENT DISPATCHER + MODULE_NAME ("dsmethod"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_parse_method + * + * PARAMETERS: Obj_handle - NTE of the method + * Level - Current nesting level + * Context - Points to a method counter + * Return_value - Not used + * + * RETURN: Status + * + * DESCRIPTION: Call the parser and parse the AML that is + * associated with the method. + * + * MUTEX: Assumes parser is locked + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_parse_method ( + ACPI_HANDLE obj_handle) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_GENERIC_OP *op; + ACPI_NAMED_OBJECT *entry; + ACPI_OWNER_ID owner_id; + + + /* Parameter Validation */ + + if (!obj_handle) { + return (AE_NULL_ENTRY); + } + + + /* Extract the method object from the method NTE */ + + entry = (ACPI_NAMED_OBJECT*) obj_handle; + obj_desc = entry->object; + if (!obj_desc) { + return (AE_NULL_OBJECT); + } + + /* Create a mutex for the method if there is a concurrency limit */ + + if ((obj_desc->method.concurrency != INFINITE_CONCURRENCY) && + (!obj_desc->method.semaphore)) + { + status = acpi_os_create_semaphore (1, + obj_desc->method.concurrency, + &obj_desc->method.semaphore); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* + * Allocate a new parser op to be the root of the parsed + * method tree + */ + + op = acpi_ps_alloc_op (AML_METHOD_OP); + if (!op) { + return (AE_NO_MEMORY); + } + + /* Init new op with the method name and pointer back to the NTE */ + + acpi_ps_set_name (op, entry->name); + op->acpi_named_object = entry; + + + /* + * Parse the method, creating a parse tree. + * + * The parse also includes a first pass load of the + * namespace where newly declared named objects are + * added into the namespace. Actual evaluation of + * the named objects (what would be called a "second + * pass") happens during the actual execution of the + * method so that operands to the named objects can + * take on dynamic run-time values. + */ + + status = acpi_ps_parse_aml (op, obj_desc->method.pcode, + obj_desc->method.pcode_length, 0); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Get a new Owner_id for objects created by this method */ + + owner_id = acpi_cm_allocate_owner_id (OWNER_TYPE_METHOD); + + /* Install the parsed tree in the method object */ + + obj_desc->method.parser_op = op; + obj_desc->method.owning_id = owner_id; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_begin_method_execution + * + * PARAMETERS: Method_entry - NTE of the method + * Obj_desc - The method object + * + * RETURN: Status + * + * DESCRIPTION: Prepare a method for execution. Parses the method if necessary, + * increments the thread count, and waits at the method semaphore + * for clearance to execute. + * + * MUTEX: Locks/unlocks parser. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_begin_method_execution ( + ACPI_NAMED_OBJECT *method_entry, + ACPI_OBJECT_INTERNAL *obj_desc) +{ + ACPI_STATUS status = AE_OK; + + + if (!method_entry) { + return (AE_NULL_ENTRY); + } + + obj_desc = acpi_ns_get_attached_object (method_entry); + if (!obj_desc) { + return (AE_NULL_OBJECT); + } + + /* + * Lock the parser while we check for and possibly parse the + * control method + */ + + acpi_cm_acquire_mutex (ACPI_MTX_PARSER); + + + /* If method is not parsed at this time, we must parse it first */ + + if (!obj_desc->method.parser_op) { + + status = acpi_ds_parse_method (method_entry); + if (ACPI_FAILURE (status)) { + acpi_cm_release_mutex (ACPI_MTX_PARSER); + return (status); + } + } + + + /* + * Increment the method parse tree thread count since there + * is one additional thread executing in it. If configured + * for deletion-on-exit, the parse tree will be deleted when + * the last thread completes execution of the method + */ + + ((ACPI_DEFERRED_OP *) obj_desc->method.parser_op)->thread_count++; + + /* + * Parsing is complete, we can unlock the parser. Parse tree + * cannot be deleted at least until this thread completes. + */ + + acpi_cm_release_mutex (ACPI_MTX_PARSER); + + /* + * If there is a concurrency limit on this method, we need to + * obtain a unit from the method semaphore. This releases the + * interpreter if we block + */ + + if (obj_desc->method.semaphore) { + status = acpi_aml_system_wait_semaphore (obj_desc->method.semaphore, + WAIT_FOREVER); + } + + + return (status); + +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_call_control_method + * + * PARAMETERS: Walk_state - Current state of the walk + * Op - Current Op to be walked + * + * RETURN: Status + * + * DESCRIPTION: Transfer execution to a called control method + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_call_control_method ( + ACPI_WALK_LIST *walk_list, + ACPI_WALK_STATE *this_walk_state, + ACPI_GENERIC_OP *op) +{ + ACPI_STATUS status; + ACPI_DEFERRED_OP *method; + ACPI_NAMED_OBJECT *method_entry; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_WALK_STATE *next_walk_state; + u32 i; + + + /* + * Prev_op points to the METHOD_CALL Op. + * Get the NTE entry (in the METHOD_CALL->NAME Op) and the + * corresponding METHOD Op + */ + + method_entry = (this_walk_state->prev_op->value.arg)->acpi_named_object; + if (!method_entry) { + return (AE_NULL_ENTRY); + } + + obj_desc = acpi_ns_get_attached_object (method_entry); + if (!obj_desc) { + return (AE_NULL_OBJECT); + } + + /* Parse method if necessary, wait on concurrency semaphore */ + + status = acpi_ds_begin_method_execution (method_entry, obj_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Save the (current) Op for when this walk is restarted */ + + this_walk_state->method_call_op = this_walk_state->prev_op; + this_walk_state->prev_op = op; + method = obj_desc->method.parser_op; + + /* Create a new state for the preempting walk */ + + next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, + (ACPI_GENERIC_OP *) method, + obj_desc, walk_list); + if (!next_walk_state) { + return (AE_NO_MEMORY); + } + + /* The Next_op of the Next_walk will be the beginning of the method */ + + next_walk_state->next_op = (ACPI_GENERIC_OP *) method; + + /* Open a new scope */ + + status = acpi_ds_scope_stack_push (method_entry->child_table, + ACPI_TYPE_METHOD, next_walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* + * Initialize the arguments for the method. The resolved + * arguments were put on the previous walk state's operand + * stack. Operands on the previous walk state stack always + * start at index 0. + */ + + status = acpi_ds_method_data_init_args (&this_walk_state->operands[0], + this_walk_state->num_operands); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* + * Delete the operands on the previous walkstate operand stack + * (they were copied to new objects) + */ + + for (i = 0; i < obj_desc->method.param_count; i++) { + acpi_cm_remove_reference (this_walk_state->operands [i]); + } + + /* Clear the operand stack */ + + this_walk_state->num_operands = 0; + + + return (AE_OK); + + + /* On error, we must delete the new walk state */ + +cleanup: + acpi_ds_terminate_control_method (next_walk_state); + acpi_ds_delete_walk_state (next_walk_state); + return (status); + +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_restart_control_method + * + * PARAMETERS: Walk_state - State of the method when it was preempted + * Op - Pointer to new current op + * + * RETURN: Status + * + * DESCRIPTION: Restart a method that was preempted + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_restart_control_method ( + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL *return_desc) +{ + ACPI_STATUS status; + + + if (return_desc) { + /* + * Get the return value (if any) from the previous method. + * NULL if no return value + */ + + status = acpi_ds_result_stack_push (return_desc, walk_state); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (return_desc); + return (status); + } + + /* + * Delete the return value if it will not be used by the + * calling method + */ + + acpi_ds_delete_result_if_not_used (walk_state->method_call_op, + return_desc, walk_state); + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_terminate_control_method + * + * PARAMETERS: Walk_state - State of the method + * + * RETURN: Status + * + * DESCRIPTION: Terminate a control method. Delete everything that the method + * created, delete all locals and arguments, and delete the parse + * tree if requested. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_terminate_control_method ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_DEFERRED_OP *op; + ACPI_NAMED_OBJECT *method_entry; + + + /* The method object should be stored in the walk state */ + + obj_desc = walk_state->method_desc; + if (!obj_desc) { + return (AE_OK); + } + + /* Delete all arguments and locals */ + + acpi_ds_method_data_delete_all (walk_state); + + /* + * Lock the parser while we terminate this method. + * If this is the last thread executing the method, + * we have additional cleanup to perform + */ + + acpi_cm_acquire_mutex (ACPI_MTX_PARSER); + + /* + * The root of the method parse tree should be stored + * in the method object + */ + + op = obj_desc->method.parser_op; + if (!op) { + goto unlock_and_exit; + } + + /* Signal completion of the execution of this method if necessary */ + + if (walk_state->method_desc->method.semaphore) { + status = acpi_os_signal_semaphore ( + walk_state->method_desc->method.semaphore, 1); + } + + /* Decrement the thread count on the method parse tree */ + + op->thread_count--; + if (!op->thread_count) { + /* + * There are no more threads executing this method. Perform + * additional cleanup. + * + * The method NTE is stored in the method Op + */ + method_entry = op->acpi_named_object; + + /* + * Delete any namespace entries created immediately underneath + * the method + */ + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + if (method_entry->child_table) { + acpi_ns_delete_namespace_subtree (method_entry); + } + + /* + * Delete any namespace entries created anywhere else within + * the namespace + */ + + acpi_ns_delete_namespace_by_owner ( + walk_state->method_desc->method.owning_id); + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + /* + * Delete the method's parse tree if asked to + */ + if (acpi_gbl_when_to_parse_methods & METHOD_DELETE_AT_COMPLETION) { + acpi_ps_delete_parse_tree ( + walk_state->method_desc->method.parser_op); + + walk_state->method_desc->method.parser_op = NULL; + } + } + +unlock_and_exit: + + acpi_cm_release_mutex (ACPI_MTX_PARSER); + return (AE_OK); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/dispatcher/dsmthdat.c linux/drivers/acpi/dispatcher/dsmthdat.c --- v2.4.0-test2/linux/drivers/acpi/dispatcher/dsmthdat.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/dispatcher/dsmthdat.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,682 @@ + +/****************************************************************************** + * + * Module Name: dsmthdat - control method arguments and local variables + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "dispatch.h" +#include "interp.h" +#include "amlcode.h" +#include "namesp.h" + + +#define _COMPONENT DISPATCHER + MODULE_NAME ("dsmthdat"); + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_method_data_init + * + * PARAMETERS: *Obj_desc + * + * RETURN: Status + * + * DESCRIPTION: Initialize the data structures that hold the method's arguments + * and locals. The data struct is an array of NTEs for each. + * This allows Ref_of and De_ref_of to work properly for these + * special data types. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_init ( + ACPI_WALK_STATE *walk_state) +{ + u32 i; + + + /* + * Walk_state fields are initialized to zero by the + * Acpi_cm_callocate(). + * + * An NTE is assigned to each argument and local so + * that Ref_of() can return a pointer to the NTE. + */ + + /* Init the method arguments */ + + for (i = 0; i < MTH_NUM_ARGS; i++) { + MOVE_UNALIGNED32_TO_32 (&walk_state->arguments[i].name, + NAMEOF_ARG_NTE); + + walk_state->arguments[i].name |= (i << 24); + walk_state->arguments[i].data_type = ACPI_DESC_TYPE_NAMED; + walk_state->arguments[i].type = + INTERNAL_TYPE_METHOD_ARGUMENT; + } + + /* Init the method locals */ + + for (i = 0; i < MTH_NUM_LOCALS; i++) { + MOVE_UNALIGNED32_TO_32 (&walk_state->local_variables[i].name, + NAMEOF_LOCAL_NTE); + + walk_state->local_variables[i].name |= (i << 24); + walk_state->local_variables[i].data_type = ACPI_DESC_TYPE_NAMED; + walk_state->local_variables[i].type = + INTERNAL_TYPE_METHOD_LOCAL_VAR; + } + + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_method_data_delete_all + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Delete method locals and arguments. Arguments are only + * deleted if this method was called from another method. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_delete_all ( + ACPI_WALK_STATE *walk_state) +{ + u32 index; + ACPI_OBJECT_INTERNAL *object; + + + /* Delete the locals */ + + for (index = 0; index < MTH_NUM_LOCALS; index++) { + object = walk_state->local_variables[index].object; + if (object) { + /* Remove first */ + walk_state->local_variables[index].object = NULL; + /* Was given a ref when stored */ + acpi_cm_remove_reference (object); + } + } + + + /* Delete the arguments */ + + for (index = 0; index < MTH_NUM_ARGS; index++) { + object = walk_state->arguments[index].object; + if (object) { + /* Remove first */ + walk_state->arguments[index].object = NULL; + /* Was given a ref when stored */ + acpi_cm_remove_reference (object); + } + } + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_method_data_init_args + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize arguments for a method + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_init_args ( + ACPI_OBJECT_INTERNAL **params, + u32 max_param_count) +{ + ACPI_STATUS status; + u32 mindex; + u32 pindex; + + + if (!params) { + return (AE_OK); + } + + /* Copy passed parameters into the new method stack frame */ + + for (pindex = mindex = 0; + (mindex < MTH_NUM_ARGS) && (pindex < max_param_count); + mindex++) + { + if (params[pindex]) { + /* + * A valid parameter. + * Set the current method argument to the + * Params[Pindex++] argument object descriptor + */ + status = acpi_ds_method_data_set_value (MTH_TYPE_ARG, + mindex, + params[pindex]); + if (ACPI_FAILURE (status)) { + break; + } + + pindex++; + } + + else { + break; + } + } + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_method_data_get_entry + * + * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * Index - Which local_var or argument to get + * Entry - Pointer to where a pointer to the stack + * entry is returned. + * + * RETURN: Status + * + * DESCRIPTION: Get the address of the stack entry given by Type:Index + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_get_entry ( + u32 type, + u32 index, + ACPI_OBJECT_INTERNAL ***entry) +{ + ACPI_WALK_STATE *walk_state; + + + walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); + + /* + * Get the requested object. + * The stack "Type" is either a Local_variable or an Argument + */ + + switch (type) + { + + case MTH_TYPE_LOCAL: + + if (index > MTH_MAX_LOCAL) { + return (AE_BAD_PARAMETER); + } + + *entry = + (ACPI_OBJECT_INTERNAL **) &walk_state->local_variables[index].object; + break; + + + case MTH_TYPE_ARG: + + if (index > MTH_MAX_ARG) { + return (AE_BAD_PARAMETER); + } + + *entry = + (ACPI_OBJECT_INTERNAL **) &walk_state->arguments[index].object; + break; + + + default: + return (AE_BAD_PARAMETER); + } + + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_method_data_set_entry + * + * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * Index - Which local_var or argument to get + * Object - Object to be inserted into the stack entry + * + * RETURN: Status + * + * DESCRIPTION: Insert an object onto the method stack at entry Type:Index. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_set_entry ( + u32 type, + u32 index, + ACPI_OBJECT_INTERNAL *object) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL **entry; + + + /* Get a pointer to the stack entry to set */ + + status = acpi_ds_method_data_get_entry (type, index, &entry); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Increment ref count so object can't be deleted while installed */ + + acpi_cm_add_reference (object); + + /* Install the object into the stack entry */ + + *entry = object; + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_method_data_get_type + * + * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * Index - Which local_var or argument whose type + * to get + * + * RETURN: Data type of selected Arg or Local + * Used only in Exec_monadic2()/Type_op. + * + ****************************************************************************/ + +OBJECT_TYPE_INTERNAL +acpi_ds_method_data_get_type ( + u32 type, + u32 index) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL **entry; + ACPI_OBJECT_INTERNAL *object; + + + /* Get a pointer to the requested stack entry */ + + status = acpi_ds_method_data_get_entry (type, index, &entry); + if (ACPI_FAILURE (status)) { + return ((ACPI_TYPE_NOT_FOUND)); + } + + /* Get the object from the method stack */ + + object = *entry; + + /* Get the object type */ + + if (!object) { + /* Any == 0 => "uninitialized" -- see spec 15.2.3.5.2.28 */ + return (ACPI_TYPE_ANY); + } + + return (object->common.type); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_method_data_get_nte + * + * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * Index - Which local_var or argument whose type + * to get + * + * RETURN: Get the NTE associated with a local or arg. + * + ****************************************************************************/ + +ACPI_NAMED_OBJECT* +acpi_ds_method_data_get_nte ( + u32 type, + u32 index) +{ + ACPI_NAMED_OBJECT *entry = NULL; + ACPI_WALK_STATE *walk_state; + + + walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); + + + switch (type) + { + + case MTH_TYPE_LOCAL: + + if (index > MTH_MAX_LOCAL) { + return (entry); + } + + entry = &walk_state->local_variables[index]; + break; + + + case MTH_TYPE_ARG: + + if (index > MTH_MAX_ARG) { + return (entry); + } + + entry = &walk_state->arguments[index]; + break; + + + default: + break; + } + + + return (entry); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_method_data_get_value + * + * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * Index - Which local_var or argument to get + * *Dest_desc - Descriptor into which selected Arg + * or Local value should be copied + * + * RETURN: Status + * + * DESCRIPTION: Retrieve value of selected Arg or Local from the method frame + * at the current top of the method stack. + * Used only in Acpi_aml_resolve_to_value(). + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_get_value ( + u32 type, + u32 index, + ACPI_OBJECT_INTERNAL **dest_desc) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL **entry; + ACPI_OBJECT_INTERNAL *object; + + + /* Validate the object descriptor */ + + if (!dest_desc) { + return (AE_BAD_PARAMETER); + } + + + /* Get a pointer to the requested method stack entry */ + + status = acpi_ds_method_data_get_entry (type, index, &entry); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Get the object from the method stack */ + + object = *entry; + + + /* Examine the returned object, it must be valid. */ + + if (!object) { + /* + * Index points to uninitialized object stack value. + * This means that either 1) The expected argument was + * not passed to the method, or 2) A local variable + * was referenced by the method (via the ASL) + * before it was initialized. Either case is an error. + */ + + switch (type) + { + case MTH_TYPE_ARG: + return (AE_AML_UNINITIALIZED_ARG); + break; + + case MTH_TYPE_LOCAL: + return (AE_AML_UNINITIALIZED_LOCAL); + break; + } + } + + + /* + * Index points to initialized and valid object stack value. + * Return an additional reference to the object + */ + + *dest_desc = object; + acpi_cm_add_reference (object); + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_method_data_delete_value + * + * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * Index - Which local_var or argument to delete + * + * RETURN: Status + * + * DESCRIPTION: Delete the entry at Type:Index on the method stack. Inserts + * a null into the stack slot after the object is deleted. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_delete_value ( + u32 type, + u32 index) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL **entry; + ACPI_OBJECT_INTERNAL *object; + + + /* Get a pointer to the requested entry */ + + status = acpi_ds_method_data_get_entry (type, index, &entry); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Get the current entry in this slot k */ + + object = *entry; + + /* + * Undefine the Arg or Local by setting its descriptor + * pointer to NULL. Locals/Args can contain both + * ACPI_OBJECT_INTERNALS and ACPI_NAMED_OBJECTs + */ + *entry = NULL; + + + if ((object) && + (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL))) + { + /* + * There is a valid object in this slot + * Decrement the reference count by one to balance the + * increment when the object was stored in the slot. + */ + + acpi_cm_remove_reference (object); + } + + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_method_data_set_value + * + * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * Index - Which local_var or argument to set + * *Src_desc - Value to be stored + * *Dest_desc - Descriptor into which *Src_desc + * can be copied, or NULL if one must + * be allocated for the purpose. If + * provided, this descriptor will be + * used for the new value. + * + * RETURN: Status + * + * DESCRIPTION: Store a value in an Arg or Local. The Src_desc is installed + * as the new value for the Arg or Local and the reference count + * is incremented. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_set_value ( + u32 type, + u32 index, + ACPI_OBJECT_INTERNAL *src_desc) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL **entry; + + + /* Parameter validation */ + + if (!src_desc) { + return (AE_BAD_PARAMETER); + } + + + /* Get a pointer to the requested method stack entry */ + + status = acpi_ds_method_data_get_entry (type, index, &entry); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + if (*entry == src_desc) { + goto cleanup; + } + + + /* + * If there is an object already in this slot, we either + * have to delete it, or if this is an argument and there + * is an object reference stored there, we have to do + * an indirect store! + */ + + if (*entry) { + /* + * Check for an indirect store if an argument + * contains an object reference (stored as an NTE). + * We don't allow this automatic dereferencing for + * locals, since a store to a local should overwrite + * anything there, including an object reference. + * + * If both Arg0 and Local0 contain Ref_of (Local4): + * + * Store (1, Arg0) - Causes indirect store to local4 + * Store (1, Local0) - Stores 1 in local0, overwriting + * the reference to local4 + * Store (1, De_refof (Local0)) - Causes indirect store to local4 + * + * Weird, but true. + */ + + if ((type == MTH_TYPE_ARG) && + (VALID_DESCRIPTOR_TYPE (*entry, ACPI_DESC_TYPE_NAMED))) + { + /* Detach an existing object from the NTE */ + + acpi_ns_detach_object (*entry); + + /* + * Store this object into the NTE + * (do the indirect store) + */ + + status = acpi_ns_attach_object (*entry, src_desc, + src_desc->common.type); + return (status); + } + + + /* + * Otherwise, just delete the existing object + * before storing the new one + */ + + acpi_ds_method_data_delete_value (type, index); + } + + + /* + * Install the Obj_stack descriptor (*Src_desc) into + * the descriptor for the Arg or Local. + * Install the new object in the stack entry + * (increments the object reference count by one) + */ + + status = acpi_ds_method_data_set_entry (type, index, src_desc); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* Normal exit */ + + return (AE_OK); + + + /* Error exit */ + +cleanup: + + return (status); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/dispatcher/dsobject.c linux/drivers/acpi/dispatcher/dsobject.c --- v2.4.0-test2/linux/drivers/acpi/dispatcher/dsobject.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/dispatcher/dsobject.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,598 @@ + +/****************************************************************************** + * + * Module Name: dsobject - Dispatcher object management routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "amlcode.h" +#include "dispatch.h" +#include "interp.h" +#include "namesp.h" + +#define _COMPONENT DISPATCHER + MODULE_NAME ("dsobject"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_init_one_object + * + * PARAMETERS: Obj_handle - NTE of the object + * Level - Current nesting level + * Context - Points to a init info struct + * Return_value - Not used + * + * RETURN: Status + * + * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object + * within the namespace. + * + * Currently, the only objects that require initialization are: + * 1) Methods + * 2) Op Regions + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_init_one_object ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value) +{ + OBJECT_TYPE_INTERNAL type; + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL *obj_desc; + INIT_WALK_INFO *info = (INIT_WALK_INFO *) context; + + + /* + * We are only interested in objects owned by the table that + * was just loaded + */ + + if (((ACPI_NAMED_OBJECT*) obj_handle)->owner_id != + info->table_desc->table_id) + { + return AE_OK; + } + + + /* And even then, we are only interested in a few object types */ + + type = acpi_ns_get_type (obj_handle); + + switch (type) + { + + case ACPI_TYPE_REGION: + + acpi_ds_initialize_region (obj_handle); + + info->op_region_count++; + break; + + + case ACPI_TYPE_METHOD: + + info->method_count++; + + + /* + * Always parse methods to detect errors, we may delete + * the parse tree below + */ + + status = acpi_ds_parse_method (obj_handle); + + /* TBD: [Errors] what do we do with an error? */ + + if (ACPI_FAILURE (status)) { + break; + } + + /* + * Keep the parse tree only if we are parsing all methods + * at init time (versus just-in-time) + */ + + if (acpi_gbl_when_to_parse_methods != METHOD_PARSE_AT_INIT) { + + acpi_ns_delete_namespace_subtree (obj_handle); + + obj_desc = ((ACPI_NAMED_OBJECT*)obj_handle)->object; + acpi_ps_delete_parse_tree (obj_desc->method.parser_op); + obj_desc->method.parser_op = NULL; + } + + break; + + default: + break; + } + + /* + * We ignore errors from above, and always return OK, since + * we don't want to abort the walk on a single error. + */ + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_initialize_objects + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Walk the entire namespace and perform any necessary initialization + * on the objects found therein + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_initialize_objects ( + ACPI_TABLE_DESC *table_desc, + ACPI_NAMED_OBJECT *start_entry) +{ + ACPI_STATUS status; + INIT_WALK_INFO info; + + + info.method_count = 0; + info.op_region_count = 0; + info.table_desc = table_desc; + + + /* Walk entire namespace from the supplied root */ + + status = acpi_walk_namespace (ACPI_TYPE_ANY, start_entry, + ACPI_INT32_MAX, acpi_ds_init_one_object, + &info, NULL); + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_init_object_from_op + * + * PARAMETERS: Op - Parser op used to init the internal object + * Opcode - AML opcode associated with the object + * Obj_desc - Namespace object to be initialized + * + * RETURN: Status + * + * DESCRIPTION: Initialize a namespace object from a parser Op and its + * associated arguments. The namespace object is a more compact + * representation of the Op and its arguments. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_init_object_from_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op, + u16 opcode, + ACPI_OBJECT_INTERNAL *obj_desc) +{ + ACPI_STATUS status; + ACPI_GENERIC_OP *arg; + ACPI_BYTELIST_OP *byte_list; + ACPI_OBJECT_INTERNAL *arg_desc; + ACPI_OP_INFO *op_info; + + + op_info = acpi_ps_get_opcode_info (opcode); + if (!op_info) { + /* Unknown opcode */ + + return AE_TYPE; + } + + + /* Get and prepare the first argument */ + + switch (obj_desc->common.type) + { + case ACPI_TYPE_BUFFER: + + /* First arg is a number */ + + acpi_ds_create_operand (walk_state, op->value.arg); + arg_desc = walk_state->operands [walk_state->num_operands - 1]; + acpi_ds_obj_stack_pop (1, walk_state); + + /* Resolve the object (could be an arg or local) */ + + status = acpi_aml_resolve_to_value (&arg_desc); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (arg_desc); + return status; + } + + /* We are expecting a number */ + + if (arg_desc->common.type != ACPI_TYPE_NUMBER) { + acpi_cm_remove_reference (arg_desc); + return AE_TYPE; + } + + /* Get the value, delete the internal object */ + + obj_desc->buffer.length = arg_desc->number.value; + acpi_cm_remove_reference (arg_desc); + + /* Allocate the buffer */ + + obj_desc->buffer.pointer = + acpi_cm_callocate (obj_desc->buffer.length); + + if (!obj_desc->buffer.pointer) { + return AE_NO_MEMORY; + } + + /* + * Second arg is the buffer data (optional) + * Byte_list can be either individual bytes or a + * string initializer! + */ + + /* skip first arg */ + arg = op->value.arg; + byte_list = (ACPI_BYTELIST_OP *) arg->next; + if (byte_list) { + if (byte_list->opcode != AML_BYTELIST_OP) { + return AE_TYPE; + } + + MEMCPY (obj_desc->buffer.pointer, byte_list->data, + obj_desc->buffer.length); + } + + break; + + + case ACPI_TYPE_NUMBER: + obj_desc->number.value = op->value.integer; + break; + + + case ACPI_TYPE_STRING: + obj_desc->string.pointer = op->value.string; + obj_desc->string.length = STRLEN (op->value.string); + break; + + + case ACPI_TYPE_METHOD: + break; + + + case INTERNAL_TYPE_REFERENCE: + + switch (op_info->flags & OP_INFO_TYPE) + { + case OPTYPE_LOCAL_VARIABLE: + + /* Split the opcode into a base opcode + offset */ + + obj_desc->reference.op_code = AML_LOCAL_OP; + obj_desc->reference.offset = opcode - AML_LOCAL_OP; + break; + + case OPTYPE_METHOD_ARGUMENT: + + /* Split the opcode into a base opcode + offset */ + + obj_desc->reference.op_code = AML_ARG_OP; + obj_desc->reference.offset = opcode - AML_ARG_OP; + break; + + default: /* Constants, Literals, etc.. */ + + if (op->opcode == AML_NAMEPATH_OP) { + /* Nte was saved in Op */ + + obj_desc->reference.nte = op->acpi_named_object; + } + + obj_desc->reference.op_code = opcode; + break; + } + + break; + + + default: + + break; + } + + return AE_OK; +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_build_internal_simple_obj + * + * PARAMETERS: Op - Parser object to be translated + * Obj_desc_ptr - Where the ACPI internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Translate a parser Op object to the equivalent namespace object + * Simple objects are any objects other than a package object! + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_build_internal_simple_obj ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op, + ACPI_OBJECT_INTERNAL **obj_desc_ptr) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + OBJECT_TYPE_INTERNAL type; + ACPI_STATUS status; + + + if (op->opcode == AML_NAMEPATH_OP) { + /* + * This is an object reference. If The name was + * previously looked up in the NS, it is stored in this op. + * Otherwise, go ahead and look it up now + */ + + if (!op->acpi_named_object) { + status = acpi_ns_lookup (walk_state->scope_info, + op->value.string, ACPI_TYPE_ANY, + IMODE_EXECUTE, + NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, + NULL, + (ACPI_NAMED_OBJECT**)&(op->acpi_named_object)); + + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* + * The reference will be a Reference + * TBD: [Restructure] unless we really need a separate + * type of INTERNAL_TYPE_REFERENCE change + * Acpi_ds_map_opcode_to_data_type to handle this case + */ + type = INTERNAL_TYPE_REFERENCE; + } + else { + type = acpi_ds_map_opcode_to_data_type (op->opcode, NULL); + } + + + /* Create and init the internal ACPI object */ + + obj_desc = acpi_cm_create_internal_object (type); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + status = acpi_ds_init_object_from_op (walk_state, op, + op->opcode, obj_desc); + + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (obj_desc); + return (status); + } + + *obj_desc_ptr = obj_desc; + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_build_internal_package_obj + * + * PARAMETERS: Op - Parser object to be translated + * Obj_desc_ptr - Where the ACPI internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Translate a parser Op package object to the equivalent + * namespace object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_build_internal_package_obj ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op, + ACPI_OBJECT_INTERNAL **obj_desc_ptr) +{ + ACPI_GENERIC_OP *arg; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_STATUS status = AE_OK; + + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* The first argument must be the package length */ + + arg = op->value.arg; + obj_desc->package.count = arg->value.integer; + + /* + * Allocate the array of pointers (ptrs to the + * individual objects) Add an extra pointer slot so + * that the list is always null terminated. + */ + + obj_desc->package.elements = + acpi_cm_callocate ((obj_desc->package.count + 1) * + sizeof (void *)); + + if (!obj_desc->package.elements) { + /* Package vector allocation failure */ + + REPORT_ERROR ("Ds_build_internal_package_obj: Package vector allocation failure"); + + acpi_cm_free (obj_desc); + return (AE_NO_MEMORY); + } + + obj_desc->package.next_element = obj_desc->package.elements; + + /* + * Now init the elements of the package + */ + + arg = arg->next; + while (arg) { + if (arg->opcode == AML_PACKAGE_OP) { + status = acpi_ds_build_internal_package_obj (walk_state, arg, + obj_desc->package.next_element); + } + + else { + status = acpi_ds_build_internal_simple_obj (walk_state, arg, + obj_desc->package.next_element); + } + + obj_desc->package.next_element++; + arg = arg->next; + } + + *obj_desc_ptr = obj_desc; + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_build_internal_object + * + * PARAMETERS: Op - Parser object to be translated + * Obj_desc_ptr - Where the ACPI internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Translate a parser Op object to the equivalent namespace + * object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_build_internal_object ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op, + ACPI_OBJECT_INTERNAL **obj_desc_ptr) +{ + ACPI_STATUS status; + + + if (op->opcode == AML_PACKAGE_OP) { + status = acpi_ds_build_internal_package_obj (walk_state, op, + obj_desc_ptr); + } + + else { + status = acpi_ds_build_internal_simple_obj (walk_state, op, + obj_desc_ptr); + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_create_named_object + * + * PARAMETERS: Op - Parser object to be translated + * Obj_desc_ptr - Where the ACPI internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_create_named_object ( + ACPI_WALK_STATE *walk_state, + ACPI_NAMED_OBJECT *entry, + ACPI_GENERIC_OP *op) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL *obj_desc; + + + if (!op->value.arg) { + /* No arguments, there is nothing to do */ + + return (AE_OK); + } + + + /* Build an internal object for the argument(s) */ + + status = acpi_ds_build_internal_object (walk_state, + op->value.arg, &obj_desc); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* Re-type the object according to it's argument */ + + entry->type = obj_desc->common.type; + + /* Init obj */ + + status = acpi_ns_attach_object ((ACPI_HANDLE) entry, obj_desc, + (u8) entry->type); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + return (status); + + +cleanup: + + acpi_cm_remove_reference (obj_desc); + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/dispatcher/dsopcode.c linux/drivers/acpi/dispatcher/dsopcode.c --- v2.4.0-test2/linux/drivers/acpi/dispatcher/dsopcode.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/dispatcher/dsopcode.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,464 @@ + +/****************************************************************************** + * + * Module Name: dsopcode - Dispatcher Op Region support + * and handling of "control" opcodes + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "amlcode.h" +#include "dispatch.h" +#include "interp.h" +#include "namesp.h" +#include "events.h" +#include "tables.h" + +#define _COMPONENT DISPATCHER + MODULE_NAME ("dsopcode"); + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_get_region_arguments + * + * PARAMETERS: Rgn_desc - A valid region object + * + * RETURN: Status. + * + * DESCRIPTION: Get region address and length. This implements the late + * evaluation of these region attributes. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_get_region_arguments ( + ACPI_OBJECT_INTERNAL *rgn_desc) +{ + ACPI_OBJECT_INTERNAL *method_desc; + ACPI_NAMED_OBJECT *entry; + ACPI_GENERIC_OP *op; + ACPI_GENERIC_OP *region_op; + ACPI_STATUS status; + ACPI_TABLE_DESC *table_desc; + + + if (rgn_desc->region.region_flags & REGION_AGRUMENT_DATA_VALID) { + return (AE_OK); + } + + + method_desc = rgn_desc->region.method; + entry = rgn_desc->region.nte; + + + /* + * Allocate a new parser op to be the root of the parsed + * Op_region tree + */ + + op = acpi_ps_alloc_op (AML_REGION_OP); + if (!op) { + return AE_NO_MEMORY; + } + + /* Save the NTE for use in Acpi_ps_parse_aml */ + + op->acpi_named_object = acpi_ns_get_parent_entry (entry); + + /* Get a handle to the parent ACPI table */ + + status = acpi_tb_handle_to_object (entry->owner_id, &table_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Parse the entire Op_region declaration, creating a parse tree */ + + status = acpi_ps_parse_aml (op, method_desc->method.pcode, + method_desc->method.pcode_length, 0); + if (ACPI_SUCCESS (status)) { + /* Get and init the actual Region_op created above */ + + region_op = op->value.arg; + region_op->acpi_named_object = entry; + + /* Acpi_evaluate the address and length arguments for the Op_region */ + + acpi_ps_walk_parsed_aml (region_op, region_op, NULL, NULL, NULL, + NULL, table_desc->table_id, + acpi_ds_exec_begin_op, acpi_ds_exec_end_op); + } + + /* All done with the parse tree, delete it */ + + acpi_ps_delete_parse_tree (op); + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_initialize_region + * + * PARAMETERS: Op - A valid region Op object + * + * RETURN: Status + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_initialize_region ( + ACPI_HANDLE obj_handle) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_STATUS status; + + + obj_desc = acpi_ns_get_attached_object (obj_handle); + + /* Namespace is NOT locked */ + + status = acpi_ev_initialize_region (obj_desc, FALSE); + + return status; +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_eval_region_operands + * + * PARAMETERS: Op - A valid region Op object + * + * RETURN: Status + * + * DESCRIPTION: Get region address and length + * Called from Acpi_ds_exec_end_op during Op_region parse tree walk + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_eval_region_operands ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_OBJECT_INTERNAL *region_desc; + ACPI_NAMED_OBJECT *entry; + ACPI_GENERIC_OP *next_op; + + + /* + * This is where we evaluate the address and length fields of the Op_region declaration + */ + + entry = op->acpi_named_object; + + /* Next_op points to the op that holds the Space_iD */ + next_op = op->value.arg; + + /* Next_op points to address op */ + next_op = next_op->next; + + /* Acpi_evaluate/create the address and length operands */ + + status = acpi_ds_create_operands (walk_state, next_op); + if (ACPI_FAILURE (status)) { + return (status); + } + + region_desc = acpi_ns_get_attached_object (entry); + if (!region_desc) { + return (AE_NOT_EXIST); + } + + /* Get the length and save it */ + + /* Top of stack */ + obj_desc = walk_state->operands[walk_state->num_operands - 1]; + + region_desc->region.length = obj_desc->number.value; + acpi_cm_remove_reference (obj_desc); + + /* Get the address and save it */ + + /* Top of stack - 1 */ + obj_desc = walk_state->operands[walk_state->num_operands - 2]; + + region_desc->region.address = obj_desc->number.value; + acpi_cm_remove_reference (obj_desc); + + + /* Now the address and length are valid for this opregion */ + + region_desc->region.region_flags |= REGION_AGRUMENT_DATA_VALID; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_exec_begin_control_op + * + * PARAMETERS: Walk_list - The list that owns the walk stack + * Op - The control Op + * + * RETURN: Status + * + * DESCRIPTION: Handles all control ops encountered during control method + * execution. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_exec_begin_control_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op) +{ + ACPI_STATUS status = AE_OK; + ACPI_GENERIC_STATE *control_state; + + + switch (op->opcode) + { + case AML_IF_OP: + case AML_WHILE_OP: + + /* + * IF/WHILE: Create a new control state to manage these + * constructs. We need to manage these as a stack, in order + * to handle nesting. + */ + + control_state = acpi_cm_create_control_state (); + if (!control_state) { + status = AE_NO_MEMORY; + break; + } + + acpi_cm_push_generic_state (&walk_state->control_state, control_state); + break; + + + case AML_ELSE_OP: + + /* Predicate is in the state object */ + /* If predicate is true, the IF was executed, ignore ELSE part */ + + if (walk_state->last_predicate) { + status = AE_CTRL_TRUE; + } + + break; + + + case AML_RETURN_OP: + + break; + + + default: + break; + } + + return status; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_exec_end_control_op + * + * PARAMETERS: Walk_list - The list that owns the walk stack + * Op - The control Op + * + * RETURN: Status + * + * DESCRIPTION: Handles all control ops encountered during control method + * execution. + * + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_exec_end_control_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op) +{ + ACPI_STATUS status = AE_OK; + ACPI_GENERIC_STATE *control_state; + + + switch (op->opcode) + { + case AML_IF_OP: + + /* + * Save the result of the predicate in case there is an + * ELSE to come + */ + + walk_state->last_predicate = + (u8) walk_state->control_state->common.value; + + /* + * Pop the control state that was created at the start + * of the IF and free it + */ + + control_state = + acpi_cm_pop_generic_state (&walk_state->control_state); + + acpi_cm_delete_generic_state (control_state); + + break; + + + case AML_ELSE_OP: + + break; + + + case AML_WHILE_OP: + + if (walk_state->control_state->common.value) { + /* Predicate was true, go back and evaluate it again! */ + + status = AE_CTRL_TRUE; + } + + else { + /* Pop this control state and free it */ + + control_state = + acpi_cm_pop_generic_state (&walk_state->control_state); + acpi_cm_delete_generic_state (control_state); + } + + break; + + + case AML_RETURN_OP: + + + /* One optional operand -- the return value */ + + if (op->value.arg) { + status = acpi_ds_create_operands (walk_state, op->value.arg); + if (ACPI_FAILURE (status)) { + return status; + } + + /* + * TBD: [Restructure] Just check for NULL arg + * to signify no return value??? + */ + + /* + * If value being returned is a Reference (such as + * an arg or local), resolve it now because it may + * cease to exist at the end of the method. + */ + + status = acpi_aml_resolve_to_value (&walk_state->operands [0]); + if (ACPI_FAILURE (status)) { + return status; + } + + /* + * Get the return value and save as the last result + * value + * This is the only place where Walk_state->Return_desc + * is set to anything other than zero! + */ + + walk_state->return_desc = walk_state->operands[0]; + } + + else { + /* No return operand */ + + acpi_cm_remove_reference (walk_state->operands [0]); + + walk_state->operands [0] = NULL; + walk_state->num_operands = 0; + walk_state->return_desc = NULL; + } + + + /* End the control method execution right now */ + status = AE_CTRL_TERMINATE; + break; + + + case AML_NOOP_CODE: + + /* Just do nothing! */ + break; + + + case AML_BREAK_POINT_OP: + + /* Call up to the OS dependent layer to handle this */ + + acpi_os_breakpoint (NULL); + + /* If it returns, we are done! */ + + break; + + + case AML_BREAK_OP: + + /* + * As per the ACPI specification: + * "The break operation causes the current package + * execution to complete" + * "Break -- Stop executing the current code package + * at this point" + * + * Returning AE_FALSE here will cause termination of + * the current package, and execution will continue one + * level up, starting with the completion of the parent Op. + */ + + status = AE_CTRL_FALSE; + break; + + + default: + + status = AE_AML_BAD_OPCODE; + break; + } + + + return status; +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/dispatcher/dsutils.c linux/drivers/acpi/dispatcher/dsutils.c --- v2.4.0-test2/linux/drivers/acpi/dispatcher/dsutils.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/dispatcher/dsutils.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,694 @@ + +/****************************************************************************** + * + * Module Name: dsutils - Dispatcher utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "amlcode.h" +#include "dispatch.h" +#include "interp.h" +#include "namesp.h" +#include "debugger.h" + +#define _COMPONENT PARSER + MODULE_NAME ("dsutils"); + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_delete_result_if_not_used + * + * PARAMETERS: Op + * Result_obj + * Walk_state + * + * RETURN: Status + * + * DESCRIPTION: Used after interpretation of an opcode. If there is an internal + * result descriptor, check if the parent opcode will actually use + * this result. If not, delete the result now so that it will + * not become orphaned. + * + ****************************************************************************/ + +void +acpi_ds_delete_result_if_not_used ( + ACPI_GENERIC_OP *op, + ACPI_OBJECT_INTERNAL *result_obj, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OP_INFO *parent_info; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_STATUS status; + + + if (!op) { + return; + } + + if (!result_obj) { + return; + } + + if (!op->parent) { + /* + * If there is no parent, the result can't possibly be used! + * (An executing method typically has no parent, since each + * method is parsed separately + */ + + /* + * Must pop the result stack (Obj_desc should be equal + * to Result_obj) + */ + + status = acpi_ds_result_stack_pop (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + return; + } + + acpi_cm_remove_reference (result_obj); + + return; + } + + + /* + * Get info on the parent. The root Op is AML_SCOPE + */ + + parent_info = acpi_ps_get_opcode_info (op->parent->opcode); + if (!parent_info) { + return; + } + + + /* Never delete the return value associated with a return opcode */ + + if (op->parent->opcode == AML_RETURN_OP) { + return; + } + + + /* + * Decide what to do with the result based on the parent. If + * the parent opcode will not use the result, delete the object. + * Otherwise leave it as is, it will be deleted when it is used + * as an operand later. + */ + + switch (parent_info->flags & OP_INFO_TYPE) + { + /* + * In these cases, the parent will never use the return object, + * so delete it here and now. + */ + case OPTYPE_CONTROL: /* IF, ELSE, WHILE only */ + case OPTYPE_NAMED_OBJECT: /* Scope, method, etc. */ + + /* + * Must pop the result stack (Obj_desc should be equal + * to Result_obj) + */ + + status = acpi_ds_result_stack_pop (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + return; + } + + acpi_cm_remove_reference (result_obj); + break; + + /* + * In all other cases. the parent will actually use the return + * object, so keep it. + */ + default: + break; + } + + return; +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_create_operand + * + * PARAMETERS: Walk_state + * Arg + * + * RETURN: Status + * + * DESCRIPTION: Translate a parse tree object that is an argument to an AML + * opcode to the equivalent interpreter object. This may include + * looking up a name or entering a new name into the internal + * namespace. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_create_operand ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *arg) +{ + ACPI_STATUS status = AE_OK; + char *name_string; + u32 name_length; + OBJECT_TYPE_INTERNAL data_type; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_GENERIC_OP *parent_op; + u16 opcode; + u32 flags; + OPERATING_MODE interpreter_mode; + + + /* A valid name must be looked up in the namespace */ + + if ((arg->opcode == AML_NAMEPATH_OP) && + (arg->value.string)) + { + /* Get the entire name string from the AML stream */ + + status = acpi_aml_get_name_string (ACPI_TYPE_ANY, + arg->value.buffer, + &name_string, + &name_length); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * All prefixes have been handled, and the name is + * in Name_string + */ + + /* + * Differentiate between a namespace "create" operation + * versus a "lookup" operation (IMODE_LOAD_PASS2 vs. + * IMODE_EXECUTE) in order to support the creation of + * namespace objects during the execution of control methods. + */ + + parent_op = arg->parent; + if ((acpi_ps_is_named_object_op (parent_op->opcode)) && + (parent_op->opcode != AML_METHODCALL_OP) && + (parent_op->opcode != AML_NAMEPATH_OP)) + { + /* Enter name into namespace if not found */ + + interpreter_mode = IMODE_LOAD_PASS2; + } + + else { + /* Return a failure if name not found */ + + interpreter_mode = IMODE_EXECUTE; + } + + status = acpi_ns_lookup (walk_state->scope_info, name_string, + ACPI_TYPE_ANY, interpreter_mode, + NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, + walk_state, + (ACPI_NAMED_OBJECT**) &obj_desc); + + /* Free the namestring created above */ + + acpi_cm_free (name_string); + + /* + * The only case where we pass through (ignore) a NOT_FOUND + * error is for the Cond_ref_of opcode. + */ + + if (status == AE_NOT_FOUND) { + if (parent_op->opcode == AML_COND_REF_OF_OP) { + /* + * For the Conditional Reference op, it's OK if + * the name is not found; We just need a way to + * indicate this to the interpreter, set the + * object to the root + */ + obj_desc = (ACPI_OBJECT_INTERNAL *) acpi_gbl_root_object; + status = AE_OK; + } + + else { + /* + * We just plain didn't find it -- which is a + * very serious error at this point + */ + status = AE_AML_NAME_NOT_FOUND; + } + } + + /* Check status from the lookup */ + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Put the resulting object onto the current object stack */ + + status = acpi_ds_obj_stack_push (obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + + else { + /* Check for null name case */ + + if (arg->opcode == AML_NAMEPATH_OP) { + /* + * If the name is null, this means that this is an + * optional result parameter that was not specified + * in the original ASL. Create an Reference for a + * placeholder + */ + opcode = AML_ZERO_OP; /* Has no arguments! */ + + /* + * TBD: [Investigate] anything else needed for the + * zero op lvalue? + */ + } + + else { + opcode = arg->opcode; + } + + + /* Get the data type of the argument */ + + data_type = acpi_ds_map_opcode_to_data_type (opcode, &flags); + if (data_type == INTERNAL_TYPE_INVALID) { + return (AE_NOT_IMPLEMENTED); + } + + if (flags & OP_HAS_RETURN_VALUE) { + /* + * Use value that was already previously returned + * by the evaluation of this argument + */ + + status = acpi_ds_result_stack_pop (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* + * Only error is underflow, and this indicates + * a missing or null operand! + */ + return (status); + } + + } + + else { + /* Create an ACPI_INTERNAL_OBJECT for the argument */ + + obj_desc = acpi_cm_create_internal_object (data_type); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Initialize the new object */ + + status = acpi_ds_init_object_from_op (walk_state, arg, + opcode, obj_desc); + if (ACPI_FAILURE (status)) { + acpi_cm_free (obj_desc); + return (status); + } + } + + /* Put the operand object on the object stack */ + + status = acpi_ds_obj_stack_push (obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + } + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_create_operands + * + * PARAMETERS: First_arg - First argument of a parser argument tree + * + * RETURN: Status + * + * DESCRIPTION: Convert an operator's arguments from a parse tree format to + * namespace objects and place those argument object on the object + * stack in preparation for evaluation by the interpreter. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_create_operands ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *first_arg) +{ + ACPI_STATUS status = AE_OK; + ACPI_GENERIC_OP *arg; + u32 args_pushed = 0; + + + arg = first_arg; + + + /* For all arguments in the list... */ + + while (arg) { + + status = acpi_ds_create_operand (walk_state, arg); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* Move on to next argument, if any */ + + arg = arg->next; + args_pushed++; + } + + return (status); + + +cleanup: + /* + * We must undo everything done above; meaning that we must + * pop everything off of the operand stack and delete those + * objects + */ + + acpi_ds_obj_stack_pop_and_delete (args_pushed, walk_state); + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_resolve_operands + * + * PARAMETERS: Walk_state - Current walk state with operands on stack + * + * RETURN: Status + * + * DESCRIPTION: Resolve all operands to their values. Used to prepare + * arguments to a control method invocation (a call from one + * method to another.) + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_resolve_operands ( + ACPI_WALK_STATE *walk_state) +{ + u32 i; + ACPI_STATUS status = AE_OK; + + + /* + * Attempt to resolve each of the valid operands + * Method arguments are passed by value, not by reference + */ + + /* + * TBD: [Investigate] Note from previous parser: + * Ref_of problem with Acpi_aml_resolve_to_value() conversion. + */ + + for (i = 0; i < walk_state->num_operands; i++) { + status = acpi_aml_resolve_to_value (&walk_state->operands[i]); + if (ACPI_FAILURE (status)) { + break; + } + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_map_opcode_to_data_type + * + * PARAMETERS: Opcode - AML opcode to map + * Out_flags - Additional info about the opcode + * + * RETURN: The ACPI type associated with the opcode + * + * DESCRIPTION: Convert a raw AML opcode to the associated ACPI data type, + * if any. If the opcode returns a value as part of the + * intepreter execution, a flag is returned in Out_flags. + * + ****************************************************************************/ + +OBJECT_TYPE_INTERNAL +acpi_ds_map_opcode_to_data_type ( + u16 opcode, + u32 *out_flags) +{ + OBJECT_TYPE_INTERNAL data_type = INTERNAL_TYPE_INVALID; + ACPI_OP_INFO *op_info; + u32 flags = 0; + + + op_info = acpi_ps_get_opcode_info (opcode); + if (!op_info) { + /* Unknown opcode */ + + return data_type; + } + + switch (op_info->flags & OP_INFO_TYPE) + { + + case OPTYPE_LITERAL: + + switch (opcode) + { + case AML_BYTE_OP: + case AML_WORD_OP: + case AML_DWORD_OP: + + data_type = ACPI_TYPE_NUMBER; + break; + + + case AML_STRING_OP: + + data_type = ACPI_TYPE_STRING; + break; + + case AML_NAMEPATH_OP: + data_type = INTERNAL_TYPE_REFERENCE; + break; + } + + break; + + + case OPTYPE_DATA_TERM: + + switch (opcode) + { + case AML_BUFFER_OP: + + data_type = ACPI_TYPE_BUFFER; + break; + + case AML_PACKAGE_OP: + + data_type = ACPI_TYPE_PACKAGE; + break; + } + + break; + + + case OPTYPE_CONSTANT: + case OPTYPE_METHOD_ARGUMENT: + case OPTYPE_LOCAL_VARIABLE: + + data_type = INTERNAL_TYPE_REFERENCE; + break; + + + case OPTYPE_MONADIC2: + case OPTYPE_MONADIC2_r: + case OPTYPE_DYADIC2: + case OPTYPE_DYADIC2_r: + case OPTYPE_DYADIC2_s: + case OPTYPE_INDEX: + case OPTYPE_MATCH: + + flags = OP_HAS_RETURN_VALUE; + data_type = ACPI_TYPE_ANY; + + break; + + case OPTYPE_METHOD_CALL: + + flags = OP_HAS_RETURN_VALUE; + data_type = ACPI_TYPE_METHOD; + + break; + + + case OPTYPE_NAMED_OBJECT: + + data_type = acpi_ds_map_named_opcode_to_data_type (opcode); + + break; + + + case OPTYPE_DYADIC1: + case OPTYPE_CONTROL: + + /* No mapping needed at this time */ + + break; + + + default: + + break; + } + + /* Return flags to caller if requested */ + + if (out_flags) { + *out_flags = flags; + } + + return data_type; +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_map_named_opcode_to_data_type + * + * PARAMETERS: Opcode - The Named AML opcode to map + * + * RETURN: The ACPI type associated with the named opcode + * + * DESCRIPTION: Convert a raw Named AML opcode to the associated data type. + * Named opcodes are a subsystem of the AML opcodes. + * + ****************************************************************************/ + +OBJECT_TYPE_INTERNAL +acpi_ds_map_named_opcode_to_data_type ( + u16 opcode) +{ + OBJECT_TYPE_INTERNAL data_type; + + + /* Decode Opcode */ + + switch (opcode) + { + case AML_SCOPE_OP: + data_type = INTERNAL_TYPE_SCOPE; + break; + + case AML_DEVICE_OP: + data_type = ACPI_TYPE_DEVICE; + break; + + case AML_THERMAL_ZONE_OP: + data_type = ACPI_TYPE_THERMAL; + break; + + case AML_METHOD_OP: + data_type = ACPI_TYPE_METHOD; + break; + + case AML_POWER_RES_OP: + data_type = ACPI_TYPE_POWER; + break; + + case AML_PROCESSOR_OP: + data_type = ACPI_TYPE_PROCESSOR; + break; + + case AML_DEF_FIELD_OP: /* Def_field_op */ + data_type = INTERNAL_TYPE_DEF_FIELD_DEFN; + break; + + case AML_INDEX_FIELD_OP: /* Index_field_op */ + data_type = INTERNAL_TYPE_INDEX_FIELD_DEFN; + break; + + case AML_BANK_FIELD_OP: /* Bank_field_op */ + data_type = INTERNAL_TYPE_BANK_FIELD_DEFN; + break; + + case AML_NAMEDFIELD_OP: /* NO CASE IN ORIGINAL */ + data_type = ACPI_TYPE_ANY; + break; + + case AML_NAME_OP: /* Name_op - special code in original */ + case AML_NAMEPATH_OP: + data_type = ACPI_TYPE_ANY; + break; + + case AML_ALIAS_OP: + data_type = INTERNAL_TYPE_ALIAS; + break; + + case AML_MUTEX_OP: + data_type = ACPI_TYPE_MUTEX; + break; + + case AML_EVENT_OP: + data_type = ACPI_TYPE_EVENT; + break; + + case AML_REGION_OP: + data_type = ACPI_TYPE_REGION; + break; + + + default: + data_type = ACPI_TYPE_ANY; + break; + + } + + return data_type; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/dispatcher/dswexec.c linux/drivers/acpi/dispatcher/dswexec.c --- v2.4.0-test2/linux/drivers/acpi/dispatcher/dswexec.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/dispatcher/dswexec.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,572 @@ +/****************************************************************************** + * + * Module Name: dswexec - Dispatcher method execution callbacks; + * Dispatch to interpreter. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "amlcode.h" +#include "dispatch.h" +#include "interp.h" +#include "namesp.h" +#include "debugger.h" + + +#define _COMPONENT DISPATCHER + MODULE_NAME ("dswexec"); + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_exec_begin_op + * + * PARAMETERS: Walk_state - Current state of the parse tree walk + * Op - Op that has been just been reached in the + * walk; Arguments have not been evaluated yet. + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the execution of control + * methods. This is where most operators and operands are + * dispatched to the interpreter. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_exec_begin_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op) +{ + ACPI_OP_INFO *op_info; + ACPI_STATUS status = AE_OK; + + + if (op == walk_state->origin) { + return (AE_OK); + } + + /* + * If the previous opcode was a conditional, this opcode + * must be the beginning of the associated predicate. + * Save this knowledge in the current scope descriptor + */ + + if ((walk_state->control_state) && + (walk_state->control_state->common.state == + CONTROL_CONDITIONAL_EXECUTING)) + { + walk_state->control_state->common.state = CONTROL_PREDICATE_EXECUTING; + + /* Save start of predicate */ + + walk_state->control_state->control.predicate_op = op; + } + + + op_info = acpi_ps_get_opcode_info (op->opcode); + + /* We want to send namepaths to the load code */ + + if (op->opcode == AML_NAMEPATH_OP) { + op_info->flags = OPTYPE_NAMED_OBJECT; + } + + + /* + * Handle the opcode based upon the opcode type + */ + + switch (op_info->flags & OP_INFO_TYPE) + { + case OPTYPE_CONTROL: + + status = acpi_ds_exec_begin_control_op (walk_state, op); + break; + + + case OPTYPE_NAMED_OBJECT: + + if (walk_state->origin->opcode == AML_METHOD_OP) { + /* + * Found a named object declaration during method + * execution; we must enter this object into the + * namespace. The created object is temporary and + * will be deleted upon completion of the execution + * of this method. + */ + + status = acpi_ds_load2_begin_op (walk_state, op); + } + break; + + + default: + break; + } + + /* Nothing to do here during method execution */ + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_exec_end_op + * + * PARAMETERS: Walk_state - Current state of the parse tree walk + * Op - Op that has been just been completed in the + * walk; Arguments have now been evaluated. + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during the execution of control + * methods. The only thing we really need to do here is to + * notice the beginning of IF, ELSE, and WHILE blocks. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_exec_end_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op) +{ + ACPI_STATUS status = AE_OK; + u16 opcode; + u8 optype; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_GENERIC_OP *next_op; + ACPI_NAMED_OBJECT *entry; + ACPI_GENERIC_OP *first_arg; + ACPI_OBJECT_INTERNAL *result_obj = NULL; + ACPI_OP_INFO *op_info; + u32 operand_index; + + + opcode = (u16) op->opcode; + + + op_info = acpi_ps_get_opcode_info (op->opcode); + if (!op_info) { + return (AE_NOT_IMPLEMENTED); + } + + optype = (u8) (op_info->flags & OP_INFO_TYPE); + first_arg = op->value.arg; + + /* Init the walk state */ + + walk_state->num_operands = 0; + walk_state->return_desc = NULL; + + + /* Call debugger for single step support (DEBUG build only) */ + + + /* Decode the opcode */ + + switch (optype) + { + case OPTYPE_UNDEFINED: + + return (AE_NOT_IMPLEMENTED); + break; + + + case OPTYPE_BOGUS: + break; + + case OPTYPE_CONSTANT: /* argument type only */ + case OPTYPE_LITERAL: /* argument type only */ + case OPTYPE_DATA_TERM: /* argument type only */ + case OPTYPE_LOCAL_VARIABLE: /* argument type only */ + case OPTYPE_METHOD_ARGUMENT: /* argument type only */ + break; + + + /* most operators with arguments */ + + case OPTYPE_MONADIC1: + case OPTYPE_DYADIC1: + case OPTYPE_MONADIC2: + case OPTYPE_MONADIC2_r: + case OPTYPE_DYADIC2: + case OPTYPE_DYADIC2_r: + case OPTYPE_DYADIC2_s: + case OPTYPE_RECONFIGURATION: + case OPTYPE_INDEX: + case OPTYPE_MATCH: + case OPTYPE_CREATE_FIELD: + case OPTYPE_FATAL: + + status = acpi_ds_create_operands (walk_state, first_arg); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + operand_index = walk_state->num_operands - 1; + + switch (optype) + { + + case OPTYPE_MONADIC1: + + /* 1 Operand, 0 External_result, 0 Internal_result */ + + status = acpi_aml_exec_monadic1 (opcode, walk_state); + break; + + + case OPTYPE_MONADIC2: + + /* 1 Operand, 0 External_result, 1 Internal_result */ + + status = acpi_aml_exec_monadic2 (opcode, walk_state, &result_obj); + if (ACPI_SUCCESS (status)) { + status = acpi_ds_result_stack_push (result_obj, walk_state); + } + + break; + + + case OPTYPE_MONADIC2_r: + + /* 1 Operand, 1 External_result, 1 Internal_result */ + + status = acpi_aml_exec_monadic2_r (opcode, walk_state, &result_obj); + if (ACPI_SUCCESS (status)) { + status = acpi_ds_result_stack_push (result_obj, walk_state); + } + + break; + + + case OPTYPE_DYADIC1: + + /* 2 Operands, 0 External_result, 0 Internal_result */ + + status = acpi_aml_exec_dyadic1 (opcode, walk_state); + + break; + + + case OPTYPE_DYADIC2: + + /* 2 Operands, 0 External_result, 1 Internal_result */ + + status = acpi_aml_exec_dyadic2 (opcode, walk_state, &result_obj); + if (ACPI_SUCCESS (status)) { + status = acpi_ds_result_stack_push (result_obj, walk_state); + } + + break; + + + case OPTYPE_DYADIC2_r: + + /* 2 Operands, 1 or 2 External_results, 1 Internal_result */ + + + /* NEW INTERFACE: + * Pass in Walk_state, keep result obj but let interpreter + * push the result + */ + + status = acpi_aml_exec_dyadic2_r (opcode, walk_state, &result_obj); + if (ACPI_SUCCESS (status)) { + status = acpi_ds_result_stack_push (result_obj, walk_state); + } + + break; + + + case OPTYPE_DYADIC2_s: /* Synchronization Operator */ + + /* 2 Operands, 0 External_result, 1 Internal_result */ + + status = acpi_aml_exec_dyadic2_s (opcode, walk_state, &result_obj); + if (ACPI_SUCCESS (status)) { + status = acpi_ds_result_stack_push (result_obj, walk_state); + } + + break; + + + case OPTYPE_RECONFIGURATION: + + /* 1 or 2 operands, 0 Internal Result */ + + status = acpi_aml_exec_reconfiguration (opcode, walk_state); + break; + + + case OPTYPE_CREATE_FIELD: + + /* 3 or 4 Operands, 0 External_result, 0 Internal_result */ + + status = acpi_aml_exec_create_field (opcode, walk_state); + break; + + + case OPTYPE_FATAL: + + /* 3 Operands, 0 External_result, 0 Internal_result */ + + status = acpi_aml_exec_fatal (walk_state); + break; + + + case OPTYPE_INDEX: /* Type 2 opcode with 3 operands */ + + /* 3 Operands, 1 External_result, 1 Internal_result */ + + status = acpi_aml_exec_index (walk_state, &result_obj); + if (ACPI_SUCCESS (status)) { + status = acpi_ds_result_stack_push (result_obj, walk_state); + } + + break; + + + case OPTYPE_MATCH: /* Type 2 opcode with 6 operands */ + + /* 6 Operands, 0 External_result, 1 Internal_result */ + + status = acpi_aml_exec_match (walk_state, &result_obj); + if (ACPI_SUCCESS (status)) { + status = acpi_ds_result_stack_push (result_obj, walk_state); + } + + break; + } + + break; + + + case OPTYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */ + + /* 1 Operand, 0 External_result, 0 Internal_result */ + + status = acpi_ds_exec_end_control_op (walk_state, op); + + break; + + + case OPTYPE_METHOD_CALL: + + /* + * (AML_METHODCALL) Op->Value->Arg->Acpi_named_object contains + * the method NTE pointer + */ + /* Next_op points to the op that holds the method name */ + next_op = first_arg; + entry = next_op->acpi_named_object; + + /* Next_op points to first argument op */ + next_op = next_op->next; + + + /* + * Get the method's arguments and put them on the operand stack + */ + + status = acpi_ds_create_operands (walk_state, next_op); + if (ACPI_FAILURE (status)) { + break; + } + + /* + * Since the operands will be passed to another + * control method, we must resolve all local + * references here (Local variables, arguments + * to *this* method, etc.) + */ + + status = acpi_ds_resolve_operands (walk_state); + if (ACPI_FAILURE (status)) { + break; + } + + /* Open new scope on the scope stack */ +/* + Status = Acpi_ns_scope_stack_push_entry (Entry); + if (ACPI_FAILURE (Status)) { + break; + } +*/ + + /* Tell the walk loop to preempt this running method and + execute the new method */ + + status = AE_CTRL_PENDING; + + /* Return now; we don't want to disturb anything, + especially the operand count! */ + + return (status); + break; + + + case OPTYPE_NAMED_OBJECT: + + + if ((walk_state->origin->opcode == AML_METHOD_OP) && + (walk_state->origin != op)) + { + status = acpi_ds_load2_end_op (walk_state, op); + if (ACPI_FAILURE (status)) { + break; + } + } + + switch (op->opcode) + { + case AML_REGION_OP: + + status = acpi_ds_eval_region_operands (walk_state, op); + + break; + + + case AML_METHOD_OP: + + break; + + + case AML_ALIAS_OP: + + /* Alias creation was already handled by call + to psxload above */ + break; + + + default: + /* Nothing needs to be done */ + + status = AE_OK; + break; + } + + break; + + default: + + status = AE_NOT_IMPLEMENTED; + break; + } + + + /* + * Check if we just completed the evaluation of a + * conditional predicate + */ + + if ((walk_state->control_state) && + (walk_state->control_state->common.state == + CONTROL_PREDICATE_EXECUTING) && + (walk_state->control_state->control.predicate_op == op)) + { + /* Completed the predicate, the result must be a number */ + + walk_state->control_state->common.state = 0; + + if (result_obj) { + status = acpi_ds_result_stack_pop (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + } + + else { + status = acpi_ds_create_operand (walk_state, op); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + status = acpi_aml_resolve_to_value (&walk_state->operands [0]); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + obj_desc = walk_state->operands [0]; + } + + if (!obj_desc) { + status = AE_AML_NO_OPERAND; + goto cleanup; + } + + if (obj_desc->common.type != ACPI_TYPE_NUMBER) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + /* Save the result of the predicate evaluation on + the control stack */ + + if (obj_desc->number.value) { + walk_state->control_state->common.value = TRUE; + } + else { + /* Predicate is FALSE, we will just toss the + rest of the package */ + + walk_state->control_state->common.value = FALSE; + status = AE_CTRL_FALSE; + } + + /* Break to debugger to display result */ + + /* Delete the predicate result object (we know that + we don't need it anymore) and cleanup the stack */ + + acpi_cm_remove_reference (obj_desc); + result_obj = NULL; + + walk_state->control_state->common.state = CONTROL_NORMAL; + } + + +cleanup: + + if (result_obj) { + /* Break to debugger to display result */ + + /* + * Delete the result op if and only if: + * Parent will not use the result -- such as any + * non-nested type2 op in a method (parent will be method) + */ + acpi_ds_delete_result_if_not_used (op, result_obj, walk_state); + } + + /* Always clear the object stack */ + + /* TBD: [Investigate] Clear stack of return value, + but don't delete it */ + walk_state->num_operands = 0; + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/dispatcher/dswload.c linux/drivers/acpi/dispatcher/dswload.c --- v2.4.0-test2/linux/drivers/acpi/dispatcher/dswload.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/dispatcher/dswload.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,600 @@ + +/****************************************************************************** + * + * Module Name: dswload - Dispatcher namespace load callbacks + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "amlcode.h" +#include "dispatch.h" +#include "interp.h" +#include "namesp.h" +#include "events.h" + + +#define _COMPONENT DISPATCHER + MODULE_NAME ("dswload"); + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_load1_begin_op + * + * PARAMETERS: Walk_state - Current state of the parse tree walk + * Op - Op that has been just been reached in the + * walk; Arguments have not been evaluated yet. + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the loading of ACPI tables. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_load1_begin_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op) +{ + ACPI_NAMED_OBJECT *new_entry; + ACPI_STATUS status; + OBJECT_TYPE_INTERNAL data_type; + + + /* We are only interested in opcodes that have an associated name */ + + if (!acpi_ps_is_named_op (op->opcode)) { + return AE_OK; + } + + + /* Check if this object has already been installed in the namespace */ + + if (op->acpi_named_object) { + return AE_OK; + } + + /* Map the raw opcode into an internal object type */ + + data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode); + + /* Attempt to type a NAME opcode by examining the argument */ + + /* TBD: [Investigate] is this the right place to do this? */ + + if (op->opcode == AML_NAME_OP) { + if (op->value.arg) { + + data_type = acpi_ds_map_opcode_to_data_type ((op->value.arg)->opcode, + NULL); + } + } + + + /* + * Enter the named type into the internal namespace. We enter the name + * as we go downward in the parse tree. Any necessary subobjects that involve + * arguments to the opcode must be created as we go back up the parse tree later. + */ + status = acpi_ns_lookup (walk_state->scope_info, + (char *) &((ACPI_NAMED_OP *)op)->name, + data_type, IMODE_LOAD_PASS1, + NS_NO_UPSEARCH, walk_state, &(new_entry)); + + if (ACPI_SUCCESS (status)) { + /* + * Put the NTE in the "op" object that the parser uses, so we + * can get it again quickly when this scope is closed + */ + op->acpi_named_object = new_entry; + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_load1_end_op + * + * PARAMETERS: Walk_state - Current state of the parse tree walk + * Op - Op that has been just been completed in the + * walk; Arguments have now been evaluated. + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during the loading of the namespace, + * both control methods and everything else. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_load1_end_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op) +{ + OBJECT_TYPE_INTERNAL data_type; + + + /* We are only interested in opcodes that have an associated name */ + + if (!acpi_ps_is_named_op (op->opcode)) { + return AE_OK; + } + + /* TBD: [Investigate] can this be removed? */ + + if (op->opcode == AML_SCOPE_OP) { + if (((ACPI_NAMED_OP *)op)->name == -1) { + return AE_OK; + } + } + + + data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode); + + /* Pop the scope stack */ + + if (acpi_ns_opens_scope (data_type)) { + + acpi_ds_scope_stack_pop (walk_state); + } + + return AE_OK; + +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_load2_begin_op + * + * PARAMETERS: Walk_state - Current state of the parse tree walk + * Op - Op that has been just been reached in the + * walk; Arguments have not been evaluated yet. + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the loading of ACPI tables. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_load2_begin_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op) +{ + ACPI_NAMED_OBJECT *new_entry; + ACPI_STATUS status; + OBJECT_TYPE_INTERNAL data_type; + char *buffer_ptr; + void *original = NULL; + + + /* We only care about Namespace opcodes here */ + + if (!acpi_ps_is_namespace_op (op->opcode) && + op->opcode != AML_NAMEPATH_OP) + { + return AE_OK; + } + + + /* + * Get the name we are going to enter or lookup in the namespace + */ + if (op->opcode == AML_NAMEPATH_OP) { + /* For Namepath op , get the path string */ + + buffer_ptr = op->value.string; + if (!buffer_ptr) { + /* No name, just exit */ + + return AE_OK; + } + } + + else { + /* Get name from the op */ + + buffer_ptr = (char *) &((ACPI_NAMED_OP *)op)->name; + } + + + /* Map the raw opcode into an internal object type */ + + data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode); + + + if (op->opcode == AML_DEF_FIELD_OP || + op->opcode == AML_BANK_FIELD_OP || + op->opcode == AML_INDEX_FIELD_OP) + { + new_entry = NULL; + status = AE_OK; + } + + else if (op->opcode == AML_NAMEPATH_OP) { + /* + * The Name_path is an object reference to an existing object. Don't enter the + * name into the namespace, but look it up for use later + */ + status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, + data_type, IMODE_EXECUTE, + NS_SEARCH_PARENT, walk_state, + &(new_entry)); + } + + else { + if (op->acpi_named_object) { + original = op->acpi_named_object; + new_entry = op->acpi_named_object; + + if (acpi_ns_opens_scope (data_type)) { + status = acpi_ds_scope_stack_push (new_entry->child_table, + data_type, + walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + } + return AE_OK; + } + + /* + * Enter the named type into the internal namespace. We enter the name + * as we go downward in the parse tree. Any necessary subobjects that involve + * arguments to the opcode must be created as we go back up the parse tree later. + */ + status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, + data_type, IMODE_EXECUTE, + NS_NO_UPSEARCH, walk_state, + &(new_entry)); + } + + if (ACPI_SUCCESS (status)) { + /* + * Put the NTE in the "op" object that the parser uses, so we + * can get it again quickly when this scope is closed + */ + op->acpi_named_object = new_entry; + + } + + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_load2_end_op + * + * PARAMETERS: Walk_state - Current state of the parse tree walk + * Op - Op that has been just been completed in the + * walk; Arguments have now been evaluated. + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during the loading of the namespace, + * both control methods and everything else. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_load2_end_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op) +{ + ACPI_STATUS status = AE_OK; + OBJECT_TYPE_INTERNAL data_type; + ACPI_NAMED_OBJECT *entry; + ACPI_GENERIC_OP *arg; + ACPI_NAMED_OBJECT *new_entry; + + + if (!acpi_ps_is_namespace_object_op (op->opcode)) { + return AE_OK; + } + + if (op->opcode == AML_SCOPE_OP) { + if (((ACPI_NAMED_OP *)op)->name == -1) { + return AE_OK; + } + } + + + data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode); + + /* + * Get the NTE/name from the earlier lookup + * (It was saved in the *op structure) + */ + entry = op->acpi_named_object; + + /* + * Put the NTE on the object stack (Contains the ACPI Name of + * this object) + */ + + walk_state->operands[0] = (void *) entry; + walk_state->num_operands = 1; + + /* Pop the scope stack */ + + if (acpi_ns_opens_scope (data_type)) { + + acpi_ds_scope_stack_pop (walk_state); + } + + + /* + * Named operations are as follows: + * + * AML_SCOPE + * AML_DEVICE + * AML_THERMALZONE + * AML_METHOD + * AML_POWERRES + * AML_PROCESSOR + * AML_FIELD + * AML_INDEXFIELD + * AML_BANKFIELD + * AML_NAMEDFIELD + * AML_NAME + * AML_ALIAS + * AML_MUTEX + * AML_EVENT + * AML_OPREGION + * AML_CREATEFIELD + * AML_CREATEBITFIELD + * AML_CREATEBYTEFIELD + * AML_CREATEWORDFIELD + * AML_CREATEDWORDFIELD + * AML_METHODCALL + */ + + + /* Decode the opcode */ + + arg = op->value.arg; + + switch (op->opcode) + { + + case AML_CREATE_FIELD_OP: + case AML_BIT_FIELD_OP: + case AML_BYTE_FIELD_OP: + case AML_WORD_FIELD_OP: + case AML_DWORD_FIELD_OP: + + /* Get the Name_string argument */ + + if (op->opcode == AML_CREATE_FIELD_OP) { + arg = acpi_ps_get_arg (op, 3); + } + else { + /* Create Bit/Byte/Word/Dword field */ + + arg = acpi_ps_get_arg (op, 2); + } + + /* + * Enter the Name_string into the namespace + */ + + status = acpi_ns_lookup (walk_state->scope_info, + arg->value.string, + INTERNAL_TYPE_DEF_ANY, + IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + walk_state, &(new_entry)); + + if (ACPI_SUCCESS (status)) { + /* We could put the returned object (NTE) on the object stack for later, but + * for now, we will put it in the "op" object that the parser uses, so we + * can get it again at the end of this scope + */ + op->acpi_named_object = new_entry; + } + + break; + + + case AML_METHODCALL_OP: + + /* + * Lookup the method name and save the NTE + */ + + status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + ACPI_TYPE_ANY, IMODE_LOAD_PASS2, + NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, + walk_state, &(new_entry)); + + if (ACPI_SUCCESS (status)) { + +/* has name already been resolved by here ??*/ + + /* TBD: [Restructure] Make sure that what we found is indeed a method! */ + /* We didn't search for a method on purpose, to see if the name would resolve! */ + + /* We could put the returned object (NTE) on the object stack for later, but + * for now, we will put it in the "op" object that the parser uses, so we + * can get it again at the end of this scope + */ + op->acpi_named_object = new_entry; + } + + + break; + + + case AML_PROCESSOR_OP: + + /* Nothing to do other than enter object into namespace */ + + status = acpi_aml_exec_create_processor (op, (ACPI_HANDLE) entry); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + break; + + + case AML_POWER_RES_OP: + + /* Nothing to do other than enter object into namespace */ + + status = acpi_aml_exec_create_power_resource (op, (ACPI_HANDLE) entry); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + break; + + + case AML_THERMAL_ZONE_OP: + + /* Nothing to do other than enter object into namespace */ + + break; + + + case AML_DEF_FIELD_OP: + + arg = op->value.arg; + + status = acpi_ds_create_field (op, + (ACPI_HANDLE) arg->acpi_named_object, + walk_state); + break; + + + case AML_INDEX_FIELD_OP: + + arg = op->value.arg; + + status = acpi_ds_create_index_field (op, + (ACPI_HANDLE) arg->acpi_named_object, + walk_state); + break; + + + case AML_BANK_FIELD_OP: + + arg = op->value.arg; + status = acpi_ds_create_bank_field (op, + (ACPI_HANDLE) arg->acpi_named_object, + walk_state); + break; + + + /* + * Method_op Pkg_length Names_string Method_flags Term_list + */ + case AML_METHOD_OP: + + if (!entry->object) { + status = acpi_aml_exec_create_method (((ACPI_DEFERRED_OP *) op)->body, + ((ACPI_DEFERRED_OP *) op)->body_length, + arg->value.integer, (ACPI_HANDLE) entry); + } + + break; + + + case AML_MUTEX_OP: + + status = acpi_ds_create_operands (walk_state, arg); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + status = acpi_aml_exec_create_mutex (walk_state); + break; + + + case AML_EVENT_OP: + + status = acpi_ds_create_operands (walk_state, arg); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + status = acpi_aml_exec_create_event (walk_state); + break; + + + case AML_REGION_OP: + + + /* + * The Op_region is not fully parsed at this time. Only valid argument is the Space_id. + * (We must save the address of the AML of the address and length operands) + */ + + status = acpi_aml_exec_create_region (((ACPI_DEFERRED_OP *) op)->body, + ((ACPI_DEFERRED_OP *) op)->body_length, + arg->value.integer, walk_state); + + break; + + + /* Namespace Modifier Opcodes */ + + case AML_ALIAS_OP: + + status = acpi_ds_create_operands (walk_state, arg); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + status = acpi_aml_exec_create_alias (walk_state); + break; + + + case AML_NAME_OP: + + status = acpi_ds_create_named_object (walk_state, entry, op); + + break; + + + case AML_NAMEPATH_OP: + + break; + + + default: + break; + } + + +cleanup: + /* Remove the NTE pushed at the very beginning */ + acpi_ds_obj_stack_pop (1, walk_state); + return (status); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/dispatcher/dswscope.c linux/drivers/acpi/dispatcher/dswscope.c --- v2.4.0-test2/linux/drivers/acpi/dispatcher/dswscope.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/dispatcher/dswscope.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,161 @@ + +/****************************************************************************** + * + * Module Name: dswscope - Scope stack manipulation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" +#include "dispatch.h" + + +#define _COMPONENT NAMESPACE + MODULE_NAME ("dswscope"); + + +#define STACK_POP(head) head + + +/**************************************************************************** + * + * FUNCTION: Acpi_ds_scope_stack_clear + * + * PARAMETERS: None + * + * DESCRIPTION: Pop (and free) everything on the scope stack except the + * root scope object (which remains at the stack top.) + * + ***************************************************************************/ + +void +acpi_ds_scope_stack_clear ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_GENERIC_STATE *scope_info; + + + while (walk_state->scope_info) { + /* Pop a scope off the stack */ + + scope_info = walk_state->scope_info; + walk_state->scope_info = scope_info->scope.next; + + acpi_cm_delete_generic_state (scope_info); + } +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ds_scope_stack_push + * + * PARAMETERS: *New_scope, - Name to be made current + * Type, - Type of frame being pushed + * + * DESCRIPTION: Push the current scope on the scope stack, and make the + * passed nte current. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ds_scope_stack_push ( + ACPI_NAME_TABLE *new_scope, + OBJECT_TYPE_INTERNAL type, + ACPI_WALK_STATE *walk_state) +{ + ACPI_GENERIC_STATE *scope_info; + + + if (!new_scope) { + /* invalid scope */ + + REPORT_ERROR ("Ds_scope_stack_push: null scope passed"); + return (AE_BAD_PARAMETER); + } + + /* Make sure object type is valid */ + + if (!acpi_aml_validate_object_type (type)) { + REPORT_WARNING ("Ds_scope_stack_push: type code out of range"); + } + + + /* Allocate a new scope object */ + + scope_info = acpi_cm_create_generic_state (); + if (!scope_info) { + return (AE_NO_MEMORY); + } + + /* Init new scope object */ + + scope_info->scope.name_table = new_scope; + scope_info->common.value = (u16) type; + + /* Push new scope object onto stack */ + + acpi_cm_push_generic_state (&walk_state->scope_info, scope_info); + + return (AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ds_scope_stack_pop + * + * PARAMETERS: Type - The type of frame to be found + * + * DESCRIPTION: Pop the scope stack until a frame of the requested type + * is found. + * + * RETURN: Count of frames popped. If no frame of the requested type + * was found, the count is returned as a negative number and + * the scope stack is emptied (which sets the current scope + * to the root). If the scope stack was empty at entry, the + * function is a no-op and returns 0. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ds_scope_stack_pop ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_GENERIC_STATE *scope_info; + + + /* + * Pop scope info object off the stack. + */ + + scope_info = acpi_cm_pop_generic_state (&walk_state->scope_info); + if (!scope_info) { + return (AE_STACK_UNDERFLOW); + } + + acpi_cm_delete_generic_state (scope_info); + + return (AE_OK); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/dispatcher/dswstate.c linux/drivers/acpi/dispatcher/dswstate.c --- v2.4.0-test2/linux/drivers/acpi/dispatcher/dswstate.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/dispatcher/dswstate.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,648 @@ +/****************************************************************************** + * + * Module Name: dswstate - Dispatcher parse tree walk management routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "parser.h" +#include "dispatch.h" +#include "namesp.h" +#include "interp.h" + +#define _COMPONENT DISPATCHER + MODULE_NAME ("dswstate"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_result_stack_clear + * + * PARAMETERS: Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Reset this walk's result stack pointers to zero, thus setting + * the stack to zero. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_result_stack_clear ( + ACPI_WALK_STATE *walk_state) +{ + + walk_state->num_results = 0; + walk_state->current_result = 0; + + return AE_OK; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_result_stack_push + * + * PARAMETERS: Object - Object to push + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Push an object onto this walk's result stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_result_stack_push ( + void *object, + ACPI_WALK_STATE *walk_state) +{ + + + if (walk_state->num_results >= OBJ_NUM_OPERANDS) { + return AE_STACK_OVERFLOW; + } + + walk_state->results [walk_state->num_results] = object; + walk_state->num_results++; + + return AE_OK; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_result_stack_pop + * + * PARAMETERS: Object - Where to return the popped object + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In + * other words, this is a FIFO. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_result_stack_pop ( + ACPI_OBJECT_INTERNAL **object, + ACPI_WALK_STATE *walk_state) +{ + + + /* Check for stack underflow */ + + if (walk_state->num_results == 0) { + return AE_AML_NO_OPERAND; + } + + + /* Pop the stack */ + + walk_state->num_results--; + + /* Check for a valid result object */ + + if (!walk_state->results [walk_state->num_results]) { + return AE_AML_NO_OPERAND; + } + + *object = walk_state->results [walk_state->num_results]; + walk_state->results [walk_state->num_results] = NULL; + + return AE_OK; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_obj_stack_delete_all + * + * PARAMETERS: Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Clear the object stack by deleting all objects that are on it. + * Should be used with great care, if at all! + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_obj_stack_delete_all ( + ACPI_WALK_STATE *walk_state) +{ + u32 i; + + + /* The stack size is configurable, but fixed */ + + for (i = 0; i < OBJ_NUM_OPERANDS; i++) { + if (walk_state->operands[i]) { + acpi_cm_remove_reference (walk_state->operands[i]); + walk_state->operands[i] = NULL; + } + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_obj_stack_push + * + * PARAMETERS: Object - Object to push + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Push an object onto this walk's object/operand stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_obj_stack_push ( + void *object, + ACPI_WALK_STATE *walk_state) +{ + + + /* Check for stack overflow */ + + if (walk_state->num_operands >= OBJ_NUM_OPERANDS) { + return AE_STACK_OVERFLOW; + } + + /* Put the object onto the stack */ + + walk_state->operands [walk_state->num_operands] = object; + walk_state->num_operands++; + + return AE_OK; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_obj_stack_pop_object + * + * PARAMETERS: Pop_count - Number of objects/entries to pop + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT + * deleted by this routine. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_obj_stack_pop_object ( + ACPI_OBJECT_INTERNAL **object, + ACPI_WALK_STATE *walk_state) +{ + + + /* Check for stack underflow */ + + if (walk_state->num_operands == 0) { + return AE_AML_NO_OPERAND; + } + + + /* Pop the stack */ + + walk_state->num_operands--; + + /* Check for a valid operand */ + + if (!walk_state->operands [walk_state->num_operands]) { + return AE_AML_NO_OPERAND; + } + + /* Get operand and set stack entry to null */ + + *object = walk_state->operands [walk_state->num_operands]; + walk_state->operands [walk_state->num_operands] = NULL; + + return AE_OK; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_obj_stack_pop + * + * PARAMETERS: Pop_count - Number of objects/entries to pop + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT + * deleted by this routine. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_obj_stack_pop ( + u32 pop_count, + ACPI_WALK_STATE *walk_state) +{ + u32 i; + + + for (i = 0; i < pop_count; i++) { + /* Check for stack underflow */ + + if (walk_state->num_operands == 0) { + return AE_STACK_UNDERFLOW; + } + + /* Just set the stack entry to null */ + + walk_state->num_operands--; + walk_state->operands [walk_state->num_operands] = NULL; + } + + return AE_OK; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_obj_stack_pop_and_delete + * + * PARAMETERS: Pop_count - Number of objects/entries to pop + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop this walk's object stack and delete each object that is + * popped off. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_obj_stack_pop_and_delete ( + u32 pop_count, + ACPI_WALK_STATE *walk_state) +{ + u32 i; + ACPI_OBJECT_INTERNAL *obj_desc; + + + for (i = 0; i < pop_count; i++) { + /* Check for stack underflow */ + + if (walk_state->num_operands == 0) { + return AE_STACK_UNDERFLOW; + } + + /* Pop the stack and delete an object if present in this stack entry */ + + walk_state->num_operands--; + obj_desc = walk_state->operands [walk_state->num_operands]; + if (obj_desc) { + acpi_cm_remove_reference (walk_state->operands [walk_state->num_operands]); + walk_state->operands [walk_state->num_operands] = NULL; + } + } + + return AE_OK; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_obj_stack_get_value + * + * PARAMETERS: Index - Stack index whose value is desired. Based + * on the top of the stack (index=0 == top) + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Retrieve an object from this walk's object stack. Index must + * be within the range of the current stack pointer. + * + ******************************************************************************/ + +void * +acpi_ds_obj_stack_get_value ( + u32 index, + ACPI_WALK_STATE *walk_state) +{ + + + /* Can't do it if the stack is empty */ + + if (walk_state->num_operands == 0) { + return (NULL); + } + + /* or if the index is past the top of the stack */ + + if (index > (walk_state->num_operands - (u32) 1)) { + return (NULL); + } + + + return (walk_state->operands[(NATIVE_UINT)(walk_state->num_operands - 1) - + index]); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_get_current_walk_state + * + * PARAMETERS: Walk_list - Get current active state for this walk list + * + * RETURN: Pointer to the current walk state + * + * DESCRIPTION: Get the walk state that is at the head of the list (the "current" + * walk state. + * + ******************************************************************************/ + +ACPI_WALK_STATE * +acpi_ds_get_current_walk_state ( + ACPI_WALK_LIST *walk_list) + +{ + + if (!walk_list) { + return NULL; + } + + return walk_list->walk_state; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_push_walk_state + * + * PARAMETERS: Walk_state - State to push + * Walk_list - The list that owns the walk stack + * + * RETURN: None + * + * DESCRIPTION: Place the Walk_state at the head of the state list. + * + ******************************************************************************/ + +void +acpi_ds_push_walk_state ( + ACPI_WALK_STATE *walk_state, + ACPI_WALK_LIST *walk_list) +{ + + + walk_state->next = walk_list->walk_state; + walk_list->walk_state = walk_state; + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_pop_walk_state + * + * PARAMETERS: Walk_list - The list that owns the walk stack + * + * RETURN: A Walk_state object popped from the stack + * + * DESCRIPTION: Remove and return the walkstate object that is at the head of + * the walk stack for the given walk list. NULL indicates that + * the list is empty. + * + ******************************************************************************/ + +ACPI_WALK_STATE * +acpi_ds_pop_walk_state ( + ACPI_WALK_LIST *walk_list) +{ + ACPI_WALK_STATE *walk_state; + + + walk_state = walk_list->walk_state; + + if (walk_state) { + /* Next walk state becomes the current walk state */ + + walk_list->walk_state = walk_state->next; + + /* + * Don't clear the NEXT field, this serves as an indicator + * that there is a parent WALK STATE + * Walk_state->Next = NULL; + */ + } + + return (walk_state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_create_walk_state + * + * PARAMETERS: Origin - Starting point for this walk + * Walk_list - Owning walk list + * + * RETURN: Pointer to the new walk state. + * + * DESCRIPTION: Allocate and initialize a new walk state. The current walk state + * is set to this new state. + * + ******************************************************************************/ + +ACPI_WALK_STATE * +acpi_ds_create_walk_state ( + ACPI_OWNER_ID owner_id, + ACPI_GENERIC_OP *origin, + ACPI_OBJECT_INTERNAL *mth_desc, + ACPI_WALK_LIST *walk_list) +{ + ACPI_WALK_STATE *walk_state; + + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + acpi_gbl_walk_state_cache_requests++; + + /* Check the cache first */ + + if (acpi_gbl_walk_state_cache) { + /* There is an object available, use it */ + + walk_state = acpi_gbl_walk_state_cache; + acpi_gbl_walk_state_cache = walk_state->next; + + acpi_gbl_walk_state_cache_hits++; + acpi_gbl_walk_state_cache_depth--; + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + } + + else { + /* The cache is empty, create a new object */ + + /* Avoid deadlock with Acpi_cm_callocate */ + acpi_cm_release_mutex (ACPI_MTX_CACHES); + + walk_state = acpi_cm_callocate (sizeof (ACPI_WALK_STATE)); + if (!walk_state) { + return (NULL); + } + } + + walk_state->data_type = ACPI_DESC_TYPE_WALK; + walk_state->owner_id = owner_id; + walk_state->origin = origin; + walk_state->method_desc = mth_desc; + + /* Init the method args/local */ + + acpi_ds_method_data_init (walk_state); + + /* Put the new state at the head of the walk list */ + + acpi_ds_push_walk_state (walk_state, walk_list); + + return (walk_state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_delete_walk_state + * + * PARAMETERS: Walk_state - State to delete + * + * RETURN: Status + * + * DESCRIPTION: Delete a walk state including all internal data structures + * + ******************************************************************************/ + +void +acpi_ds_delete_walk_state ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_GENERIC_STATE *state; + + + if (!walk_state) { + return; + } + + if (walk_state->data_type != ACPI_DESC_TYPE_WALK) { + return; + } + + /* Always must free any linked control states */ + + while (walk_state->control_state) { + state = walk_state->control_state; + walk_state->control_state = state->common.next; + + acpi_cm_delete_generic_state (state); + } + + + /* Always must free any linked parse states */ + + while (walk_state->scope_info) { + state = walk_state->scope_info; + walk_state->scope_info = state->common.next; + + acpi_cm_delete_generic_state (state); + } + + /* If walk cache is full, just free this wallkstate object */ + + if (acpi_gbl_walk_state_cache_depth >= MAX_WALK_CACHE_DEPTH) { + acpi_cm_free (walk_state); + } + + /* Otherwise put this object back into the cache */ + + else { + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + + /* Clear the state */ + + MEMSET (walk_state, 0, sizeof (ACPI_WALK_STATE)); + walk_state->data_type = ACPI_DESC_TYPE_WALK; + + /* Put the object at the head of the global cache list */ + + walk_state->next = acpi_gbl_walk_state_cache; + acpi_gbl_walk_state_cache = walk_state; + acpi_gbl_walk_state_cache_depth++; + + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + } + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ds_delete_walk_state_cache + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Purge the global state object cache. Used during subsystem + * termination. + * + ******************************************************************************/ + +void +acpi_ds_delete_walk_state_cache ( + void) +{ + ACPI_WALK_STATE *next; + + + /* Traverse the global cache list */ + + while (acpi_gbl_walk_state_cache) { + /* Delete one cached state object */ + + next = acpi_gbl_walk_state_cache->next; + acpi_cm_free (acpi_gbl_walk_state_cache); + acpi_gbl_walk_state_cache = next; + } + + return; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/events/evevent.c linux/drivers/acpi/events/evevent.c --- v2.4.0-test2/linux/drivers/acpi/events/evevent.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/events/evevent.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,679 @@ +/****************************************************************************** + * + * Module Name: evevent - Fixed and General Purpose Acpi_event + * handling and dispatch + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "hardware.h" +#include "events.h" +#include "namesp.h" +#include "common.h" + +#define _COMPONENT EVENT_HANDLING + MODULE_NAME ("evevent"); + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_fixed_event_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize the Fixed Acpi_event data structures + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ev_fixed_event_initialize(void) +{ + int i = 0; + + /* Initialize the structure that keeps track of fixed event handlers */ + + for (i = 0; i < NUM_FIXED_EVENTS; i++) { + acpi_gbl_fixed_event_handlers[i].handler = NULL; + acpi_gbl_fixed_event_handlers[i].context = NULL; + } + + acpi_hw_register_access (ACPI_WRITE, ACPI_MTX_LOCK, ACPI_EVENT_PMTIMER + + TMR_EN, 0); + acpi_hw_register_access (ACPI_WRITE, ACPI_MTX_LOCK, ACPI_EVENT_GLOBAL + + TMR_EN, 0); + acpi_hw_register_access (ACPI_WRITE, ACPI_MTX_LOCK, ACPI_EVENT_POWER_BUTTON + + TMR_EN, 0); + acpi_hw_register_access (ACPI_WRITE, ACPI_MTX_LOCK, ACPI_EVENT_SLEEP_BUTTON + + TMR_EN, 0); + acpi_hw_register_access (ACPI_WRITE, ACPI_MTX_LOCK, ACPI_EVENT_RTC + + TMR_EN, 0); + + return AE_OK; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_fixed_event_detect + * + * PARAMETERS: None + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Checks the PM status register for fixed events + * + ******************************************************************************/ + +u32 +acpi_ev_fixed_event_detect(void) +{ + u32 int_status = INTERRUPT_NOT_HANDLED; + u32 status_register = 0; + u32 enable_register = 0; + + /* + * Read the fixed feature status and enable registers, as all the cases + * depend on their values. + */ + + status_register = (u32) acpi_os_in16 (acpi_gbl_FACP->pm1a_evt_blk); + if (acpi_gbl_FACP->pm1b_evt_blk) { + status_register |= (u32) acpi_os_in16 (acpi_gbl_FACP->pm1b_evt_blk); + } + + enable_register = (u32) acpi_os_in16 (acpi_gbl_FACP->pm1a_evt_blk + + DIV_2 (acpi_gbl_FACP->pm1_evt_len)); + if (acpi_gbl_FACP->pm1b_evt_blk) { + enable_register |= (u32) acpi_os_in16 (acpi_gbl_FACP->pm1b_evt_blk + + DIV_2 (acpi_gbl_FACP->pm1_evt_len)); + } + + /* power management timer roll over */ + + if ((status_register & ACPI_STATUS_PMTIMER) && + (enable_register & ACPI_ENABLE_PMTIMER)) + { + int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_PMTIMER); + } + + /* global event (BIOS want's the global lock) */ + + if ((status_register & ACPI_STATUS_GLOBAL) && + (enable_register & ACPI_ENABLE_GLOBAL)) + { + int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_GLOBAL); + } + + /* power button event */ + + if ((status_register & ACPI_STATUS_POWER_BUTTON) && + (enable_register & ACPI_ENABLE_POWER_BUTTON)) + { + int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_POWER_BUTTON); + } + + /* sleep button event */ + + if ((status_register & ACPI_STATUS_SLEEP_BUTTON) && + (enable_register & ACPI_ENABLE_SLEEP_BUTTON)) + { + int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_SLEEP_BUTTON); + } + + return int_status; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_fixed_event_dispatch + * + * PARAMETERS: Event - Event type + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Clears the status bit for the requested event, calls the + * handler that previously registered for the event. + * + ******************************************************************************/ + +u32 +acpi_ev_fixed_event_dispatch ( + u32 event) +{ + /* Clear the status bit */ + + acpi_hw_register_access (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, (s32)TMR_STS + + event, 1); + + /* + * Make sure we've got a handler. If not, report an error. + * The event is disabled to prevent further interrupts. + */ + if (NULL == acpi_gbl_fixed_event_handlers[event].handler) { + acpi_hw_register_access (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, + TMR_EN + event, 0); + + REPORT_ERROR("No installed handler for fixed event."); + return INTERRUPT_NOT_HANDLED; + } + + /* Invoke the handler */ + + return (acpi_gbl_fixed_event_handlers[event].handler)( + acpi_gbl_fixed_event_handlers[event].context); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_gpe_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize the GPE data structures + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ev_gpe_initialize (void) +{ + u32 i; + u32 j; + u32 register_index; + u32 gpe_number; + u16 gpe0register_count; + u16 gpe1_register_count; + + + /* + * Setup various GPE counts + */ + + gpe0register_count = (u16) DIV_2 (acpi_gbl_FACP->gpe0blk_len); + gpe1_register_count = (u16) DIV_2 (acpi_gbl_FACP->gpe1_blk_len); + acpi_gbl_gpe_register_count = gpe0register_count + gpe1_register_count; + + /* + * Allocate the Gpe information block + */ + + acpi_gbl_gpe_registers = acpi_cm_callocate (acpi_gbl_gpe_register_count * + sizeof (ACPI_GPE_REGISTERS)); + if (!acpi_gbl_gpe_registers) { + return (AE_NO_MEMORY); + } + + /* + * Allocate the Gpe dispatch handler block + * There are eight distinct GP events per register. + * Initialization to zeros is sufficient + */ + + acpi_gbl_gpe_info = acpi_cm_callocate (MUL_8 (acpi_gbl_gpe_register_count) * + sizeof (ACPI_GPE_LEVEL_INFO)); + if (!acpi_gbl_gpe_info) { + acpi_cm_free (acpi_gbl_gpe_registers); + return (AE_NO_MEMORY); + } + + /* Set the Gpe validation table to GPE_INVALID */ + + MEMSET (acpi_gbl_gpe_valid, (int) ACPI_GPE_INVALID, NUM_GPE); + + /* + * Initialize the Gpe information and validation blocks. A goal of these + * blocks is to hide the fact that there are two separate GPE register sets + * In a given block, the status registers occupy the first half, and + * the enable registers occupy the second half. + */ + + /* GPE Block 0 */ + + register_index = 0; + + for (i = 0; i < gpe0register_count; i++) { + acpi_gbl_gpe_registers[register_index].status_addr = + (u16) (acpi_gbl_FACP->gpe0blk + i); + + acpi_gbl_gpe_registers[register_index].enable_addr = + (u16) (acpi_gbl_FACP->gpe0blk + i + gpe0register_count); + + acpi_gbl_gpe_registers[register_index].gpe_base = (u8) MUL_8 (i); + + for (j = 0; j < 8; j++) { + gpe_number = acpi_gbl_gpe_registers[register_index].gpe_base + j; + acpi_gbl_gpe_valid[gpe_number] = (u8) register_index; + } + + /* + * Clear the status/enable registers. Note that status registers + * are cleared by writing a '1', while enable registers are cleared + * by writing a '0'. + */ + acpi_os_out8 (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00); + acpi_os_out8 (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF); + + register_index++; + } + + /* GPE Block 1 */ + + for (i = 0; i < gpe1_register_count; i++) { + acpi_gbl_gpe_registers[register_index].status_addr = + (u16) (acpi_gbl_FACP->gpe1_blk + i); + + acpi_gbl_gpe_registers[register_index].enable_addr = + (u16) (acpi_gbl_FACP->gpe1_blk + i + gpe1_register_count); + + acpi_gbl_gpe_registers[register_index].gpe_base = + (u8) (acpi_gbl_FACP->gpe1_base + MUL_8 (i)); + + for (j = 0; j < 8; j++) { + gpe_number = acpi_gbl_gpe_registers[register_index].gpe_base + j; + acpi_gbl_gpe_valid[gpe_number] = (u8) register_index; + } + + /* + * Clear the status/enable registers. Note that status registers + * are cleared by writing a '1', while enable registers are cleared + * by writing a '0'. + */ + acpi_os_out8 (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00); + acpi_os_out8 (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF); + + register_index++; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_save_method_info + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Called from Acpi_walk_namespace. Expects each object to be a + * control method under the _GPE portion of the namespace. + * Extract the name and GPE type from the object, saving this + * information for quick lookup during GPE dispatch + * + * The name of each GPE control method is of the form: + * "_Lnn" or "_Enn" + * Where: + * L - means that the GPE is level triggered + * E - means that the GPE is edge triggered + * nn - is the GPE number + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ev_save_method_info ( + ACPI_HANDLE obj_handle, + u32 level, + void *obj_desc, + void **return_value) +{ + u32 gpe_number; + char name[ACPI_NAME_SIZE + 1]; + u8 type; + + + /* Extract the name from the object and convert to a string */ + + MOVE_UNALIGNED32_TO_32 (name, &((ACPI_NAMED_OBJECT*) obj_handle)->name); + name[ACPI_NAME_SIZE] = 0; + + /* + * Edge/Level determination is based on the 2nd char of the method name + */ + if (name[1] == 'L') { + type = ACPI_EVENT_LEVEL_TRIGGERED; + } + else if (name[1] == 'E') { + type = ACPI_EVENT_EDGE_TRIGGERED; + } + else { + /* Unknown method type, just ignore it! */ + + return AE_OK; + } + + /* Convert the last two characters of the name to the Gpe Number */ + + gpe_number = STRTOUL (&name[2], NULL, 16); + if (gpe_number == ACPI_UINT32_MAX) { + /* Conversion failed; invalid method, just ignore it */ + + return AE_OK; + } + + /* Ensure that we have a valid GPE number */ + + if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { + /* Not valid, all we can do here is ignore it */ + + return AE_OK; + } + + /* + * Now we can add this information to the Gpe_info block + * for use during dispatch of this GPE. + */ + + acpi_gbl_gpe_info [gpe_number].type = type; + acpi_gbl_gpe_info [gpe_number].method_handle = obj_handle; + + + /* + * Enable the GPE (SCIs should be disabled at this point) + */ + + acpi_hw_enable_gpe (gpe_number); + + return AE_OK; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_init_gpe_control_methods + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Obtain the control methods associated with the GPEs. + * + * NOTE: Must be called AFTER namespace initialization! + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ev_init_gpe_control_methods (void) +{ + ACPI_STATUS status; + + + /* Get a permanent handle to the _GPE object */ + + status = acpi_get_handle (NULL, "\\_GPE", &acpi_gbl_gpe_obj_handle); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Traverse the namespace under \_GPE to find all methods there */ + + status = acpi_walk_namespace (ACPI_TYPE_METHOD, acpi_gbl_gpe_obj_handle, + ACPI_INT32_MAX, acpi_ev_save_method_info, + NULL, NULL); + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_gpe_cleanup + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Cleanup in preparation for unload. + * + ******************************************************************************/ + +void +acpi_ev_gpe_cleanup (void) +{ + + acpi_cm_free (acpi_gbl_gpe_registers); + acpi_cm_free (acpi_gbl_gpe_info); + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_gpe_detect + * + * PARAMETERS: None + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Detect if any GP events have occurred + * + ******************************************************************************/ + +u32 +acpi_ev_gpe_detect (void) +{ + u32 int_status = INTERRUPT_NOT_HANDLED; + u32 i; + u32 j; + u8 enabled_status_byte; + u8 bit_mask; + + + /* + * Read all of the 8-bit GPE status and enable registers + * in both of the register blocks, saving all of it. + * Find all currently active GP events. + */ + + for (i = 0; i < acpi_gbl_gpe_register_count; i++) { + acpi_gbl_gpe_registers[i].status = + acpi_os_in8 (acpi_gbl_gpe_registers[i].status_addr); + + acpi_gbl_gpe_registers[i].enable = + acpi_os_in8 (acpi_gbl_gpe_registers[i].enable_addr); + + /* First check if there is anything active at all in this register */ + + enabled_status_byte = (u8) (acpi_gbl_gpe_registers[i].status & + acpi_gbl_gpe_registers[i].enable); + + if (!enabled_status_byte) { + /* No active GPEs in this register, move on */ + + continue; + } + + /* Now look at the individual GPEs in this byte register */ + + for (j = 0, bit_mask = 1; j < 8; j++, bit_mask <<= 1) { + /* Examine one GPE bit */ + + if (enabled_status_byte & bit_mask) { + /* + * Found an active GPE. Dispatch the event to a handler + * or method. + */ + int_status |= + acpi_ev_gpe_dispatch (acpi_gbl_gpe_registers[i].gpe_base + j); + } + } + } + + return int_status; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_asynch_execute_gpe_method + * + * PARAMETERS: Gpe_number - The 0-based Gpe number + * + * RETURN: None + * + * DESCRIPTION: Perform the actual execution of a GPE control method. This + * function is called from an invocation of Acpi_os_queue_for_execution + * (and therefore does NOT execute at interrupt level) so that + * the control method itself is not executed in the context of + * the SCI interrupt handler. + * + ******************************************************************************/ + +void +acpi_ev_asynch_execute_gpe_method ( + void *context) +{ + u32 gpe_number = (u32) context; + ACPI_GPE_LEVEL_INFO gpe_info; + + + /* Take a snapshot of the GPE info for this level */ + + acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + gpe_info = acpi_gbl_gpe_info [gpe_number]; + acpi_cm_release_mutex (ACPI_MTX_EVENTS); + + /* + * Function Handler (e.g. EC): + * --------------------------- + * Execute the installed function handler to handle this event. + */ + if (gpe_info.handler) { + gpe_info.handler (gpe_info.context); + } + + /* + * Method Handler (_Lxx, _Exx): + * ---------------------------- + * Acpi_evaluate the _Lxx/_Exx control method that corresponds to this GPE. + */ + else if (gpe_info.method_handle) { + acpi_ns_evaluate_by_handle (gpe_info.method_handle, NULL, NULL); + } + + /* + * Level-Triggered? + * ---------------- + * If level-triggered, clear the GPE status bit after execution. Note + * that edge-triggered events are cleared prior to calling (via DPC) + * this function. + */ + if (gpe_info.type | ACPI_EVENT_LEVEL_TRIGGERED) { + acpi_hw_clear_gpe (gpe_number); + } + + /* + * Enable the GPE. + */ + acpi_hw_enable_gpe (gpe_number); + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_gpe_dispatch + * + * PARAMETERS: Gpe_number - The 0-based Gpe number + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Handle and dispatch a General Purpose Acpi_event. + * Clears the status bit for the requested event. + * + * TBD: [Investigate] is this still valid or necessary: + * The Gpe handler differs from the fixed events in that it clears the enable + * bit rather than the status bit to clear the interrupt. This allows + * software outside of interrupt context to determine what caused the SCI and + * dispatch the correct AML. + * + ******************************************************************************/ + +u32 +acpi_ev_gpe_dispatch ( + u32 gpe_number) +{ + + /*DEBUG_INCREMENT_EVENT_COUNT (EVENT_GENERAL);*/ + + /* Ensure that we have a valid GPE number */ + + if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { + return (INTERRUPT_NOT_HANDLED); + } + + /* + * Disable the GPE. + */ + acpi_hw_disable_gpe (gpe_number); + + /* + * Edge-Triggered? + * --------------- + * If edge-triggered, clear the GPE status bit now. Note that + * level-triggered events are cleared after the GPE is serviced + * (see Acpi_ev_asynch_execute_gpe_method). + */ + if (acpi_gbl_gpe_info [gpe_number].type | ACPI_EVENT_EDGE_TRIGGERED) { + acpi_hw_clear_gpe (gpe_number); + } + + /* + * Queue-up the Handler: + * --------------------- + * Queue the handler, which is either an installable function handler + * (e.g. EC) or a control method (e.g. _Lxx/_Exx) for later execution. + */ + if (acpi_gbl_gpe_info [gpe_number].handler || + acpi_gbl_gpe_info [gpe_number].method_handle) + { + if (ACPI_FAILURE (acpi_os_queue_for_execution (OSD_PRIORITY_GPE, + acpi_ev_asynch_execute_gpe_method, + (void*)(NATIVE_UINT)gpe_number))) + { + /* + * Shoudn't occur, but if it does report an error. Note that + * the GPE will remain disabled until the ACPI Core Subsystem + * is restarted, or the handler is removed/reinstalled. + */ + REPORT_ERROR ("Unable to queue-up handler for GPE."); + } + } + + /* + * Non Handled GPEs: + * ----------------- + * GPEs without handlers are disabled and kept that way until a handler + * is registered for them. + */ + else { + REPORT_ERROR ("No installed handler for GPE."); + } + + return (INTERRUPT_HANDLED); +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/events/evmisc.c linux/drivers/acpi/events/evmisc.c --- v2.4.0-test2/linux/drivers/acpi/events/evmisc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/events/evmisc.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,357 @@ +/****************************************************************************** + * + * Module Name: evmisc - ACPI device notification handler dispatch + * and ACPI Global Lock support + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "events.h" +#include "namesp.h" +#include "interp.h" +#include "hardware.h" + +#define _COMPONENT EVENT_HANDLING + MODULE_NAME ("evmisc"); + + +/************************************************************************** + * + * FUNCTION: Acpi_ev_notify_dispatch + * + * PARAMETERS: + * + * RETURN: None. + * + * DESCRIPTION: Dispatch a device notification event to a previously + * installed handler. + * + *************************************************************************/ + +void +acpi_ev_notify_dispatch ( + ACPI_HANDLE device, + u32 notify_value) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_OBJECT_INTERNAL *handler_obj; + NOTIFY_HANDLER handler; + + + /* + * For value 1 (Ejection Request), some device method may need to be run. + * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run. + * For value 0x80 (Status Change) on the power button or sleep button, + * initiate soft-off or sleep operation? + */ + + + switch (notify_value) + { + case 0: + break; + + case 1: + break; + + case 2: + break; + + case 0x80: + break; + + default: + break; + } + + + /* + * Invoke a global notify handler if installed. + * This is done _before_ we invoke the per-device handler attached to the device. + */ + + if (notify_value <= MAX_SYS_NOTIFY) { + /* Global system notification handler */ + + if (acpi_gbl_sys_notify.handler) { + acpi_gbl_sys_notify.handler (device, notify_value, + acpi_gbl_sys_notify.context); + } + } + + else { + /* Global driver notification handler */ + + if (acpi_gbl_drv_notify.handler) { + acpi_gbl_drv_notify.handler (device, notify_value, + acpi_gbl_drv_notify.context); + } + } + + + /* + * Get the notify object which must be attached to the device NTE + */ + + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device); + if (!obj_desc) { + /* There can be no notify handler for this device */ + + return; + } + + + /* We have the notify object, Get the right handler */ + + if (notify_value <= MAX_SYS_NOTIFY) { + handler_obj = obj_desc->device.sys_handler; + } + else { + handler_obj = obj_desc->device.drv_handler; + } + + /* Validate the handler */ + + if (!handler_obj) { + /* There is no notify handler for this device */ + + return; + } + + /* There is a handler, invoke it */ + + handler = handler_obj->notify_handler.handler; + handler (device, notify_value, handler_obj->notify_handler.context); + +} + + +/*************************************************************************** + * + * FUNCTION: Acpi_ev_global_lock_thread + * + * RETURN: None + * + * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the + * Global Lock. Simply signal all threads that are waiting + * for the lock. + * + **************************************************************************/ + +void +acpi_ev_global_lock_thread ( + void *context) +{ + + /* Signal threads that are waiting for the lock */ + + if (acpi_gbl_global_lock_thread_count) { + /* Send sufficient units to the semaphore */ + + acpi_os_signal_semaphore (acpi_gbl_global_lock_semaphore, + acpi_gbl_global_lock_thread_count); + } +} + + +/*************************************************************************** + * + * FUNCTION: Acpi_ev_global_lock_handler + * + * RETURN: Status + * + * DESCRIPTION: Invoked directly from the SCI handler when a global lock + * release interrupt occurs. Grab the global lock and queue + * the global lock thread for execution + * + **************************************************************************/ + +u32 +acpi_ev_global_lock_handler ( + void *context) +{ + u8 acquired = FALSE; + void *global_lock; + + + /* + * Attempt to get the lock + * If we don't get it now, it will be marked pending and we will + * take another interrupt when it becomes free. + */ + + global_lock = &acpi_gbl_FACS->global_lock; + ACPI_ACQUIRE_GLOBAL_LOCK (global_lock, acquired); + if (acquired) { + /* Got the lock, now wake all threads waiting for it */ + + acpi_gbl_global_lock_acquired = TRUE; + + /* Run the Global Lock thread which will signal all waiting threads */ + + acpi_os_queue_for_execution (OSD_PRIORITY_HIGH, acpi_ev_global_lock_thread, + context); + } + + return INTERRUPT_HANDLED; +} + + +/*************************************************************************** + * + * FUNCTION: Acpi_ev_init_global_lock_handler + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for the global lock release event + * + **************************************************************************/ + +ACPI_STATUS +acpi_ev_init_global_lock_handler (void) +{ + ACPI_STATUS status; + + + status = acpi_install_fixed_event_handler (ACPI_EVENT_GLOBAL, + acpi_ev_global_lock_handler, NULL); + + return (status); +} + + +/*************************************************************************** + * + * FUNCTION: Acpi_ev_acquire_global_lock + * + * RETURN: Status + * + * DESCRIPTION: Attempt to gain ownership of the Global Lock. + * + **************************************************************************/ + +ACPI_STATUS +acpi_ev_acquire_global_lock(void) +{ + ACPI_STATUS status = AE_OK; + u8 acquired = FALSE; + void *global_lock; + + + /* One more thread wants the global lock */ + + acpi_gbl_global_lock_thread_count++; + + + /* If we (OS side) have the hardware lock already, we are done */ + + if (acpi_gbl_global_lock_acquired) { + return (AE_OK); + } + + /* Only if the FACS is valid */ + + if (!acpi_gbl_FACS) { + return (AE_OK); + } + + + /* We must acquire the actualy hardware lock */ + + global_lock = &acpi_gbl_FACS->global_lock; + ACPI_ACQUIRE_GLOBAL_LOCK (global_lock, acquired); + if (acquired) { + /* We got the lock */ + + acpi_gbl_global_lock_acquired = TRUE; + + return (AE_OK); + } + + + /* + * Did not get the lock. The pending bit was set above, and we must now + * wait until we get the global lock released interrupt. + */ + + /* + * Acquire the global lock semaphore first. + * Since this wait will block, we must release the interpreter + */ + + acpi_aml_exit_interpreter (); + status = acpi_aml_system_wait_semaphore (acpi_gbl_global_lock_semaphore, + ACPI_UINT32_MAX); + acpi_aml_enter_interpreter (); + + + return (status); +} + + +/*************************************************************************** + * + * FUNCTION: Acpi_ev_release_global_lock + * + * DESCRIPTION: Releases ownership of the Global Lock. + * + **************************************************************************/ + +void +acpi_ev_release_global_lock (void) +{ + u8 pending = FALSE; + void *global_lock; + + + if (!acpi_gbl_FACS) { + return; + } + + /* One fewer thread has the global lock */ + + acpi_gbl_global_lock_thread_count--; + + + /* Have all threads released the lock? */ + + if (!acpi_gbl_global_lock_thread_count) { + /* + * No more threads holding lock, we can do the actual hardware + * release + */ + + global_lock = &acpi_gbl_FACS->global_lock; + ACPI_RELEASE_GLOBAL_LOCK (global_lock, pending); + acpi_gbl_global_lock_acquired = FALSE; + + /* + * If the pending bit was set, we must write GBL_RLS to the control + * register + */ + if (pending) { + acpi_hw_register_access (ACPI_WRITE, ACPI_MTX_LOCK, + (s32)PM1_CONTROL | GBL_RLS, 1); + } + } + + return; +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/events/evregion.c linux/drivers/acpi/events/evregion.c --- v2.4.0-test2/linux/drivers/acpi/events/evregion.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/events/evregion.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,690 @@ +/****************************************************************************** + * + * Module Name: evregion - ACPI Address_space / Op_region handler dispatch + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "events.h" +#include "namesp.h" +#include "interp.h" +#include "amlcode.h" + +#define _COMPONENT EVENT_HANDLING + MODULE_NAME ("evregion"); + + +#define PCI_ROOT_HID_STRING "PNP0A03" +#define PCI_ROOT_HID_VALUE 0x030AD041 /* EISAID("PNP0A03") */ + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_find_one_pci_root_bus + * + * PARAMETERS: + * + * RETURN: None + * + * DESCRIPTION: + * + *****************************************************************************/ + +ACPI_STATUS +acpi_ev_find_one_pci_root_bus ( + ACPI_HANDLE obj_handle, + u32 nesting_level, + void *context, + void **return_value) +{ + ACPI_NAMED_OBJECT *entry; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_STATUS status; + + + entry = (ACPI_NAMED_OBJECT*) obj_handle; + obj_desc = ((ACPI_NAMED_OBJECT*)obj_handle)->object; + + + /* + * We are looking for all valid _HID objects. + */ + + if (STRNCMP ((char *)&entry->name, METHOD_NAME__HID, ACPI_NAME_SIZE) || + (!obj_desc)) + { + return AE_OK; + } + + + /* + * Found an _HID object. + * Now we need a HID with the value EISAID("PNP0A03") + * HID can be either a number or a string. + */ + + switch (obj_desc->common.type) + { + case ACPI_TYPE_NUMBER: + + if (obj_desc->number.value != PCI_ROOT_HID_VALUE) { + return AE_OK; + } + + break; + + case ACPI_TYPE_STRING: + + if (STRNCMP (obj_desc->string.pointer, PCI_ROOT_HID_STRING, + sizeof (PCI_ROOT_HID_STRING))) + { + return AE_OK; + } + + break; + + default: + + return AE_OK; + } + + + /* + * We found a valid PCI_ROOT_HID. + * The parent of the HID entry is the PCI device; Install the default PCI + * handler for this PCI device. + */ + + status = acpi_install_address_space_handler (acpi_ns_get_parent_entry (entry), + ADDRESS_SPACE_PCI_CONFIG, + ACPI_DEFAULT_HANDLER, NULL, NULL); + + return AE_OK; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_find_pci_root_buses + * + * PARAMETERS: + * + * RETURN: None + * + * DESCRIPTION: + * + *****************************************************************************/ + +ACPI_STATUS +acpi_ev_find_pci_root_buses ( + void) +{ + + acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + FALSE, acpi_ev_find_one_pci_root_bus, NULL, NULL); + + return AE_OK; +} + + +/************************************************************************** + * + * FUNCTION: Acpi_ev_install_default_address_space_handlers + * + * PARAMETERS: + * + * RETURN: Status + * + * DESCRIPTION: Installs the core subsystem address space handlers. + * + *************************************************************************/ + +ACPI_STATUS +acpi_ev_install_default_address_space_handlers ( + void) +{ + ACPI_STATUS status; + + + /* + * NOTE: All address spaces (PCI Config, EC, SMBus) are scope dependent + * and registration must occur for a specific device. In the case + * system memory and IO address spaces there is currently no device + * associated with the address space. For these we use the root. + */ + + status = acpi_install_address_space_handler (acpi_gbl_root_object, + ADDRESS_SPACE_SYSTEM_MEMORY, + ACPI_DEFAULT_HANDLER, NULL, NULL); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_install_address_space_handler (acpi_gbl_root_object, + ADDRESS_SPACE_SYSTEM_IO, + ACPI_DEFAULT_HANDLER, NULL, NULL); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Install PCI config space handler for all PCI root bridges. A PCI root + * bridge is found by searching for devices containing a HID with the value + * EISAID("PNP0A03") + */ + + acpi_ev_find_pci_root_buses (); + + + return (AE_OK); +} + + +/* TBD: [Restructure] Move to the methods directory */ + +/************************************************************************** + * + * FUNCTION: Acpi_ev_execute_reg_method + * + * PARAMETERS: Region_obj - Object structure + * Function - On (1) or Off (0) + * + * RETURN: Status + * + * DESCRIPTION: Execute _REG method for a region + * + *************************************************************************/ + +ACPI_STATUS +acpi_ev_execute_reg_method ( + ACPI_OBJECT_INTERNAL *region_obj, + u32 function) +{ + ACPI_OBJECT_INTERNAL *params[3]; + ACPI_OBJECT_INTERNAL space_iD_obj; + ACPI_OBJECT_INTERNAL function_obj; + ACPI_STATUS status; + + + if (region_obj->region.REGmethod == NULL) { + return (AE_OK); + } + + /* + * _REG method has two arguments + * Arg0: Integer: Operation region space ID + * Same value as Region_obj->Region.Space_id + * Arg1: Integer: connection status + * 1 for connecting the handler, + * 0 for disconnecting the handler + * Passed as a parameter + */ + + acpi_cm_init_static_object (&space_iD_obj); + acpi_cm_init_static_object (&function_obj); + + /* + * Method requires two parameters. + */ + params [0] = &space_iD_obj; + params [1] = &function_obj; + params [2] = NULL; + + /* + * Set up the parameter objects + */ + space_iD_obj.common.type = ACPI_TYPE_NUMBER; + space_iD_obj.number.value = region_obj->region.space_id; + + function_obj.common.type = ACPI_TYPE_NUMBER; + function_obj.number.value = function; + + /* + * Execute the method, no return value + */ + status = acpi_ns_evaluate_by_handle (region_obj->region.REGmethod, params, NULL); + return (status); +} + + +/************************************************************************** + * + * FUNCTION: Acpi_ev_address_space_dispatch + * + * PARAMETERS: Region_obj - internal region object + * Space_id - ID of the address space (0-255) + * Function - Read or Write operation + * Address - Where in the space to read or write + * Bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * + * RETURN: Status + * + * DESCRIPTION: Dispatch an address space or operation region access to + * a previously installed handler. + * + *************************************************************************/ + +ACPI_STATUS +acpi_ev_address_space_dispatch ( + ACPI_OBJECT_INTERNAL *region_obj, + u32 function, + u32 address, + u32 bit_width, + u32 *value) +{ + ACPI_STATUS status; + ADDRESS_SPACE_HANDLER handler; + ADDRESS_SPACE_SETUP region_setup; + ACPI_OBJECT_INTERNAL *handler_desc; + void *region_context; + + + /* + * Check for an installed handler + */ + handler_desc = region_obj->region.addr_handler; + + if (!handler_desc) { + return(AE_EXIST); + } + + /* + * It may be the case that the region has never been initialized + * Some types of regions require special init code + */ + if (!(region_obj->region.region_flags & REGION_INITIALIZED)) { + /* + * This region has not been initialized yet, do it + */ + region_setup = handler_desc->addr_handler.setup; + if (!region_setup) { + /* + * Bad news, no init routine and not init'd + */ + return (AE_UNKNOWN_STATUS); + } + + /* + * We must exit the interpreter because the region setup will potentially + * execute control methods + */ + acpi_aml_exit_interpreter (); + + status = region_setup (region_obj, ACPI_REGION_ACTIVATE, + handler_desc->addr_handler.context, + ®ion_context); + + /* Re-enter the interpreter */ + + acpi_aml_enter_interpreter (); + + /* + * Init routine may fail + */ + if (ACPI_FAILURE (status)) { + return(status); + } + + /* + * Save the returned context for use in all accesses to the region + */ + handler_desc->addr_handler.context = region_context; + } + + /* + * We have everything we need, begin the process + */ + handler = handler_desc->addr_handler.handler; + + if (!(handler_desc->addr_handler.flags & ADDR_HANDLER_DEFAULT_INSTALLED)) { + /* + * For handlers other than the default (supplied) handlers, we must + * exit the interpreter because the handler *might* block -- we don't + * know what it will do, so we can't hold the lock on the intepreter. + */ + acpi_aml_exit_interpreter(); + } + + /* + * Invoke the handler. + */ + status = handler (function, address, bit_width, value, + handler_desc->addr_handler.context); + + + if (!(handler_desc->addr_handler.flags & ADDR_HANDLER_DEFAULT_INSTALLED)) { + /* We just returned from a non-default handler, we must re-enter the + interpreter */ + + acpi_aml_enter_interpreter (); + } + + return (status); +} + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_disassociate_region_and_handler + * + * PARAMETERS: Handler_obj - Handler Object + * Region_obj - Region Object + * + * RETURN: None + * + * DESCRIPTION: Break the association between the handler and the region + * this is a two way association. + * + ******************************************************************************/ + +void +acpi_ev_disassociate_region_from_handler( + ACPI_OBJECT_INTERNAL *region_obj) +{ + ACPI_OBJECT_INTERNAL *handler_obj; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_OBJECT_INTERNAL **last_obj_ptr; + ADDRESS_SPACE_SETUP region_setup; + void *region_context; + ACPI_STATUS status; + + + /* + * Get the address handler from the region object + */ + + handler_obj = region_obj->region.addr_handler; + if (!handler_obj) { + /* + * This region has no handler, all done + */ + return; + } + + + /* + * Find this region in the handler's list + */ + + obj_desc = handler_obj->addr_handler.region_list; + last_obj_ptr = &handler_obj->addr_handler.region_list; + + while (obj_desc) { + /* + * See if this is the one + */ + if (obj_desc == region_obj) { + /* + * This is it, remove it from the handler's list + */ + *last_obj_ptr = obj_desc->region.link; + + /* + * Now stop region accesses by executing the _REG method + */ + acpi_ev_execute_reg_method (region_obj, 0); + + /* + * Call the setup handler with the deactivate notification + */ + region_setup = handler_obj->addr_handler.setup; + status = region_setup (region_obj, ACPI_REGION_DEACTIVATE, + handler_obj->addr_handler.context, + ®ion_context); + + /* + * Save the returned context (It is the original context + * passed into Install) + */ + handler_obj->addr_handler.context = region_context; + + /* + * Init routine may fail, Just ignore errors + */ + + /* + * Remove handler reference in the region + * + * NOTE: this doesn't mean that the region goes away + * The region is just inaccessible as indicated to + * the _REG method + * + * If the region is on the handler's list + * this better be the region's handler + */ + ACPI_ASSERT (region_obj->region.addr_handler == handler_obj); + + region_obj->region.addr_handler = NULL; + + return; + + } /* found the right handler */ + + /* + * Move through the linked list of handlers + */ + last_obj_ptr = &obj_desc->region.link; + obj_desc = obj_desc->region.link; + } + + /* + * If we get here, the region was not in the handler's region list + */ + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_associate_region_and_handler + * + * PARAMETERS: Handler_obj - Handler Object + * Region_obj - Region Object + * + * RETURN: None + * + * DESCRIPTION: Create the association between the handler and the region + * this is a two way association. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ev_associate_region_and_handler( + ACPI_OBJECT_INTERNAL *handler_obj, + ACPI_OBJECT_INTERNAL *region_obj) +{ + ACPI_STATUS status; + + + ACPI_ASSERT (region_obj->region.space_id == handler_obj->addr_handler.space_id); + ACPI_ASSERT (region_obj->region.addr_handler == 0); + + /* + * Link this region to the front of the handler's list + */ + + region_obj->region.link = handler_obj->addr_handler.region_list; + handler_obj->addr_handler.region_list = region_obj; + + /* + * set the region's handler + */ + +/* + Handler_obj->Common.Reference_count = + (u16) (Handler_obj->Common.Reference_count + + Region_obj->Common.Reference_count - 1); +*/ + region_obj->region.addr_handler = handler_obj; + + /* + * Last thing, tell all users that this region is usable + */ + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ev_execute_reg_method (region_obj, 1); + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ev_addr_handler_helper + * + * PARAMETERS: Handle - Entry to be dumped + * Level - Nesting level of the handle + * Context - Passed into Acpi_ns_walk_namespace + * + * DESCRIPTION: This routine checks to see if the object is a Region if it + * is then the address handler is installed in it. + * + * If the Object is a Device, and the device has a handler of + * the same type then the search is terminated in that branch. + * + * This is because the existing handler is closer in proximity + * to any more regions than the one we are trying to install. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ev_addr_handler_helper ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value) +{ + ACPI_OBJECT_INTERNAL *handler_obj; + ACPI_OBJECT_INTERNAL *tmp_obj; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_NAMED_OBJECT *obj_entry; + ACPI_STATUS status; + + + handler_obj = (ACPI_OBJECT_INTERNAL *) context; + + /* Parameter validation */ + + if (!handler_obj) { + return (AE_OK); + } + + /* Convert and validate the device handle */ + + obj_entry = acpi_ns_convert_handle_to_entry (obj_handle); + if (!obj_entry) { + return (AE_BAD_PARAMETER); + } + + /* + * We only care about regions.and objects + * that can have address handlers + */ + + if ((obj_entry->type != ACPI_TYPE_DEVICE) && + (obj_entry->type != ACPI_TYPE_REGION) && + (obj_entry != acpi_gbl_root_object)) + { + return (AE_OK); + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) obj_entry); + if (!obj_desc) { + /* + * The object DNE, we don't care about it + */ + return (AE_OK); + } + + /* + * Devices are handled different than regions + */ + if (IS_THIS_OBJECT_TYPE (obj_desc, ACPI_TYPE_DEVICE)) { + /* + * See if this guy has any handlers + */ + tmp_obj = obj_desc->device.addr_handler; + while (tmp_obj) { + /* + * Now let's see if it's for the same address space. + */ + if (tmp_obj->addr_handler.space_id == handler_obj->addr_handler.space_id) { + /* + * It's for the same address space + */ + + /* + * Since the object we found it on was a device, then it + * means that someone has already installed a handler for + * the branch of the namespace from this device on. Just + * bail out telling the walk routine to not traverse this + * branch. This preserves the scoping rule for handlers. + */ + return (AE_CTRL_DEPTH); + } + + /* + * Move through the linked list of handlers + */ + tmp_obj = tmp_obj->addr_handler.link; + } + + /* + * As long as the device didn't have a handler for this + * space we don't care about it. We just ignore it and + * proceed. + */ + return (AE_OK); + } + + /* + * Only here if it was a region + */ + ACPI_ASSERT (obj_desc->common.type == ACPI_TYPE_REGION); + + if (obj_desc->region.space_id != handler_obj->addr_handler.space_id) { + /* + * This region is for a different address space + * ignore it + */ + return (AE_OK); + } + + /* + * Now we have a region and it is for the handler's address + * space type. + * + * First disconnect region for any previous handler (if any) + */ + acpi_ev_disassociate_region_from_handler (obj_desc); + + /* + * Then connect the region to the new handler + */ + status = acpi_ev_associate_region_and_handler (handler_obj, obj_desc); + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/events/evrgnini.c linux/drivers/acpi/events/evrgnini.c --- v2.4.0-test2/linux/drivers/acpi/events/evrgnini.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/events/evrgnini.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,425 @@ +/****************************************************************************** + * + * Module Name: evrgnini- ACPI Address_space / Op_region init + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "events.h" +#include "namesp.h" +#include "interp.h" +#include "amlcode.h" + +#define _COMPONENT EVENT_HANDLING + MODULE_NAME ("evrgnini"); + + +/***************************************************************************** + * + * FUNCTION: Acpi_ev_system_memory_region_setup + * + * PARAMETERS: Region_obj - region we are interested in + * Function - start or stop + * Handler_context - Address space handler context + * Returned context - context to be used with each call to the + * handler for this region + * RETURN: Status + * + * DESCRIPTION: Do any prep work for region handling, a nop for now + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ev_system_memory_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **return_context) +{ + MEM_HANDLER_CONTEXT *mem_context; + ACPI_OBJECT_INTERNAL *region_obj = (ACPI_OBJECT_INTERNAL *) handle; + + + if (function == ACPI_REGION_DEACTIVATE) { + region_obj->region.region_flags &= ~(REGION_INITIALIZED); + + *return_context = NULL; + if (handler_context) { + mem_context = handler_context; + *return_context = mem_context->handler_context; + + acpi_cm_free (mem_context); + } + return (AE_OK); + } + + + /* Activate. Create a new context */ + + mem_context = acpi_cm_callocate (sizeof (MEM_HANDLER_CONTEXT)); + if (!mem_context) { + return (AE_NO_MEMORY); + } + + /* Init. (Mapping fields are all set to zeros above) */ + + mem_context->handler_context = handler_context; + region_obj->region.region_flags |= REGION_INITIALIZED; + + *return_context = mem_context; + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ev_io_space_region_setup + * + * PARAMETERS: Region_obj - region we are interested in + * Function - start or stop + * Handler_context - Address space handler context + * Returned context - context to be used with each call to the + * handler for this region + * RETURN: Status + * + * DESCRIPTION: Do any prep work for region handling + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ev_io_space_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **return_context) +{ + ACPI_OBJECT_INTERNAL *region_obj = (ACPI_OBJECT_INTERNAL *) handle; + + + if (function == ACPI_REGION_DEACTIVATE) { + region_obj->region.region_flags &= ~(REGION_INITIALIZED); + *return_context = handler_context; + return (AE_OK); + } + + /* Activate the region */ + + region_obj->region.region_flags |= REGION_INITIALIZED; + *return_context = handler_context; + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ev_pci_config_region_setup + * + * PARAMETERS: Region_obj - region we are interested in + * Function - start or stop + * Handler_context - Address space handler context + * Returned context - context to be used with each call to the + * handler for this region + * RETURN: Status + * + * DESCRIPTION: Do any prep work for region handling + * + * MUTEX: Assumes namespace is locked + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ev_pci_config_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **return_context) +{ + ACPI_STATUS status = AE_OK; + u32 temp; + PCI_HANDLER_CONTEXT *pci_context; + ACPI_OBJECT_INTERNAL *handler_obj; + ACPI_NAMED_OBJECT *search_scope; + ACPI_OBJECT_INTERNAL *region_obj = (ACPI_OBJECT_INTERNAL *) handle; + + + handler_obj = region_obj->region.addr_handler; + + if (!handler_obj) { + /* + * No installed handler. This shouldn't happen because the dispatch + * routine checks before we get here, but we check again just in case. + */ + return(AE_EXIST); + } + + if (function == ACPI_REGION_DEACTIVATE) { + region_obj->region.region_flags &= ~(REGION_INITIALIZED); + + *return_context = NULL; + if (handler_context) { + pci_context = handler_context; + *return_context = pci_context->handler_context; + + acpi_cm_free (pci_context); + } + + return (status); + } + + + /* Create a new context */ + + pci_context = acpi_cm_allocate (sizeof(PCI_HANDLER_CONTEXT)); + if (!pci_context) { + return (AE_NO_MEMORY); + } + + /* + * For PCI Config space access, we have to pass the segment, bus, + * device and function numbers. This routine must acquire those. + */ + + /* + * First get device and function numbers from the _ADR object + * in the parent's scope. + */ + ACPI_ASSERT(region_obj->region.nte); + + search_scope = acpi_ns_get_parent_entry (region_obj->region.nte); + + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + /* Acpi_evaluate the _ADR object */ + + status = acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR, search_scope, &temp); + /* + * The default is zero, since the allocation above zeroed the data, just + * do nothing on failures. + */ + if (ACPI_SUCCESS (status)) { + /* + * Got it.. + */ + pci_context->dev_func = temp; + } + + /* + * Get the _SEG and _BBN values from the device upon which the handler + * is installed. + * + * We need to get the _SEG and _BBN objects relative to the PCI BUS device. + * This is the device the handler has been registered to handle. + */ + + search_scope = handler_obj->addr_handler.nte; + + status = acpi_cm_evaluate_numeric_object (METHOD_NAME__SEG, search_scope, &temp); + if (ACPI_SUCCESS (status)) { + /* + * Got it.. + */ + pci_context->seg = temp; + } + + status = acpi_cm_evaluate_numeric_object (METHOD_NAME__BBN, search_scope, &temp); + if (ACPI_SUCCESS (status)) { + /* + * Got it.. + */ + pci_context->bus = temp; + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + *return_context = pci_context; + + region_obj->region.region_flags |= REGION_INITIALIZED; + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ev_default_region_setup + * + * PARAMETERS: Region_obj - region we are interested in + * Function - start or stop + * Handler_context - Address space handler context + * Returned context - context to be used with each call to the + * handler for this region + * RETURN: Status + * + * DESCRIPTION: Do any prep work for region handling + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ev_default_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **return_context) +{ + ACPI_OBJECT_INTERNAL *region_obj = (ACPI_OBJECT_INTERNAL *) handle; + + + if (function == ACPI_REGION_DEACTIVATE) { + region_obj->region.region_flags &= ~(REGION_INITIALIZED); + *return_context = NULL; + } + else { + region_obj->region.region_flags |= REGION_INITIALIZED; + *return_context = handler_context; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_initialize_region + * + * PARAMETERS: Region_obj - Region we are initializing + * + * RETURN: Status + * + * DESCRIPTION: Initializes the region, finds any _REG methods and saves them + * for execution at a later time + * + * Get the appropriate address space handler for a newly + * created region. + * + * This also performs address space specific intialization. For + * example, PCI regions must have an _ADR object that contains + * a PCI address in the scope of the defintion. This address is + * required to perform an access to PCI config space. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ev_initialize_region ( + ACPI_OBJECT_INTERNAL *region_obj, + u8 acpi_ns_locked) +{ + ACPI_OBJECT_INTERNAL *handler_obj; + ACPI_OBJECT_INTERNAL *obj_desc; + u32 space_id; + ACPI_NAMED_OBJECT *entry; /* Namespace Object */ + ACPI_STATUS status; + ACPI_NAMED_OBJECT *reg_entry; + ACPI_NAME *reg_name_ptr = (ACPI_NAME *) METHOD_NAME__REG; + + + if (!region_obj) { + return (AE_BAD_PARAMETER); + } + + ACPI_ASSERT(region_obj->region.nte); + + entry = acpi_ns_get_parent_entry (region_obj->region.nte); + space_id = region_obj->region.space_id; + + region_obj->region.addr_handler = NULL; + region_obj->region.REGmethod = NULL; + region_obj->region.region_flags = INITIAL_REGION_FLAGS; + + /* + * Find any "_REG" associated with this region definition + */ + status = acpi_ns_search_one_scope (*reg_name_ptr, entry->child_table, + ACPI_TYPE_METHOD, ®_entry, NULL); + if (status == AE_OK) { + /* + * The _REG method is optional and there can be only one per region + * definition. This will be executed when the handler is attached + * or removed + */ + region_obj->region.REGmethod = reg_entry; + } + + /* + * The following loop depends upon the root nte having no parent + * ie: Acpi_gbl_Root_object->Parent_entry being set to NULL + */ + while (entry) { + /* + * Check to see if a handler exists + */ + handler_obj = NULL; + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) entry); + if (obj_desc) { + /* + * can only be a handler if the object exists + */ + switch (entry->type) + { + case ACPI_TYPE_DEVICE: + + handler_obj = obj_desc->device.addr_handler; + break; + + case ACPI_TYPE_PROCESSOR: + + handler_obj = obj_desc->processor.addr_handler; + break; + + case ACPI_TYPE_THERMAL: + + handler_obj = obj_desc->thermal_zone.addr_handler; + break; + } + + while (handler_obj) { + /* + * This guy has at least one address handler + * see if it has the type we want + */ + if (handler_obj->addr_handler.space_id == space_id) { + /* + * Found it! Now update the region and the handler + */ + acpi_ev_associate_region_and_handler(handler_obj, region_obj); + return (AE_OK); + } + + handler_obj = handler_obj->addr_handler.link; + + } /* while handlerobj */ + } + + /* + * This one does not have the handler we need + * Pop up one level + */ + entry = acpi_ns_get_parent_entry (entry); + + } /* while Entry != ROOT */ + + /* + * If we get here, there is no handler for this region + */ + return (AE_NOT_EXIST); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/events/evsci.c linux/drivers/acpi/events/evsci.c --- v2.4.0-test2/linux/drivers/acpi/events/evsci.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/events/evsci.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,302 @@ +/****************************************************************************** + * + * Module Name: evsci - System Control Interrupt configuration and + * legacy to ACPI mode state transition functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "namesp.h" +#include "hardware.h" +#include "events.h" + + +#define _COMPONENT EVENT_HANDLING + MODULE_NAME ("evsci"); + + +/* + * Elements correspond to counts for + * TMR, NOT_USED, GBL, PWR_BTN, SLP_BTN, RTC, + * and GENERAL respectively. These counts + * are modified by the ACPI interrupt handler... + * Note that GENERAL should probably be split out + * into one element for each bit in the GPE + * registers + */ + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_sci_handler + * + * PARAMETERS: none + * + * RETURN: Status code indicates whether interrupt was handled. + * + * DESCRIPTION: Interrupt handler that will figure out what function or + * control method to call to deal with a SCI. Installed + * using BU interrupt support. + * + ******************************************************************************/ + +u32 +acpi_ev_sci_handler (void *context) +{ + u32 interrupt_handled = INTERRUPT_NOT_HANDLED; + + /* + * ACPI Enabled? + * ------------- + * Make sure that ACPI is enabled by checking SCI_EN. Note that we are + * required to treat the SCI interrupt as sharable, level, active low. + */ + if (!acpi_hw_register_access (ACPI_READ, ACPI_MTX_DO_NOT_LOCK, (s32)SCI_EN)) { + REPORT_ERROR ("Received and SCI but ACPI is not enabled."); + return (INTERRUPT_NOT_HANDLED); + } + + /* + * Fixed Acpi_events: + * ------------- + * Check for and dispatch any Fixed Acpi_events that have occurred + */ + interrupt_handled |= acpi_ev_fixed_event_detect (); + + /* + * GPEs: + * ----- + * Check for and dispatch any GPEs that have occurred + */ + interrupt_handled |= acpi_ev_gpe_detect (); + + return (interrupt_handled); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_install_sci_handler + * + * PARAMETERS: none + * + * RETURN: Status + * + * DESCRIPTION: Installs SCI handler. + * + ******************************************************************************/ + +u32 +acpi_ev_install_sci_handler (void) +{ + u32 except = AE_OK; + + except = acpi_os_install_interrupt_handler ( + (u32) acpi_gbl_FACP->sci_int, + acpi_ev_sci_handler, + NULL); + + return (except); +} + + +/****************************************************************************** + + * + * FUNCTION: Acpi_ev_remove_sci_handler + * + * PARAMETERS: none + * + * RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not + * installed to begin with + * + * DESCRIPTION: Restores original status of all fixed event enable bits and + * removes SCI handler. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ev_remove_sci_handler (void) +{ +#if 0 + /* TBD:[Investigate] Figure this out!! Disable all events first ??? */ + + if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (TMR_FIXED_EVENT)) { + acpi_event_disable_event (TMR_FIXED_EVENT); + } + + if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (GBL_FIXED_EVENT)) { + acpi_event_disable_event (GBL_FIXED_EVENT); + } + + if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (PWR_BTN_FIXED_EVENT)) { + acpi_event_disable_event (PWR_BTN_FIXED_EVENT); + } + + if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (SLP_BTN_FIXED_EVENT)) { + acpi_event_disable_event (SLP_BTN_FIXED_EVENT); + } + + if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (RTC_FIXED_EVENT)) { + acpi_event_disable_event (RTC_FIXED_EVENT); + } + + original_fixed_enable_bit_status = 0; + +#endif + + acpi_os_remove_interrupt_handler ( + (u32) acpi_gbl_FACP->sci_int, + acpi_ev_sci_handler); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_sci_count + * + * PARAMETERS: char * Event_name name (fully qualified name from namespace + * or one of the fixed event names defined above) + * of the event to check if it's generated an SCI. + * + * RETURN: Number of SCI's for requested event since last time i_sci_occured() + * was called for this event. + * + * DESCRIPTION: Checks to see if SCI has been generated from requested source + * since the last time this function was called. + * + ******************************************************************************/ + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_restore_acpi_state + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Restore the original ACPI state of the machine + * + ******************************************************************************/ + +void +acpi_ev_restore_acpi_state (void) +{ + s32 index; + + + /* Restore the state of the chipset enable bits. */ + + if (acpi_gbl_restore_acpi_chipset == TRUE) { + /* Restore the fixed events */ + + if (acpi_os_in16 (acpi_gbl_FACP->pm1a_evt_blk + 2) != + acpi_gbl_pm1_enable_register_save) + { + acpi_os_out16 ((acpi_gbl_FACP->pm1a_evt_blk + 2), + acpi_gbl_pm1_enable_register_save); + } + + if (acpi_gbl_FACP->pm1b_evt_blk) { + if (acpi_os_in16 (acpi_gbl_FACP->pm1b_evt_blk + 2) != + acpi_gbl_pm1_enable_register_save) + { + acpi_os_out16 ((acpi_gbl_FACP->pm1b_evt_blk + 2), + acpi_gbl_pm1_enable_register_save); + } + } + + + /* Ensure that all status bits are clear */ + + acpi_hw_clear_acpi_status (); + + + /* Now restore the GPEs */ + + for (index = 0; index < DIV_2 (acpi_gbl_FACP->gpe0blk_len); index++) { + if (acpi_os_in8 (acpi_gbl_FACP->gpe0blk + + DIV_2 (acpi_gbl_FACP->gpe0blk_len)) != + acpi_gbl_gpe0enable_register_save[index]) + { + acpi_os_out8 ((acpi_gbl_FACP->gpe0blk + + DIV_2 (acpi_gbl_FACP->gpe0blk_len)), + acpi_gbl_gpe0enable_register_save[index]); + } + } + + if (acpi_gbl_FACP->gpe1_blk && acpi_gbl_FACP->gpe1_blk_len) { + for (index = 0; index < DIV_2 (acpi_gbl_FACP->gpe1_blk_len); index++) { + if (acpi_os_in8 (acpi_gbl_FACP->gpe1_blk + + DIV_2 (acpi_gbl_FACP->gpe1_blk_len)) != + acpi_gbl_gpe1_enable_register_save[index]) + { + acpi_os_out8 ((acpi_gbl_FACP->gpe1_blk + + DIV_2 (acpi_gbl_FACP->gpe1_blk_len)), + acpi_gbl_gpe1_enable_register_save[index]); + } + } + } + + if (acpi_hw_get_mode() != acpi_gbl_original_mode) { + acpi_hw_set_mode (acpi_gbl_original_mode); + } + } + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_terminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: free memory allocated for table storage. + * + ******************************************************************************/ + +void +acpi_ev_terminate (void) +{ + + /* + * Free global tables, etc. + */ + + if (acpi_gbl_gpe_registers) { + acpi_cm_free (acpi_gbl_gpe_registers); + } + + if (acpi_gbl_gpe_info) { + acpi_cm_free (acpi_gbl_gpe_info); + } + + return; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/events/evxface.c linux/drivers/acpi/events/evxface.c --- v2.4.0-test2/linux/drivers/acpi/events/evxface.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/events/evxface.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,604 @@ +/****************************************************************************** + * + * Module Name: evxface - External interfaces for ACPI events + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "hardware.h" +#include "namesp.h" +#include "events.h" +#include "amlcode.h" +#include "interp.h" + +#define _COMPONENT EVENT_HANDLING + MODULE_NAME ("evxface"); + + +/****************************************************************************** + * + * FUNCTION: Acpi_install_fixed_event_handler + * + * PARAMETERS: Event - Event type to enable. + * Handler - Pointer to the handler function for the + * event + * Context - Value passed to the handler on each GPE + * + * RETURN: Status + * + * DESCRIPTION: Saves the pointer to the handler function and then enables the + * event. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_install_fixed_event_handler ( + u32 event, + FIXED_EVENT_HANDLER handler, + void *context) +{ + ACPI_STATUS status = AE_OK; + + + /* Sanity check the parameters. */ + + if (event >= NUM_FIXED_EVENTS) { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + + /* Don't allow two handlers. */ + + if (NULL != acpi_gbl_fixed_event_handlers[event].handler) { + status = AE_EXIST; + goto cleanup; + } + + + /* Install the handler before enabling the event - just in case... */ + + acpi_gbl_fixed_event_handlers[event].handler = handler; + acpi_gbl_fixed_event_handlers[event].context = context; + + if (1 != acpi_hw_register_access (ACPI_WRITE, + ACPI_MTX_LOCK, event + TMR_EN, 1)) + { + /* Remove the handler */ + + acpi_gbl_fixed_event_handlers[event].handler = NULL; + acpi_gbl_fixed_event_handlers[event].context = NULL; + + status = AE_ERROR; + goto cleanup; + } + + +cleanup: + acpi_cm_release_mutex (ACPI_MTX_EVENTS); + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_remove_fixed_event_handler + * + * PARAMETERS: Event - Event type to disable. + * Handler - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Disables the event and unregisters the event handler. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_remove_fixed_event_handler ( + u32 event, + FIXED_EVENT_HANDLER handler) +{ + ACPI_STATUS status = AE_OK; + + + /* Sanity check the parameters. */ + + if (event >= NUM_FIXED_EVENTS) { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + + /* Disable the event before removing the handler - just in case... */ + + if (0 != acpi_hw_register_access (ACPI_WRITE, + ACPI_MTX_LOCK, event + TMR_EN, 0)) + { + status = AE_ERROR; + goto cleanup; + } + + /* Remove the handler */ + + acpi_gbl_fixed_event_handlers[event].handler = NULL; + acpi_gbl_fixed_event_handlers[event].context = NULL; + +cleanup: + acpi_cm_release_mutex (ACPI_MTX_EVENTS); + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_install_notify_handler + * + * PARAMETERS: Device - The device for which notifies will be handled + * Handler_type - The type of handler: + * ACPI_SYSTEM_NOTIFY: System_handler (00-7f) + * ACPI_DEVICE_NOTIFY: Driver_handler (80-ff) + * Handler - Address of the handler + * Context - Value passed to the handler on each GPE + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for notifies on an ACPI device + * + ******************************************************************************/ + +ACPI_STATUS +acpi_install_notify_handler ( + ACPI_HANDLE device, + u32 handler_type, + NOTIFY_HANDLER handler, + void *context) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_OBJECT_INTERNAL *notify_obj; + ACPI_NAMED_OBJECT *obj_entry; + ACPI_STATUS status = AE_OK; + + + /* Parameter validation */ + + if ((!handler) || + (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) + { + return (AE_BAD_PARAMETER); + } + + /* Convert and validate the device handle */ + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + obj_entry = acpi_ns_convert_handle_to_entry (device); + if (!obj_entry) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + + /* + * Support for global notify handlers. These handlers are invoked for + * every notifiy of the type specifiec + */ + + if (device == ACPI_ROOT_OBJECT) { + /* + * Make sure the handler is not already installed. + */ + + if (((handler_type == ACPI_SYSTEM_NOTIFY) && + acpi_gbl_sys_notify.handler) || + ((handler_type == ACPI_DEVICE_NOTIFY) && + acpi_gbl_drv_notify.handler)) + { + status = AE_EXIST; + goto unlock_and_exit; + } + + if (handler_type == ACPI_SYSTEM_NOTIFY) { + acpi_gbl_sys_notify.nte = obj_entry; + acpi_gbl_sys_notify.handler = handler; + acpi_gbl_sys_notify.context = context; + } + + else { + acpi_gbl_drv_notify.nte = obj_entry; + acpi_gbl_drv_notify.handler = handler; + acpi_gbl_drv_notify.context = context; + } + + + /* Global notify handler installed */ + + goto unlock_and_exit; + } + + + /* + * These are the ONLY objects that can receive ACPI notifications + */ + + if ((obj_entry->type != ACPI_TYPE_DEVICE) && + (obj_entry->type != ACPI_TYPE_PROCESSOR) && + (obj_entry->type != ACPI_TYPE_POWER) && + (obj_entry->type != ACPI_TYPE_THERMAL)) + { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) obj_entry); + if (obj_desc) { + /* + * The object exists. + * Make sure the handler is not already installed. + */ + + if (((handler_type == ACPI_SYSTEM_NOTIFY) && + obj_desc->device.sys_handler) || + ((handler_type == ACPI_DEVICE_NOTIFY) && + obj_desc->device.drv_handler)) + { + status = AE_EXIST; + goto unlock_and_exit; + } + } + + else { + /* Create a new object */ + + obj_desc = acpi_cm_create_internal_object (obj_entry->type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Attach new object to the NTE */ + + status = acpi_ns_attach_object (device, obj_desc, (u8) obj_entry->type); + + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + } + + + /* + * If we get here, we know that there is no handler installed + * so let's party + */ + notify_obj = acpi_cm_create_internal_object (INTERNAL_TYPE_NOTIFY); + if (!notify_obj) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + notify_obj->notify_handler.nte = obj_entry; + notify_obj->notify_handler.handler = handler; + notify_obj->notify_handler.context = context; + + + if (handler_type == ACPI_SYSTEM_NOTIFY) { + obj_desc->device.sys_handler = notify_obj; + } + + else { + obj_desc->device.drv_handler = notify_obj; + } + + +unlock_and_exit: + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_remove_notify_handler + * + * PARAMETERS: Device - The device for which notifies will be handled + * Handler_type - The type of handler: + * ACPI_SYSTEM_NOTIFY: System_handler (00-7f) + * ACPI_DEVICE_NOTIFY: Driver_handler (80-ff) + * Handler - Address of the handler + * RETURN: Status + * + * DESCRIPTION: Remove a handler for notifies on an ACPI device + * + ******************************************************************************/ + +ACPI_STATUS +acpi_remove_notify_handler ( + ACPI_HANDLE device, + u32 handler_type, + NOTIFY_HANDLER handler) +{ + ACPI_OBJECT_INTERNAL *notify_obj; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_NAMED_OBJECT *obj_entry; + ACPI_STATUS status = AE_OK; + + + /* Parameter validation */ + + if ((!handler) || + (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) + { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* Convert and validate the device handle */ + + obj_entry = acpi_ns_convert_handle_to_entry (device); + if (!obj_entry) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* + * These are the ONLY objects that can receive ACPI notifications + */ + + if ((obj_entry->type != ACPI_TYPE_DEVICE) && + (obj_entry->type != ACPI_TYPE_PROCESSOR) && + (obj_entry->type != ACPI_TYPE_POWER) && + (obj_entry->type != ACPI_TYPE_THERMAL)) + { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) obj_entry); + if (!obj_desc) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } + + /* + * The object exists. + * + * Make sure the handler is installed. + */ + + if (handler_type == ACPI_SYSTEM_NOTIFY) { + notify_obj = obj_desc->device.sys_handler; + } + else { + notify_obj = obj_desc->device.drv_handler; + } + + if ((!notify_obj) || + (notify_obj->notify_handler.handler != handler)) + { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* + * Now we can remove the handler + */ + if (handler_type == ACPI_SYSTEM_NOTIFY) { + obj_desc->device.sys_handler = NULL; + } + else { + obj_desc->device.drv_handler = NULL; + } + + acpi_cm_remove_reference (notify_obj); + +unlock_and_exit: + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + +/****************************************************************************** + * + * FUNCTION: Acpi_install_gpe_handler + * + * PARAMETERS: Gpe_number - The GPE number. The numbering scheme is + * bank 0 first, then bank 1. + * Trigger - Whether this GPE should be treated as an + * edge- or level-triggered interrupt. + * Handler - Address of the handler + * Context - Value passed to the handler on each GPE + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for a General Purpose Acpi_event. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_install_gpe_handler ( + u32 gpe_number, + u32 type, + GPE_HANDLER handler, + void *context) +{ + ACPI_STATUS status = AE_OK; + + /* Parameter validation */ + + if (!handler || (gpe_number > NUM_GPE)) { + return (AE_BAD_PARAMETER); + } + + /* Ensure that we have a valid GPE number */ + + if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + + /* Make sure that there isn't a handler there already */ + + if (acpi_gbl_gpe_info[gpe_number].handler) { + status = AE_EXIST; + goto cleanup; + } + + /* Install the handler */ + + acpi_gbl_gpe_info[gpe_number].handler = handler; + acpi_gbl_gpe_info[gpe_number].context = context; + acpi_gbl_gpe_info[gpe_number].type = (u8) type; + + /* Clear the GPE (of stale events), the enable it */ + + acpi_hw_clear_gpe (gpe_number); + acpi_hw_enable_gpe (gpe_number); + +cleanup: + acpi_cm_release_mutex (ACPI_MTX_EVENTS); + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_remove_gpe_handler + * + * PARAMETERS: Gpe_number - The event to remove a handler + * Handler - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Remove a handler for a General Purpose Acpi_event. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_remove_gpe_handler ( + u32 gpe_number, + GPE_HANDLER handler) +{ + ACPI_STATUS status = AE_OK; + + + /* Parameter validation */ + + if (!handler || (gpe_number > NUM_GPE)) { + return (AE_BAD_PARAMETER); + } + + /* Ensure that we have a valid GPE number */ + + if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { + return (AE_BAD_PARAMETER); + } + + /* Disable the GPE before removing the handler */ + + acpi_hw_disable_gpe (gpe_number); + + acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + + /* Make sure that the installed handler is the same */ + + if (acpi_gbl_gpe_info[gpe_number].handler != handler) { + acpi_hw_enable_gpe (gpe_number); + status = AE_BAD_PARAMETER; + goto cleanup; + } + + /* Remove the handler */ + + acpi_gbl_gpe_info[gpe_number].handler = NULL; + acpi_gbl_gpe_info[gpe_number].context = NULL; + +cleanup: + acpi_cm_release_mutex (ACPI_MTX_EVENTS); + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_acquire_global_lock + * + * PARAMETERS: Timeout - How long the caller is willing to wait + * Out_handle - A handle to the lock if acquired + * + * RETURN: Status + * + * DESCRIPTION: Acquire the ACPI Global Lock + * + ******************************************************************************/ + +ACPI_STATUS +acpi_acquire_global_lock ( + u32 timeout, + u32 *out_handle) +{ + ACPI_STATUS status; + + + acpi_aml_enter_interpreter (); + + /* + * TBD: [Restructure] add timeout param to internal interface, and + * perhaps INTERPRETER_LOCKED + */ + + status = acpi_ev_acquire_global_lock (); + acpi_aml_exit_interpreter (); + + *out_handle = 0; + return status; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_release_global_lock + * + * PARAMETERS: Handle - Returned from Acpi_acquire_global_lock + * + * RETURN: Status + * + * DESCRIPTION: Release the ACPI Global Lock + * + ******************************************************************************/ + +ACPI_STATUS +acpi_release_global_lock ( + u32 handle) +{ + + + /* TBD: [Restructure] Validate handle */ + + acpi_ev_release_global_lock (); + return AE_OK; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/events/evxfevnt.c linux/drivers/acpi/events/evxfevnt.c --- v2.4.0-test2/linux/drivers/acpi/events/evxfevnt.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/events/evxfevnt.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,513 @@ +/****************************************************************************** + * + * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "hardware.h" +#include "namesp.h" +#include "events.h" +#include "amlcode.h" +#include "interp.h" + +#define _COMPONENT EVENT_HANDLING + MODULE_NAME ("evxfevnt"); + + +/************************************************************************** + * + * FUNCTION: Acpi_enable + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Ensures that the system control interrupt (SCI) is properly + * configured, disables SCI event sources, installs the SCI + * handler, and transfers the system into ACPI mode. + * + *************************************************************************/ + +ACPI_STATUS +acpi_enable (void) +{ + ACPI_STATUS status; + + + /* Make sure we've got ACPI tables */ + + if (!acpi_gbl_DSDT) { + return (AE_NO_ACPI_TABLES); + } + + /* Make sure the BIOS supports ACPI mode */ + + if (SYS_MODE_LEGACY == acpi_hw_get_mode_capabilities()) { + return (AE_ERROR); + } + + acpi_gbl_original_mode = acpi_hw_get_mode(); + + /* + * Initialize the Fixed and General Purpose Acpi_events prior. This is + * done prior to enabling SCIs to prevent interrupts from occuring + * before handers are installed. + */ + + if (ACPI_FAILURE (acpi_ev_fixed_event_initialize ())) { + return (AE_ERROR); + } + + if (ACPI_FAILURE (acpi_ev_gpe_initialize())) { + return (AE_ERROR); + } + + /* Install the SCI handler */ + + if (ACPI_FAILURE (acpi_ev_install_sci_handler ())) { + return (AE_ERROR); + } + + /* Transition to ACPI mode */ + + if (AE_OK != acpi_hw_set_mode (SYS_MODE_ACPI)) { + return (AE_ERROR); + } + + /* Install handlers for control method GPE handlers (_Lxx, _Exx) */ + + acpi_ev_init_gpe_control_methods (); + + status = acpi_ev_init_global_lock_handler (); + + return (status); +} + + +/************************************************************************** + * + * FUNCTION: Acpi_disable + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Returns the system to original ACPI/legacy mode, and + * uninstalls the SCI interrupt handler. + * + *************************************************************************/ + +ACPI_STATUS +acpi_disable (void) +{ + + + /* Restore original mode */ + + if (AE_OK != acpi_hw_set_mode (acpi_gbl_original_mode)) { + return (AE_ERROR); + } + + /* Unload the SCI interrupt handler */ + + acpi_ev_remove_sci_handler (); + acpi_ev_restore_acpi_state (); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_enable_event + * + * PARAMETERS: Event - The fixed event or GPE to be enabled + * Type - The type of event + * + * RETURN: Status + * + * DESCRIPTION: Enable an ACPI event (fixed and general purpose) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_enable_event ( + u32 event, + u32 type) +{ + ACPI_STATUS status = AE_OK; + u32 register_id; + + + /* The Type must be either Fixed Acpi_event or GPE */ + + switch (type) + { + + case ACPI_EVENT_FIXED: + + /* Decode the Fixed Acpi_event */ + + switch (event) + { + case ACPI_EVENT_PMTIMER: + register_id = TMR_EN; + break; + + case ACPI_EVENT_GLOBAL: + register_id = GBL_EN; + break; + + case ACPI_EVENT_POWER_BUTTON: + register_id = PWRBTN_EN; + break; + + case ACPI_EVENT_SLEEP_BUTTON: + register_id = SLPBTN_EN; + break; + + case ACPI_EVENT_RTC: + register_id = RTC_EN; + break; + + default: + return (AE_BAD_PARAMETER); + break; + } + + /* + * Enable the requested fixed event (by writing a one to the + * enable register bit) + */ + + acpi_hw_register_access (ACPI_WRITE, TRUE, register_id, 1); + break; + + + case ACPI_EVENT_GPE: + + /* Ensure that we have a valid GPE number */ + + if ((event >= NUM_GPE) || + (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) + { + return (AE_BAD_PARAMETER); + } + + + /* Enable the requested GPE number */ + + acpi_hw_enable_gpe (event); + break; + + + default: + + status = AE_BAD_PARAMETER; + } + + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_disable_event + * + * PARAMETERS: Event - The fixed event or GPE to be enabled + * Type - The type of event + * + * RETURN: Status + * + * DESCRIPTION: Disable an ACPI event (fixed and general purpose) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_disable_event ( + u32 event, + u32 type) +{ + ACPI_STATUS status = AE_OK; + u32 register_id; + + + /* The Type must be either Fixed Acpi_event or GPE */ + + switch (type) + { + + case ACPI_EVENT_FIXED: + + /* Decode the Fixed Acpi_event */ + + switch (event) + { + case ACPI_EVENT_PMTIMER: + register_id = TMR_EN; + break; + + case ACPI_EVENT_GLOBAL: + register_id = GBL_EN; + break; + + case ACPI_EVENT_POWER_BUTTON: + register_id = PWRBTN_EN; + break; + + case ACPI_EVENT_SLEEP_BUTTON: + register_id = SLPBTN_EN; + break; + + case ACPI_EVENT_RTC: + register_id = RTC_EN; + break; + + default: + return (AE_BAD_PARAMETER); + break; + } + + /* + * Disable the requested fixed event (by writing a zero to the + * enable register bit) + */ + + acpi_hw_register_access (ACPI_WRITE, TRUE, register_id, 0); + break; + + + case ACPI_EVENT_GPE: + + /* Ensure that we have a valid GPE number */ + + if ((event >= NUM_GPE) || + (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) + { + return (AE_BAD_PARAMETER); + } + + /* Disable the requested GPE number */ + + acpi_hw_disable_gpe (event); + break; + + + default: + status = AE_BAD_PARAMETER; + } + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_clear_event + * + * PARAMETERS: Event - The fixed event or GPE to be cleared + * Type - The type of event + * + * RETURN: Status + * + * DESCRIPTION: Clear an ACPI event (fixed and general purpose) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_clear_event ( + u32 event, + u32 type) +{ + ACPI_STATUS status = AE_OK; + u32 register_id; + + + /* The Type must be either Fixed Acpi_event or GPE */ + + switch (type) + { + + case ACPI_EVENT_FIXED: + + /* Decode the Fixed Acpi_event */ + + switch (event) + { + case ACPI_EVENT_PMTIMER: + register_id = TMR_STS; + break; + + case ACPI_EVENT_GLOBAL: + register_id = GBL_STS; + break; + + case ACPI_EVENT_POWER_BUTTON: + register_id = PWRBTN_STS; + break; + + case ACPI_EVENT_SLEEP_BUTTON: + register_id = SLPBTN_STS; + break; + + case ACPI_EVENT_RTC: + register_id = RTC_STS; + break; + + default: + return (AE_BAD_PARAMETER); + break; + } + + /* + * Clear the requested fixed event (By writing a one to the + * status register bit) + */ + + acpi_hw_register_access (ACPI_WRITE, TRUE, register_id, 1); + break; + + + case ACPI_EVENT_GPE: + + /* Ensure that we have a valid GPE number */ + + if ((event >= NUM_GPE) || + (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) + { + return (AE_BAD_PARAMETER); + } + + + acpi_hw_clear_gpe (event); + break; + + + default: + + status = AE_BAD_PARAMETER; + } + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_event_status + * + * PARAMETERS: Event - The fixed event or GPE + * Type - The type of event + * Status - Where the current status of the event will + * be returned + * + * RETURN: Status + * + * DESCRIPTION: Obtains and returns the current status of the event + * + ******************************************************************************/ + + +ACPI_STATUS +acpi_get_event_status ( + u32 event, + u32 type, + ACPI_EVENT_STATUS *event_status) +{ + ACPI_STATUS status = AE_OK; + u32 register_id; + + + if (!event_status) { + return (AE_BAD_PARAMETER); + } + + + /* The Type must be either Fixed Acpi_event or GPE */ + + switch (type) + { + + case ACPI_EVENT_FIXED: + + /* Decode the Fixed Acpi_event */ + + switch (event) + { + case ACPI_EVENT_PMTIMER: + register_id = TMR_STS; + break; + + case ACPI_EVENT_GLOBAL: + register_id = GBL_STS; + break; + + case ACPI_EVENT_POWER_BUTTON: + register_id = PWRBTN_STS; + break; + + case ACPI_EVENT_SLEEP_BUTTON: + register_id = SLPBTN_STS; + break; + + case ACPI_EVENT_RTC: + register_id = RTC_STS; + break; + + default: + return (AE_BAD_PARAMETER); + break; + } + + /* Get the status of the requested fixed event */ + + *event_status = acpi_hw_register_access (ACPI_READ, TRUE, register_id); + break; + + + case ACPI_EVENT_GPE: + + /* Ensure that we have a valid GPE number */ + + if ((event >= NUM_GPE) || + (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) + { + return (AE_BAD_PARAMETER); + } + + + /* Obtain status on the requested GPE number */ + + acpi_hw_get_gpe_status (event, event_status); + break; + + + default: + status = AE_BAD_PARAMETER; + } + + + return (status); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/events/evxfregn.c linux/drivers/acpi/events/evxfregn.c --- v2.4.0-test2/linux/drivers/acpi/events/evxfregn.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/events/evxfregn.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,389 @@ +/****************************************************************************** + * + * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and + * Address Spaces. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "hardware.h" +#include "namesp.h" +#include "events.h" +#include "amlcode.h" +#include "interp.h" + +#define _COMPONENT EVENT_HANDLING + MODULE_NAME ("evxfregn"); + + +/****************************************************************************** + * + * FUNCTION: Acpi_install_address_space_handler + * + * PARAMETERS: Device - Handle for the device + * Space_id - The address space ID + * Handler - Address of the handler + * Context - Value passed to the handler on each access + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for accesses on an address space controlled + * a specific device. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_install_address_space_handler ( + ACPI_HANDLE device, + ACPI_ADDRESS_SPACE_TYPE space_id, + ADDRESS_SPACE_HANDLER handler, + ADDRESS_SPACE_SETUP setup, + void *context) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_OBJECT_INTERNAL *handler_obj; + ACPI_NAMED_OBJECT *obj_entry; + ACPI_STATUS status = AE_OK; + OBJECT_TYPE_INTERNAL type; + u16 flags = 0; + + + /* Parameter validation */ + + if ((!device) || + ((!handler) && (handler != ACPI_DEFAULT_HANDLER)) || + (space_id > ACPI_MAX_ADDRESS_SPACE)) + { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* Convert and validate the device handle */ + + obj_entry = acpi_ns_convert_handle_to_entry (device); + if (!obj_entry) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* + * This registration is valid for only the types below + * and the root. This is where the default handlers + * get placed. + */ + + if ((obj_entry->type != ACPI_TYPE_DEVICE) && + (obj_entry->type != ACPI_TYPE_PROCESSOR) && + (obj_entry->type != ACPI_TYPE_THERMAL) && + (obj_entry != acpi_gbl_root_object)) + { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + if (handler == ACPI_DEFAULT_HANDLER) { + flags = ADDR_HANDLER_DEFAULT_INSTALLED; + + switch (space_id) + { + case ADDRESS_SPACE_SYSTEM_MEMORY: + handler = acpi_aml_system_memory_space_handler; + setup = acpi_ev_system_memory_region_setup; + break; + + case ADDRESS_SPACE_SYSTEM_IO: + handler = acpi_aml_system_io_space_handler; + setup = acpi_ev_io_space_region_setup; + break; + + case ADDRESS_SPACE_PCI_CONFIG: + handler = acpi_aml_pci_config_space_handler; + setup = acpi_ev_pci_config_region_setup; + break; + + default: + status = AE_NOT_EXIST; + goto unlock_and_exit; + break; + } + } + + /* + * If the caller hasn't specified a setup routine, use the default + */ + if (!setup) { + setup = acpi_ev_default_region_setup; + } + + /* + * Check for an existing internal object + */ + + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) obj_entry); + if (obj_desc) { + /* + * The object exists. + * Make sure the handler is not already installed. + */ + + /* check the address handler the user requested */ + + handler_obj = obj_desc->device.addr_handler; + while (handler_obj) { + /* + * We have an Address handler, see if user requested this + * address space. + */ + if(handler_obj->addr_handler.space_id == space_id) { + status = AE_EXIST; + goto unlock_and_exit; + } + + /* + * Move through the linked list of handlers + */ + handler_obj = handler_obj->addr_handler.link; + } + } + + else { + /* Obj_desc does not exist, create one */ + + if (obj_entry->type == ACPI_TYPE_ANY) { + type = ACPI_TYPE_DEVICE; + } + + else { + type = obj_entry->type; + } + + obj_desc = acpi_cm_create_internal_object (type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Init new descriptor */ + + obj_desc->common.type = (u8) type; + + /* Attach the new object to the NTE */ + + status = acpi_ns_attach_object (device, obj_desc, (u8) type); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (obj_desc); + goto unlock_and_exit; + } + + /* TBD: [Investigate] Will this always be of type DEVICE? */ + + if (type == ACPI_TYPE_DEVICE) { + obj_desc->device.handle = device; + } + } + + /* + * Now we can install the handler + * + * At this point we know that there is no existing handler. + * So, we just allocate the object for the handler and link it + * into the list. + */ + handler_obj = acpi_cm_create_internal_object (INTERNAL_TYPE_ADDRESS_HANDLER); + if (!handler_obj) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + handler_obj->addr_handler.space_id = (u16) space_id; + handler_obj->addr_handler.hflags = flags; + handler_obj->addr_handler.link = obj_desc->device.addr_handler; + handler_obj->addr_handler.region_list = NULL; + handler_obj->addr_handler.nte = obj_entry; + handler_obj->addr_handler.handler = handler; + handler_obj->addr_handler.context = context; + handler_obj->addr_handler.setup = setup; + + /* + * Now walk the namespace finding all of the regions this + * handler will manage. + * + * We start at the device and search the branch toward + * the leaf nodes until either the leaf is encountered or + * a device is detected that has an address handler of the + * same type. + * + * In either case we back up and search down the remainder + * of the branch + */ + status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, + ACPI_INT32_MAX, NS_WALK_NO_UNLOCK, + acpi_ev_addr_handler_helper, + handler_obj, NULL); + + /* + * Place this handler 1st on the list + */ + + handler_obj->common.reference_count = + (u16) (handler_obj->common.reference_count + + obj_desc->common.reference_count - 1); + obj_desc->device.addr_handler = handler_obj; + + +unlock_and_exit: + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_remove_address_space_handler + * + * PARAMETERS: Space_id - The address space ID + * Handler - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for accesses on an Operation Region + * + ******************************************************************************/ + +ACPI_STATUS +acpi_remove_address_space_handler ( + ACPI_HANDLE device, + ACPI_ADDRESS_SPACE_TYPE space_id, + ADDRESS_SPACE_HANDLER handler) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_OBJECT_INTERNAL *handler_obj; + ACPI_OBJECT_INTERNAL *region_obj; + ACPI_OBJECT_INTERNAL **last_obj_ptr; + ACPI_NAMED_OBJECT *obj_entry; + ACPI_STATUS status = AE_OK; + + + /* Parameter validation */ + + if ((!device) || + ((!handler) && (handler != ACPI_DEFAULT_HANDLER)) || + (space_id > ACPI_MAX_ADDRESS_SPACE)) + { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* Convert and validate the device handle */ + + obj_entry = acpi_ns_convert_handle_to_entry (device); + if (!obj_entry) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + + /* Make sure the internal object exists */ + + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) obj_entry); + if (!obj_desc) { + /* + * The object DNE. + */ + status = AE_NOT_EXIST; + goto unlock_and_exit; + } + + /* + * find the address handler the user requested + */ + + handler_obj = obj_desc->device.addr_handler; + last_obj_ptr = &obj_desc->device.addr_handler; + while (handler_obj) { + /* + * We have a handler, see if user requested this one + */ + + if(handler_obj->addr_handler.space_id == space_id) { + /* + * Got it, first dereference this in the Regions + */ + region_obj = handler_obj->addr_handler.region_list; + + /* Walk the handler's region list */ + + while (region_obj) { + /* + * First disassociate the handler from the region. + * + * NOTE: this doesn't mean that the region goes away + * The region is just inaccessible as indicated to + * the _REG method + */ + acpi_ev_disassociate_region_from_handler(region_obj); + + /* + * Walk the list, since we took the first region and it + * was removed from the list by the dissassociate call + * we just get the first item on the list again + */ + region_obj = handler_obj->addr_handler.region_list; + + } + + /* + * Remove this Handler object from the list + */ + *last_obj_ptr = handler_obj->addr_handler.link; + + /* + * Now we can delete the handler object + */ + acpi_cm_remove_reference (handler_obj); + acpi_cm_remove_reference (handler_obj); + + goto unlock_and_exit; + } + + /* + * Move through the linked list of handlers + */ + last_obj_ptr = &handler_obj->addr_handler.link; + handler_obj = handler_obj->addr_handler.link; + } + + + /* + * The handler does not exist + */ + status = AE_NOT_EXIST; + + +unlock_and_exit: + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/hardware/hwacpi.c linux/drivers/acpi/hardware/hwacpi.c --- v2.4.0-test2/linux/drivers/acpi/hardware/hwacpi.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/hardware/hwacpi.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,207 @@ + +/****************************************************************************** + * + * Module Name: hwacpi - ACPI hardware functions - mode and timer + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "hardware.h" + + +#define _COMPONENT HARDWARE + MODULE_NAME ("hwacpi"); + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_set_mode + * + * PARAMETERS: Mode - SYS_MODE_ACPI or SYS_MODE_LEGACY + * + * RETURN: Status + * + * DESCRIPTION: Transitions the system into the requested mode or does nothing + * if the system is already in that mode. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_hw_set_mode ( + u32 mode) +{ + + ACPI_STATUS status = AE_ERROR; + + + if (mode == SYS_MODE_ACPI) { + /* BIOS should have disabled ALL fixed and GP events */ + + acpi_os_out8 (acpi_gbl_FACP->smi_cmd, acpi_gbl_FACP->acpi_enable); + } + + else if (mode == SYS_MODE_LEGACY) { + /* + * BIOS should clear all fixed status bits and restore fixed event + * enable bits to default + */ + + acpi_os_out8 (acpi_gbl_FACP->smi_cmd, acpi_gbl_FACP->acpi_disable); + } + + if (acpi_hw_get_mode () == mode) { + status = AE_OK; + } + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw + + * + * PARAMETERS: none + * + * RETURN: SYS_MODE_ACPI or SYS_MODE_LEGACY + * + * DESCRIPTION: Return current operating state of system. Determined by + * querying the SCI_EN bit. + * + ******************************************************************************/ + +u32 +acpi_hw_get_mode (void) +{ + + + if (acpi_hw_register_access (ACPI_READ, ACPI_MTX_LOCK, (s32)SCI_EN)) { + return (SYS_MODE_ACPI); + } + else { + return (SYS_MODE_LEGACY); + } +} + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_get_mode_capabilities + * + * PARAMETERS: none + * + * RETURN: logical OR of SYS_MODE_ACPI and SYS_MODE_LEGACY determined at initial + * system state. + * + * DESCRIPTION: Returns capablities of system + * + ******************************************************************************/ + +u32 +acpi_hw_get_mode_capabilities (void) +{ + + + if (!(acpi_gbl_system_flags & SYS_MODES_MASK)) { + if (acpi_hw_get_mode () == SYS_MODE_LEGACY) { + /* + * Assume that if this call is being made, Acpi_init has been called + * and ACPI support has been established by the presence of the + * tables. Therefore since we're in SYS_MODE_LEGACY, the system + * must support both modes + */ + + acpi_gbl_system_flags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY); + } + + else { + /* TBD: [Investigate] !!! this may be unsafe... */ + /* + * system is is ACPI mode, so try to switch back to LEGACY to see if + * it is supported + */ + acpi_hw_set_mode (SYS_MODE_LEGACY); + + if (acpi_hw_get_mode () == SYS_MODE_LEGACY) { + /* Now in SYS_MODE_LEGACY, so both are supported */ + + acpi_gbl_system_flags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY); + acpi_hw_set_mode (SYS_MODE_ACPI); + } + + else { + /* Still in SYS_MODE_ACPI so this must be an ACPI only system */ + + acpi_gbl_system_flags |= SYS_MODE_ACPI; + } + } + } + + return (acpi_gbl_system_flags & SYS_MODES_MASK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_pmt_ticks + * + * PARAMETERS: none + * + * RETURN: Current value of the ACPI PMT (timer) + * + * DESCRIPTION: Obtains current value of ACPI PMT + * + ******************************************************************************/ + +u32 +acpi_hw_pmt_ticks (void) +{ + u32 ticks; + + ticks = acpi_os_in32 (acpi_gbl_FACP->pm_tmr_blk); + + return (ticks); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_pmt_resolution + * + * PARAMETERS: none + * + * RETURN: Number of bits of resolution in the PMT (either 24 or 32) + * + * DESCRIPTION: Obtains resolution of the ACPI PMT (either 24bit or 32bit) + * + ******************************************************************************/ + +u32 +acpi_hw_pmt_resolution (void) +{ + if (0 == acpi_gbl_FACP->tmr_val_ext) { + return (24); + } + + return (32); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/hardware/hwcpu32.c linux/drivers/acpi/hardware/hwcpu32.c --- v2.4.0-test2/linux/drivers/acpi/hardware/hwcpu32.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/hardware/hwcpu32.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,716 @@ +/****************************************************************************** + * + * Name: hwcpu32.c - CPU support for IA32 (Throttling, Cx_states) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "namesp.h" +#include "hardware.h" + +#define _COMPONENT HARDWARE + MODULE_NAME ("Hwcpu32"); + + +#define BIT_4 0x10 /* TBD: [investigate] is this correct? */ + + +/**************************************************************************** + * + * FUNCTION: Acpi_hw_enter_c1 + * + * PARAMETERS: Pblk_address - Address of the processor control block + * Pm_timer_ticks - Number of PM timer ticks elapsed while asleep + * + * RETURN: Function status. + * + * DESCRIPTION: Set C1 state on IA32 processor (halt) + * + ****************************************************************************/ + +ACPI_STATUS +acpi_hw_enter_c1( + ACPI_IO_ADDRESS pblk_address, + u32 *pm_timer_ticks) +{ + u32 timer = 0; + + + if (!pm_timer_ticks) { + /* + * Enter C1: + * --------- + */ + enable(); + halt(); + *pm_timer_ticks = ACPI_UINT32_MAX; + } + else { + timer = acpi_hw_pmt_ticks (); + + /* + * Enter C1: + * --------- + */ + enable (); + halt (); + + /* + * Compute Time in C1: + * ------------------- + */ + timer = acpi_hw_pmt_ticks () - timer; + + *pm_timer_ticks = timer; + } + + return AE_OK; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_hw_enter_c2 + * + * PARAMETERS: Pblk_address - Address of the processor control block + * Pm_timer_ticks - Number of PM timer ticks elapsed while asleep + * + * RETURN: + * + * DESCRIPTION: Set C2 state on IA32 processor + * + ****************************************************************************/ + +ACPI_STATUS +acpi_hw_enter_c2( + ACPI_IO_ADDRESS pblk_address, + u32 *pm_timer_ticks) +{ + u32 timer = 0; + + + if (!pblk_address || !pm_timer_ticks) { + return AE_BAD_PARAMETER; + } + + /* + * Disable interrupts before all C2/C3 transitions. + */ + disable (); + + timer = acpi_hw_pmt_ticks (); + + /* + * Enter C2: + * --------- + * Read from the P_LVL2 (P_BLK+4) register to invoke a C2 transition. + */ + acpi_os_in8 ((ACPI_IO_ADDRESS) (pblk_address + 4)); + + /* + * Perform Dummy Op: + * ----------------- + * We have to do something useless after reading LVL2 because chipsets + * cannot guarantee that STPCLK# gets asserted in time to freeze execution. + */ + acpi_os_in8 ((ACPI_IO_ADDRESS) acpi_gbl_FACP->pm2_cnt_blk); + + /* + * Compute Time in C2: + * ------------------- + */ + timer = acpi_hw_pmt_ticks () - timer; + + *pm_timer_ticks = timer; + + /* + * Re-enable interrupts after coming out of C2/C3. + */ + enable (); + + return AE_OK; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_hw_enter_c3 + * + * PARAMETERS: Pblk_address - Address of the processor control block + * Pm_timer_ticks - Number of PM timer ticks elapsed while asleep + * + * RETURN: Status of function + * + * DESCRIPTION: Set C3 state on IA32 processor (UP only, cache coherency via + * disabling bus mastering) + * + ****************************************************************************/ + +ACPI_STATUS +acpi_hw_enter_c3( + ACPI_IO_ADDRESS pblk_address, + u32 *pm_timer_ticks) +{ + u32 timer = 0; + u8 pm2_cnt_blk = 0; + u32 bus_master_status = 0; + + + if (!pblk_address || !pm_timer_ticks) { + return AE_BAD_PARAMETER; + } + + /* + * Check the BM_STS bit, if it is set, do not enter C3 + * but clear the bit (with a write) and exit, telling + * the calling module that we spent zero time in C3. + * If bus mastering continues, this action should + * eventually cause a demotion to C2 + */ + if (1 == (bus_master_status = + acpi_hw_register_access (ACPI_READ, ACPI_MTX_LOCK, (s32)BM_STS))) + { + /* + * Clear the BM_STS bit by setting it. + */ + acpi_hw_register_access (ACPI_WRITE, ACPI_MTX_LOCK, (s32)BM_STS, 1); + *pm_timer_ticks = 0; + return AE_OK; + } + + /* + * Disable interrupts before all C2/C3 transitions. + */ + disable(); + + /* + * Disable Bus Mastering: + * ---------------------- + * Set the PM2_CNT.ARB_DIS bit (bit #0), preserving all other bits. + */ + pm2_cnt_blk = acpi_os_in8 ((ACPI_IO_ADDRESS) acpi_gbl_FACP->pm2_cnt_blk); + pm2_cnt_blk |= 0x01; + acpi_os_out8 ((ACPI_IO_ADDRESS) acpi_gbl_FACP->pm2_cnt_blk, pm2_cnt_blk); + + /* + * Get the timer base before entering C state + */ + timer = acpi_hw_pmt_ticks (); + + /* + * Enter C3: + * --------- + * Read from the P_LVL3 (P_BLK+5) register to invoke a C3 transition. + */ + acpi_os_in8 ((ACPI_IO_ADDRESS)(pblk_address + 5)); + + /* + * Perform Dummy Op: + * ----------------- + * We have to do something useless after reading LVL3 because chipsets + * cannot guarantee that STPCLK# gets asserted in time to freeze execution. + */ + acpi_os_in8 ((ACPI_IO_ADDRESS) acpi_gbl_FACP->pm2_cnt_blk); + + /* + * Immediately compute the time in the C state + */ + timer = acpi_hw_pmt_ticks() - timer; + + /* + * Re-Enable Bus Mastering: + * ------------------------ + * Clear the PM2_CNT.ARB_DIS bit (bit #0), preserving all other bits. + */ + pm2_cnt_blk = acpi_os_in8 ((ACPI_IO_ADDRESS) acpi_gbl_FACP->pm2_cnt_blk); + pm2_cnt_blk &= 0xFE; + acpi_os_out8 ((ACPI_IO_ADDRESS) acpi_gbl_FACP->pm2_cnt_blk, pm2_cnt_blk); + + /* TBD: [Unhandled]: Support 24-bit timers (this algorithm assumes 32-bit) */ + + *pm_timer_ticks = timer; + + /* + * Re-enable interrupts after coming out of C2/C3. + */ + enable(); + + return AE_OK; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_hw_enter_cx + * + * PARAMETERS: Processor_handle - handle of the processor + * + * RETURN: Status of function + * + * DESCRIPTION: Invoke the currently active processor Cx handler to put this + * processor to sleep. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_hw_enter_cx ( + ACPI_IO_ADDRESS pblk_address, + u32 *pm_timer_ticks) +{ + + if (!acpi_hw_cx_handlers[acpi_hw_active_cx_state]) { + return AE_SUPPORT; + } + + return (acpi_hw_cx_handlers[acpi_hw_active_cx_state] (pblk_address, pm_timer_ticks)); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_hw_set_cx + * + * PARAMETERS: State - value (1-3) of the Cx state to 'make active' + * + * RETURN: Function status. + * + * DESCRIPTION: Sets the state to use during calls to Acpi_hw_enter_cx(). + * + ****************************************************************************/ + +ACPI_STATUS +acpi_hw_set_cx ( + u32 cx_state) +{ + /* + * Supported State? + * ---------------- + */ + if ((cx_state < 1) || (cx_state > 3)) { + return AE_BAD_PARAMETER; + } + + if (!acpi_hw_cx_handlers[cx_state]) { + return AE_SUPPORT; + } + + /* + * New Cx State? + * ------------- + * We only care when moving from one state to another... + */ + if (acpi_hw_active_cx_state == cx_state) { + return AE_OK; + } + + /* + * Prepare to Use New State: + * ------------------------- + * If the new Cx_state is C3, the BM_RLD bit must be set to allow + * the generation of a bus master requets to cause the processor + * in the C3 state to transition to the C0 state. + */ + switch (cx_state) + { + case 3: + acpi_hw_register_access (ACPI_WRITE, ACPI_MTX_LOCK, (s32)BM_RLD, 1); + break; + } + + /* + * Clean up from Old State: + * ------------------------ + * If the old Cx_state was C3, the BM_RLD bit is reset. When the + * bit is reset, the generation of a bus master request does not + * effect any processor in the C3 state. + */ + switch (acpi_hw_active_cx_state) + { + case 3: + acpi_hw_register_access (ACPI_WRITE, ACPI_MTX_LOCK, (s32)BM_RLD, 0); + break; + } + + /* + * Enable: + * ------- + */ + acpi_hw_active_cx_state = cx_state; + + return AE_OK; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_hw_get_cx_info + * + * PARAMETERS: Cx_states - Information (latencies) on all Cx states + * + * RETURN: Status of function + * + * DESCRIPTION: This function is called both to initialize Cx handling + * and retrieve the current Cx information (latency values). + * + ****************************************************************************/ + +ACPI_STATUS +acpi_hw_get_cx_info ( + u32 cx_states[]) +{ + u8 SMP_system = FALSE; + + + if (!cx_states) { + return(AE_BAD_PARAMETER); + } + + /* + * TBD: [Unhandled] need to init SMP_system using info from the MAPIC + * table. + */ + + /* + * Set Defaults: + * ------------- + * C0 and C1 support is implied (but what about that PROC_C1 register + * in the FADT?!?!). Set C2/C3 to max. latency (not supported until + * proven otherwise). + */ + cx_states[0] = 0; + cx_states[1] = 0; + cx_states[2] = MAX_CX_STATE_LATENCY; + cx_states[3] = MAX_CX_STATE_LATENCY; + + /* + * C2 Supported? + * ------------- + * We're only supporting C2 when the latency is <= 100 microseconds, + * and on SMP systems when P_LVL2_UP (which indicates C2 only on UP) + * is not set. + */ + if (acpi_gbl_FACP->plvl2_lat <= 100) { + if (!SMP_system) { + acpi_hw_cx_handlers[2] = acpi_hw_enter_c2; + cx_states[2] = acpi_gbl_FACP->plvl2_lat; + } + + else if (!acpi_gbl_FACP->plvl2_up) { + acpi_hw_cx_handlers[2] = acpi_hw_enter_c2; + cx_states[2] = acpi_gbl_FACP->plvl2_lat; + } + } + + /* + * C3 Supported? + * ------------- + * We're only supporting C3 on UP systems when the latency is + * <= 1000 microseconds and that include the ability to disable + * Bus Mastering while in C3 (ARB_DIS) but allows Bus Mastering + * requests to wake the system from C3 (BM_RLD). Note his method + * of maintaining cache coherency (disabling of bus mastering) + * cannot be used on SMP systems, and flushing caches (e.g. WBINVD) + * is simply too costly (at this time). + */ + if (acpi_gbl_FACP->plvl3_lat <= 1000) { + if (!SMP_system && (acpi_gbl_FACP->pm2_cnt_blk && + acpi_gbl_FACP->pm2_cnt_len)) + { + acpi_hw_cx_handlers[3] = acpi_hw_enter_c3; + cx_states[3] = acpi_gbl_FACP->plvl3_lat; + } + } + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_hw_get_cx_handler + * + * PARAMETERS: State - the Cx state + * Handler - pointer to location for the returned handler + * + * RETURN: Status of function + * + * DESCRIPTION: This function is called to get an installed Cx state handler. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_hw_get_cx_handler ( + u32 cx_state, + ACPI_C_STATE_HANDLER *handler) +{ + + if ((cx_state == 0) || (cx_state >= MAX_CX_STATES) || !handler) { + return(AE_BAD_PARAMETER); + } + + *handler = acpi_hw_cx_handlers[cx_state]; + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_hw_set_cx_handler + * + * PARAMETERS: Cx_state - the Cx state + * Handler - new Cx state handler + * + * RETURN: Status of function + * + * DESCRIPTION: This function is called to install a new Cx state handler. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_hw_set_cx_handler ( + u32 cx_state, + ACPI_C_STATE_HANDLER handler) +{ + + if ((cx_state == 0) || (cx_state >= MAX_CX_STATES) || !handler) { + return(AE_BAD_PARAMETER); + } + + acpi_hw_cx_handlers[cx_state] = handler; + + return(AE_OK); +} + + +/************************************************************************** + * + * FUNCTION: Acpi_hw_local_pow + * + * PARAMETERS: x,y operands + * + * RETURN: result + * + * DESCRIPTION: Compute x ^ y + * + *************************************************************************/ + +NATIVE_UINT +acpi_hw_local_pow ( + NATIVE_UINT x, + NATIVE_UINT y) +{ + NATIVE_UINT i; + NATIVE_UINT result = 1; + + + for (i = 0; i < y; i++) { + result = result * x; + } + + return result; +} + + +/************************************************************************** + * + * FUNCTION: Acpi_hw_enable_throttling + * + * PARAMETERS: Pblk_address - Address of Pcnt (Processor Control) + * register + * + * RETURN: none + * + * DESCRIPTION: Enable throttling by setting the THT_EN bit. + * + *************************************************************************/ + +void +acpi_hw_enable_throttling ( + ACPI_IO_ADDRESS pblk_address) +{ + u32 pblk_value; + + + pblk_value = acpi_os_in32 (pblk_address); + pblk_value = pblk_value | BIT_4; + acpi_os_out32 (pblk_address, pblk_value); + + return; +} + + +/************************************************************************** + * + * FUNCTION: Acpi_hw_disable_throttling + * + * PARAMETERS: Pblk_address - Address of Pcnt (Processor Control) + * register + * + * RETURN: none + * + * DESCRIPTION:Disable throttling by clearing the THT_EN bit + * + *************************************************************************/ + +void +acpi_hw_disable_throttling ( + ACPI_IO_ADDRESS pblk_address) +{ + u32 pblk_value; + + + pblk_value = acpi_os_in32 (pblk_address); + pblk_value = pblk_value & (~(u32)BIT_4); + acpi_os_out32 (pblk_address, pblk_value); + + return; +} + + +/************************************************************************** + * + * FUNCTION: Acpi_hw_get_duty_cycle + * + * PARAMETERS: Duty_offset Pcnt register duty cycle field offset + * Pblk_address Pcnt register address in chipset + * Num_throttle_states # of CPU throttle states this system + * supports + * + * RETURN: none + * + * DESCRIPTION: Get the duty cycle from the chipset + * + *************************************************************************/ + +u32 +acpi_hw_get_duty_cycle ( + u8 duty_offset, + ACPI_IO_ADDRESS pblk_address, + u32 num_throttle_states) +{ + NATIVE_UINT index; + u32 duty32_value; + u32 pcnt_mask_off_duty_field; + + + /* + * Use Num_throttle_states - 1 as mask [ex. 8 - 1 = 7 (Fh)] + * and then shift it into the right position + */ + pcnt_mask_off_duty_field = num_throttle_states - 1; + + /* + * Read in the current value from the port + */ + duty32_value = acpi_os_in32 ((ACPI_IO_ADDRESS) pblk_address); + + /* + * Shift the the value to LSB + */ + for (index = 0; index < (NATIVE_UINT) duty_offset; index++) { + duty32_value = duty32_value >> 1; + } + + /* + * Get the duty field only + */ + duty32_value = duty32_value & pcnt_mask_off_duty_field; + + return ((u32) duty32_value); +} + + +/************************************************************************** + * + * FUNCTION: Acpi_hw_program_duty_cycle + * + * PARAMETERS: Duty_offset Pcnt register duty cycle field offset + * Duty_cycle duty cycle to program into chipset + * Pblk_address Pcnt register address in chipset + * Num_throttle_states # of CPU throttle states this system + * supports + * + * RETURN: none + * + * DESCRIPTION: Program chipset with specified duty cycle by bit-shifting the + * duty cycle bits to the appropriate offset, reading the duty + * cycle register, OR-ing in the duty cycle, and writing it to + * the Pcnt register. + * + *************************************************************************/ + +void +acpi_hw_program_duty_cycle ( + u8 duty_offset, + u32 duty_cycle, + ACPI_IO_ADDRESS pblk_address, + u32 num_throttle_states) +{ + NATIVE_UINT index; + u32 duty32_value; + u32 pcnt_mask_off_duty_field; + u32 port_value; + + + /* + * valid Duty_cycle passed + */ + duty32_value = duty_cycle; + + /* + * use Num_throttle_states - 1 as mask [ex. 8 - 1 = 7 (Fh)] + * and then shift it into the right position + */ + pcnt_mask_off_duty_field = num_throttle_states - 1; + + /* + * Shift the mask + */ + for (index = 0; index < (NATIVE_UINT) duty_offset; index++) { + pcnt_mask_off_duty_field = pcnt_mask_off_duty_field << 1; + duty32_value = duty32_value << 1; + } + + /* + * Read in the current value from the port + */ + port_value = acpi_os_in32 ((ACPI_IO_ADDRESS) pblk_address); + + /* + * Mask off the duty field so we don't OR in junk! + */ + port_value = port_value & (~pcnt_mask_off_duty_field); + + /* + * OR in the bits we want to write out to the port + */ + port_value = (port_value | duty32_value) & (~(u32)BIT_4); + + /* + * write it to the port + */ + acpi_os_out32 ((ACPI_IO_ADDRESS) pblk_address, port_value); + + return; +} + + \ No newline at end of file diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/hardware/hwgpe.c linux/drivers/acpi/hardware/hwgpe.c --- v2.4.0-test2/linux/drivers/acpi/hardware/hwgpe.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/hardware/hwgpe.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,208 @@ +/****************************************************************************** + * + * Module Name: hwgpe - Low level GPE enable/disable/clear functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "hardware.h" +#include "namesp.h" +#include "events.h" + +#define _COMPONENT HARDWARE + MODULE_NAME ("hwgpe"); + + +u8 decode_to8bit [8] = {1,2,4,8,16,32,64,128}; + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_enable_gpe + * + * PARAMETERS: Gpe_number - The GPE + * + * RETURN: None + * + * DESCRIPTION: Enable a single GPE. + * + ******************************************************************************/ + +void +acpi_hw_enable_gpe ( + u32 gpe_number) +{ + u8 in_byte; + u32 register_index; + u8 bit_mask; + + /* + * Translate GPE number to index into global registers array. + */ + register_index = acpi_gbl_gpe_valid[gpe_number]; + + /* + * Figure out the bit offset for this GPE within the target register. + */ + bit_mask = decode_to8bit [MOD_8 (gpe_number)]; + + /* + * Read the current value of the register, set the appropriate bit + * to enable the GPE, and write out the new register. + */ + in_byte = acpi_os_in8 (acpi_gbl_gpe_registers[register_index].enable_addr); + acpi_os_out8 (acpi_gbl_gpe_registers[register_index].enable_addr, + (u8)(in_byte | bit_mask)); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_disable_gpe + * + * PARAMETERS: Gpe_number - The GPE + * + * RETURN: None + * + * DESCRIPTION: Disable a single GPE. + * + ******************************************************************************/ + +void +acpi_hw_disable_gpe ( + u32 gpe_number) +{ + u8 in_byte; + u32 register_index; + u8 bit_mask; + + /* + * Translate GPE number to index into global registers array. + */ + register_index = acpi_gbl_gpe_valid[gpe_number]; + + /* + * Figure out the bit offset for this GPE within the target register. + */ + bit_mask = decode_to8bit [MOD_8 (gpe_number)]; + + /* + * Read the current value of the register, clear the appropriate bit, + * and write out the new register value to disable the GPE. + */ + in_byte = acpi_os_in8 (acpi_gbl_gpe_registers[register_index].enable_addr); + acpi_os_out8 (acpi_gbl_gpe_registers[register_index].enable_addr, + (u8)(in_byte & ~bit_mask)); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_clear_gpe + * + * PARAMETERS: Gpe_number - The GPE + * + * RETURN: None + * + * DESCRIPTION: Clear a single GPE. + * + ******************************************************************************/ + +void +acpi_hw_clear_gpe ( + u32 gpe_number) +{ + u32 register_index; + u8 bit_mask; + + /* + * Translate GPE number to index into global registers array. + */ + register_index = acpi_gbl_gpe_valid[gpe_number]; + + /* + * Figure out the bit offset for this GPE within the target register. + */ + bit_mask = decode_to8bit [MOD_8 (gpe_number)]; + + /* + * Write a one to the appropriate bit in the status register to + * clear this GPE. + */ + acpi_os_out8 (acpi_gbl_gpe_registers[register_index].status_addr, bit_mask); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_get_gpe_status + * + * PARAMETERS: Gpe_number - The GPE + * + * RETURN: None + * + * DESCRIPTION: Return the status of a single GPE. + * + ******************************************************************************/ + +void +acpi_hw_get_gpe_status ( + u32 gpe_number, + ACPI_EVENT_STATUS *event_status) +{ + u8 in_byte = 0; + u32 register_index = 0; + u8 bit_mask = 0; + + if (!event_status) { + return; + } + + (*event_status) = 0; + + /* + * Translate GPE number to index into global registers array. + */ + register_index = acpi_gbl_gpe_valid[gpe_number]; + + /* + * Figure out the bit offset for this GPE within the target register. + */ + bit_mask = decode_to8bit [MOD_8 (gpe_number)]; + + /* + * Enabled?: + */ + in_byte = acpi_os_in8 (acpi_gbl_gpe_registers[register_index].enable_addr); + + if (bit_mask & in_byte) { + (*event_status) |= ACPI_EVENT_FLAG_ENABLED; + } + + /* + * Set? + */ + in_byte = acpi_os_in8 (acpi_gbl_gpe_registers[register_index].status_addr); + + if (bit_mask & in_byte) { + (*event_status) |= ACPI_EVENT_FLAG_SET; + } +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/hardware/hwregs.c linux/drivers/acpi/hardware/hwregs.c --- v2.4.0-test2/linux/drivers/acpi/hardware/hwregs.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/hardware/hwregs.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,608 @@ + +/****************************************************************************** + * + * Module Name: hwregs - Read/write access functions for the various ACPI + * control and status registers. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "hardware.h" +#include "namesp.h" + +#define _COMPONENT HARDWARE + MODULE_NAME ("hwregs"); + + +/* This matches the #defines in actypes.h. */ + +ACPI_STRING sleep_state_table[] = {"\\_S0_","\\_S1_","\\_S2_","\\_S3_", + "\\_S4_","\\_S4_b","\\_S5_"}; + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_get_bit_shift + * + * PARAMETERS: Mask - Input mask to determine bit shift from. + * Must have at least 1 bit set. + * + * RETURN: Bit location of the lsb of the mask + * + * DESCRIPTION: Returns the bit number for the low order bit that's set. + * + ******************************************************************************/ + +s32 +acpi_hw_get_bit_shift ( + u32 mask) +{ + s32 shift; + + + for (shift = 0; ((mask >> shift) & 1) == 0; shift++) { ; } + + return (shift); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_clear_acpi_status + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Clears all fixed and general purpose status bits + * + ******************************************************************************/ + +void +acpi_hw_clear_acpi_status (void) +{ + u16 gpe_length; + u16 index; + + + acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE); + + acpi_os_out16 (acpi_gbl_FACP->pm1a_evt_blk, (u16) ALL_FIXED_STS_BITS); + + if (acpi_gbl_FACP->pm1b_evt_blk) { + acpi_os_out16 ((u16) acpi_gbl_FACP->pm1b_evt_blk, + (u16) ALL_FIXED_STS_BITS); + } + + /* now clear the GPE Bits */ + + if (acpi_gbl_FACP->gpe0blk_len) { + gpe_length = (u16) DIV_2 (acpi_gbl_FACP->gpe0blk_len); + + for (index = 0; index < gpe_length; index++) { + acpi_os_out8 ((acpi_gbl_FACP->gpe0blk + index), (u8) 0xff); + } + } + + if (acpi_gbl_FACP->gpe1_blk_len) { + gpe_length = (u16) DIV_2 (acpi_gbl_FACP->gpe1_blk_len); + + for (index = 0; index < gpe_length; index++) { + acpi_os_out8 ((acpi_gbl_FACP->gpe1_blk + index), (u8) 0xff); + } + } + + acpi_cm_release_mutex (ACPI_MTX_HARDWARE); + return; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_hw_obtain_sleep_type_register_data + * + * PARAMETERS: Sleep_state - Numeric state requested + * *Slp_Typ_a - Pointer to byte to receive SLP_TYPa value + * *Slp_Typ_b - Pointer to byte to receive SLP_TYPb value + * + * RETURN: Status - ACPI status + * + * DESCRIPTION: Acpi_hw_obtain_sleep_type_register_data() obtains the SLP_TYP and + * SLP_TYPb values for the sleep state requested. + * + + ***************************************************************************/ + +ACPI_STATUS +acpi_hw_obtain_sleep_type_register_data ( + u8 sleep_state, + u8 *slp_typ_a, + u8 *slp_typ_b) +{ + ACPI_STATUS status = AE_OK; + ACPI_OBJECT_INTERNAL *obj_desc; + + + /* + * Validate parameters + */ + + if ((sleep_state > ACPI_S_STATES_MAX) || + !slp_typ_a || !slp_typ_b) + { + return (AE_BAD_PARAMETER); + } + + /* + * Acpi_evaluate the namespace object containing the values for this state + */ + + status = acpi_ns_evaluate_by_name (sleep_state_table[sleep_state], NULL, &obj_desc); + if (AE_OK == status) { + if (obj_desc) { + /* + * We got something, now ensure it is correct. The object must + * be a package and must have at least 2 numeric values as the + * two elements + */ + + if ((obj_desc->common.type != ACPI_TYPE_PACKAGE) || + ((obj_desc->package.elements[0])->common.type != + ACPI_TYPE_NUMBER) || + ((obj_desc->package.elements[1])->common.type != + ACPI_TYPE_NUMBER)) + { + /* Invalid _Sx_ package type or value */ + + REPORT_ERROR ("Object type returned from interpreter differs from expected value"); + status = AE_ERROR; + } + else { + /* + * Valid _Sx_ package size, type, and value + */ + *slp_typ_a = + (u8) (obj_desc->package.elements[0])->number.value; + + *slp_typ_b = + (u8) (obj_desc->package.elements[1])->number.value; + } + + acpi_cm_remove_reference (obj_desc); + } + } + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_register_access + * + * PARAMETERS: Read_write - Either ACPI_READ or ACPI_WRITE. + * Use_lock - Lock the hardware + * Register_id - index of ACPI register to access + * Value - (only used on write) value to write to the + * register. Shifted all the way right. + * + * RETURN: Value written to or read from specified register. This value + * is shifted all the way right. + * + * DESCRIPTION: Generic ACPI register read/write function. + * + ******************************************************************************/ + +u32 +acpi_hw_register_access ( + NATIVE_UINT read_write, + u8 use_lock, + u32 register_id, + ...) /* Value (only used on write) */ +{ + u32 register_value = 0; + u32 mask = 0; + u32 value = 0; + ACPI_IO_ADDRESS gpe_reg = 0; + + + if (read_write == ACPI_WRITE) { + va_list marker; + + va_start (marker, register_id); + value = va_arg (marker, s32); + va_end (marker); + } + + /* + * TBD: [Restructure] May want to split the Acpi_event code and the + * Control code + */ + + /* + * Decode the Register ID + */ + + switch (register_id & REGISTER_BLOCK_MASK) + { + case PM1_EVT: + + if (register_id < TMR_EN) { + /* status register */ + + if (ACPI_MTX_LOCK == use_lock) { + acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE); + } + + + register_value = (u32) acpi_os_in16 (acpi_gbl_FACP->pm1a_evt_blk); + if (acpi_gbl_FACP->pm1b_evt_blk) { + register_value |= (u32) acpi_os_in16 (acpi_gbl_FACP->pm1b_evt_blk); + } + + switch (register_id) + { + case TMR_STS: + mask = TMR_STS_MASK; + break; + + case BM_STS: + mask = BM_STS_MASK; + break; + + case GBL_STS: + mask = GBL_STS_MASK; + break; + + case PWRBTN_STS: + mask = PWRBTN_STS_MASK; + break; + + case SLPBTN_STS: + mask = SLPBTN_STS_MASK; + break; + + case RTC_STS: + mask = RTC_STS_MASK; + break; + + case WAK_STS: + mask = WAK_STS_MASK; + break; + + default: + mask = 0; + break; + } + + if (read_write == ACPI_WRITE) { + /* + * Status registers are different from the rest. Clear by + * writing 1, writing 0 has no effect. So, the only relevent + * information is the single bit we're interested in, all + * others should be written as 0 so they will be left + * unchanged + */ + + value <<= acpi_hw_get_bit_shift (mask); + value &= mask; + + if (value) { + acpi_os_out16 (acpi_gbl_FACP->pm1a_evt_blk, (u16) value); + + if (acpi_gbl_FACP->pm1b_evt_blk) { + acpi_os_out16 (acpi_gbl_FACP->pm1b_evt_blk, (u16) value); + } + + register_value = 0; + } + } + + if (ACPI_MTX_LOCK == use_lock) { + acpi_cm_release_mutex (ACPI_MTX_HARDWARE); + } + } + + else { + /* enable register */ + + if (ACPI_MTX_LOCK == use_lock) { + acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE); + } + + register_value = (u32) acpi_os_in16 (acpi_gbl_FACP->pm1a_evt_blk + + DIV_2 (acpi_gbl_FACP->pm1_evt_len)); + + if (acpi_gbl_FACP->pm1b_evt_blk) { + register_value |= (u32) acpi_os_in16 (acpi_gbl_FACP->pm1b_evt_blk + + DIV_2 (acpi_gbl_FACP->pm1_evt_len)); + + } + + switch (register_id) + { + case TMR_EN: + mask = TMR_EN_MASK; + break; + + case GBL_EN: + mask = GBL_EN_MASK; + break; + + case PWRBTN_EN: + mask = PWRBTN_EN_MASK; + break; + + case SLPBTN_EN: + mask = SLPBTN_EN_MASK; + break; + + case RTC_EN: + mask = RTC_EN_MASK; + break; + + default: + mask = 0; + break; + } + + if (read_write == ACPI_WRITE) { + register_value &= ~mask; + value <<= acpi_hw_get_bit_shift (mask); + value &= mask; + register_value |= value; + + acpi_os_out16 ((acpi_gbl_FACP->pm1a_evt_blk + + DIV_2 (acpi_gbl_FACP->pm1_evt_len)), + (u16) register_value); + + if (acpi_gbl_FACP->pm1b_evt_blk) { + acpi_os_out16 ((acpi_gbl_FACP->pm1b_evt_blk + + DIV_2 (acpi_gbl_FACP->pm1_evt_len)), + (u16) register_value); + } + } + if(ACPI_MTX_LOCK == use_lock) { + acpi_cm_release_mutex (ACPI_MTX_HARDWARE); + } + } + break; + + + case PM1_CONTROL: + + register_value = 0; + + if (ACPI_MTX_LOCK == use_lock) { + acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE); + } + + if (register_id != SLP_TYPE_B) { + /* + * SLP_TYPx registers are written differently + * than any other control registers with + * respect to A and B registers. The value + * for A may be different than the value for B + */ + + register_value = (u32) acpi_os_in16 (acpi_gbl_FACP->pm1a_cnt_blk); + } + + if (acpi_gbl_FACP->pm1b_cnt_blk && register_id != (s32) SLP_TYPE_A) { + register_value |= (u32) acpi_os_in16 (acpi_gbl_FACP->pm1b_cnt_blk); + } + + switch (register_id) + { + case SCI_EN: + mask = SCI_EN_MASK; + break; + + case BM_RLD: + mask = BM_RLD_MASK; + break; + + case GBL_RLS: + mask = GBL_RLS_MASK; + break; + + case SLP_TYPE_A: + case SLP_TYPE_B: + mask = SLP_TYPE_X_MASK; + break; + + case SLP_EN: + mask = SLP_EN_MASK; + break; + + default: + mask = 0; + break; + } + + if (read_write == ACPI_WRITE) { + register_value &= ~mask; + value <<= acpi_hw_get_bit_shift (mask); + value &= mask; + register_value |= value; + + /* + * SLP_TYPE_x registers are written differently + * than any other control registers with + * respect to A and B registers. The value + * for A may be different than the value for B + */ + + if (register_id != SLP_TYPE_B) { + if (mask == SLP_EN_MASK) { + disable(); /* disable interrupts */ + } + + acpi_os_out16 (acpi_gbl_FACP->pm1a_cnt_blk, (u16) register_value); + + if (mask == SLP_EN_MASK) { + /* + * Enable interrupts, the SCI handler is likely going to + * be invoked as soon as interrupts are enabled, since gpe's + * and most fixed resume events also generate SCI's. + */ + enable(); + } + } + + if (acpi_gbl_FACP->pm1b_cnt_blk && register_id != (s32) SLP_TYPE_A) { + acpi_os_out16 (acpi_gbl_FACP->pm1b_cnt_blk, (u16) register_value); + } + } + + if (ACPI_MTX_LOCK == use_lock) { + acpi_cm_release_mutex (ACPI_MTX_HARDWARE); + } + break; + + + case PM2_CONTROL: + + if (ACPI_MTX_LOCK == use_lock) { + acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE); + } + + register_value = (u32) acpi_os_in16 (acpi_gbl_FACP->pm2_cnt_blk); + switch (register_id) + { + case ARB_DIS: + mask = ARB_DIS_MASK; + break; + + default: + mask = 0; + break; + } + + if (read_write == ACPI_WRITE) { + register_value &= ~mask; + value <<= acpi_hw_get_bit_shift (mask); + value &= mask; + register_value |= value; + + acpi_os_out16 (acpi_gbl_FACP->pm2_cnt_blk, (u16) register_value); + } + + if (ACPI_MTX_LOCK == use_lock) { + acpi_cm_release_mutex (ACPI_MTX_HARDWARE); + } + break; + + + case PM_TIMER: + + register_value = acpi_os_in32 (acpi_gbl_FACP->pm_tmr_blk); + mask = 0xFFFFFFFF; + break; + + + case GPE1_EN_BLOCK: + + gpe_reg = (acpi_gbl_FACP->gpe1_blk + acpi_gbl_FACP->gpe1_base) + + (gpe_reg + (DIV_2 (acpi_gbl_FACP->gpe1_blk_len))); + + + case GPE1_STS_BLOCK: + + if (!gpe_reg) { + gpe_reg = (acpi_gbl_FACP->gpe1_blk + acpi_gbl_FACP->gpe1_base); + } + + + case GPE0_EN_BLOCK: + + if (!gpe_reg) { + gpe_reg = acpi_gbl_FACP->gpe0blk + DIV_2 (acpi_gbl_FACP->gpe0blk_len); + } + + + case GPE0_STS_BLOCK: + + if (!gpe_reg) { + gpe_reg = acpi_gbl_FACP->gpe0blk; + } + + /* Determine the bit to be accessed */ + + mask = (((u32) register_id) & BIT_IN_REGISTER_MASK); + mask = 1 << (mask-1); + + /* The base address of the GPE 0 Register Block */ + /* Plus 1/2 the length of the GPE 0 Register Block */ + /* The enable register is the register following the Status Register */ + /* and each register is defined as 1/2 of the total Register Block */ + + /* This sets the bit within Enable_bit that needs to be written to */ + /* the register indicated in Mask to a 1, all others are 0 */ + + if (mask > LOW_BYTE) { + /* Shift the value 1 byte to the right and add 1 to the register */ + + mask >>= ONE_BYTE; + gpe_reg++; + } + + /* Now get the current Enable Bits in the selected Reg */ + + if(ACPI_MTX_LOCK == use_lock) { + acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE); + } + + register_value = (u32) acpi_os_in8 (gpe_reg); + if (read_write == ACPI_WRITE) { + register_value &= ~mask; + value <<= acpi_hw_get_bit_shift (mask); + value &= mask; + register_value |= value; + + /* This write will put the Action state into the General Purpose */ + + /* Enable Register indexed by the value in Mask */ + + acpi_os_out8 (gpe_reg, (u8) register_value); + register_value = (u32) acpi_os_in8 (gpe_reg); + } + + if(ACPI_MTX_LOCK == use_lock) { + acpi_cm_release_mutex (ACPI_MTX_HARDWARE); + } + break; + + + case PROCESSOR_BLOCK: + default: + + mask = 0; + break; + } + + + register_value &= mask; + register_value >>= acpi_hw_get_bit_shift (mask); + + return (register_value); +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/hardware/hwxface.c linux/drivers/acpi/hardware/hwxface.c --- v2.4.0-test2/linux/drivers/acpi/hardware/hwxface.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/hardware/hwxface.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,576 @@ + +/****************************************************************************** + * + * Name: hwxface.c - Hardware access external interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "namesp.h" +#include "hardware.h" + +#define _COMPONENT HARDWARE + MODULE_NAME ("hwxface"); + + +/****************************************************************************** + * + * Hardware globals + * + ******************************************************************************/ + + +ACPI_C_STATE_HANDLER acpi_hw_cx_handlers[MAX_CX_STATES] = + {NULL, acpi_hw_enter_c1, NULL, NULL}; + +u32 acpi_hw_active_cx_state = 1; + + +/**************************************************************************** + * + * FUNCTION: Acpi_get_processor_throttling_info + * + * PARAMETERS: Processor_handle - handle for the cpu to get info about + * User_buffer - caller supplied buffer + * + * RETURN: Status of function + * + * DESCRIPTION: Get throttling capabilities for the processor, this routine + * builds the data directly into the callers buffer + * + ****************************************************************************/ + +ACPI_STATUS +acpi_get_processor_throttling_info ( + ACPI_HANDLE processor_handle, + ACPI_BUFFER *user_buffer) +{ + NATIVE_UINT percent_step; + NATIVE_UINT next_percent; + NATIVE_UINT num_throttle_states; + NATIVE_UINT buffer_space_needed; + NATIVE_UINT i; + u8 duty_offset; + u8 duty_width; + ACPI_NAMED_OBJECT *cpu_entry; + ACPI_OBJECT_INTERNAL *cpu_obj; + ACPI_CPU_THROTTLING_STATE *state_ptr; + + + /* + * Have to at least have a buffer to return info in + */ + if (!user_buffer) { + return(AE_BAD_PARAMETER); + } + + /* + * Convert and validate the device handle + */ + + cpu_entry = acpi_ns_convert_handle_to_entry (processor_handle); + if (!cpu_entry) { + return (AE_BAD_PARAMETER); + } + + /* + * Check for an existing internal object + */ + + cpu_obj = acpi_ns_get_attached_object ((ACPI_HANDLE) cpu_entry); + if (!cpu_obj) { + return (AE_NOT_FOUND); + } + + duty_offset = acpi_gbl_FACP->duty_offset; + duty_width = acpi_gbl_FACP->duty_width; + + /* + * P0 must always have a P_BLK all others may be null + * in either case, we can't thottle a processor that has no P_BLK + * + * Also if no Duty width, one state and it is 100% + * + */ + if (!cpu_obj->processor.pblk_length || !duty_width || + (0xFFFF < cpu_obj->processor.pblk_address)) + { + /* + * Acpi_even though we can't throttle, we still have one state (100%) + */ + num_throttle_states = 1; + } + + else { + num_throttle_states = (int) acpi_hw_local_pow (2,duty_width); + } + + buffer_space_needed = num_throttle_states * sizeof (ACPI_CPU_THROTTLING_STATE); + + if ((user_buffer->length < buffer_space_needed) || !user_buffer->pointer) { + user_buffer->length = buffer_space_needed; + return (AE_BUFFER_OVERFLOW); + } + + user_buffer->length = buffer_space_needed; + state_ptr = (ACPI_CPU_THROTTLING_STATE *) user_buffer->pointer; + percent_step = 1000 / num_throttle_states; + + /* + * Build each entry in the buffer. Note that we're using the value + * 1000 and dividing each state by 10 to better avoid round-off + * accumulation. Also note that the throttling STATES are ordered + * sequentially from 100% (state 0) on down (e.g. 87.5% = state 1), + * which is exactly opposite from duty cycle values (12.5% = state 1). + */ + for (i = 0, next_percent = 1000; i < num_throttle_states; i++) { + state_ptr[i].state_number = i; + state_ptr[i].percent_of_clock = next_percent / 10; + next_percent -= percent_step; + } + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_get_processor_throttling_state + * + * PARAMETERS: Processor_handle - handle for the cpu to throttle + * Throttle_state - throttling state to enter + * + * RETURN: Status of function + * + * DESCRIPTION: Get current hardware throttling state + * + ****************************************************************************/ + +ACPI_STATUS +acpi_get_processor_throttling_state ( + ACPI_HANDLE processor_handle, + u32 *throttle_state) +{ + ACPI_NAMED_OBJECT *cpu_entry; + ACPI_OBJECT_INTERNAL *cpu_obj; + u32 num_throttle_states; + u32 duty_cycle; + u8 duty_offset; + u8 duty_width; + + + /* Convert and validate the device handle */ + + cpu_entry = acpi_ns_convert_handle_to_entry (processor_handle); + if (!cpu_entry || !throttle_state) { + return (AE_BAD_PARAMETER); + } + + /* Check for an existing internal object */ + + cpu_obj = acpi_ns_get_attached_object ((ACPI_HANDLE) cpu_entry); + if (!cpu_obj) { + return (AE_NOT_FOUND); + } + + duty_offset = acpi_gbl_FACP->duty_offset; + duty_width = acpi_gbl_FACP->duty_width; + + /* + * Must have a valid P_BLK P0 must have a P_BLK all others may be null + * in either case, we can't thottle a processor that has no P_BLK + * that means we are in the only supported state (0 - 100%) + * + * also, if Duty_width is zero there are no additional states + */ + if (!cpu_obj->processor.pblk_length || !duty_width || + (0xFFFF < cpu_obj->processor.pblk_address)) + { + *throttle_state = 0; + return(AE_OK); + } + + num_throttle_states = (u32) acpi_hw_local_pow (2,duty_width); + + /* + * Get the current duty cycle value. + */ + duty_cycle = acpi_hw_get_duty_cycle (duty_offset, + cpu_obj->processor.pblk_address, + num_throttle_states); + + /* + * Convert duty cycle to throttling state (invert). + */ + if (duty_cycle == 0) { + *throttle_state = 0; + } + + else { + *throttle_state = num_throttle_states - duty_cycle; + } + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_set_processor_throttling_state + * + * PARAMETERS: Processor_handle - handle for the cpu to throttle + * Throttle_state - throttling state to enter + * + * RETURN: Status of function + * + * DESCRIPTION: Set hardware into requested throttling state, the handle + * passed in must have a valid P_BLK + * + ****************************************************************************/ + +ACPI_STATUS +acpi_set_processor_throttling_state ( + ACPI_HANDLE processor_handle, + u32 throttle_state) +{ + ACPI_NAMED_OBJECT *cpu_entry; + ACPI_OBJECT_INTERNAL *cpu_obj; + u32 num_throttle_states = 0; + u8 duty_offset = 0; + u8 duty_width = 0; + u32 duty_cycle = 0; + + + /* Convert and validate the device handle */ + + cpu_entry = acpi_ns_convert_handle_to_entry (processor_handle); + if (!cpu_entry) { + return (AE_BAD_PARAMETER); + } + + /* Check for an existing internal object */ + + cpu_obj = acpi_ns_get_attached_object ((ACPI_HANDLE) cpu_entry); + if (!cpu_obj) { + return (AE_NOT_FOUND); + } + + duty_offset = acpi_gbl_FACP->duty_offset; + duty_width = acpi_gbl_FACP->duty_width; + + /* + * Must have a valid P_BLK P0 must have a P_BLK all others may be null + * in either case, we can't thottle a processor that has no P_BLK + * that means we are in the only supported state (0 - 100%) + * + * also, if Duty_width is zero there are no additional states + */ + if (!cpu_obj->processor.pblk_length || !duty_width || + (0xFFFF < cpu_obj->processor.pblk_address)) + { + /* + * If caller wants to set the state to the only state we handle + * we're done. + */ + if (throttle_state == 0) { + return (AE_OK); + } + + /* + * Can't set this state + */ + return (AE_SUPPORT); + } + + num_throttle_states = (int) acpi_hw_local_pow (2,duty_width); + + /* + * Convert throttling state to duty cycle (invert). + */ + if (throttle_state > 0) { + duty_cycle = num_throttle_states - throttle_state; + } + + /* + * Turn off throttling (don't muck with the h/w while throttling). + */ + acpi_hw_disable_throttling (cpu_obj->processor.pblk_address); + + /* + * Program the throttling state. + */ + acpi_hw_program_duty_cycle (duty_offset, duty_cycle, + cpu_obj->processor.pblk_address, num_throttle_states); + + /* + * Only enable throttling for non-zero states (0 - 100%) + */ + if (throttle_state) { + acpi_hw_enable_throttling (cpu_obj->processor.pblk_address); + } + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_get_processor_cx_info + * + * PARAMETERS: Processor_handle - handle for the cpu return info about + * User_buffer - caller supplied buffer + * + * RETURN: Status of function + * + * DESCRIPTION: Get Cx state latencies, this routine + * builds the data directly into the callers buffer + * + * + ****************************************************************************/ + +ACPI_STATUS +acpi_get_processor_cx_info ( + ACPI_HANDLE processor_handle, + ACPI_BUFFER *user_buffer) +{ + ACPI_STATUS status = AE_OK; + u32 cx_state_latencies[4] = {0, 0, 0, 0}; + NATIVE_UINT buffer_space_needed = 0; + ACPI_CX_STATE *state_ptr = NULL; + NATIVE_UINT i = 0; + + + /* + * Have to at least have a buffer to return info in + */ + if (!user_buffer) { + return (AE_BAD_PARAMETER); + } + + status = acpi_hw_get_cx_info (cx_state_latencies); + if (ACPI_FAILURE (status)) { + return (status); + } + + buffer_space_needed = 4 * sizeof (ACPI_CX_STATE); + + if ((user_buffer->length < buffer_space_needed) || !user_buffer->pointer) { + user_buffer->length = buffer_space_needed; + return (AE_BUFFER_OVERFLOW); + } + + user_buffer->length = buffer_space_needed; + + state_ptr = (ACPI_CX_STATE *) user_buffer->pointer; + + for (i = 0; i < 4; i++) { + state_ptr[i].state_number = i; + state_ptr[i].latency = cx_state_latencies[i]; + } + + return (AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_set_processor_sleep_state + * + * PARAMETERS: Processor_handle - handle for the cpu return info about + * Cx_state - the Cx sleeping state (C1-C3) to make + * 'active' + * + * RETURN: Status of function + * + * DESCRIPTION: Sets which Cx state will be used during calls to + * Acpi_processor_sleep () + * + ****************************************************************************/ + +ACPI_STATUS +acpi_set_processor_sleep_state ( + ACPI_HANDLE processor_handle, + u32 cx_state) +{ + ACPI_STATUS status; + + + status = acpi_hw_set_cx (cx_state); + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_processor_sleep + * + * PARAMETERS: Processor_handle - handle for the cpu to put to sleep (Cx) + * Time_sleeping - time (in microseconds) elapsed while + * sleeping + * + * RETURN: Status of function + * + * DESCRIPTION: Puts the processor into the currently active sleep state (Cx) + * + ****************************************************************************/ + +ACPI_STATUS +acpi_processor_sleep ( + ACPI_HANDLE processor_handle, + u32 *pm_timer_ticks) +{ + ACPI_NAMED_OBJECT *cpu_entry = NULL; + ACPI_OBJECT_INTERNAL *cpu_obj = NULL; + ACPI_IO_ADDRESS pblk_address = 0; + + + /* + * Convert Processor_handle to Pblk_addres... + */ + + /* Convert and validate the device handle */ + + cpu_entry = acpi_ns_convert_handle_to_entry (processor_handle); + if (!cpu_entry) { + return AE_BAD_PARAMETER; + } + + /* Check for an existing internal object */ + + cpu_obj = acpi_ns_get_attached_object ((ACPI_HANDLE) cpu_entry); + if (!cpu_obj) { + return AE_NOT_FOUND; + } + + /* Get the processor register block (P_BLK) address */ + + pblk_address = cpu_obj->processor.pblk_address; + if (!cpu_obj->processor.pblk_length) { + /* Ensure a NULL addresss (note that P_BLK isn't required for C1) */ + + pblk_address = 0; + } + + /* + * Enter the currently active Cx sleep state. + */ + return acpi_hw_enter_cx (pblk_address, pm_timer_ticks); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_timer + * + * PARAMETERS: none + * + * RETURN: Current value of the ACPI PMT (timer) + * + * DESCRIPTION: Obtains current value of ACPI PMT + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_timer ( + u32 *out_ticks) +{ + + if (!out_ticks) { + return (AE_BAD_PARAMETER); + } + + *out_ticks = acpi_hw_pmt_ticks (); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_set_firmware_waking_vector + * + * PARAMETERS: Physical_address - Physical address of ACPI real mode + * entry point. + * + * RETURN: AE_OK or AE_ERROR + * + * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS + * + ******************************************************************************/ + +ACPI_STATUS +acpi_set_firmware_waking_vector ( + void *physical_address) +{ + + /* Make sure that we have an FACS */ + + if (!acpi_gbl_FACS) { + return (AE_NO_ACPI_TABLES); + } + + /* Set the vector */ + + * ((void **) acpi_gbl_FACS->firmware_waking_vector) = physical_address; + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_firmware_waking_vector + * + * PARAMETERS: *Physical_address - Output buffer where contents of + * the d_firmware_waking_vector field of + * the FACS will be stored. + * + * RETURN: Status + * + * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_firmware_waking_vector ( + void **physical_address) +{ + + if (!physical_address) { + return (AE_BAD_PARAMETER); + } + + /* Make sure that we have an FACS */ + + if (!acpi_gbl_FACS) { + return (AE_NO_ACPI_TABLES); + } + + /* Get the vector */ + + *physical_address = * ((void **) acpi_gbl_FACS->firmware_waking_vector); + + + return (AE_OK); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/acenv.h linux/drivers/acpi/include/acenv.h --- v2.4.0-test2/linux/drivers/acpi/include/acenv.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/acenv.h Thu Jul 6 01:22:24 2000 @@ -0,0 +1,301 @@ + +/****************************************************************************** + * + * Name: acenv.h - Generation environment specific items + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACENV_H__ +#define __ACENV_H__ + + +/* + * Environment configuration. The purpose of this file is to interface to the + * local generation environment. + * + * 1) ACPI_USE_SYSTEM_CLIBRARY - Define this if linking to an actual C library. + * Otherwise, local versions of string/memory functions will be used. + * 2) ACPI_USE_STANDARD_HEADERS - Define this if linking to a C library and + * the standard header files may be used. + * + * The ACPI subsystem only uses low level C library functions that do not call + * operating system services and may therefore be inlined in the code. + * + * It may be necessary to tailor these include files to the target + * generation environment. + * + * + * Functions and constants used from each header: + * + * string.h: memcpy + * memset + * strcat + * strcmp + * strcpy + * strlen + * strncmp + * strncat + * strncpy + * + * stdlib.h: strtoul + * + * stdarg.h: va_list + * va_arg + * va_start + * va_end + * + */ + + +/* + * Environment-specific configuration + */ + +#ifdef _LINUX + +#include +#include +#include +#include + +/* Single threaded */ + +#define ACPI_APPLICATION + +/* Use native Linux string library */ + +#define ACPI_USE_SYSTEM_CLIBRARY + +/* Special functions */ + +#define strtoul simple_strtoul + +#else + +/* All other environments */ + +#define ACPI_USE_STANDARD_HEADERS + +#endif + + +/****************************************************************************** + * + * C library configuration + * + *****************************************************************************/ + +#ifdef ACPI_USE_SYSTEM_CLIBRARY +/* + * Use the standard C library headers. + * We want to keep these to a minimum. + * + */ + +#ifdef ACPI_USE_STANDARD_HEADERS +/* + * Use the standard headers from the standard locations + */ +#include +#include +#include + +#endif /* ACPI_USE_STANDARD_HEADERS */ + +/* + * We will be linking to the standard Clib functions + */ + +#define STRSTR(s1,s2) strstr((char *) (s1), (char *) (s2)) +#define STRUPR(s) strupr((char *) (s)) +#define STRLEN(s) strlen((char *) (s)) +#define STRCPY(d,s) strcpy((char *) (d), (char *) (s)) +#define STRNCPY(d,s,n) strncpy((char *) (d), (char *) (s), (n)) +#define STRNCMP(d,s,n) strncmp((char *) (d), (char *) (s), (n)) +#define STRCMP(d,s) strcmp((char *) (d), (char *) (s)) +#define STRCAT(d,s) strcat((char *) (d), (char *) (s)) +#define STRNCAT(d,s,n) strncat((char *) (d), (char *) (s), (n)) +#define STRTOUL(d,s,n) strtoul((char *) (d), (char **) (s), (n)) +#define MEMCPY(d,s,n) memcpy(d, s, (size_t) n) +#define MEMSET(d,s,n) memset(d, s, (size_t) n) +#define TOUPPER toupper +#define TOLOWER tolower + + +/****************************************************************************** + * + * Not using native C library, use local implementations + * + *****************************************************************************/ +#else + +/* + * Use local definitions of C library macros and functions + * NOTE: The function implementations may not be as efficient + * as an inline or assembly code implementation provided by a + * native C library. + */ + +#ifndef va_arg + +#ifndef _VALIST +#define _VALIST +typedef char *va_list; +#endif /* _VALIST */ + +/* + * Storage alignment properties + */ + +#define _AUPBND (sizeof(int) - 1) +#define _ADNBND (sizeof(int) - 1) + +/* + * Variable argument list macro definitions + */ + +#define _bnd(X, bnd) (((sizeof(X)) + (bnd)) & (~(bnd))) +#define va_arg(ap, T) (*(T *)(((ap) += ((_bnd(T, _AUPBND))) \ + - (_bnd(T, _ADNBND))))) +#define va_end(ap) (void)0 +#define va_start(ap, A) (void) ((ap) = (((char *)&(A)) \ + + (_bnd(A, _AUPBND)))) + +#endif /* va_arg */ + + +#define STRSTR(s1,s2) acpi_cm_strstr ((char *) (s1), (char *) (s2)) +#define STRUPR(s) acpi_cm_strupr ((char *) (s)) +#define STRLEN(s) acpi_cm_strlen ((char *) (s)) +#define STRCPY(d,s) acpi_cm_strcpy ((char *) (d), (char *) (s)) +#define STRNCPY(d,s,n) acpi_cm_strncpy ((char *) (d), (char *) (s), (n)) +#define STRNCMP(d,s,n) acpi_cm_strncmp ((char *) (d), (char *) (s), (n)) +#define STRCMP(d,s) acpi_cm_strcmp ((char *) (d), (char *) (s)) +#define STRCAT(d,s) acpi_cm_strcat ((char *) (d), (char *) (s)) +#define STRNCAT(d,s,n) acpi_cm_strncat ((char *) (d), (char *) (s), (n)) +#define STRTOUL(d,s,n) acpi_cm_strtoul ((char *) (d), (char **) (s), (n)) +#define MEMCPY(d,s,n) acpi_cm_memcpy ((void *) (d), (const void *) (s), (n)) +#define MEMSET(d,v,n) acpi_cm_memset ((void *) (d), (v), (n)) +#define TOUPPER acpi_cm_to_upper +#define TOLOWER acpi_cm_to_lower + +#endif /* ACPI_USE_SYSTEM_CLIBRARY */ + + +/****************************************************************************** + * + * Assembly code macros + * + *****************************************************************************/ + +/* + * Handle platform- and compiler-specific assembly language differences. + * + * Notes: + * 1) Interrupt 3 is used to break into a debugger + * 2) Interrupts are turned off during ACPI register setup + */ + + +#ifdef __GNUC__ + +#ifdef __ia64__ +#define _IA64 +#endif + +#define ACPI_ASM_MACROS +#define causeinterrupt(level) +#define BREAKPOINT3 +#define disable() __cli() +#define enable() __sti() +#define halt() __asm__ __volatile__ ("sti; hlt":::"memory") +#define wbinvd() + + +/*! [Begin] no source code translation + * + * A brief explanation as GNU inline assembly is a bit hairy + * %0 is the output parameter in EAX ("=a") + * %1 and %2 are the input parameters in ECX ("c") and an immediate value ("i") respectively + * All actual register references are preceded with "%%" as in "%%edx" + * Immediate values in the assembly are preceded by "$" as in "$0x1" + * The final asm parameter is the non-output registers altered by the operation + */ +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ + do { \ + int dummy; \ + asm("1: movl (%1),%%eax;" \ + "movl %%eax,%%edx;" \ + "andl %2,%%edx;" \ + "btsl $0x1,%%edx;" \ + "adcl $0x0,%%edx;" \ + "lock; cmpxchgl %%edx,(%1);" \ + "jnz 1b;" \ + "cmpb $0x3,%%dl;" \ + "sbbl %%eax,%%eax" \ + :"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~1L):"dx"); \ + } while(0) + +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ + do { \ + int dummy; \ + asm("1: movl (%1),%%eax;" \ + "movl %%eax,%%edx;" \ + "andl %2,%%edx;" \ + "lock; cmpxchgl %%edx,(%1);" \ + "jnz 1b;" \ + "andl $0x1,%%eax" \ + :"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~3L):"dx"); \ + } while(0) +/*! [End] no source code translation !*/ + +#endif /* __GNUC__ */ + + +#ifndef ACPI_ASM_MACROS + +/* Unrecognized compiler, use defaults */ + +#define ACPI_ASM_MACROS +#define causeinterrupt(level) +#define BREAKPOINT3 +#define disable() +#define enable() +#define halt() + +#define ACPI_ACQUIRE_GLOBAL_LOCK(Glptr, acq) +#define ACPI_RELEASE_GLOBAL_LOCK(Glptr, acq) + +#endif /* ACPI_ASM_MACROS */ + + +#ifdef ACPI_APPLICATION + +/* Don't want software interrupts within a ring3 application */ + +#undef causeinterrupt +#undef BREAKPOINT3 +#define causeinterrupt(level) +#define BREAKPOINT3 +#endif + + +#endif /* __ACENV_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/acexcep.h linux/drivers/acpi/include/acexcep.h --- v2.4.0-test2/linux/drivers/acpi/include/acexcep.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/acexcep.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,162 @@ + +/****************************************************************************** + * + * Name: acexcep.h - Exception codes returned by the ACPI subsystem + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACEXCEP_H__ +#define __ACEXCEP_H__ + + +/* + * Exceptions returned by external ACPI interfaces + */ + +#define ACPI_SUCCESS(a) (!(a)) +#define ACPI_FAILURE(a) (a) + +#define AE_OK (ACPI_STATUS) 0x0000 +#define AE_CTRL_RETURN_VALUE (ACPI_STATUS) 0x0001 +#define AE_CTRL_PENDING (ACPI_STATUS) 0x0002 +#define AE_CTRL_TERMINATE (ACPI_STATUS) 0x0003 +#define AE_CTRL_TRUE (ACPI_STATUS) 0x0004 +#define AE_CTRL_FALSE (ACPI_STATUS) 0x0005 +#define AE_CTRL_DEPTH (ACPI_STATUS) 0x0006 +#define AE_CTRL_RESERVED (ACPI_STATUS) 0x0007 +#define AE_AML_ERROR (ACPI_STATUS) 0x0008 +#define AE_AML_PARSE (ACPI_STATUS) 0x0009 +#define AE_AML_BAD_OPCODE (ACPI_STATUS) 0x000A +#define AE_AML_NO_OPERAND (ACPI_STATUS) 0x000B +#define AE_AML_OPERAND_TYPE (ACPI_STATUS) 0x000C +#define AE_AML_OPERAND_VALUE (ACPI_STATUS) 0x000D +#define AE_AML_UNINITIALIZED_LOCAL (ACPI_STATUS) 0x000E +#define AE_AML_UNINITIALIZED_ARG (ACPI_STATUS) 0x000F +#define AE_AML_UNINITIALIZED_ELEMENT (ACPI_STATUS) 0x0010 +#define AE_AML_NUMERIC_OVERFLOW (ACPI_STATUS) 0x0011 +#define AE_AML_REGION_LIMIT (ACPI_STATUS) 0x0012 +#define AE_AML_BUFFER_LIMIT (ACPI_STATUS) 0x0013 +#define AE_AML_PACKAGE_LIMIT (ACPI_STATUS) 0x0014 +#define AE_AML_DIVIDE_BY_ZERO (ACPI_STATUS) 0x0015 +#define AE_AML_BAD_NAME (ACPI_STATUS) 0x0016 +#define AE_AML_NAME_NOT_FOUND (ACPI_STATUS) 0x0017 +#define AE_AML_INTERNAL (ACPI_STATUS) 0x0018 +#define AE_AML_RESERVED (ACPI_STATUS) 0x0019 +#define AE_ERROR (ACPI_STATUS) 0x001A +#define AE_NO_ACPI_TABLES (ACPI_STATUS) 0x001B +#define AE_NO_NAMESPACE (ACPI_STATUS) 0x001C +#define AE_NO_MEMORY (ACPI_STATUS) 0x001D +#define AE_BAD_SIGNATURE (ACPI_STATUS) 0x001E +#define AE_BAD_HEADER (ACPI_STATUS) 0x001F +#define AE_BAD_CHECKSUM (ACPI_STATUS) 0x0020 +#define AE_BAD_PARAMETER (ACPI_STATUS) 0x0021 +#define AE_BAD_CHARACTER (ACPI_STATUS) 0x0022 +#define AE_BAD_PATHNAME (ACPI_STATUS) 0x0023 +#define AE_BAD_DATA (ACPI_STATUS) 0x0024 +#define AE_BAD_ADDRESS (ACPI_STATUS) 0x0025 +#define AE_NOT_FOUND (ACPI_STATUS) 0x0026 +#define AE_NOT_EXIST (ACPI_STATUS) 0x0027 +#define AE_EXIST (ACPI_STATUS) 0x0028 +#define AE_TYPE (ACPI_STATUS) 0x0029 +#define AE_NULL_OBJECT (ACPI_STATUS) 0x002A +#define AE_NULL_ENTRY (ACPI_STATUS) 0x002B +#define AE_BUFFER_OVERFLOW (ACPI_STATUS) 0x002C +#define AE_STACK_OVERFLOW (ACPI_STATUS) 0x002D +#define AE_STACK_UNDERFLOW (ACPI_STATUS) 0x002E +#define AE_NOT_IMPLEMENTED (ACPI_STATUS) 0x002F +#define AE_VERSION_MISMATCH (ACPI_STATUS) 0x0030 +#define AE_SUPPORT (ACPI_STATUS) 0x0031 +#define AE_SHARE (ACPI_STATUS) 0x0032 +#define AE_LIMIT (ACPI_STATUS) 0x0033 +#define AE_TIME (ACPI_STATUS) 0x0034 +#define AE_UNKNOWN_STATUS (ACPI_STATUS) 0x0035 +#define ACPI_MAX_STATUS (ACPI_STATUS) 0x0035 +#define ACPI_NUM_STATUS (ACPI_STATUS) 0x0036 + + +#ifdef DEFINE_ACPI_GLOBALS + +/* + * String versions of the exception codes above + * These strings must match the corresponding defines exactly + */ +static char *acpi_gbl_exception_names[] = +{ + "AE_OK", + "AE_CTRL_RETURN_VALUE", + "AE_CTRL_PENDING", + "AE_CTRL_TERMINATE", + "AE_CTRL_TRUE", + "AE_CTRL_FALSE", + "AE_CTRL_DEPTH", + "AE_CTRL_RESERVED", + "AE_AML_ERROR", + "AE_AML_PARSE", + "AE_AML_BAD_OPCODE", + "AE_AML_NO_OPERAND", + "AE_AML_OPERAND_TYPE", + "AE_AML_OPERAND_VALUE", + "AE_AML_UNINITIALIZED_LOCAL", + "AE_AML_UNINITIALIZED_ARG", + "AE_AML_UNINITIALIZED_ELEMENT", + "AE_AML_NUMERIC_OVERFLOW", + "AE_AML_REGION_LIMIT", + "AE_AML_BUFFER_LIMIT", + "AE_AML_PACKAGE_LIMIT", + "AE_AML_DIVIDE_BY_ZERO", + "AE_AML_BAD_NAME", + "AE_AML_NAME_NOT_FOUND", + "AE_AML_INTERNAL", + "AE_AML_RESERVED", + "AE_ERROR", + "AE_NO_ACPI_TABLES", + "AE_NO_NAMESPACE", + "AE_NO_MEMORY", + "AE_BAD_SIGNATURE", + "AE_BAD_HEADER", + "AE_BAD_CHECKSUM", + "AE_BAD_PARAMETER", + "AE_BAD_CHARACTER", + "AE_BAD_PATHNAME", + "AE_BAD_DATA", + "AE_BAD_ADDRESS", + "AE_NOT_FOUND", + "AE_NOT_EXIST", + "AE_EXIST", + "AE_TYPE", + "AE_NULL_OBJECT", + "AE_NULL_ENTRY", + "AE_BUFFER_OVERFLOW", + "AE_STACK_OVERFLOW", + "AE_STACK_UNDERFLOW", + "AE_NOT_IMPLEMENTED", + "AE_VERSION_MISMATCH", + "AE_SUPPORT", + "AE_SHARE", + "AE_LIMIT", + "AE_TIME", + "AE_UNKNOWN_STATUS" +}; + +#endif /* DEFINE_ACPI_GLOBALS */ + + +#endif /* __ACEXCEP_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/acobject.h linux/drivers/acpi/include/acobject.h --- v2.4.0-test2/linux/drivers/acpi/include/acobject.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/acobject.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,508 @@ + +/****************************************************************************** + * + * Name: acobject.h - Definition of ACPI_OBJECT_INTERNAL (Internal object only) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ACOBJECT_H +#define _ACOBJECT_H + +#include "actypes.h" +#include "macros.h" +#include "internal.h" + +/* + * The ACPI_OBJECT_INTERNAL is used to pass AML operands from the dispatcher + * to the interpreter, and to keep track of the various handlers such as + * address space handlers and notify handlers. The object is a constant + * size in order to allow them to be cached and reused. + * + * All variants of the ACPI_OBJECT_INTERNAL are defined with the same + * sequence of field types, with fields that are not used in a particular + * variant being named "Reserved". This is not strictly necessary, but + * may in some circumstances simplify understanding if these structures + * need to be displayed in a debugger having limited (or no) support for + * union types. It also simplifies some debug code in Dump_table() which + * dumps multi-level values: fetching Buffer.Pointer suffices to pick up + * the value or next level for any of several types. + */ + +/****************************************************************************** + * + * Common Descriptors + * + *****************************************************************************/ + +/* + * Common area for all objects. + * + * Data_type is used to differentiate between internal descriptors, and MUST + * be the first byte in this structure. + */ + + +#define ACPI_OBJECT_COMMON_HEADER /* Two 32-bit fields */\ + u8 data_type; /* To differentiate various internal objs */\ + u8 type; /* ACPI_OBJECT_TYPE */\ + u8 size; /* Size of entire descriptor */\ + u8 flags;\ + u16 reference_count; /* For object deletion management */\ + u16 acpi_cm_fill2;\ + union acpi_obj_internal *next; \ + +/* Defines for flag byte above */ + +#define AO_STATIC_ALLOCATION 0x1 + + +/* + * Common bitfield for the field objects + */ +#define ACPI_COMMON_FIELD_INFO /* Three 32-bit values */\ + u32 offset; /* Byte offset within containing object */\ + u16 length; /* # of bits in buffer */ \ + u8 granularity;\ + u8 bit_offset; /* Bit offset within min read/write data unit */\ + u8 access; /* Access_type */\ + u8 lock_rule;\ + u8 update_rule;\ + u8 access_attribute; + + +/****************************************************************************** + * + * Individual Object Descriptors + * + *****************************************************************************/ + + +typedef struct /* COMMON */ +{ + ACPI_OBJECT_COMMON_HEADER + UCHAR first_non_common_byte; + +} ACPI_OBJECT_COMMON; + + +typedef struct /* NUMBER - has value */ +{ + ACPI_OBJECT_COMMON_HEADER + + u32 value; + u32 reserved2; + u32 reserved3; + u32 reserved4; + + void *reserved_p1; + void *reserved_p2; + void *reserved_p3; + void *reserved_p4; + void *reserved_p5; + +} ACPI_OBJECT_NUMBER; + + +typedef struct /* STRING - has length and pointer */ +{ + ACPI_OBJECT_COMMON_HEADER + + u32 length; /* # of bytes in string, excluding trailing null */ + u32 reserved2; + u32 reserved3; + u32 reserved4; + + char *pointer; /* String value in AML stream or in allocated space */ + void *reserved_p2; + void *reserved_p3; + void *reserved_p4; + void *reserved_p5; + +} ACPI_OBJECT_STRING; + + +typedef struct /* BUFFER - has length, sequence, and pointer */ +{ + ACPI_OBJECT_COMMON_HEADER + + u32 length; /* # of bytes in buffer */ + u32 sequence; /* Sequential count of buffers created */ + u32 reserved3; + u32 reserved4; + + u8 *pointer; /* points to the buffer in allocated space */ + void *reserved_p2; + void *reserved_p3; + void *reserved_p4; + void *reserved_p5; + +} ACPI_OBJECT_BUFFER; + + +typedef struct /* PACKAGE - has count, elements, next element */ +{ + ACPI_OBJECT_COMMON_HEADER + + u32 count; /* # of elements in package */ + u32 reserved2; + u32 reserved3; + u32 reserved4; + + union acpi_obj_internal **elements; /* Array of pointers to Acpi_objects */ + union acpi_obj_internal **next_element; /* used only while initializing */ + void *reserved_p3; + void *reserved_p4; + void *reserved_p5; + +} ACPI_OBJECT_PACKAGE; + + +typedef struct /* FIELD UNIT */ +{ + ACPI_OBJECT_COMMON_HEADER + + ACPI_COMMON_FIELD_INFO + u32 sequence; /* Container's sequence number */ + + union acpi_obj_internal *container; /* Containing object (Buffer) */ + void *reserved_p2; + void *reserved_p3; + void *reserved_p4; + void *reserved_p5; + +} ACPI_OBJECT_FIELD_UNIT; + + +typedef struct /* DEVICE - has handle and notification handler/context */ +{ + ACPI_OBJECT_COMMON_HEADER + + u32 reserved1; + u32 reserved2; + u32 reserved3; + u32 reserved4; + + ACPI_HANDLE handle; + union acpi_obj_internal *sys_handler; /* Handler for system notifies */ + union acpi_obj_internal *drv_handler; /* Handler for driver notifies */ + union acpi_obj_internal *addr_handler; /* Handler for Address space */ + void *reserved_p5; + +} ACPI_OBJECT_DEVICE; + + +typedef struct /* EVENT */ +{ + ACPI_OBJECT_COMMON_HEADER + + u16 lock_count; + u16 thread_id; + u16 signal_count; + u16 fill1; + u32 reserved3; + u32 reserved4; + + void *semaphore; + void *reserved_p2; + void *reserved_p3; + void *reserved_p4; + void *reserved_p5; + +} ACPI_OBJECT_EVENT; + + +#define INFINITE_CONCURRENCY 0xFF + +typedef struct /* METHOD */ +{ + ACPI_OBJECT_COMMON_HEADER + + u8 method_flags; + u8 param_count; + u8 concurrency; + u8 fill1; + u32 pcode_length; + u32 table_length; + ACPI_OWNER_ID owning_id; + u16 reserved4; + + u8 *pcode; + u8 *acpi_table; + void *parser_op; + void *semaphore; + void *reserved_p5; + +} ACPI_OBJECT_METHOD; + + +typedef struct /* MUTEX */ +{ + ACPI_OBJECT_COMMON_HEADER + + u16 lock_count; + u16 thread_id; + u16 sync_level; + u16 fill1; + u32 reserved3; + u32 reserved4; + + void *semaphore; + void *reserved_p2; + void *reserved_p3; + void *reserved_p4; + void *reserved_p5; + +} ACPI_OBJECT_MUTEX; + +/* Flags for Region */ + +#define INITIAL_REGION_FLAGS 0x0000 /* value set when the region is created */ +#define REGION_AGRUMENT_DATA_VALID 0x0001 /* Addr/Len are set */ +#define REGION_INITIALIZED 0x0002 /* region init handler has been called */ + /* this includes _REG method, if any */ + +typedef struct /* REGION */ +{ + ACPI_OBJECT_COMMON_HEADER + + u16 space_id; + u16 region_flags; /* bits defined above */ + u32 address; + u32 length; + u32 reserved4; /* Region Specific data (PCI _ADR) */ + + union acpi_obj_internal *method; /* Associated control method */ + union acpi_obj_internal *addr_handler; /* Handler for system notifies */ + union acpi_obj_internal *link; /* Link in list of regions */ + /* list is owned by Addr_handler */ + ACPI_NAMED_OBJECT *REGmethod; /* _REG method for this region (if any) */ + ACPI_NAMED_OBJECT *nte; /* containing object */ + +} ACPI_OBJECT_REGION; + + +typedef struct /* POWER RESOURCE - has Handle and notification handler/context*/ +{ + ACPI_OBJECT_COMMON_HEADER + + u32 system_level; + u32 resource_order; + u32 reserved3; + u32 reserved4; + + ACPI_HANDLE handle; + union acpi_obj_internal *sys_handler; /* Handler for system notifies */ + union acpi_obj_internal *drv_handler; /* Handler for driver notifies */ + void *reserved_p4; + void *reserved_p5; + +} ACPI_OBJECT_POWER_RESOURCE; + + +typedef struct /* PROCESSOR - has Handle and notification handler/context*/ +{ + ACPI_OBJECT_COMMON_HEADER + + u32 proc_id; + ACPI_IO_ADDRESS pblk_address; + u16 fill1; + u32 pblk_length; + u32 reserved4; + + ACPI_HANDLE handle; + union acpi_obj_internal *sys_handler; /* Handler for system notifies */ + union acpi_obj_internal *drv_handler; /* Handler for driver notifies */ + union acpi_obj_internal *addr_handler; /* Handler for Address space */ + void *reserved_p5; + +} ACPI_OBJECT_PROCESSOR; + + +typedef struct /* THERMAL ZONE - has Handle and Handler/Context */ +{ + ACPI_OBJECT_COMMON_HEADER + + u32 reserved1; + u32 reserved2; + u32 reserved3; + u32 reserved4; + + ACPI_HANDLE handle; + union acpi_obj_internal *sys_handler; /* Handler for system notifies */ + union acpi_obj_internal *drv_handler; /* Handler for driver notifies */ + union acpi_obj_internal *addr_handler; /* Handler for Address space */ + void *reserved_p5; + +} ACPI_OBJECT_THERMAL_ZONE; + + +/* + * Internal types + */ + +typedef struct /* FIELD */ +{ + ACPI_OBJECT_COMMON_HEADER + + ACPI_COMMON_FIELD_INFO + u32 reserved4; + + union acpi_obj_internal *container; /* Containing object */ + void *reserved_p2; + void *reserved_p3; + void *reserved_p4; + void *reserved_p5; + +} ACPI_OBJECT_FIELD; + + +typedef struct /* BANK FIELD */ +{ + ACPI_OBJECT_COMMON_HEADER + + ACPI_COMMON_FIELD_INFO + u32 value; /* Value to store into Bank_select */ + + ACPI_HANDLE bank_select; /* Bank select register */ + union acpi_obj_internal *container; /* Containing object */ + void *reserved_p3; + void *reserved_p4; + void *reserved_p5; + +} ACPI_OBJECT_BANK_FIELD; + + +typedef struct /* INDEX FIELD */ +{ + /* + * No container pointer needed since the index and data register definitions + * will define how to access the respective registers + */ + ACPI_OBJECT_COMMON_HEADER + + ACPI_COMMON_FIELD_INFO + u32 value; /* Value to store into Index register */ + + ACPI_HANDLE index; /* Index register */ + ACPI_HANDLE data; /* Data register */ + void *reserved_p3; + void *reserved_p4; + void *reserved_p5; + +} ACPI_OBJECT_INDEX_FIELD; + + +typedef struct /* NOTIFY HANDLER */ +{ + ACPI_OBJECT_COMMON_HEADER + + u32 reserved1; + u32 reserved2; + u32 reserved3; + u32 reserved4; + + ACPI_NAMED_OBJECT *nte; /* Parent device */ + NOTIFY_HANDLER handler; + void *context; + void *reserved_p4; + void *reserved_p5; + +} ACPI_OBJECT_NOTIFY_HANDLER; + + +/* Flags for address handler */ + +#define ADDR_HANDLER_DEFAULT_INSTALLED 0x1 + +typedef struct /* ADDRESS HANDLER */ +{ + ACPI_OBJECT_COMMON_HEADER + + u16 space_id; + u16 hflags; + ADDRESS_SPACE_HANDLER handler; + + ACPI_NAMED_OBJECT *nte; /* Parent device */ + void *context; + ADDRESS_SPACE_SETUP setup; + union acpi_obj_internal *link; /* Link to next handler on device */ + union acpi_obj_internal *region_list; /* regions using this handler */ + +} ACPI_OBJECT_ADDR_HANDLER; + + +/* + * The Reference object type is used for these opcodes: + * Arg[0-6], Local[0-7], Index_op, Name_op, Zero_op, One_op, Ones_op, Debug_op + */ + +typedef struct /* Reference - Local object type */ +{ + ACPI_OBJECT_COMMON_HEADER + + u16 op_code; + u8 fill1; + u8 target_type; /* Used for Index_op */ + u32 offset; /* Used for Arg_op, Local_op, and Index_op */ + u32 reserved3; + u32 reserved4; + + void *object; /* Name_op=>HANDLE to obj, Index_op=>ACPI_OBJECT_INTERNAL */ + ACPI_NAMED_OBJECT *nte; + union acpi_obj_internal **where; + void *reserved_p4; + void *reserved_p5; + +} ACPI_OBJECT_REFERENCE; + + +/****************************************************************************** + * + * ACPI_OBJECT_INTERNAL Descriptor - a giant union of all of the above + * + *****************************************************************************/ + +typedef union acpi_obj_internal +{ + ACPI_OBJECT_COMMON common; + ACPI_OBJECT_NUMBER number; + ACPI_OBJECT_STRING string; + ACPI_OBJECT_BUFFER buffer; + ACPI_OBJECT_PACKAGE package; + ACPI_OBJECT_FIELD_UNIT field_unit; + ACPI_OBJECT_DEVICE device; + ACPI_OBJECT_EVENT event; + ACPI_OBJECT_METHOD method; + ACPI_OBJECT_MUTEX mutex; + ACPI_OBJECT_REGION region; + ACPI_OBJECT_POWER_RESOURCE power_resource; + ACPI_OBJECT_PROCESSOR processor; + ACPI_OBJECT_THERMAL_ZONE thermal_zone; + ACPI_OBJECT_FIELD field; + ACPI_OBJECT_BANK_FIELD bank_field; + ACPI_OBJECT_INDEX_FIELD index_field; + ACPI_OBJECT_REFERENCE reference; + ACPI_OBJECT_NOTIFY_HANDLER notify_handler; + ACPI_OBJECT_ADDR_HANDLER addr_handler; + +} ACPI_OBJECT_INTERNAL; + +#endif /* _ACOBJECT_H */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/acpi.h linux/drivers/acpi/include/acpi.h --- v2.4.0-test2/linux/drivers/acpi/include/acpi.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/acpi.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,50 @@ + +/****************************************************************************** + * + * Name: acpi.h - Master include file, Publics and external data. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACPI_H__ +#define __ACPI_H__ + +/* + * Common includes for all ACPI driver files + * We put them here because we don't want to duplicate them + * in the rest of the source code again and again. + */ +#include "config.h" /* Configuration constants */ +#include "acenv.h" /* Target environment specific items */ +#include "actypes.h" /* Fundamental data types */ +#include "acexcep.h" /* Local exception codes */ +#include "macros.h" /* C macros */ +#include "actables.h" /* Acpi table definitions */ +#include "internal.h" /* Internal data types */ +#include "output.h" /* Error output and Debug macros */ +#include "acpiosxf.h" /* Interfaces to the Acpi-to-OS layer*/ +#include "acpixf.h" /* Acpi core external interfaces */ +#include "acobject.h" /* Acpi internal object */ +#include "globals.h" /* All global variables */ +#include "hardware.h" /* Hardware defines and interfaces */ +#include "common.h" /* Common (global) interfaces */ + + +#endif /* __ACPI_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/acpiosxf.h linux/drivers/acpi/include/acpiosxf.h --- v2.4.0-test2/linux/drivers/acpi/include/acpiosxf.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/acpiosxf.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,296 @@ + +/****************************************************************************** + * + * Name: acpiosd.h - All interfaces to the OS-dependent layer. These + * interfaces must be implemented by the OS-dependent + * front-end to the ACPI subsystem. + * + *****************************************************************************/ + + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACPIOSD_H__ +#define __ACPIOSD_H__ + +#include "acenv.h" +#include "actypes.h" + + +/* Priorities for Acpi_os_queue_for_execution */ + +#define OSD_PRIORITY_HIGH 1 +#define OSD_PRIORITY_MED 2 +#define OSD_PRIORITY_LO 3 +#define OSD_PRIORITY_GPE OSD_PRIORITY_HIGH + +#define ACPI_NO_UNIT_LIMIT ((u32) -1) +#define ACPI_MUTEX_SEM 1 + + +/* + * Types specific to the OS-dependent layer interfaces + */ + +typedef +u32 (*OSD_HANDLER) ( + void *context); + +typedef +void (*OSD_EXECUTION_CALLBACK) ( + void *context); + + +/* + * Initialization and shutdown primitives (Optional) + */ + +ACPI_STATUS +acpi_os_initialize ( + void); + +ACPI_STATUS +acpi_os_terminate ( + void); + +/* + * Synchronization primitives + */ + +ACPI_STATUS +acpi_os_create_semaphore ( + u32 max_units, + u32 initial_units, + ACPI_HANDLE *out_handle); + +ACPI_STATUS +acpi_os_delete_semaphore ( + ACPI_HANDLE handle); + +ACPI_STATUS +acpi_os_wait_semaphore ( + ACPI_HANDLE handle, + u32 units, + u32 timeout); + +ACPI_STATUS +acpi_os_signal_semaphore ( + ACPI_HANDLE handle, + u32 units); + +/* + * Memory allocation and mapping + */ + +void * +acpi_os_allocate ( + u32 size); + +void * +acpi_os_callocate ( + u32 size); + +void +acpi_os_free ( + void * memory); + +ACPI_STATUS +acpi_os_map_memory ( + void *physical_address, + u32 length, + void **logical_address); + +void +acpi_os_unmap_memory ( + void *logical_address, + u32 length); + + +/* + * Interrupt handlers + */ + +ACPI_STATUS +acpi_os_install_interrupt_handler ( + u32 interrupt_number, + OSD_HANDLER service_routine, + void *context); + +ACPI_STATUS +acpi_os_remove_interrupt_handler ( + u32 interrupt_number, + OSD_HANDLER service_routine); + + +/* + * Scheduling + */ + +ACPI_STATUS +acpi_os_queue_for_execution ( + u32 priority, + OSD_EXECUTION_CALLBACK function, + void *context); + +void +acpi_os_sleep ( + u32 seconds, + u32 milliseconds); + +void +acpi_os_sleep_usec ( + u32 microseconds); + +/* + * Platform/Hardware independent I/O interfaces + */ + +u8 +acpi_os_in8 ( + ACPI_IO_ADDRESS in_port); + + +u16 +acpi_os_in16 ( + ACPI_IO_ADDRESS in_port); + +u32 +acpi_os_in32 ( + ACPI_IO_ADDRESS in_port); + +void +acpi_os_out8 ( + ACPI_IO_ADDRESS out_port, + u8 value); + +void +acpi_os_out16 ( + ACPI_IO_ADDRESS out_port, + u16 value); + +void +acpi_os_out32 ( + ACPI_IO_ADDRESS out_port, + u32 value); + + +/* + * Standard access to PCI configuration space + */ + +ACPI_STATUS +acpi_os_read_pci_cfg_byte ( + u32 bus, + u32 device_function, + u32 register, + u8 *value); + +ACPI_STATUS +acpi_os_read_pci_cfg_word ( + u32 bus, + u32 device_function, + u32 register, + u16 *value); + +ACPI_STATUS +acpi_os_read_pci_cfg_dword ( + u32 bus, + u32 device_function, + u32 register, + u32 *value); + +ACPI_STATUS +acpi_os_write_pci_cfg_byte ( + u32 bus, + u32 device_function, + u32 register, + u8 value); + +ACPI_STATUS +acpi_os_write_pci_cfg_word ( + u32 bus, + u32 device_function, + u32 register, + u16 value); + + +ACPI_STATUS +acpi_os_write_pci_cfg_dword ( + u32 bus, + u32 device_function, + u32 register, + u32 value); + + +/* + * Miscellaneous + */ + +ACPI_STATUS +acpi_os_breakpoint ( + char *message); + +u8 +acpi_os_readable ( + void *pointer, + u32 length); + + +u8 +acpi_os_writable ( + void *pointer, + u32 length); + + +/* + * Debug print routines + */ + +s32 +acpi_os_printf ( + const char *format, + ...); + +s32 +acpi_os_vprintf ( + const char *format, + va_list args); + +/* + * Debug input + */ + +u32 +acpi_os_get_line ( + char *buffer); + + +/* + * Debug + */ + +void +acpi_os_dbg_assert( + void *failed_assertion, + void *file_name, + u32 line_number, + char *message); + + +#endif /* __ACPIOSD_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/acpixf.h linux/drivers/acpi/include/acpixf.h --- v2.4.0-test2/linux/drivers/acpi/include/acpixf.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/acpixf.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,299 @@ + +/****************************************************************************** + * + * Name: acxface.h - External interfaces to the ACPI subsystem + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __ACXFACE_H__ +#define __ACXFACE_H__ + +#include "actypes.h" +#include "actables.h" + +/* + * Global interfaces + */ + +ACPI_STATUS +acpi_initialize ( + ACPI_INIT_DATA *init_data); + +ACPI_STATUS +acpi_terminate ( + void); + +ACPI_STATUS +acpi_enable ( + void); + +ACPI_STATUS +acpi_disable ( + void); + +ACPI_STATUS +acpi_get_system_info( + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_format_exception ( + ACPI_STATUS exception, + ACPI_BUFFER *out_buffer); + + +/* + * ACPI table manipulation interfaces + */ + +ACPI_STATUS +acpi_load_firmware_tables ( + void); + +ACPI_STATUS +acpi_load_table ( + ACPI_TABLE_HEADER *table_ptr); + +ACPI_STATUS +acpi_unload_table ( + ACPI_TABLE_TYPE table_type); + +ACPI_STATUS +acpi_get_table_header ( + ACPI_TABLE_TYPE table_type, + u32 instance, + ACPI_TABLE_HEADER *out_table_header); + +ACPI_STATUS +acpi_get_table ( + ACPI_TABLE_TYPE table_type, + u32 instance, + ACPI_BUFFER *ret_buffer); + + +/* + * Namespace and name interfaces + */ + +ACPI_STATUS +acpi_load_namespace ( + void); + +ACPI_STATUS +acpi_walk_namespace ( + ACPI_OBJECT_TYPE type, + ACPI_HANDLE start_object, + u32 max_depth, + WALK_CALLBACK user_function, + void *context, + void * *return_value); + +ACPI_STATUS +acpi_get_name ( + ACPI_HANDLE handle, + u32 name_type, + ACPI_BUFFER *ret_path_ptr); + +ACPI_STATUS +acpi_get_handle ( + ACPI_HANDLE parent, + ACPI_STRING pathname, + ACPI_HANDLE *ret_handle); + + +/* + * Object manipulation and enumeration + */ + +ACPI_STATUS +acpi_evaluate_object ( + ACPI_HANDLE object, + ACPI_STRING pathname, + ACPI_OBJECT_LIST *parameter_objects, + ACPI_BUFFER *return_object_buffer); + +ACPI_STATUS +acpi_get_object_info ( + ACPI_HANDLE device, + ACPI_DEVICE_INFO *info); + +ACPI_STATUS +acpi_get_next_object ( + ACPI_OBJECT_TYPE type, + ACPI_HANDLE parent, + ACPI_HANDLE child, + ACPI_HANDLE *out_handle); + +ACPI_STATUS +acpi_get_type ( + ACPI_HANDLE object, + ACPI_OBJECT_TYPE *out_type); + +ACPI_STATUS +acpi_get_parent ( + ACPI_HANDLE object, + ACPI_HANDLE *out_handle); + + +/* + * Acpi_event handler interfaces + */ + +ACPI_STATUS +acpi_install_fixed_event_handler ( + u32 acpi_event, + FIXED_EVENT_HANDLER handler, + void *context); + +ACPI_STATUS +acpi_remove_fixed_event_handler ( + u32 acpi_event, + FIXED_EVENT_HANDLER handler); + +ACPI_STATUS +acpi_install_notify_handler ( + ACPI_HANDLE device, + u32 handler_type, + NOTIFY_HANDLER handler, + void *context); + +ACPI_STATUS +acpi_remove_notify_handler ( + ACPI_HANDLE device, + u32 handler_type, + NOTIFY_HANDLER handler); + +ACPI_STATUS +acpi_install_address_space_handler ( + ACPI_HANDLE device, + ACPI_ADDRESS_SPACE_TYPE space_id, + ADDRESS_SPACE_HANDLER handler, + ADDRESS_SPACE_SETUP setup, + void *context); + +ACPI_STATUS +acpi_remove_address_space_handler ( + ACPI_HANDLE device, + ACPI_ADDRESS_SPACE_TYPE space_id, + ADDRESS_SPACE_HANDLER handler); + +ACPI_STATUS +acpi_install_gpe_handler ( + u32 gpe_number, + u32 type, + GPE_HANDLER handler, + void *context); + +ACPI_STATUS +acpi_remove_gpe_handler ( + u32 gpe_number, + GPE_HANDLER handler); + +ACPI_STATUS +acpi_enable_event ( + u32 acpi_event, + u32 type); + +ACPI_STATUS +acpi_disable_event ( + u32 acpi_event, + u32 type); + +ACPI_STATUS +acpi_clear_event ( + u32 acpi_event, + u32 type); + +ACPI_STATUS +acpi_get_event_status ( + u32 acpi_event, + u32 type, + ACPI_EVENT_STATUS *event_status); + +/* + * Resource interfaces + */ + +ACPI_STATUS +acpi_get_current_resources( + ACPI_HANDLE device_handle, + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_get_possible_resources( + ACPI_HANDLE device_handle, + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_set_current_resources ( + ACPI_HANDLE device_handle, + ACPI_BUFFER *in_buffer); + +ACPI_STATUS +acpi_get_irq_routing_table ( + ACPI_HANDLE bus_device_handle, + ACPI_BUFFER *ret_buffer); + + +/* + * Hardware (ACPI device) interfaces + */ + +ACPI_STATUS +acpi_set_firmware_waking_vector ( + void *physical_address); + +ACPI_STATUS +acpi_get_firmware_waking_vector ( + void **physical_address); + +ACPI_STATUS +acpi_get_processor_throttling_info ( + ACPI_HANDLE processor_handle, + ACPI_BUFFER *user_buffer); + +ACPI_STATUS +acpi_set_processor_throttling_state ( + ACPI_HANDLE processor_handle, + u32 throttle_state); + +ACPI_STATUS +acpi_get_processor_throttling_state ( + ACPI_HANDLE processor_handle, + u32 *throttle_state); + +ACPI_STATUS +acpi_get_processor_cx_info ( + ACPI_HANDLE processor_handle, + ACPI_BUFFER *user_buffer); + +ACPI_STATUS +acpi_set_processor_sleep_state ( + ACPI_HANDLE processor_handle, + u32 cx_state); + +ACPI_STATUS +acpi_processor_sleep ( + ACPI_HANDLE processor_handle, + u32 *pm_timer_ticks); + + +#endif /* __ACXFACE_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/actables.h linux/drivers/acpi/include/actables.h --- v2.4.0-test2/linux/drivers/acpi/include/actables.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/actables.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,188 @@ + +/****************************************************************************** + * + * Name: actables.h - Table data structures defined in ACPI specification + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACTABLES_H__ +#define __ACTABLES_H__ + + +/* + * Values for description table header signatures + */ + +#define RSDP_SIG "RSD PTR " /* RSDT Pointer signature */ +#define APIC_SIG "APIC" /* Multiple APIC Description Table */ +#define DSDT_SIG "DSDT" /* Differentiated System Description Table */ +#define FACP_SIG "FACP" /* Fixed ACPI Description Table */ +#define FACS_SIG "FACS" /* Firmware ACPI Control Structure */ +#define PSDT_SIG "PSDT" /* Persistent System Description Table */ +#define RSDT_SIG "RSDT" /* Root System Description Table */ +#define SSDT_SIG "SSDT" /* Secondary System Description Table */ +#define SBST_SIG "SBST" /* Smart Battery Specification Table */ +#define BOOT_SIG "BOOT" /* Boot table */ + + +#define GL_OWNED 0x02 /* Ownership of global lock is bit 1 */ + +/* values of Mapic.Model */ + +#define DUAL_PIC 0 +#define MULTIPLE_APIC 1 + +/* values of Type in APIC_HEADER */ + +#define APIC_PROC 0 +#define APIC_IO 1 + + +/* + * Architecture-independent tables + * The architecture dependent tables are in separate files + */ + +typedef struct /* Root System Descriptor Pointer */ +{ + char signature [8]; /* contains "RSD PTR " */ + u8 checksum; /* to make sum of struct == 0 */ + char oem_id [6]; /* OEM identification */ + u8 reserved; /* reserved - must be zero */ + u32 rsdt_physical_address; /* physical address of RSDT */ + +} ROOT_SYSTEM_DESCRIPTOR_POINTER; + + +typedef struct /* ACPI common table header */ +{ + char signature [4]; /* identifies type of table */ + u32 length; /* length of table, in bytes, + * including header */ + u8 revision; /* specification minor version # */ + u8 checksum; /* to make sum of entire table == 0 */ + char oem_id [6]; /* OEM identification */ + char oem_table_id [8]; /* OEM table identification */ + u32 oem_revision; /* OEM revision number */ + char asl_compiler_id [4]; /* ASL compiler vendor ID */ + u32 asl_compiler_revision; /* ASL compiler revision number */ + +} ACPI_TABLE_HEADER; + + +typedef struct /* APIC Table */ +{ + ACPI_TABLE_HEADER header; /* table header */ + u32 local_apic_address; /* Physical address for accessing local APICs */ + u32 PCATcompat : 1; /* a one indicates system also has dual 8259s */ + u32 reserved1 : 31; + +} APIC_TABLE; + + +typedef struct /* APIC Header */ +{ + u8 type; /* APIC type. Either APIC_PROC or APIC_IO */ + u8 length; /* Length of APIC structure */ + +} APIC_HEADER; + + +typedef struct /* Processor APIC */ +{ + APIC_HEADER header; + u8 processor_apic_id; /* ACPI processor id */ + u8 local_apic_id; /* processor's local APIC id */ + u32 processor_enabled: 1; /* Processor is usable if set */ + u32 reserved1 : 32; + +} PROCESSOR_APIC; + + +typedef struct /* IO APIC */ +{ + APIC_HEADER header; + u8 io_apic_id; /* I/O APIC ID */ + u8 reserved; /* reserved - must be zero */ + u32 io_apic_address; /* APIC's physical address */ + u32 vector; /* interrupt vector index where INTI + * lines start */ +} IO_APIC; + + +/* +** IA64 TODO: Add SAPIC Tables +*/ + +/* +** IA64 TODO: Modify Smart Battery Description to comply with ACPI IA64 +** extensions. +*/ +typedef struct /* Smart Battery Description Table */ +{ + ACPI_TABLE_HEADER header; + u32 warning_level; + u32 low_level; + u32 critical_level; + +} SMART_BATTERY_DESCRIPTION_TABLE; + + +/* + * ACPI Table information. We save the table address, length, + * and type of memory allocation (mapped or allocated) for each + * table for 1) when we exit, and 2) if a new table is installed + */ + +#define ACPI_MEM_NOT_ALLOCATED 0 +#define ACPI_MEM_ALLOCATED 1 +#define ACPI_MEM_MAPPED 2 + +#define ACPI_TABLE_SINGLE 0 +#define ACPI_TABLE_MULTIPLE 1 + + +/* Data about each known table type */ + +typedef struct _acpi_table_support +{ + char *name; + char *signature; + u8 sig_length; + u8 flags; + u16 status; + void **global_ptr; + +} ACPI_TABLE_SUPPORT; + + +/* + * Get the architecture-specific tables + */ + +#ifdef IA64 +#include "actbl64.h" +#else +#include "actbl32.h" +#endif + + +#endif /* __ACTABLES_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/actbl32.h linux/drivers/acpi/include/actbl32.h --- v2.4.0-test2/linux/drivers/acpi/include/actbl32.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/actbl32.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,114 @@ +/****************************************************************************** + * + * Name: actbl32.h - ACPI tables specific to IA32 + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACTBL32_H__ +#define __ACTBL32_H__ + + +/* IA32 Root System Description Table */ + +typedef struct +{ + ACPI_TABLE_HEADER header; /* Table header */ + void *table_offset_entry [1]; /* Array of pointers to other */ + /* tables' headers */ +} ROOT_SYSTEM_DESCRIPTION_TABLE; + + +/* IA32 Firmware ACPI Control Structure */ + +typedef struct +{ + char signature[4]; /* signature "FACS" */ + u32 length; /* length of structure, in bytes */ + u32 hardware_signature; /* hardware configuration signature */ + u32 firmware_waking_vector; /* ACPI OS waking vector */ + u32 global_lock; /* Global Lock */ + u32 S4_bios_f : 1; /* Indicates if S4_bIOS support is present */ + u32 reserved1 : 31; /* must be 0 */ + u8 resverved3 [40]; /* reserved - must be zero */ + +} FIRMWARE_ACPI_CONTROL_STRUCTURE; + + +/* IA32 Fixed ACPI Description Table */ + +typedef struct +{ + ACPI_TABLE_HEADER header; /* table header */ + ACPI_TBLPTR firmware_ctrl; /* Physical address of FACS */ + ACPI_TBLPTR dsdt; /* Physical address of DSDT */ + u8 model; /* System Interrupt Model */ + u8 reserved1; /* reserved */ + u16 sci_int; /* System vector of SCI interrupt */ + ACPI_IO_ADDRESS smi_cmd; /* Port address of SMI command port */ + u8 acpi_enable; /* value to write to smi_cmd to enable ACPI */ + u8 acpi_disable; /* value to write to smi_cmd to disable ACPI */ + u8 S4_bios_req; /* Value to write to SMI CMD to enter S4_bIOS state */ + u8 reserved2; /* reserved - must be zero */ + ACPI_IO_ADDRESS pm1a_evt_blk; /* Port address of Power Mgt 1a Acpi_event Reg Blk */ + ACPI_IO_ADDRESS pm1b_evt_blk; /* Port address of Power Mgt 1b Acpi_event Reg Blk */ + ACPI_IO_ADDRESS pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ + ACPI_IO_ADDRESS pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ + ACPI_IO_ADDRESS pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ + ACPI_IO_ADDRESS pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ + ACPI_IO_ADDRESS gpe0blk; /* Port addr of General Purpose Acpi_event 0 Reg Blk */ + ACPI_IO_ADDRESS gpe1_blk; /* Port addr of General Purpose Acpi_event 1 Reg Blk */ + u8 pm1_evt_len; /* Byte Length of ports at pm1_x_evt_blk */ + u8 pm1_cnt_len; /* Byte Length of ports at pm1_x_cnt_blk */ + u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ + u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ + u8 gpe0blk_len; /* Byte Length of ports at gpe0_blk */ + u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ + u8 gpe1_base; /* offset in gpe model where gpe1 events start */ + u8 reserved3; /* reserved */ + u16 plvl2_lat; /* worst case HW latency to enter/exit C2 state */ + u16 plvl3_lat; /* worst case HW latency to enter/exit C3 state */ + u16 flush_size; /* Size of area read to flush caches */ + u16 flush_stride; /* Stride used in flushing caches */ + u8 duty_offset; /* bit location of duty cycle field in p_cnt reg */ + u8 duty_width; /* bit width of duty cycle field in p_cnt reg */ + u8 day_alrm; /* index to day-of-month alarm in RTC CMOS RAM */ + u8 mon_alrm; /* index to month-of-year alarm in RTC CMOS RAM */ + u8 century; /* index to century in RTC CMOS RAM */ + u8 reserved4; /* reserved */ + u8 reserved4a; /* reserved */ + u8 reserved4b; /* reserved */ + u32 wb_invd : 1; /* wbinvd instruction works properly */ + u32 wb_invd_flush : 1; /* wbinvd flushes but does not invalidate */ + u32 proc_c1 : 1; /* all processors support C1 state */ + u32 plvl2_up : 1; /* C2 state works on MP system */ + u32 pwr_button : 1; /* Power button is handled as a generic feature */ + u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ + u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ + u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */ + u32 tmr_val_ext : 1; /* tmr_val is 32 bits */ + u32 reserved5 : 23; /* reserved - must be zero */ + +} FIXED_ACPI_DESCRIPTION_TABLE; + + +#endif /* __ACTBL32_H__ */ + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/actbl64.h linux/drivers/acpi/include/actbl64.h --- v2.4.0-test2/linux/drivers/acpi/include/actbl64.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/actbl64.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,115 @@ + +/****************************************************************************** + * + * Name: actbl64.h - ACPI tables specific to IA64 + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACTBL64_H__ +#define __ACTBL64_H__ + + +typedef UINT64 IO_ADDRESS; /* Only for clarity in declarations */ + + +/* IA64 Root System Description Table */ + +typedef struct +{ + ACPI_TABLE_HEADER header; /* Table header */ + u32 reserved_pad; /* IA64 alignment, must be 0 */ + void *table_offset_entry [1]; /* Array of pointers to other */ + /* tables' headers */ +} ROOT_SYSTEM_DESCRIPTION_TABLE; + + +/* IA64 Firmware ACPI Control Structure */ + +typedef struct +{ + char signature[4]; /* signature "FACS" */ + u32 length; /* length of structure, in bytes */ + u32 hardware_signature; /* hardware configuration signature */ + u32 reserved4; /* must be 0 */ + UINT64 firmware_waking_vector; /* ACPI OS waking vector */ + UINT64 global_lock; /* Global Lock */ + u32 S4_bios_f : 1; /* Indicates if S4_bIOS support is present */ + u32 reserved1 : 31; /* must be 0 */ + u8 resverved3 [28]; /* reserved - must be zero */ + +} FIRMWARE_ACPI_CONTROL_STRUCTURE; + + +/* IA64 Fixed ACPI Description Table */ + +typedef struct +{ + ACPI_TABLE_HEADER header; /* table header */ + u32 reserved_pad; /* IA64 alignment, must be 0 */ + ACPI_TBLPTR firmware_ctrl; /* Physical address of FACS */ + ACPI_TBLPTR acpi_dsdt; /* Physical address of DSDT */ + u8 model; /* System Interrupt Model */ + u8 address_space; /* Address Space Bitmask */ + u16 sci_int; /* System vector of SCI interrupt */ + u8 acpi_enable; /* value to write to smi_cmd to enable ACPI */ + u8 acpi_disable; /* value to write to smi_cmd to disable ACPI */ + u8 S4_bios_req; /* Value to write to SMI CMD to enter S4_bIOS state */ + u8 reserved2; /* reserved - must be zero */ + UINT64 smi_cmd; /* Port address of SMI command port */ + UINT64 pm1a_evt_blk; /* Port address of Power Mgt 1a Acpi_event Reg Blk */ + UINT64 pm1b_evt_blk; /* Port address of Power Mgt 1b Acpi_event Reg Blk */ + UINT64 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ + UINT64 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ + UINT64 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ + UINT64 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ + UINT64 gpe0blk; /* Port addr of General Purpose Acpi_event 0 Reg Blk */ + UINT64 gpe1_blk; /* Port addr of General Purpose Acpi_event 1 Reg Blk */ + u8 pm1_evt_len; /* Byte Length of ports at pm1_x_evt_blk */ + u8 pm1_cnt_len; /* Byte Length of ports at pm1_x_cnt_blk */ + u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ + u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ + u8 gpe0blk_len; /* Byte Length of ports at gpe0_blk */ + u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ + u8 gpe1_base; /* offset in gpe model where gpe1 events start */ + u8 reserved3; /* reserved */ + u16 Plvl2_lat; /* worst case HW latency to enter/exit C2 state */ + u16 Plvl3_lat; /* worst case HW latency to enter/exit C3 state */ + u8 day_alrm; /* index to day-of-month alarm in RTC CMOS RAM */ + u8 mon_alrm; /* index to month-of-year alarm in RTC CMOS RAM */ + u8 century; /* index to century in RTC CMOS RAM */ + u8 reserved4; /* reserved */ + u32 flush_cash : 1; /* PAL_FLUSH_CACHE is correctly supported */ + u32 reserved5 : 1; /* reserved - must be zero */ + u32 proc_c1 : 1; /* all processors support C1 state */ + u32 Plvl2_up : 1; /* C2 state works on MP system */ + u32 pwr_button : 1; /* Power button is handled as a generic feature */ + u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ + u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ + u32 RTCS4 : 1; /* RTC wakeup stat not possible from S4 */ + u32 tmr_val_ext : 1; /* tmr_val is 32 bits */ + u32 dock_cap : 1; /* Supports Docking */ + u32 reserved6 : 22; /* reserved - must be zero */ + +} FIXED_ACPI_DESCRIPTION_TABLE; + + +#endif /* __ACTBL64_H__ */ + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/actypes.h linux/drivers/acpi/include/actypes.h --- v2.4.0-test2/linux/drivers/acpi/include/actypes.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/actypes.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,970 @@ + +/****************************************************************************** + * + * Name: actypes.h - Common data types for the entire ACPI subsystem + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ACTYPES_H +#define _ACTYPES_H + +/*! [Begin] no source code translation (keep the typedefs) */ + +/* + * Data types - Fixed across all compilation models + * + * BOOLEAN Logical Boolean. 1 byte value containing a 0 for FALSE or a 1 for TRUE. Other values are undefined. + * INT8 8-bit (1 byte) signed value + * UINT8 8-bit (1 byte) unsigned value + * INT16 16-bit (2 byte) signed value + * UINT16 16-bit (2 byte) unsigned value + * INT32 32-bit (4 byte) signed value + * UINT32 32-bit (4 byte) unsigned value + * INT64 64-bit (8 byte) signed value + * UINT64 64-bit (8 byte) unsigned value + * NATIVE_INT 32-bit on IA-32, 64-bit on IA-64 signed value + * NATIVE_UINT 32-bit on IA-32, 64-bit on IA-64 unsigned value + * UCHAR Character. 1 byte unsigned value. + */ + +#ifdef _IA64 +/* + * 64-bit type definitions + */ +typedef signed char INT8; +typedef unsigned char UINT8; +typedef unsigned char UCHAR; +typedef short INT16; +typedef unsigned short UINT16; +typedef int INT32; +typedef unsigned int UINT32; +typedef long INT64; +typedef unsigned long UINT64; + +typedef UINT64 NATIVE_UINT; +typedef INT64 NATIVE_INT; + +typedef NATIVE_UINT ACPI_TBLPTR; +typedef UINT64 ACPI_IO_ADDRESS; + +#define ALIGNED_ADDRESS_BOUNDARY 0x00000008 + +/* (No hardware alignment support in IA64) */ + + +#elif _IA16 +/* + * 16-bit type definitions + */ +typedef signed char INT8; +typedef unsigned char UINT8; +typedef unsigned char UCHAR; +typedef int INT16; +typedef unsigned int UINT16; +typedef long INT32; +typedef unsigned long UINT32; + +typedef UINT16 NATIVE_UINT; +typedef INT16 NATIVE_INT; + +typedef UINT32 ACPI_TBLPTR; +typedef UINT32 ACPI_IO_ADDRESS; + +#define ALIGNED_ADDRESS_BOUNDARY 0x00000002 +#define _HW_ALIGNMENT_SUPPORT + + +#else +/* + * 32-bit type definitions (default) + */ +typedef signed char INT8; +typedef unsigned char UINT8; +typedef unsigned char UCHAR; +typedef short INT16; +typedef unsigned short UINT16; +typedef int INT32; +typedef unsigned int UINT32; + +typedef UINT32 NATIVE_UINT; +typedef INT32 NATIVE_INT; + +typedef NATIVE_UINT ACPI_TBLPTR; +typedef UINT32 ACPI_IO_ADDRESS; + +#define ALIGNED_ADDRESS_BOUNDARY 0x00000004 +#define _HW_ALIGNMENT_SUPPORT + + +#endif + + + +/* + * Miscellaneous common types + */ + +typedef UINT8 BOOLEAN; +typedef UINT32 UINT32_BIT; +typedef NATIVE_INT ACPI_PTRDIFF; +typedef NATIVE_UINT ACPI_SIZE; + + +/* + * Data type ranges + */ + +#define ACPI_UCHAR_MAX (UCHAR) 0xFF +#define ACPI_INT32_MAX (INT32) 0x7FFFFFFF +#define ACPI_UINT32_MAX (UINT32) 0xFFFFFFFF + + +#ifdef DEFINE_ALTERNATE_TYPES +/* + * Types used only in translated source + */ +typedef INT8 s8; +typedef INT16 s16; +typedef INT32 s32; +typedef UINT8 u8; +typedef UINT16 u16; +typedef UINT32 u32; +#endif + +/*! [End] no source code translation !*/ + + +/* + * Useful defines + */ + +#ifdef FALSE +#undef FALSE +#endif +#define FALSE (1 == 0) + +#ifdef TRUE +#undef TRUE +#endif +#define TRUE (1 == 1) + +#ifndef NULL +#define NULL (void *) 0 +#endif + + +/* + * Local datatypes + */ + +typedef u32 ACPI_STATUS; /* All ACPI Exceptions */ +typedef u32 ACPI_NAME; /* 4-char ACPI name */ +typedef char* ACPI_STRING; /* Null terminated ASCII string */ +typedef void* ACPI_HANDLE; /* Actually a ptr to an NTE */ + + +/* + * Constants with special meanings + */ + +#define ACPI_ROOT_OBJECT (ACPI_HANDLE)(-1) + + +/* + * Sleep state constants + */ +#define ACPI_STATE_S0 (u8) 0 +#define ACPI_STATE_S1 (u8) 1 +#define ACPI_STATE_S2 (u8) 2 +#define ACPI_STATE_S3 (u8) 3 +#define ACPI_STATE_S4 (u8) 4 +#define ACPI_STATE_S4_bIOS (u8) 5 +#define ACPI_STATE_S5 (u8) 6 +#define ACPI_S_STATES_MAX ACPI_STATE_S5 + + +/* + * Table types. These values are passed to the table related APIs + */ + +typedef u32 ACPI_TABLE_TYPE; + +#define ACPI_TABLE_RSDP (ACPI_TABLE_TYPE) 0 +#define ACPI_TABLE_APIC (ACPI_TABLE_TYPE) 1 +#define ACPI_TABLE_DSDT (ACPI_TABLE_TYPE) 2 +#define ACPI_TABLE_FACP (ACPI_TABLE_TYPE) 3 +#define ACPI_TABLE_FACS (ACPI_TABLE_TYPE) 4 +#define ACPI_TABLE_PSDT (ACPI_TABLE_TYPE) 5 +#define ACPI_TABLE_RSDT (ACPI_TABLE_TYPE) 6 +#define ACPI_TABLE_SSDT (ACPI_TABLE_TYPE) 7 +#define ACPI_TABLE_SBST (ACPI_TABLE_TYPE) 8 +#define ACPI_TABLE_BOOT (ACPI_TABLE_TYPE) 9 +#define ACPI_TABLE_MAX 9 +#define NUM_ACPI_TABLES 10 + + +/* + * Types associated with names. The first group of + * values correspond to the definition of the ACPI Object_type operator (See the ACPI Spec). + * Therefore, only add to the first group if the spec changes! + * + * Types must be kept in sync with the Acpi_ns_properties and Acpi_ns_type_names arrays + */ + +typedef u32 ACPI_OBJECT_TYPE; +typedef u8 OBJECT_TYPE_INTERNAL; + +#define ACPI_TYPE_ANY 0 /* 0x00 */ +#define ACPI_TYPE_NUMBER 1 /* 0x01 Byte/Word/Dword/Zero/One/Ones */ +#define ACPI_TYPE_STRING 2 /* 0x02 */ +#define ACPI_TYPE_BUFFER 3 /* 0x03 */ +#define ACPI_TYPE_PACKAGE 4 /* 0x04 Byte_const, multiple Data_term/Constant/Super_name */ +#define ACPI_TYPE_FIELD_UNIT 5 /* 0x05 */ +#define ACPI_TYPE_DEVICE 6 /* 0x06 Name, multiple Named_object */ +#define ACPI_TYPE_EVENT 7 /* 0x07 */ +#define ACPI_TYPE_METHOD 8 /* 0x08 Name, Byte_const, multiple Code */ +#define ACPI_TYPE_MUTEX 9 /* 0x09 */ +#define ACPI_TYPE_REGION 10 /* 0x0A */ +#define ACPI_TYPE_POWER 11 /* 0x0B Name,Byte_const,Word_const,multi Named_object */ +#define ACPI_TYPE_PROCESSOR 12 /* 0x0C Name,Byte_const,DWord_const,Byte_const,multi Nm_o */ +#define ACPI_TYPE_THERMAL 13 /* 0x0D Name, multiple Named_object */ +#define ACPI_TYPE_BUFFER_FIELD 14 /* 0x0E */ +#define ACPI_TYPE_DDB_HANDLE 15 /* 0x0F */ +#define ACPI_TYPE_DEBUG_OBJECT 16 /* 0x10 */ + +#define ACPI_TYPE_MAX 16 + +/* + * This section contains object types that do not relate to the ACPI Object_type operator. + * They are used for various internal purposes only. A numerical gap is provided in + * case additional "official" Object_types are added in the future. Also, values exceeding + * the largest official ACPI Object_type must not overlap with defined AML opcodes. + */ +#define INTERNAL_TYPE_BEGIN 25 +#define INTERNAL_TYPE_DEF_FIELD 25 /* 0x19 */ +#define INTERNAL_TYPE_BANK_FIELD 26 /* 0x1A */ +#define INTERNAL_TYPE_INDEX_FIELD 27 /* 0x1B */ +#define INTERNAL_TYPE_DEF_FIELD_DEFN 28 /* 0x1C Name, Byte_const, multiple Field_element */ +#define INTERNAL_TYPE_BANK_FIELD_DEFN 29 /* 0x1D 2 Name,DWord_const,Byte_const,multi Field_element */ +#define INTERNAL_TYPE_INDEX_FIELD_DEFN 30 /* 0x1E 2 Name, Byte_const, multiple Field_element */ +#define INTERNAL_TYPE_IF 31 /* 0x1F Op_code, multiple Code */ +#define INTERNAL_TYPE_ELSE 32 /* 0x20 multiple Code */ +#define INTERNAL_TYPE_WHILE 33 /* 0x21 Op_code, multiple Code */ +#define INTERNAL_TYPE_SCOPE 34 /* 0x22 Name, multiple Named_object */ +#define INTERNAL_TYPE_DEF_ANY 35 /* 0x23 type is Any, suppress search of enclosing scopes */ +#define INTERNAL_TYPE_REFERENCE 36 /* 0x24 Arg#, Local#, Name, Debug; used only in descriptors */ +#define INTERNAL_TYPE_ALIAS 37 /* 0x25 */ +#define INTERNAL_TYPE_NOTIFY 38 /* 0x26 */ +#define INTERNAL_TYPE_ADDRESS_HANDLER 39 /* 0x27 */ +#define INTERNAL_TYPE_METHOD_ARGUMENT 40 /* 0x28 */ +#define INTERNAL_TYPE_METHOD_LOCAL_VAR 41 /* 0x29 */ + +#define INTERNAL_TYPE_MAX 41 + +#define INTERNAL_TYPE_INVALID 42 +#define ACPI_TYPE_NOT_FOUND 0xFF + +/* + * Acpi_event Types: + * ------------ + * Fixed & general purpose... + */ + +typedef u32 ACPI_EVENT_TYPE; + +#define ACPI_EVENT_FIXED (ACPI_EVENT_TYPE) 0 +#define ACPI_EVENT_GPE (ACPI_EVENT_TYPE) 1 + +/* + * Fixed events + */ + +#define ACPI_EVENT_PMTIMER (ACPI_EVENT_TYPE) 0 + /* + * There's no bus master event so index 1 is used for IRQ's that are not + * handled by the SCI handler + */ +#define ACPI_EVENT_NOT_USED (ACPI_EVENT_TYPE) 1 +#define ACPI_EVENT_GLOBAL (ACPI_EVENT_TYPE) 2 +#define ACPI_EVENT_POWER_BUTTON (ACPI_EVENT_TYPE) 3 +#define ACPI_EVENT_SLEEP_BUTTON (ACPI_EVENT_TYPE) 4 +#define ACPI_EVENT_RTC (ACPI_EVENT_TYPE) 5 +#define ACPI_EVENT_GENERAL (ACPI_EVENT_TYPE) 6 +#define ACPI_EVENT_MAX 6 +#define NUM_FIXED_EVENTS (ACPI_EVENT_TYPE) 7 + +#define ACPI_GPE_INVALID 0xFF +#define ACPI_GPE_MAX 0xFF +#define NUM_GPE 256 + +#define ACPI_EVENT_LEVEL_TRIGGERED (ACPI_EVENT_TYPE) 1 +#define ACPI_EVENT_EDGE_TRIGGERED (ACPI_EVENT_TYPE) 2 + +/* + * Acpi_event Status: + * ------------- + * The encoding of ACPI_EVENT_STATUS is illustrated below. + * Note that a set bit (1) indicates the property is TRUE + * (e.g. if bit 0 is set then the event is enabled). + * +---------------+-+-+ + * | Bits 31:2 |1|0| + * +---------------+-+-+ + * | | | + * | | +- Enabled? + * | +--- Set? + * +----------- + */ +typedef u32 ACPI_EVENT_STATUS; + +#define ACPI_EVENT_FLAG_ENABLED (ACPI_EVENT_STATUS) 0x01 +#define ACPI_EVENT_FLAG_SET (ACPI_EVENT_STATUS) 0x02 + + +/* Notify types */ + +#define ACPI_SYSTEM_NOTIFY 0 +#define ACPI_DEVICE_NOTIFY 1 +#define ACPI_MAX_NOTIFY_HANDLER_TYPE 1 + +#define MAX_SYS_NOTIFY 0x7f + + +/* Address Space (Operation Region) Types */ + +typedef u32 ACPI_ADDRESS_SPACE_TYPE; + +#define ADDRESS_SPACE_SYSTEM_MEMORY (ACPI_ADDRESS_SPACE_TYPE) 0 +#define ADDRESS_SPACE_SYSTEM_IO (ACPI_ADDRESS_SPACE_TYPE) 1 +#define ADDRESS_SPACE_PCI_CONFIG (ACPI_ADDRESS_SPACE_TYPE) 2 +#define ADDRESS_SPACE_EC (ACPI_ADDRESS_SPACE_TYPE) 3 +#define ADDRESS_SPACE_SMBUS (ACPI_ADDRESS_SPACE_TYPE) 4 + + +/* + * External ACPI object definition + */ + +typedef union acpi_obj +{ + ACPI_OBJECT_TYPE type; /* See definition of Acpi_ns_type for values */ + struct + { + ACPI_OBJECT_TYPE type; + u32 value; /* The actual number */ + } number; + + struct + { + ACPI_OBJECT_TYPE type; + u32 length; /* # of bytes in string, excluding trailing null */ + char *pointer; /* points to the string value */ + } string; + + struct + { + ACPI_OBJECT_TYPE type; + u32 length; /* # of bytes in buffer */ + u8 *pointer; /* points to the buffer */ + } buffer; + + struct + { + ACPI_OBJECT_TYPE type; + u32 fill1; + ACPI_HANDLE handle; /* object reference */ + } reference; + + struct + { + ACPI_OBJECT_TYPE type; + u32 count; /* # of elements in package */ + union acpi_obj *elements; /* Pointer to an array of ACPI_OBJECTs */ + } package; + + struct + { + ACPI_OBJECT_TYPE type; + u32 proc_id; + u32 pblk_address; + u32 pblk_length; + } processor; + + struct + { + ACPI_OBJECT_TYPE type; + u32 system_level; + u32 resource_order; + } power_resource; + +} ACPI_OBJECT, *PACPI_OBJECT; + + +/* + * List of objects, used as a parameter list for control method evaluation + */ + +typedef struct acpi_obj_list +{ + u32 count; + ACPI_OBJECT *pointer; + +} ACPI_OBJECT_LIST, *PACPI_OBJECT_LIST; + + +/* + * Miscellaneous common Data Structures used by the interfaces + */ + +typedef struct +{ + u32 length; /* Length in bytes of the buffer */ + void *pointer; /* pointer to buffer */ + +} ACPI_BUFFER; + + +/* + * Name_type for Acpi_get_name + */ + +#define ACPI_FULL_PATHNAME 0 +#define ACPI_SINGLE_NAME 1 +#define ACPI_NAME_TYPE_MAX 1 + + +/* + * Structure and flags for Acpi_get_system_info + */ + +#define SYS_MODE_UNKNOWN 0x0000 +#define SYS_MODE_ACPI 0x0001 +#define SYS_MODE_LEGACY 0x0002 +#define SYS_MODES_MASK 0x0003 + +/* + * ACPI CPU Cx state handler + */ +typedef +ACPI_STATUS (*ACPI_SET_C_STATE_HANDLER) ( + NATIVE_UINT pblk_address); + +/* + * ACPI Cx State info + */ +typedef struct +{ + u32 state_number; + u32 latency; +} ACPI_CX_STATE; + +/* + * ACPI CPU throttling info + */ +typedef struct +{ + u32 state_number; + u32 percent_of_clock; +} ACPI_CPU_THROTTLING_STATE; + +/* + * ACPI Table Info. One per ACPI table _type_ + */ +typedef struct acpi_table_info +{ + u32 count; + +} ACPI_TABLE_INFO; + + +/* + * System info returned by Acpi_get_system_info() + */ + +typedef struct _acpi_sys_info +{ + u32 acpi_ca_version; + u32 flags; + u32 timer_resolution; + u32 reserved1; + u32 reserved2; + u32 debug_level; + u32 debug_layer; + u32 num_table_types; + ACPI_TABLE_INFO table_info [NUM_ACPI_TABLES]; + +} ACPI_SYSTEM_INFO; + + +/* + * System Initiailization data. This data is passed to ACPIInitialize + * copyied to global data and retained by ACPI CA + */ + +typedef struct _acpi_init_data +{ + void *RSDP_physical_address; /* Address of RSDP, needed it it is */ + /* not found in the IA32 manner */ +} ACPI_INIT_DATA; + +/* + * Various handlers and callback procedures + */ + +typedef +u32 (*FIXED_EVENT_HANDLER) ( + void *context); + +typedef +void (*GPE_HANDLER) ( + void *context); + +typedef +void (*NOTIFY_HANDLER) ( + ACPI_HANDLE device, + u32 value, + void *context); + +#define ADDRESS_SPACE_READ 1 +#define ADDRESS_SPACE_WRITE 2 + +typedef +ACPI_STATUS (*ADDRESS_SPACE_HANDLER) ( + u32 function, + u32 address, + u32 bit_width, + u32 *value, + void *context); + +#define ACPI_DEFAULT_HANDLER ((ADDRESS_SPACE_HANDLER) NULL) + + +typedef +ACPI_STATUS (*ADDRESS_SPACE_SETUP) ( + ACPI_HANDLE region_handle, + u32 function, + void *handler_context, + void **return_context); + +#define ACPI_REGION_ACTIVATE 0 +#define ACPI_REGION_DEACTIVATE 1 + +typedef +ACPI_STATUS (*WALK_CALLBACK) ( + ACPI_HANDLE obj_handle, + u32 nesting_level, + void *context, + void **return_value); + + +/* Interrupt handler return values */ + +#define INTERRUPT_NOT_HANDLED 0x00 +#define INTERRUPT_HANDLED 0x01 + + +/* Structure and flags for Acpi_get_device_info */ + +#define ACPI_VALID_HID 0x1 +#define ACPI_VALID_UID 0x2 +#define ACPI_VALID_ADR 0x4 +#define ACPI_VALID_STA 0x8 + + +#define ACPI_COMMON_OBJ_INFO \ + ACPI_OBJECT_TYPE type; /* ACPI object type */\ + ACPI_NAME name; /* ACPI object Name */\ + /*\ + * TBD: [Restructure] Do we want or need these next two??\ + */\ + ACPI_HANDLE parent; /* Parent object */\ + ACPI_HANDLE children; /* Linked list of children */\ + u32 valid /* ????? */ + +typedef struct +{ + ACPI_COMMON_OBJ_INFO; +} ACPI_OBJ_INFO_HEADER; + + +typedef struct +{ + ACPI_COMMON_OBJ_INFO; + + /* + * TBD: [Restructure]: a HID or a _UID can return either a number or a string + */ + char hardware_id [9]; /* _HID value if any */ + char unique_id[9]; /* _UID value if any */ + u32 address; /* _ADR value if any */ + u32 current_status; /* _STA value */ +} ACPI_DEVICE_INFO; + + +/* Context structs for address space handlers */ + +typedef struct +{ + void *handler_context; + u32 seg; + u32 bus; + u32 dev_func; +} PCI_HANDLER_CONTEXT; + + +typedef struct +{ + void *handler_context; + char *mapped_physical_address; + char *mapped_logical_address; + u32 mapped_length; + +} MEM_HANDLER_CONTEXT; + + +/* + * C-state handler + */ + +typedef ACPI_STATUS (*ACPI_C_STATE_HANDLER) (ACPI_IO_ADDRESS, u32*); + + +/* + * Definitions for Resource Attributes + */ + +/* + * Memory Attributes + */ +#define READ_ONLY_MEMORY (u8) 0x00 +#define READ_WRITE_MEMORY (u8) 0x01 + +#define NON_CACHEABLE_MEMORY (u8) 0x00 +#define CACHABLE_MEMORY (u8) 0x01 +#define WRITE_COMBINING_MEMORY (u8) 0x02 +#define PREFETCHABLE_MEMORY (u8) 0x03 + +/* + * IO Attributes + * The ISA IO ranges are: n000-n0FFh, n400-n4_fFh, n800-n8_fFh, n_c00-n_cFFh. + * The non-ISA IO ranges are: n100-n3_fFh, n500-n7_fFh, n900-n_bFFh, n_cD0-n_fFFh. + */ +#define NON_ISA_ONLY_RANGES (u8) 0x01 +#define ISA_ONLY_RANGES (u8) 0x02 +#define ENTIRE_RANGE (NON_ISA_ONLY_RANGES | ISA_ONLY_RANGES) + +/* + * IO Port Descriptor Decode + */ +#define DECODE_10 (u8) 0x00 /* 10-bit IO address decode */ +#define DECODE_16 (u8) 0x01 /* 16-bit IO address decode */ + +/* + * IRQ Attributes + */ +#define EDGE_SENSITIVE (u8) 0x00 +#define LEVEL_SENSITIVE (u8) 0x01 + +#define ACTIVE_HIGH (u8) 0x00 +#define ACTIVE_LOW (u8) 0x01 + +#define EXCLUSIVE (u8) 0x00 +#define SHARED (u8) 0x01 + +/* + * DMA Attributes + */ +#define COMPATIBILITY (u8) 0x00 +#define TYPE_A (u8) 0x01 +#define TYPE_B (u8) 0x02 +#define TYPE_F (u8) 0x03 + +#define NOT_BUS_MASTER (u8) 0x00 +#define BUS_MASTER (u8) 0x01 + +#define TRANSFER_8 (u8) 0x00 +#define TRANSFER_8_16 (u8) 0x01 +#define TRANSFER_16 (u8) 0x02 + +/* + * Start Dependent Functions Priority definitions + */ +#define GOOD_CONFIGURATION (u8) 0x00 +#define ACCEPTABLE_CONFIGURATION (u8) 0x01 +#define SUB_OPTIMAL_CONFIGURATION (u8) 0x02 + +/* + * 16, 32 and 64-bit Address Descriptor resource types + */ +#define MEMORY_RANGE (u8) 0x00 +#define IO_RANGE (u8) 0x01 +#define BUS_NUMBER_RANGE (u8) 0x02 + +#define ADDRESS_NOT_FIXED (u8) 0x00 +#define ADDRESS_FIXED (u8) 0x01 + +#define POS_DECODE (u8) 0x00 +#define SUB_DECODE (u8) 0x01 + +#define PRODUCER (u8) 0x00 +#define CONSUMER (u8) 0x01 + + +/* + * Structures used to describe device resources + */ +typedef struct +{ + u32 edge_level; + u32 active_high_low; + u32 shared_exclusive; + u32 number_of_interrupts; + u32 interrupts[1]; + +} IRQ_RESOURCE; + +typedef struct +{ + u32 type; + u32 bus_master; + u32 transfer; + u32 number_of_channels; + u32 channels[1]; + +} DMA_RESOURCE; + +typedef struct +{ + u32 compatibility_priority; + u32 performance_robustness; + +} START_DEPENDENT_FUNCTIONS_RESOURCE; + +/* + * END_DEPENDENT_FUNCTIONS_RESOURCE struct is not + * needed because it has no fields + */ + +typedef struct +{ + u32 io_decode; + u32 min_base_address; + u32 max_base_address; + u32 alignment; + u32 range_length; + +} IO_RESOURCE; + +typedef struct +{ + u32 base_address; + u32 range_length; + +} FIXED_IO_RESOURCE; + +typedef struct +{ + u32 length; + u8 reserved[1]; + +} VENDOR_RESOURCE; + +typedef struct +{ + u32 read_write_attribute; + u32 min_base_address; + u32 max_base_address; + u32 alignment; + u32 range_length; + +} MEMORY24_RESOURCE; + +typedef struct +{ + u32 read_write_attribute; + u32 min_base_address; + u32 max_base_address; + u32 alignment; + u32 range_length; + +} MEMORY32_RESOURCE; + +typedef struct +{ + u32 read_write_attribute; + u32 range_base_address; + u32 range_length; + +} FIXED_MEMORY32_RESOURCE; + +typedef struct +{ + u16 cache_attribute; + u16 read_write_attribute; + +} MEMORY_ATTRIBUTE; + +typedef struct +{ + u16 range_attribute; + u16 reserved; + +} IO_ATTRIBUTE; + +typedef struct +{ + u16 reserved1; + u16 reserved2; + +} BUS_ATTRIBUTE; + +typedef union +{ + MEMORY_ATTRIBUTE memory; + IO_ATTRIBUTE io; + BUS_ATTRIBUTE bus; + +} ATTRIBUTE_DATA; + +typedef struct +{ + u32 resource_type; + u32 producer_consumer; + u32 decode; + u32 min_address_fixed; + u32 max_address_fixed; + ATTRIBUTE_DATA attribute; + u32 granularity; + u32 min_address_range; + u32 max_address_range; + u32 address_translation_offset; + u32 address_length; + u32 resource_source_index; + u32 resource_source_string_length; + u8 resource_source[1]; + +} ADDRESS16_RESOURCE; + +typedef struct +{ + u32 resource_type; + u32 producer_consumer; + u32 decode; + u32 min_address_fixed; + u32 max_address_fixed; + ATTRIBUTE_DATA attribute; + u32 granularity; + u32 min_address_range; + u32 max_address_range; + u32 address_translation_offset; + u32 address_length; + u32 resource_source_index; + u32 resource_source_string_length; + u8 resource_source[1]; + +} ADDRESS32_RESOURCE; + +typedef struct +{ + u32 producer_consumer; + u32 edge_level; + u32 active_high_low; + u32 shared_exclusive; + u32 number_of_interrupts; + u32 interrupts[1]; + u32 resource_source_index; + u32 resource_source_string_length; + u8 resource_source[1]; + +} EXTENDED_IRQ_RESOURCE; + +typedef enum +{ + irq, + dma, + start_dependent_functions, + end_dependent_functions, + io, + fixed_io, + vendor_specific, + end_tag, + memory24, + memory32, + fixed_memory32, + address16, + address32, + extended_irq +} RESOURCE_TYPE; + +typedef union +{ + IRQ_RESOURCE irq; + DMA_RESOURCE dma; + START_DEPENDENT_FUNCTIONS_RESOURCE start_dependent_functions; + IO_RESOURCE io; + FIXED_IO_RESOURCE fixed_io; + VENDOR_RESOURCE vendor_specific; + MEMORY24_RESOURCE memory24; + MEMORY32_RESOURCE memory32; + FIXED_MEMORY32_RESOURCE fixed_memory32; + ADDRESS16_RESOURCE address16; + ADDRESS32_RESOURCE address32; + EXTENDED_IRQ_RESOURCE extended_irq; +} RESOURCE_DATA; + +typedef struct _resource_tag +{ + RESOURCE_TYPE id; + u32 length; + RESOURCE_DATA data; +} RESOURCE; + +#define RESOURCE_LENGTH 12 +#define RESOURCE_LENGTH_NO_DATA 8 + +/* + * END: Definitions for Resource Attributes + */ + +/* + * Definitions for PCI Routing tables + */ +typedef struct +{ + u32 address; + u32 pin; + u32 source_index; + u8 source[1]; + +} PRT_ENTRY; + +typedef struct _prt_tag +{ + u32 length; + PRT_ENTRY data; + +} PCI_ROUTING_TABLE; + + +/* + * END: Definitions for PCI Routing tables + */ + +#endif /* ACTYPES_H */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/amlcode.h linux/drivers/acpi/include/amlcode.h --- v2.4.0-test2/linux/drivers/acpi/include/amlcode.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/amlcode.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,452 @@ + +/****************************************************************************** + * + * Name: amlcode.h - Definitions for AML, as included in "definition blocks" + * Declarations and definitions contained herein are derived + * directly from the ACPI specification. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __AMLCODE_H__ +#define __AMLCODE_H__ + + +/* primary opcodes */ + +#define AML_NULL_CHAR (u16) 0x00 + +#define AML_ZERO_OP (u16) 0x00 +#define AML_ONE_OP (u16) 0x01 +#define AML_UNASSIGNED (u16) 0x02 +#define AML_ALIAS_OP (u16) 0x06 +#define AML_NAME_OP (u16) 0x08 +#define AML_BYTE_OP (u16) 0x0a +#define AML_WORD_OP (u16) 0x0b +#define AML_DWORD_OP (u16) 0x0c +#define AML_STRING_OP (u16) 0x0d +#define AML_SCOPE_OP (u16) 0x10 +#define AML_BUFFER_OP (u16) 0x11 +#define AML_PACKAGE_OP (u16) 0x12 +#define AML_METHOD_OP (u16) 0x14 +#define AML_DUAL_NAME_PREFIX (u16) 0x2e +#define AML_MULTI_NAME_PREFIX_OP (u16) 0x2f +#define AML_NAME_CHAR_SUBSEQ (u16) 0x30 +#define AML_NAME_CHAR_FIRST (u16) 0x41 +#define AML_OP_PREFIX (u16) 0x5b +#define AML_ROOT_PREFIX (u16) 0x5c +#define AML_PARENT_PREFIX (u16) 0x5e +#define AML_LOCAL_OP (u16) 0x60 +#define AML_LOCAL0 (u16) 0x60 +#define AML_LOCAL1 (u16) 0x61 +#define AML_LOCAL2 (u16) 0x62 +#define AML_LOCAL3 (u16) 0x63 +#define AML_LOCAL4 (u16) 0x64 +#define AML_LOCAL5 (u16) 0x65 +#define AML_LOCAL6 (u16) 0x66 +#define AML_LOCAL7 (u16) 0x67 +#define AML_ARG_OP (u16) 0x68 +#define AML_ARG0 (u16) 0x68 +#define AML_ARG1 (u16) 0x69 +#define AML_ARG2 (u16) 0x6a +#define AML_ARG3 (u16) 0x6b +#define AML_ARG4 (u16) 0x6c +#define AML_ARG5 (u16) 0x6d +#define AML_ARG6 (u16) 0x6e +#define AML_STORE_OP (u16) 0x70 +#define AML_REF_OF_OP (u16) 0x71 +#define AML_ADD_OP (u16) 0x72 +#define AML_CONCAT_OP (u16) 0x73 +#define AML_SUBTRACT_OP (u16) 0x74 +#define AML_INCREMENT_OP (u16) 0x75 +#define AML_DECREMENT_OP (u16) 0x76 +#define AML_MULTIPLY_OP (u16) 0x77 +#define AML_DIVIDE_OP (u16) 0x78 +#define AML_SHIFT_LEFT_OP (u16) 0x79 +#define AML_SHIFT_RIGHT_OP (u16) 0x7a +#define AML_BIT_AND_OP (u16) 0x7b +#define AML_BIT_NAND_OP (u16) 0x7c +#define AML_BIT_OR_OP (u16) 0x7d +#define AML_BIT_NOR_OP (u16) 0x7e +#define AML_BIT_XOR_OP (u16) 0x7f +#define AML_BIT_NOT_OP (u16) 0x80 +#define AML_FIND_SET_LEFT_BIT_OP (u16) 0x81 +#define AML_FIND_SET_RIGHT_BIT_OP (u16) 0x82 +#define AML_DEREF_OF_OP (u16) 0x83 +#define AML_NOTIFY_OP (u16) 0x86 +#define AML_SIZE_OF_OP (u16) 0x87 +#define AML_INDEX_OP (u16) 0x88 +#define AML_MATCH_OP (u16) 0x89 +#define AML_DWORD_FIELD_OP (u16) 0x8a +#define AML_WORD_FIELD_OP (u16) 0x8b +#define AML_BYTE_FIELD_OP (u16) 0x8c +#define AML_BIT_FIELD_OP (u16) 0x8d +#define AML_TYPE_OP (u16) 0x8e +#define AML_LAND_OP (u16) 0x90 +#define AML_LOR_OP (u16) 0x91 +#define AML_LNOT_OP (u16) 0x92 +#define AML_LEQUAL_OP (u16) 0x93 +#define AML_LGREATER_OP (u16) 0x94 +#define AML_LLESS_OP (u16) 0x95 +#define AML_IF_OP (u16) 0xa0 +#define AML_ELSE_OP (u16) 0xa1 +#define AML_WHILE_OP (u16) 0xa2 +#define AML_NOOP_CODE (u16) 0xa3 +#define AML_RETURN_OP (u16) 0xa4 +#define AML_BREAK_OP (u16) 0xa5 +#define AML_BREAK_POINT_OP (u16) 0xcc +#define AML_ONES_OP (u16) 0xff + +/* prefixed opcodes */ + +#define AML_EXTOP (u16) 0x005b + + +#define AML_MUTEX_OP (u16) 0x5b01 +#define AML_EVENT_OP (u16) 0x5b02 +#define AML_SHIFT_RIGHT_BIT_OP (u16) 0x5b10 +#define AML_SHIFT_LEFT_BIT_OP (u16) 0x5b11 +#define AML_COND_REF_OF_OP (u16) 0x5b12 +#define AML_CREATE_FIELD_OP (u16) 0x5b13 +#define AML_LOAD_OP (u16) 0x5b20 +#define AML_STALL_OP (u16) 0x5b21 +#define AML_SLEEP_OP (u16) 0x5b22 +#define AML_ACQUIRE_OP (u16) 0x5b23 +#define AML_SIGNAL_OP (u16) 0x5b24 +#define AML_WAIT_OP (u16) 0x5b25 +#define AML_RESET_OP (u16) 0x5b26 +#define AML_RELEASE_OP (u16) 0x5b27 +#define AML_FROM_BCDOP (u16) 0x5b28 +#define AML_TO_BCDOP (u16) 0x5b29 +#define AML_UN_LOAD_OP (u16) 0x5b2a +#define AML_REVISION_OP (u16) 0x5b30 +#define AML_DEBUG_OP (u16) 0x5b31 +#define AML_FATAL_OP (u16) 0x5b32 +#define AML_REGION_OP (u16) 0x5b80 +#define AML_DEF_FIELD_OP (u16) 0x5b81 +#define AML_DEVICE_OP (u16) 0x5b82 +#define AML_PROCESSOR_OP (u16) 0x5b83 +#define AML_POWER_RES_OP (u16) 0x5b84 +#define AML_THERMAL_ZONE_OP (u16) 0x5b85 +#define AML_INDEX_FIELD_OP (u16) 0x5b86 +#define AML_BANK_FIELD_OP (u16) 0x5b87 + + +/* Bogus opcodes (they are actually two separate opcodes) */ + +#define AML_LGREATEREQUAL_OP (u16) 0x9295 +#define AML_LLESSEQUAL_OP (u16) 0x9294 +#define AML_LNOTEQUAL_OP (u16) 0x9293 + + +/* Internal opcodes */ + +#define AML_NAMEPATH_OP (u16) 0x002d +#define AML_NAMEDFIELD_OP (u16) 0x0030 +#define AML_RESERVEDFIELD_OP (u16) 0x0031 +#define AML_ACCESSFIELD_OP (u16) 0x0032 +#define AML_BYTELIST_OP (u16) 0x0033 +#define AML_STATICSTRING_OP (u16) 0x0034 +#define AML_METHODCALL_OP (u16) 0x0035 + + +/* + * argument types + */ + +/* +#define AML_ASCIICHARLIST_ARG 'A' +#define AML_BYTEDATA_ARG 'b' +#define AML_BYTELIST_ARG 'B' +#define AML_DWORDDATA_ARG 'd' +#define AML_DATAOBJECT_ARG 'o' +#define AML_DATAOBJECTLIST_ARG 'O' +#define AML_FIELDLIST_ARG 'F' +#define AML_NAMESTRING_ARG 'n' +#define AML_OBJECTLIST_ARG 'P' +#define AML_PKGLENGTH_ARG 'p' +#define AML_SUPERNAME_ARG 's' +#define AML_TARGET_ARG 'l' +#define AML_TERMARG_ARG 't' +#define AML_TERMLIST_ARG 'T' +#define AML_WORDDATA_ARG 'w' +*/ + + +#define ARG_NONE 0x0 + +/* + * Argument types for the AML Parser + * Each field in the Arg_types u32 is 5 bits, allowing for a maximum of 6 arguments. + * There can be up to 31 unique argument types + */ + +#define ARGP_BYTEDATA 0x01 +#define ARGP_BYTELIST 0x02 +#define ARGP_CHARLIST 0x03 +#define ARGP_DATAOBJ 0x04 +#define ARGP_DATAOBJLIST 0x05 +#define ARGP_DWORDDATA 0x06 +#define ARGP_FIELDLIST 0x07 +#define ARGP_NAME 0x08 +#define ARGP_NAMESTRING 0x09 +#define ARGP_OBJLIST 0x0A +#define ARGP_PKGLENGTH 0x0B +#define ARGP_SUPERNAME 0x0C +#define ARGP_TARGET 0x0D +#define ARGP_TERMARG 0x0E +#define ARGP_TERMLIST 0x0F +#define ARGP_WORDDATA 0x10 + +/* + * Resolved argument types for the AML Interpreter + * Each field in the Arg_types u32 is 5 bits, allowing for a maximum of 6 arguments. + * There can be up to 31 unique argument types + */ + +#define ARGI_ANYTYPE 0x01 +#define ARGI_TARGETREF 0x02 +#define ARGI_REFERENCE 0x03 +#define ARGI_IF 0x04 +#define ARGI_NUMBER 0x05 +#define ARGI_STRING 0x06 +#define ARGI_BUFFER 0x07 +#define ARGI_PACKAGE 0x08 +#define ARGI_DATAOBJECT 0x09 /* Buffer, string, package or NTE reference - Used only by Size_of operator*/ +#define ARGI_COMPLEXOBJ 0x0A /* Buffer or package */ +#define ARGI_MUTEX 0x0B +#define ARGI_EVENT 0x0C +#define ARGI_REGION 0x0D +#define ARGI_DDBHANDLE 0x0E + +#define ARGI_INVALID_OPCODE 0xFFFFFFFF + + +/* + * hash offsets + */ +#define AML_EXTOP_HASH_OFFSET 22 +#define AML_LNOT_HASH_OFFSET 19 + + +/* + * opcode groups and types + */ + +#define OPGRP_NAMED 0x01 +#define OPGRP_FIELD 0x02 +#define OPGRP_BYTELIST 0x04 + +#define OPTYPE_UNDEFINED 0 + + +#define OPTYPE_LITERAL 1 +#define OPTYPE_CONSTANT 2 +#define OPTYPE_METHOD_ARGUMENT 3 +#define OPTYPE_LOCAL_VARIABLE 4 +#define OPTYPE_DATA_TERM 5 + +/* Type 1 opcodes */ + +#define OPTYPE_MONADIC1 6 +#define OPTYPE_DYADIC1 7 + + +/* Type 2 opcodes */ + +#define OPTYPE_MONADIC2 8 +#define OPTYPE_MONADIC2_r 9 +#define OPTYPE_DYADIC2 10 +#define OPTYPE_DYADIC2_r 11 +#define OPTYPE_DYADIC2_s 12 +#define OPTYPE_INDEX 13 +#define OPTYPE_MATCH 14 + +/* Generic for an op that returns a value */ + +#define OPTYPE_METHOD_CALL 15 + + +/* Misc */ + +#define OPTYPE_CREATE_FIELD 16 +#define OPTYPE_FATAL 17 +#define OPTYPE_CONTROL 18 +#define OPTYPE_RECONFIGURATION 19 +#define OPTYPE_NAMED_OBJECT 20 + +#define OPTYPE_BOGUS 21 + + +/* Comparison operation codes for Match_op operator */ + +typedef enum +{ + MATCH_MTR = 0, + MATCH_MEQ = 1, + MATCH_MLE = 2, + MATCH_MLT = 3, + MATCH_MGE = 4, + MATCH_MGT = 5 + +} AML_MATCH_OPERATOR; + +#define MAX_MATCH_OPERATOR 5 + + +/* Field Access Types */ + +#define ACCESS_TYPE_MASK 0x0f +#define ACCESS_TYPE_SHIFT 0 + +typedef enum +{ + ACCESS_ANY_ACC = 0, + ACCESS_BYTE_ACC = 1, + ACCESS_WORD_ACC = 2, + ACCESS_DWORD_ACC = 3, + ACCESS_BLOCK_ACC = 4, + ACCESS_SMBSEND_RECV_ACC = 5, + ACCESS_SMBQUICK_ACC = 6 + +} AML_ACCESS_TYPE; + + +/* Field Lock Rules */ + +#define LOCK_RULE_MASK 0x10 +#define LOCK_RULE_SHIFT 4 + +typedef enum +{ + GLOCK_NEVER_LOCK = 0, + GLOCK_ALWAYS_LOCK = 1 + +} AML_LOCK_RULE; + + +/* Field Update Rules */ + +#define UPDATE_RULE_MASK 0x060 +#define UPDATE_RULE_SHIFT 5 + +typedef enum +{ + UPDATE_PRESERVE = 0, + UPDATE_WRITE_AS_ONES = 1, + UPDATE_WRITE_AS_ZEROS = 2 + +} AML_UPDATE_RULE; + + +/* bit fields in Method_flags byte */ + +#define METHOD_FLAGS_ARG_COUNT 0x07 +#define METHOD_FLAGS_SERIALIZED 0x08 + + +/* Array sizes. Used for range checking also */ + +#define NUM_REGION_TYPES 5 +#define NUM_ACCESS_TYPES 7 +#define NUM_UPDATE_RULES 3 +#define NUM_MATCH_OPS 7 +#define NUM_OPCODES 256 +#define NUM_FIELD_NAMES 2 + +/* External declarations of the AML tables */ + +extern u8 acpi_gbl_aml [NUM_OPCODES]; +extern u16 acpi_gbl_pfx [NUM_OPCODES]; +extern char *acpi_gbl_short_ops [NUM_OPCODES]; +extern char *acpi_gbl_long_ops [NUM_OPCODES]; +extern char *acpi_gbl_region_types [NUM_REGION_TYPES]; +extern char *acpi_gbl_match_ops [NUM_MATCH_OPS]; +extern char *acpi_gbl_access_types [NUM_ACCESS_TYPES]; +extern char *acpi_gbl_update_rules [NUM_UPDATE_RULES]; +extern char *acpi_gbl_FEnames [NUM_FIELD_NAMES]; + + +/* + * AML tables + */ + +#ifdef DEFINE_AML_GLOBALS + +/* Data used in keeping track of fields */ + +char *acpi_gbl_FEnames[NUM_FIELD_NAMES] = +{ + "skip", + "?access?" +}; /* FE = Field Element */ + + +/* Region type decoding */ + +char *acpi_gbl_region_types[NUM_REGION_TYPES] = +{ + "System_memory", + "System_iO", + "PCIConfig", + "Embedded_control", + "SMBus" +}; + + +char *acpi_gbl_match_ops[NUM_MATCH_OPS] = +{ + "Error", + "MTR", + "MEQ", + "MLE", + "MLT", + "MGE", + "MGT" +}; + + +/* Access type decoding */ + +char *acpi_gbl_access_types[NUM_ACCESS_TYPES] = +{ + "Any_acc", + "Byte_acc", + "Word_acc", + "DWord_acc", + "Block_acc", + "SMBSend_recv_acc", + "SMBQuick_acc" +}; + + +/* Update rule decoding */ + +char *acpi_gbl_update_rules[NUM_UPDATE_RULES] = +{ + "Preserve", + "Write_as_ones", + "Write_as_zeros" +}; + + +#endif /* DEFINE_AML_GLOBALS */ + +#endif /* __AMLCODE_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/common.h linux/drivers/acpi/include/common.h --- v2.4.0-test2/linux/drivers/acpi/include/common.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/common.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,650 @@ + +/****************************************************************************** + * + * Name: common.h -- prototypes for the common (subsystem-wide) procedures + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _COMMON_H +#define _COMMON_H + + +#define REF_INCREMENT (u16) 0 +#define REF_DECREMENT (u16) 1 +#define REF_FORCE_DELETE (u16) 2 + +/* Acpi_cm_dump_buffer */ + +#define DB_BYTE_DISPLAY 1 +#define DB_WORD_DISPLAY 2 +#define DB_DWORD_DISPLAY 4 +#define DB_QWORD_DISPLAY 8 + + +/* Global initialization interfaces */ + +void +acpi_cm_init_globals ( + ACPI_INIT_DATA *init_data); + +void +acpi_cm_terminate ( + void); + + +/* + * Acpi_cm_init - miscellaneous initialization and shutdown + */ + +ACPI_STATUS +acpi_cm_hardware_initialize ( + void); + +ACPI_STATUS +acpi_cm_subsystem_shutdown ( + void); + +/* + * Acpi_cm_global - Global data structures and procedures + */ + +char * +acpi_cm_get_mutex_name ( + u32 mutex_id); + +char * +acpi_cm_get_type_name ( + u32 type); + +u8 +acpi_cm_valid_object_type ( + u32 type); + +ACPI_OWNER_ID +acpi_cm_allocate_owner_id ( + u32 id_type); + + +/* + * Acpi_cm_clib - Local implementations of C library functions + */ + +ACPI_SIZE +acpi_cm_strlen ( + const char *string); + +char * +acpi_cm_strcpy ( + char *dst_string, + const char *src_string); + +char * +acpi_cm_strncpy ( + char *dst_string, + const char *src_string, + ACPI_SIZE count); + +u32 +acpi_cm_strncmp ( + const char *string1, + const char *string2, + ACPI_SIZE count); + +u32 +acpi_cm_strcmp ( + const char *string1, + const char *string2); + +char * +acpi_cm_strcat ( + char *dst_string, + const char *src_string); + +char * +acpi_cm_strncat ( + char *dst_string, + const char *src_string, + ACPI_SIZE count); + +u32 +acpi_cm_strtoul ( + const char *string, + char **terminator, + s32 base); + +char * +acpi_cm_strstr ( + char *string1, + char *string2); + +char * +acpi_cm_strupr ( + char *src_string); + +void * +acpi_cm_memcpy ( + void *dest, + const void *src, + ACPI_SIZE count); + +void * +acpi_cm_memset ( + void *dest, + s32 value, + ACPI_SIZE count); + +s32 +acpi_cm_to_upper ( + s32 c); + +s32 +acpi_cm_to_lower ( + s32 c); + + +/* + * Acpi_cm_copy - Object construction and conversion interfaces + */ + +ACPI_STATUS +acpi_cm_build_simple_object( + ACPI_OBJECT_INTERNAL *obj, + ACPI_OBJECT *user_obj, + char *data_space, + u32 *buffer_space_used); + +ACPI_STATUS +acpi_cm_build_package_object ( + ACPI_OBJECT_INTERNAL *obj, + char *buffer, + u32 *space_used); + +ACPI_STATUS +acpi_cm_build_external_object ( + ACPI_OBJECT_INTERNAL *obj, + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_cm_build_internal_simple_object( + ACPI_OBJECT *user_obj, + ACPI_OBJECT_INTERNAL *obj); + +ACPI_STATUS +acpi_cm_build_internal_object ( + ACPI_OBJECT *obj, + ACPI_OBJECT_INTERNAL *internal_obj); + +ACPI_STATUS +acpi_cm_copy_internal_simple_object ( + ACPI_OBJECT_INTERNAL *source_obj, + ACPI_OBJECT_INTERNAL *dest_obj); + +ACPI_STATUS +acpi_cm_build_copy_internal_package_object ( + ACPI_OBJECT_INTERNAL *source_obj, + ACPI_OBJECT_INTERNAL *dest_obj); + + +/* + * Acpi_cm_create - Object creation + */ + +ACPI_STATUS +acpi_cm_update_object_reference ( + ACPI_OBJECT_INTERNAL *object, + u16 action); + +ACPI_OBJECT_INTERNAL * +_cm_create_internal_object ( + char *module_name, + s32 line_number, + s32 component_id, + OBJECT_TYPE_INTERNAL type); + + +/* + * Acpi_cm_debug - Debug interfaces + */ + +s32 +get_debug_level ( + void); + +void +set_debug_level ( + s32 level); + +void +function_trace ( + ACPI_STRING module_name, + s32 line_number, + s32 component_id, + ACPI_STRING function_name); + +void +function_trace_ptr ( + ACPI_STRING module_name, + s32 line_number, + s32 component_id, + ACPI_STRING function_name, + void *pointer); + +void +function_trace_u32 ( + ACPI_STRING module_name, + s32 line_number, + s32 component_id, + ACPI_STRING function_name, + u32 integer); + +void +function_trace_str ( + ACPI_STRING module_name, + s32 line_number, + s32 component_id, + ACPI_STRING function_name, + char *string); + +void +function_exit ( + ACPI_STRING module_name, + s32 line_number, + s32 component_id, + ACPI_STRING function_name); + +void +function_status_exit ( + ACPI_STRING module_name, + s32 line_number, + s32 component_id, + ACPI_STRING function_name, + ACPI_STATUS status); + +void +function_value_exit ( + ACPI_STRING module_name, + s32 line_number, + s32 component_id, + ACPI_STRING function_name, + NATIVE_UINT value); + +void +function_ptr_exit ( + ACPI_STRING module_name, + s32 line_number, + s32 component_id, + ACPI_STRING function_name, + char *ptr); + +void +debug_print_prefix ( + ACPI_STRING module_name, + s32 line_number); + +void +debug_print ( + ACPI_STRING module_name, + s32 line_number, + s32 component_id, + s32 print_level, + char *format, ...); + +void +debug_print_raw ( + char *format, ...); + +void +_report_info ( + ACPI_STRING module_name, + s32 line_number, + s32 component_id, + ACPI_STRING message); + +void +_report_error ( + ACPI_STRING module_name, + s32 line_number, + s32 component_id, + ACPI_STRING message); + +void +_report_warning ( + ACPI_STRING module_name, + s32 line_number, + s32 component_id, + ACPI_STRING message); + +void +_report_success ( + ACPI_STRING module_name, + s32 line_number, + s32 component_id, + ACPI_STRING message); + +void +acpi_cm_dump_buffer ( + char *buffer, + u32 count, + u32 display, + s32 component_id); + + +/* + * Acpi_cm_delete - Object deletion + */ + +void +acpi_cm_delete_internal_obj ( + ACPI_OBJECT_INTERNAL *object); + +void +acpi_cm_delete_internal_package_object ( + ACPI_OBJECT_INTERNAL *object); + +void +acpi_cm_delete_internal_simple_object ( + ACPI_OBJECT_INTERNAL *object); + +ACPI_STATUS +acpi_cm_delete_internal_object_list ( + ACPI_OBJECT_INTERNAL **obj_list); + + +/* + * Acpi_cm_eval - object evaluation + */ + +/* Method name strings */ + +#define METHOD_NAME__HID "_HID" +#define METHOD_NAME__UID "_UID" +#define METHOD_NAME__ADR "_ADR" +#define METHOD_NAME__STA "_STA" +#define METHOD_NAME__REG "_REG" +#define METHOD_NAME__SEG "_SEG" +#define METHOD_NAME__BBN "_BBN" + + +ACPI_STATUS +acpi_cm_evaluate_numeric_object ( + char *method_name, + ACPI_NAMED_OBJECT *acpi_device, + u32 *address); + +ACPI_STATUS +acpi_cm_execute_HID ( + ACPI_NAMED_OBJECT *acpi_device, + DEVICE_ID *hid); + +ACPI_STATUS +acpi_cm_execute_STA ( + ACPI_NAMED_OBJECT *acpi_device, + u32 *status_flags); + +ACPI_STATUS +acpi_cm_execute_UID ( + ACPI_NAMED_OBJECT *acpi_device, + DEVICE_ID *uid); + + +/* + * Acpi_cm_error - exception interfaces + */ + +char * +acpi_cm_format_exception ( + ACPI_STATUS status); + + +/* + * Acpi_cm_mutex - mutual exclusion interfaces + */ + +ACPI_STATUS +acpi_cm_mutex_initialize ( + void); + +void +acpi_cm_mutex_terminate ( + void); + +ACPI_STATUS +acpi_cm_create_mutex ( + ACPI_MUTEX_HANDLE mutex_id); + +ACPI_STATUS +acpi_cm_delete_mutex ( + ACPI_MUTEX_HANDLE mutex_id); + +ACPI_STATUS +acpi_cm_acquire_mutex ( + ACPI_MUTEX_HANDLE mutex_id); + +ACPI_STATUS +acpi_cm_release_mutex ( + ACPI_MUTEX_HANDLE mutex_id); + + +/* + * Acpi_cm_object - internal object create/delete/cache routines + */ + +#define acpi_cm_create_internal_object(t) _cm_create_internal_object(_THIS_MODULE,__LINE__,_COMPONENT,t) +#define acpi_cm_allocate_object_desc() _cm_allocate_object_desc(_THIS_MODULE,__LINE__,_COMPONENT) + +void * +_cm_allocate_object_desc ( + char *module_name, + s32 line_number, + s32 component_id); + +void +acpi_cm_delete_object_desc ( + ACPI_OBJECT_INTERNAL *object); + +u8 +acpi_cm_valid_internal_object ( + void *object); + + +/* + * Acpi_cm_ref_cnt - Object reference count management + */ + +void +acpi_cm_add_reference ( + ACPI_OBJECT_INTERNAL *object); + +void +acpi_cm_remove_reference ( + ACPI_OBJECT_INTERNAL *object); + +/* + * Acpi_cm_size - Object size routines + */ + +ACPI_STATUS +acpi_cm_get_simple_object_size ( + ACPI_OBJECT_INTERNAL *obj, + u32 *obj_length); + +ACPI_STATUS +acpi_cm_get_package_object_size ( + ACPI_OBJECT_INTERNAL *obj, + u32 *obj_length); + +ACPI_STATUS +acpi_cm_get_object_size( + ACPI_OBJECT_INTERNAL *obj, + u32 *obj_length); + + +/* + * Acpi_cm_state - Generic state creation/cache routines + */ + +void +acpi_cm_push_generic_state ( + ACPI_GENERIC_STATE **list_head, + ACPI_GENERIC_STATE *state); + +ACPI_GENERIC_STATE * +acpi_cm_pop_generic_state ( + ACPI_GENERIC_STATE **list_head); + + +ACPI_GENERIC_STATE * +acpi_cm_create_generic_state ( + void); + +ACPI_GENERIC_STATE * +acpi_cm_create_update_state ( + ACPI_OBJECT_INTERNAL *object, + u16 action); + +ACPI_STATUS +acpi_cm_create_update_state_and_push ( + ACPI_OBJECT_INTERNAL *object, + u16 action, + ACPI_GENERIC_STATE **state_list); + +ACPI_GENERIC_STATE * +acpi_cm_create_control_state ( + void); + +void +acpi_cm_delete_generic_state ( + ACPI_GENERIC_STATE *state); + +void +acpi_cm_delete_generic_state_cache ( + void); + +void +acpi_cm_delete_object_cache ( + void); + +/* + * Acpi_cmutils + */ + +u8 +acpi_cm_valid_acpi_name ( + u32 name); + +u8 +acpi_cm_valid_acpi_character ( + char character); + + +/* + * Memory allocation functions and related macros. + * Macros that expand to include filename and line number + */ + +void * +_cm_allocate ( + u32 size, + u32 component, + ACPI_STRING module, + s32 line); + +void * +_cm_callocate ( + u32 size, + u32 component, + ACPI_STRING module, + s32 line); + +void +_cm_free ( + void *address, + u32 component, + ACPI_STRING module, + s32 line); + +void +acpi_cm_init_static_object ( + ACPI_OBJECT_INTERNAL *obj_desc); + +#define acpi_cm_allocate(a) _cm_allocate(a,_COMPONENT,_THIS_MODULE,__LINE__) +#define acpi_cm_callocate(a) _cm_callocate(a, _COMPONENT,_THIS_MODULE,__LINE__) +#define acpi_cm_free(a) _cm_free(a,_COMPONENT,_THIS_MODULE,__LINE__) + +#ifndef ACPI_DEBUG + +#define acpi_cm_add_element_to_alloc_list(a,b,c,d,e,f) +#define acpi_cm_delete_element_from_alloc_list(a,b,c,d) +#define acpi_cm_dump_current_allocations(a,b) +#define acpi_cm_dump_allocation_info() + +#define DECREMENT_OBJECT_METRICS(a) +#define INCREMENT_OBJECT_METRICS(a) +#define INITIALIZE_ALLOCATION_METRICS() + +#else + +#define INITIALIZE_ALLOCATION_METRICS() \ + acpi_gbl_current_object_count = 0; \ + acpi_gbl_current_object_size = 0; \ + acpi_gbl_running_object_count = 0; \ + acpi_gbl_running_object_size = 0; \ + acpi_gbl_max_concurrent_object_count = 0; \ + acpi_gbl_max_concurrent_object_size = 0; \ + acpi_gbl_current_alloc_size = 0; \ + acpi_gbl_current_alloc_count = 0; \ + acpi_gbl_running_alloc_size = 0; \ + acpi_gbl_running_alloc_count = 0; \ + acpi_gbl_max_concurrent_alloc_size = 0; \ + acpi_gbl_max_concurrent_alloc_count = 0 + +#define DECREMENT_OBJECT_METRICS(a) \ + acpi_gbl_current_object_count--; \ + acpi_gbl_current_object_size -= a + +#define INCREMENT_OBJECT_METRICS(a) \ + acpi_gbl_current_object_count++; \ + acpi_gbl_running_object_count++; \ + if (acpi_gbl_max_concurrent_object_count < acpi_gbl_current_object_count) \ + { \ + acpi_gbl_max_concurrent_object_count = acpi_gbl_current_object_count; \ + } \ + acpi_gbl_running_object_size += a; \ + acpi_gbl_current_object_size += a; \ + if (acpi_gbl_max_concurrent_object_size < acpi_gbl_current_object_size) \ + { \ + acpi_gbl_max_concurrent_object_size = acpi_gbl_current_object_size; \ + } + + +void +acpi_cm_dump_allocation_info ( + void); + +void +acpi_cm_dump_current_allocations ( + u32 component, + ACPI_STRING module); + +#endif + + +#endif /* _COMMON_H */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/config.h linux/drivers/acpi/include/config.h --- v2.4.0-test2/linux/drivers/acpi/include/config.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/config.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,185 @@ + +/****************************************************************************** + * + * Name: config.h - Global configuration constants + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _CONFIG_H +#define _CONFIG_H + + +/****************************************************************************** + * + * Compile-time options + * + *****************************************************************************/ + +/* + * ACPI_DEBUG - This switch enables all the debug facilities of the ACPI + * subsystem. This includes the DEBUG_PRINT output statements + * When disabled, all DEBUG_PRINT statements are compiled out. + * + * ACPI_APPLICATION - Use this switch if the subsystem is going to be run + * at the application level. + * + */ + + +/****************************************************************************** + * + * Subsystem Constants + * + *****************************************************************************/ + + +/* Version string */ + +#define ACPI_CA_VERSION __DATE__ + +/* Name of host operating system (returned by the _OS_ namespace object) */ + +#ifdef _LINUX +#define ACPI_OS_NAME "Linux" +#else +#define ACPI_OS_NAME "Intel ACPI/CA Core Subsystem" +#endif + + +/* + * How and when control methods will be parsed + * The default action is to parse all methods at table load time to verify them, but delete the parse trees + * to conserve memory. Methods are parsed just in time before execution and the parse tree is deleted + * when execution completes. + */ +#define METHOD_PARSE_AT_INIT 0x0 /* Parse at table init, never delete the method parse tree */ +#define METHOD_PARSE_JUST_IN_TIME 0x1 /* Parse only when a method is invoked */ +#define METHOD_DELETE_AT_COMPLETION 0x2 /* Delete parse tree on method completion */ + +/* Default parsing configuration */ + +#define METHOD_PARSE_CONFIGURATION (METHOD_PARSE_JUST_IN_TIME | METHOD_DELETE_AT_COMPLETION) + + +/* Maximum objects in the various object caches */ + +#define MAX_STATE_CACHE_DEPTH 24 /* State objects for stacks */ +#define MAX_PARSE_CACHE_DEPTH 512 /* Parse tree objects */ +#define MAX_OBJECT_CACHE_DEPTH 32 /* Interpreter operand objects */ +#define MAX_WALK_CACHE_DEPTH 2 /* Objects for parse tree walks (method execution) */ + +/* + * Name_space Table size + * + * All tables are the same size to simplify the implementation. + * Tables may be extended by allocating additional tables that + * are in turn linked together to form a chain of tables. + */ + +#define NS_TABLE_SIZE 16 + +/* String size constants */ + +#define MAX_STRING_LENGTH 512 +#define PATHNAME_MAX 256 /* A full namespace pathname */ + + +/* Maximum count for a semaphore object */ + +#define MAX_SEMAPHORE_COUNT 256 + + +/* Max reference count (for debug only) */ + +#define MAX_REFERENCE_COUNT 0x200 + + +/* Size of cached memory mapping for system memory operation region */ + +#define SYSMEM_REGION_WINDOW_SIZE 4096 + + +/* + * Debugger threading model + * Use single threaded if the entire subsystem is contained in an application + * Use multiple threaded when the the subsystem is running in the kernel. + * + * By default the model is single threaded if ACPI_APPLICATION is set, + * multi-threaded if ACPI_APPLICATION is not set. + */ + +#define DEBUGGER_SINGLE_THREADED 0 +#define DEBUGGER_MULTI_THREADED 1 + +#ifdef ACPI_APPLICATION +#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED + +#else +#define DEBUGGER_THREADING DEBUGGER_MULTI_THREADED +#endif + + +/****************************************************************************** + * + * ACPI Specification constants (Do not change unless the specification changes) + * + *****************************************************************************/ + +/* + * Method info (in WALK_STATE), containing local variables and argumetns + */ + +#define MTH_NUM_LOCALS 8 +#define MTH_MAX_LOCAL 7 + +#define MTH_NUM_ARGS 7 +#define MTH_MAX_ARG 6 + +/* + * Operand Stack (in WALK_STATE), Must be large enough to contain MTH_MAX_ARG + */ + +#define OBJ_NUM_OPERANDS 8 +#define OBJ_MAX_OPERAND 7 + +/* Names within the namespace are 4 bytes long */ + +#define ACPI_NAME_SIZE 4 +#define PATH_SEGMENT_LENGTH 5 /* 4 chars for name + 1 char for separator */ +#define PATH_SEPARATOR '.' + + +/* Constants used in searching for the RSDP in low memory */ + +#define LO_RSDP_WINDOW_BASE (void *) 0 +#define HI_RSDP_WINDOW_BASE (void *) 0xE0000 +#define LO_RSDP_WINDOW_SIZE 0x400 +#define HI_RSDP_WINDOW_SIZE 0x20000 +#define RSDP_SCAN_STEP 16 + + +/* Maximum nesting of package objects */ + +#define MAX_PACKAGE_DEPTH 16 + + +#endif /* _CONFIG_H */ + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/debugger.h linux/drivers/acpi/include/debugger.h --- v2.4.0-test2/linux/drivers/acpi/include/debugger.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/debugger.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,394 @@ + +/****************************************************************************** + * + * Name: debugger.h - ACPI/AML debugger + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DEBUGGER_H__ +#define __DEBUGGER_H__ + + +#define DB_MAX_ARGS 8 /* Must be max method args + 1 */ + +#define DB_COMMAND_PROMPT '-' +#define DB_EXECUTE_PROMPT '%' + + +extern int optind; +extern char *optarg; +extern u8 *aml_ptr; +extern u32 acpi_aml_length; + +extern u8 opt_tables; +extern u8 opt_disasm; +extern u8 opt_stats; +extern u8 opt_parse_jit; +extern u8 opt_verbose; + + +extern char *args[DB_MAX_ARGS]; +extern char line_buf[80]; +extern char scope_buf[40]; +extern char debug_filename[40]; +extern u8 output_to_file; +extern char *buffer; +extern char *filename; +extern char *INDENT_STRING; +extern u32 acpi_gbl_method_breakpoint; +extern u8 acpi_gbl_db_output_flags; +extern u32 acpi_gbl_db_debug_level; +extern u32 acpi_gbl_db_console_debug_level; + +extern u32 num_names; +extern u32 num_methods; +extern u32 num_regions; +extern u32 num_packages; +extern u32 num_aliases; +extern u32 num_devices; +extern u32 num_field_defs; +extern u32 num_thermal_zones; +extern u32 num_named_objects; +extern u32 num_grammar_elements; +extern u32 num_method_elements ; +extern u32 num_mutexes; +extern u32 num_power_resources; +extern u32 num_bank_fields ; +extern u32 num_index_fields; +extern u32 num_events; + +extern u32 size_of_parse_tree; +extern u32 size_of_method_trees; +extern u32 size_of_nTes; +extern u32 size_of_acpi_objects; + + +#define BUFFER_SIZE 4196 + +#define DB_REDIRECTABLE_OUTPUT 0x01 +#define DB_CONSOLE_OUTPUT 0x02 +#define DB_DUPLICATE_OUTPUT 0x03 + + +typedef struct command_info +{ + char *name; /* Command Name */ + char min_args; /* Minimum arguments required */ + +} COMMAND_INFO; + + +typedef struct argument_info +{ + char *name; /* Argument Name */ + +} ARGUMENT_INFO; + + +#define PARAM_LIST(pl) pl + +#define DBTEST_OUTPUT_LEVEL(lvl) if (opt_verbose) + +#define VERBOSE_PRINT(fp) DBTEST_OUTPUT_LEVEL(lvl) {\ + acpi_os_printf PARAM_LIST(fp);} + +#define EX_NO_SINGLE_STEP 1 +#define EX_SINGLE_STEP 2 + + +/* Prototypes */ + + +/* + * dbapi - external debugger interfaces + */ + +int +acpi_db_initialize ( + void); + +ACPI_STATUS +acpi_db_single_step ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op, + u8 op_type); + + +/* + * dbcmds - debug commands and output routines + */ + + +void +acpi_db_display_table_info ( + char *table_arg); + +void +acpi_db_unload_acpi_table ( + char *table_arg, + char *instance_arg); + +void +acpi_db_set_method_breakpoint ( + char *location, + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op); + +void +acpi_db_set_method_call_breakpoint ( + ACPI_GENERIC_OP *op); + +void +acpi_db_disassemble_aml ( + char *statements, + ACPI_GENERIC_OP *op); + +void +acpi_db_dump_namespace ( + char *start_arg, + char *depth_arg); + +void +acpi_db_dump_namespace_by_owner ( + char *owner_arg, + char *depth_arg); + +void +acpi_db_send_notify ( + char *name, + u32 value); + +void +acpi_db_set_method_data ( + char *type_arg, + char *index_arg, + char *value_arg); + +ACPI_STATUS +acpi_db_display_objects ( + char *obj_type_arg, + char *display_count_arg); + +ACPI_STATUS +acpi_db_find_name_in_namespace ( + char *name_arg); + +void +acpi_db_set_scope ( + char *name); + +void +acpi_db_find_references ( + char *object_arg); + + +/* + * dbdisasm - AML disassembler + */ + +void +acpi_db_display_op ( + ACPI_GENERIC_OP *origin, + u32 num_opcodes); + +void +acpi_db_display_namestring ( + char *name); + +void +acpi_db_display_path ( + ACPI_GENERIC_OP *op); + +void +acpi_db_display_opcode ( + ACPI_GENERIC_OP *op); + + +/* + * dbdisply - debug display commands + */ + + +void +acpi_db_display_method_info ( + ACPI_GENERIC_OP *op); + +void +acpi_db_decode_and_display_object ( + char *target, + char *output_type); + +void +acpi_db_display_result_object ( + ACPI_OBJECT_INTERNAL *ret_desc); + +ACPI_STATUS +acpi_db_display_all_methods ( + char *display_count_arg); + +void +acpi_db_display_internal_object ( + ACPI_OBJECT_INTERNAL *obj_desc); + +void +acpi_db_display_arguments ( + void); + +void +acpi_db_display_locals ( + void); + +void +acpi_db_display_results ( + void); + +void +acpi_db_display_calling_tree ( + void); + +void +acpi_db_display_argument_object ( + ACPI_OBJECT_INTERNAL *obj_desc); + + +/* + * dbexec - debugger control method execution + */ + +void +acpi_db_execute ( + char *name, + char **args, + u32 flags); + +void +acpi_db_create_execution_threads ( + char *num_threads_arg, + char *num_loops_arg, + char *method_name_arg); + + +/* + * dbfileio - Debugger file I/O commands + */ + +OBJECT_TYPE_INTERNAL +acpi_db_match_argument ( + char *user_argument, + ARGUMENT_INFO *arguments); + + +void +acpi_db_close_debug_file ( + void); + +void +acpi_db_open_debug_file ( + char *name); + +ACPI_STATUS +acpi_db_load_acpi_table ( + char *filename); + + +/* + * dbhistry - debugger HISTORY command + */ + +void +acpi_db_add_to_history ( + char *command_line); + +void +acpi_db_display_history (void); + +char * +acpi_db_get_from_history ( + char *command_num_arg); + + +/* + * dbinput - user front-end to the AML debugger + */ + +ACPI_STATUS +acpi_db_command_dispatch ( + char *input_buffer, + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op); + +void +acpi_db_execute_thread ( + void *context); + +ACPI_STATUS +acpi_db_user_commands ( + char prompt, + ACPI_GENERIC_OP *op); + + +/* + * dbstats - Generation and display of ACPI table statistics + */ + +void +acpi_db_generate_statistics ( + ACPI_GENERIC_OP *root, + u8 is_method); + + +ACPI_STATUS +acpi_db_display_statistics ( + char *type_arg); + + +/* + * dbutils - AML debugger utilities + */ + +void +acpi_db_set_output_destination ( + s32 where); + +void +acpi_db_dump_buffer ( + u32 address); + +void +acpi_db_dump_object ( + ACPI_OBJECT *obj_desc, + u32 level); + +void +acpi_db_prep_namestring ( + char *name); + + +ACPI_STATUS +acpi_db_second_pass_parse ( + ACPI_GENERIC_OP *root); + +ACPI_NAMED_OBJECT* +acpi_db_local_ns_lookup ( + char *name); + + +#endif /* __DEBUGGER_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/dispatch.h linux/drivers/acpi/include/dispatch.h --- v2.4.0-test2/linux/drivers/acpi/include/dispatch.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/dispatch.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,383 @@ +/****************************************************************************** + * + * Module Name: dispatch.h + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _DISPATCH_H_ +#define _DISPATCH_H_ + + +#define NAMEOF_LOCAL_NTE "__L0" +#define NAMEOF_ARG_NTE "__A0" + + +/* For Acpi_ds_method_data_set_value */ + +#define MTH_TYPE_LOCAL 0 +#define MTH_TYPE_ARG 1 + + +/* Common interfaces */ + +ACPI_STATUS +acpi_ds_obj_stack_push ( + void *object, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_obj_stack_pop ( + u32 pop_count, + ACPI_WALK_STATE *walk_state); + +void * +acpi_ds_obj_stack_get_value ( + u32 index, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_obj_stack_pop_object ( + ACPI_OBJECT_INTERNAL **object, + ACPI_WALK_STATE *walk_state); + + +/* dsregion - Op region support */ + +ACPI_STATUS +acpi_ds_get_region_arguments ( + ACPI_OBJECT_INTERNAL *rgn_desc); + + +/* dsctrl - Parser/Interpreter interface, control stack routines */ + +/* +ACPI_CTRL_STATE * +Acpi_ds_create_control_state (void); + +void +Acpi_ds_push_control_state ( + ACPI_CTRL_STATE *Control_state, + ACPI_WALK_STATE *Walk_state); + +ACPI_CTRL_STATE * +Acpi_ds_pop_control_state ( + ACPI_WALK_STATE *Walk_state); +*/ + +ACPI_STATUS +acpi_ds_exec_begin_control_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op); + +ACPI_STATUS +acpi_ds_exec_end_control_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op); + + +/* dsexec - Parser/Interpreter interface, method execution callbacks */ + +ACPI_STATUS +acpi_ds_exec_begin_op ( + ACPI_WALK_STATE *state, + ACPI_GENERIC_OP *op); + +ACPI_STATUS +acpi_ds_exec_end_op ( + ACPI_WALK_STATE *state, + ACPI_GENERIC_OP *op); + + +/* dsfield - Parser/Interpreter interface for AML fields */ + + +ACPI_STATUS +acpi_ds_create_field ( + ACPI_GENERIC_OP *op, + ACPI_HANDLE region, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_create_bank_field ( + ACPI_GENERIC_OP *op, + ACPI_HANDLE region, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_create_index_field ( + ACPI_GENERIC_OP *op, + ACPI_HANDLE region, + ACPI_WALK_STATE *walk_state); + + +/* dsload - Parser/Interpreter interface, namespace load callbacks */ + +ACPI_STATUS +acpi_ds_load1_begin_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op); + +ACPI_STATUS +acpi_ds_load1_end_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op); + +ACPI_STATUS +acpi_ds_load2_begin_op ( + ACPI_WALK_STATE *state, + ACPI_GENERIC_OP *op); + +ACPI_STATUS +acpi_ds_load2_end_op ( + ACPI_WALK_STATE *state, + ACPI_GENERIC_OP *op); + + +/* dsmthdat - method data (locals/args) */ + + +ACPI_STATUS +acpi_ds_method_data_delete_all ( + ACPI_WALK_STATE *walk_state); + +u8 +acpi_ds_is_method_value ( + ACPI_OBJECT_INTERNAL *obj_desc); + +OBJECT_TYPE_INTERNAL +acpi_ds_method_data_get_type ( + u32 type, + u32 index); + +ACPI_STATUS +acpi_ds_method_data_get_value ( + u32 type, + u32 index, + ACPI_OBJECT_INTERNAL **obj_desc); + +ACPI_STATUS +acpi_ds_method_data_set_value ( + u32 type, + u32 index, + ACPI_OBJECT_INTERNAL *obj_desc); + +ACPI_STATUS +acpi_ds_method_data_delete_value ( + u32 type, + u32 index); + +ACPI_STATUS +acpi_ds_method_data_init_args ( + ACPI_OBJECT_INTERNAL **params, + u32 param_count); + +ACPI_NAMED_OBJECT* +acpi_ds_method_data_get_nte ( + u32 type, + u32 index); + +ACPI_STATUS +acpi_ds_method_data_init ( + ACPI_WALK_STATE *walk_state); + + +/* dsmethod - Parser/Interpreter interface - control method parsing */ + +ACPI_STATUS +acpi_ds_parse_method ( + ACPI_HANDLE obj_handle); + +ACPI_STATUS +acpi_ds_call_control_method ( + ACPI_WALK_LIST *walk_list, + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op); + +ACPI_STATUS +acpi_ds_restart_control_method ( + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL *return_desc); + +ACPI_STATUS +acpi_ds_terminate_control_method ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_begin_method_execution ( + ACPI_NAMED_OBJECT *method_entry, + ACPI_OBJECT_INTERNAL *obj_desc); + + +/* dsobj - Parser/Interpreter interface - object initialization and conversion */ + +ACPI_STATUS +acpi_ds_init_one_object ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value); + +ACPI_STATUS +acpi_ds_initialize_objects ( + ACPI_TABLE_DESC *table_desc, + ACPI_NAMED_OBJECT *start_entry); + +ACPI_STATUS +acpi_ds_build_internal_package_obj ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op, + ACPI_OBJECT_INTERNAL **obj_desc); + +ACPI_STATUS +acpi_ds_build_internal_object ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op, + ACPI_OBJECT_INTERNAL **obj_desc_ptr); + +ACPI_STATUS +acpi_ds_init_object_from_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op, + u16 opcode, + ACPI_OBJECT_INTERNAL *obj_desc); + +ACPI_STATUS +acpi_ds_create_named_object ( + ACPI_WALK_STATE *walk_state, + ACPI_NAMED_OBJECT *entry, + ACPI_GENERIC_OP *op); + + +/* dsregn - Parser/Interpreter interface - Op Region parsing */ + +ACPI_STATUS +acpi_ds_eval_region_operands ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op); + +ACPI_STATUS +acpi_ds_initialize_region ( + ACPI_HANDLE obj_handle); + + +/* dsutils - Parser/Interpreter interface utility routines */ + +void +acpi_ds_delete_result_if_not_used ( + ACPI_GENERIC_OP *op, + ACPI_OBJECT_INTERNAL *result_obj, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_create_operand ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *arg); + +ACPI_STATUS +acpi_ds_create_operands ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *first_arg); + +ACPI_STATUS +acpi_ds_resolve_operands ( + ACPI_WALK_STATE *walk_state); + +OBJECT_TYPE_INTERNAL +acpi_ds_map_opcode_to_data_type ( + u16 opcode, + u32 *out_flags); + +OBJECT_TYPE_INTERNAL +acpi_ds_map_named_opcode_to_data_type ( + u16 opcode); + + +/* + * dswscope - Scope Stack manipulation + */ + +ACPI_STATUS +acpi_ds_scope_stack_push ( + ACPI_NAME_TABLE *new_scope, + OBJECT_TYPE_INTERNAL type, + ACPI_WALK_STATE *walk_state); + + +ACPI_STATUS +acpi_ds_scope_stack_pop ( + ACPI_WALK_STATE *walk_state); + +void +acpi_ds_scope_stack_clear ( + ACPI_WALK_STATE *walk_state); + + +/* Acpi_dswstate - parser WALK_STATE management routines */ + +ACPI_WALK_STATE * +acpi_ds_create_walk_state ( + ACPI_OWNER_ID owner_id, + ACPI_GENERIC_OP *origin, + ACPI_OBJECT_INTERNAL *mth_desc, + ACPI_WALK_LIST *walk_list); + +ACPI_STATUS +acpi_ds_obj_stack_delete_all ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_obj_stack_pop_and_delete ( + u32 pop_count, + ACPI_WALK_STATE *walk_state); + +void +acpi_ds_delete_walk_state ( + ACPI_WALK_STATE *walk_state); + +ACPI_WALK_STATE * +acpi_ds_pop_walk_state ( + ACPI_WALK_LIST *walk_list); + +ACPI_STATUS +acpi_ds_result_stack_pop ( + ACPI_OBJECT_INTERNAL **object, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_result_stack_push ( + void *object, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_result_stack_clear ( + ACPI_WALK_STATE *walk_state); + +ACPI_WALK_STATE * +acpi_ds_get_current_walk_state ( + ACPI_WALK_LIST *walk_list); + +void +acpi_ds_delete_walk_state_cache ( + void); + + +#endif /* _DISPATCH_H_ */ \ No newline at end of file diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/events.h linux/drivers/acpi/include/events.h --- v2.4.0-test2/linux/drivers/acpi/include/events.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/events.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,209 @@ + +/****************************************************************************** + * + * Name: events.h - Acpi_event subcomponent prototypes and defines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __EVENTS_H__ +#define __EVENTS_H__ + + +/* + * Acpi_evfixed - Fixed event handling + */ + +ACPI_STATUS +acpi_ev_fixed_event_initialize ( + void); + +u32 +acpi_ev_fixed_event_detect ( + void); + +u32 +acpi_ev_fixed_event_dispatch ( + u32 acpi_event); + + +/* + * Acpi_evglock - Global Lock support + */ + +ACPI_STATUS +acpi_ev_acquire_global_lock( + void); + +void +acpi_ev_release_global_lock( + void); + +ACPI_STATUS +acpi_ev_init_global_lock_handler ( + void); + + +/* + * Acpi_evgpe - GPE handling and dispatch + */ + +ACPI_STATUS +acpi_ev_gpe_initialize ( + void); + +ACPI_STATUS +acpi_ev_init_gpe_control_methods ( + void); + +u32 +acpi_ev_gpe_dispatch ( + u32 gpe_number); + +u32 +acpi_ev_gpe_detect ( + void); + + +/* + * Acpi_evnotify - Device Notify handling and dispatch + */ + +void +acpi_ev_notify_dispatch ( + ACPI_HANDLE device, + u32 notify_value); + + +/* + * Acpi_evregion - Address Space handling + */ + +ACPI_STATUS +acpi_ev_install_default_address_space_handlers ( + void); + +ACPI_STATUS +acpi_ev_address_space_dispatch ( + ACPI_OBJECT_INTERNAL *region_obj, + u32 function, + u32 address, + u32 bit_width, + u32 *value); + + +ACPI_STATUS +acpi_ev_addr_handler_helper ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value); + +void +acpi_ev_disassociate_region_from_handler( + ACPI_OBJECT_INTERNAL *region_obj); + + +ACPI_STATUS +acpi_ev_associate_region_and_handler( + ACPI_OBJECT_INTERNAL *handler_obj, + ACPI_OBJECT_INTERNAL *region_obj); + + +/* + * Acpi_evregini - Region initialization and setup + */ + +ACPI_STATUS +acpi_ev_system_memory_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **return_context); + +ACPI_STATUS +acpi_ev_io_space_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **return_context); + +ACPI_STATUS +acpi_ev_pci_config_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **return_context); + +ACPI_STATUS +acpi_ev_default_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **return_context); + +ACPI_STATUS +acpi_ev_initialize_region ( + ACPI_OBJECT_INTERNAL *region_obj, + u8 acpi_ns_locked); + + +/* + * Acpi_evsci - SCI (System Control Interrupt) handling/dispatch + */ + +u32 +acpi_ev_install_sci_handler ( + void); + +ACPI_STATUS +acpi_ev_remove_sci_handler ( + void); + +s32 +acpi_ev_initialize_sCI ( + s32 program_sCI); + +void +acpi_ev_restore_acpi_state ( + void); + +void +acpi_ev_terminate ( + void); + + +/* Debug support */ + +#ifdef ACPI_DEBUG + +s32 +acpi_ev_sci_count ( + u32 acpi_event); + +#define DEBUG_INCREMENT_EVENT_COUNT(a) acpi_gbl_event_count[a]++; + +#else + +#define DEBUG_INCREMENT_EVENT_COUNT(a) +#endif + + +#endif /* __EVENTS_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/globals.h linux/drivers/acpi/include/globals.h --- v2.4.0-test2/linux/drivers/acpi/include/globals.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/globals.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,311 @@ + +/****************************************************************************** + * + * Name: globals.h - Declarations for global variables + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GLOBALS_H__ +#define __GLOBALS_H__ + + +/* + * Ensure that the globals are actually defined only once + */ +#ifdef DEFINE_ACPI_GLOBALS +#define ACPI_EXTERN +#else +#define ACPI_EXTERN extern +#endif + + +extern char *msg_acpi_error_break; + +/***************************************************************************** + * + * Debug support + * + ****************************************************************************/ + +/* Runtime configuration of debug print levels */ + +extern u32 acpi_dbg_level; +extern u32 acpi_dbg_layer; + + +/* Procedure nesting level for debug output */ + +extern u32 acpi_gbl_nesting_level; + + +/***************************************************************************** + * + * ACPI Table globals + * + ****************************************************************************/ + +/* + * Table pointers. + * Although these pointers are somewhat redundant with the global Acpi_table, + * they are convenient because they are typed pointers. + * + * These tables are single-table only; meaning that there can be at most one + * of each in the system. Each global points to the actual table. + * + */ +ACPI_EXTERN ROOT_SYSTEM_DESCRIPTOR_POINTER *acpi_gbl_RSDP; +ACPI_EXTERN ROOT_SYSTEM_DESCRIPTION_TABLE *acpi_gbl_RSDT; +ACPI_EXTERN FIRMWARE_ACPI_CONTROL_STRUCTURE *acpi_gbl_FACS; +ACPI_EXTERN FIXED_ACPI_DESCRIPTION_TABLE *acpi_gbl_FACP; +ACPI_EXTERN APIC_TABLE *acpi_gbl_APIC; +ACPI_EXTERN ACPI_TABLE_HEADER *acpi_gbl_DSDT; +ACPI_EXTERN ACPI_TABLE_HEADER *acpi_gbl_SBST; +/* + * Since there may be multiple SSDTs and PSDTS, a single pointer is not + * sufficient; Therefore, there isn't one! + */ + + +/* + * ACPI Table info arrays + */ +extern ACPI_TABLE_DESC acpi_gbl_acpi_tables[NUM_ACPI_TABLES]; +extern ACPI_TABLE_SUPPORT acpi_gbl_acpi_table_data[NUM_ACPI_TABLES]; + +/* + * Predefined mutex objects. This array contains the + * actual OS mutex handles, indexed by the local ACPI_MUTEX_HANDLEs. + * (The table maps local handles to the real OS handles) + */ +ACPI_EXTERN ACPI_MUTEX_INFO acpi_gbl_acpi_mutex_info [NUM_MTX]; +extern ACPI_INIT_DATA acpi_gbl_acpi_init_data; + + +/***************************************************************************** + * + * Miscellaneous globals + * + ****************************************************************************/ + + +ACPI_EXTERN u8 *acpi_gbl_gpe0enable_register_save; +ACPI_EXTERN u8 *acpi_gbl_gpe1_enable_register_save; +ACPI_EXTERN ACPI_WALK_STATE *acpi_gbl_breakpoint_walk; +ACPI_EXTERN ACPI_GENERIC_STATE *acpi_gbl_generic_state_cache; +ACPI_EXTERN ACPI_GENERIC_OP *acpi_gbl_parse_cache; +ACPI_EXTERN ACPI_OBJECT_INTERNAL *acpi_gbl_object_cache; +ACPI_EXTERN ACPI_WALK_STATE *acpi_gbl_walk_state_cache; +ACPI_EXTERN ACPI_HANDLE acpi_gbl_global_lock_semaphore; + + +ACPI_EXTERN u32 acpi_gbl_global_lock_thread_count; +ACPI_EXTERN u32 acpi_gbl_restore_acpi_chipset; +ACPI_EXTERN u32 acpi_gbl_original_mode; +ACPI_EXTERN u32 acpi_gbl_edge_level_save; +ACPI_EXTERN u32 acpi_gbl_irq_enable_save; +ACPI_EXTERN u32 acpi_gbl_rsdp_original_location; + +ACPI_EXTERN u32 acpi_gbl_state_cache_requests; +ACPI_EXTERN u32 acpi_gbl_state_cache_hits; +ACPI_EXTERN u32 acpi_gbl_parse_cache_requests; +ACPI_EXTERN u32 acpi_gbl_parse_cache_hits; +ACPI_EXTERN u32 acpi_gbl_object_cache_requests; +ACPI_EXTERN u32 acpi_gbl_object_cache_hits; +ACPI_EXTERN u32 acpi_gbl_walk_state_cache_requests; +ACPI_EXTERN u32 acpi_gbl_walk_state_cache_hits; +ACPI_EXTERN u32 acpi_gbl_ns_lookup_count; +ACPI_EXTERN u32 acpi_gbl_ps_find_count; + + +ACPI_EXTERN u16 acpi_gbl_generic_state_cache_depth; +ACPI_EXTERN u16 acpi_gbl_parse_cache_depth; +ACPI_EXTERN u16 acpi_gbl_object_cache_depth; +ACPI_EXTERN u16 acpi_gbl_walk_state_cache_depth; +ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save; +ACPI_EXTERN u16 acpi_gbl_next_table_owner_id; +ACPI_EXTERN u16 acpi_gbl_next_method_owner_id; + +ACPI_EXTERN u8 acpi_gbl_debugger_configuration; +ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; +ACPI_EXTERN u8 acpi_gbl_global_lock_set; /* TBD: [Restructure] OBSOLETE?? */ +ACPI_EXTERN u8 acpi_gbl_step_to_next_call; +ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; + + +ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER acpi_gbl_drv_notify; +ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER acpi_gbl_sys_notify; + + +extern u8 acpi_gbl_shutdown; +extern u32 acpi_gbl_system_flags; +extern u32 acpi_gbl_startup_flags; + + +/***************************************************************************** + * + * Namespace globals + * + ****************************************************************************/ + +#define NUM_NS_TYPES INTERNAL_TYPE_INVALID+1 +#define NUM_PREDEFINED_NAMES 9 + + +ACPI_EXTERN ACPI_NAME_TABLE acpi_gbl_root_name_table; +ACPI_EXTERN ACPI_NAMED_OBJECT *acpi_gbl_root_object; + +extern u8 acpi_gbl_ns_properties[NUM_NS_TYPES]; +extern PREDEFINED_NAMES acpi_gbl_pre_defined_names [NUM_PREDEFINED_NAMES]; + + +/* Used to detect memory leaks (DEBUG ONLY) */ + +#ifdef ACPI_DEBUG +ACPI_EXTERN ALLOCATION_INFO *acpi_gbl_head_alloc_ptr; +ACPI_EXTERN ALLOCATION_INFO *acpi_gbl_tail_alloc_ptr; +#endif + + +/***************************************************************************** + * + * Interpreter globals + * + ****************************************************************************/ + + +ACPI_EXTERN u32 acpi_gbl_when_to_parse_methods; +ACPI_EXTERN ACPI_WALK_LIST *acpi_gbl_current_walk_list; + +/* Base of AML block, and pointer to current location in it */ + +ACPI_EXTERN u8 *acpi_gbl_Pcode_base; +ACPI_EXTERN u8 *acpi_gbl_Pcode; + +/* + * Length of AML block, and remaining length of current package. + */ +ACPI_EXTERN u32 acpi_gbl_Pcode_block_len; +ACPI_EXTERN u32 acpi_gbl_Pcode_len; + +ACPI_EXTERN u32 acpi_gbl_buf_seq; /* Counts allocated Buffer descriptors */ +ACPI_EXTERN s32 acpi_gbl_named_object_err; /* Indicate if inc_error should be called */ + +/* + * Handle to the last method found - used during pass1 of load + */ +ACPI_EXTERN ACPI_HANDLE acpi_gbl_last_method; + +/* + * Table of Address Space handlers + */ + +ACPI_EXTERN ACPI_ADDRESS_SPACE_INFO acpi_gbl_address_spaces[ACPI_NUM_ADDRESS_SPACES]; + + +/* Control method single step flag */ + +ACPI_EXTERN u8 acpi_gbl_cm_single_step; + + +/***************************************************************************** + * + * Parser globals + * + ****************************************************************************/ + +ACPI_EXTERN ACPI_GENERIC_OP *acpi_gbl_parsed_namespace_root; + +extern ACPI_OP_INFO acpi_gbl_aml_op_info[]; +extern u8 acpi_gbl_aml_op_info_index[256]; +extern char *acpi_gbl_parser_id; + + +/***************************************************************************** + * + * Hardware globals + * + ****************************************************************************/ + +extern ACPI_C_STATE_HANDLER acpi_hw_cx_handlers[MAX_CX_STATES]; +extern u32 acpi_hw_active_cx_state; + + +/***************************************************************************** + * + * Event globals + * + ****************************************************************************/ + +ACPI_EXTERN ACPI_FIXED_EVENT_INFO acpi_gbl_fixed_event_handlers[NUM_FIXED_EVENTS]; + +ACPI_EXTERN ACPI_HANDLE acpi_gbl_gpe_obj_handle; +ACPI_EXTERN u32 acpi_gbl_gpe_register_count; +ACPI_EXTERN ACPI_GPE_REGISTERS *acpi_gbl_gpe_registers; +ACPI_EXTERN ACPI_GPE_LEVEL_INFO *acpi_gbl_gpe_info; + +/* + * Gpe validation and translation table + * Indexed by the GPE number, returns GPE_INVALID if the GPE is not supported. + * Otherwise, returns a valid index into the global GPE table. + * + * This table is needed because the GPE numbers supported by block 1 do not + * have to be contiguous with the GPE numbers supported by block 0. + */ +ACPI_EXTERN u8 acpi_gbl_gpe_valid [NUM_GPE]; + +/* Acpi_event counter for debug only */ + +#ifdef ACPI_DEBUG +ACPI_EXTERN u32 acpi_gbl_event_count[NUM_FIXED_EVENTS]; +#endif + + +/***************************************************************************** + * + * Debugger globals + * + ****************************************************************************/ + +ACPI_EXTERN u8 acpi_gbl_method_executing; +ACPI_EXTERN u8 acpi_gbl_db_terminate_threads; + + +/* Memory allocation metrics - Debug Only! */ + +#ifdef ACPI_DEBUG + +ACPI_EXTERN u32 acpi_gbl_current_alloc_size; +ACPI_EXTERN u32 acpi_gbl_current_alloc_count; +ACPI_EXTERN u32 acpi_gbl_running_alloc_size; +ACPI_EXTERN u32 acpi_gbl_running_alloc_count; +ACPI_EXTERN u32 acpi_gbl_max_concurrent_alloc_size; +ACPI_EXTERN u32 acpi_gbl_max_concurrent_alloc_count; +ACPI_EXTERN u32 acpi_gbl_current_object_count; +ACPI_EXTERN u32 acpi_gbl_current_object_size; +ACPI_EXTERN u32 acpi_gbl_max_concurrent_object_count; +ACPI_EXTERN u32 acpi_gbl_max_concurrent_object_size; +ACPI_EXTERN u32 acpi_gbl_running_object_count; +ACPI_EXTERN u32 acpi_gbl_running_object_size; + +#endif + + +#endif /* __GLOBALS_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/hardware.h linux/drivers/acpi/include/hardware.h --- v2.4.0-test2/linux/drivers/acpi/include/hardware.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/hardware.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,169 @@ + +/****************************************************************************** + * + * Name: hardware.h -- hardware specific interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __HARDWARE_H__ +#define __HARDWARE_H__ + + +/* Prototypes */ + + +ACPI_STATUS +acpi_hw_initialize( + void); + +ACPI_STATUS +acpi_hw_shutdown( + void); + +ACPI_STATUS +acpi_hw_initialize_system_info( + void); + +ACPI_STATUS +acpi_hw_set_mode ( + u32 mode); + +u32 +acpi_hw_get_mode ( + void); + +u32 +acpi_hw_get_mode_capabilities ( + void); + +/* Register I/O Prototypes */ + +u32 +acpi_hw_register_access ( + NATIVE_UINT read_write, + u8 use_lock, + u32 register_id, ... /* DWORD Value */); + +void +acpi_hw_clear_acpi_status ( + void); + + +/* GPE support */ + +void +acpi_hw_enable_gpe ( + u32 gpe_index); + +void +acpi_hw_disable_gpe ( + u32 gpe_index); + +void +acpi_hw_clear_gpe ( + u32 gpe_index); + +void +acpi_hw_get_gpe_status ( + u32 gpe_number, + ACPI_EVENT_STATUS *event_status); + +/* Sleep Prototypes */ + +ACPI_STATUS +acpi_hw_obtain_sleep_type_register_data ( + u8 sleep_state, + u8 *slp_typ_a, + u8 *slp_typ_b); + + +/* Cx State Prototypes */ + +ACPI_STATUS +acpi_hw_enter_c1( + ACPI_IO_ADDRESS pblk_address, + u32 *pm_timer_ticks); + +ACPI_STATUS +acpi_hw_enter_c2( + ACPI_IO_ADDRESS pblk_address, + u32 *pm_timer_ticks); + +ACPI_STATUS +acpi_hw_enter_c3( + ACPI_IO_ADDRESS pblk_address, + u32 *pm_timer_ticks); + +ACPI_STATUS +acpi_hw_enter_cx ( + ACPI_IO_ADDRESS pblk_address, + u32 *pm_timer_ticks); + +ACPI_STATUS +acpi_hw_set_cx ( + u32 cx_state); + +ACPI_STATUS +acpi_hw_get_cx_info ( + u32 cx_states[]); + + +/* Throttling Prototypes */ + +void +acpi_hw_enable_throttling ( + ACPI_IO_ADDRESS pblk_address); + +void +acpi_hw_disable_throttling ( + ACPI_IO_ADDRESS pblk_address); + +u32 +acpi_hw_get_duty_cycle ( + u8 duty_offset, + ACPI_IO_ADDRESS pblk_address, + u32 num_throttle_states); + +void +acpi_hw_program_duty_cycle ( + u8 duty_offset, + u32 duty_cycle, + ACPI_IO_ADDRESS pblk_address, + u32 num_throttle_states); + +NATIVE_UINT +acpi_hw_local_pow ( + NATIVE_UINT x, + NATIVE_UINT y); + + +/* ACPI Timer prototypes */ + +u32 +acpi_hw_pmt_ticks ( + void); + +u32 +acpi_hw_pmt_resolution ( + void); + + +#endif /* __HARDWARE_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/internal.h linux/drivers/acpi/include/internal.h --- v2.4.0-test2/linux/drivers/acpi/include/internal.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/internal.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,850 @@ + +/****************************************************************************** + * + * Name: internal.h - Internal data types used across the ACPI subsystem + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ACPI_INTERNAL_H +#define _ACPI_INTERNAL_H + +#include "config.h" + + +#define WAIT_FOREVER ((u32) -1) + +typedef void* ACPI_MUTEX; +typedef u32 ACPI_MUTEX_HANDLE; + + +/* Object descriptor types */ + +#define ACPI_DESC_TYPE_INTERNAL 0xAA +#define ACPI_DESC_TYPE_PARSER 0xBB +#define ACPI_DESC_TYPE_STATE 0xCC +#define ACPI_DESC_TYPE_WALK 0xDD +#define ACPI_DESC_TYPE_NAMED 0xEE + + +/***************************************************************************** + * + * Mutex typedefs and structs + * + ****************************************************************************/ + + +/* + * Predefined handles for the mutex objects used within the subsystem + * All mutex objects are automatically created by Acpi_cm_mutex_initialize. + * NOTE: any changes here must be reflected in the Acpi_gbl_Mutex_names table also! + */ + +#define ACPI_MTX_HARDWARE 0 +#define ACPI_MTX_MEMORY 1 +#define ACPI_MTX_CACHES 2 +#define ACPI_MTX_TABLES 3 +#define ACPI_MTX_PARSER 4 +#define ACPI_MTX_DISPATCHER 5 +#define ACPI_MTX_INTERPRETER 6 +#define ACPI_MTX_EXECUTE 7 +#define ACPI_MTX_NAMESPACE 8 +#define ACPI_MTX_EVENTS 9 +#define ACPI_MTX_OP_REGIONS 10 +#define ACPI_MTX_DEBUG_CMD_READY 11 +#define ACPI_MTX_DEBUG_CMD_COMPLETE 12 + +#define MAX_MTX 12 +#define NUM_MTX MAX_MTX+1 + + +#ifdef ACPI_DEBUG +#ifdef DEFINE_ACPI_GLOBALS + +/* Names for the mutexes used in the subsystem */ + +static char *acpi_gbl_mutex_names[] = +{ + "ACPI_MTX_Hardware", + "ACPI_MTX_Memory", + "ACPI_MTX_Caches", + "ACPI_MTX_Tables", + "ACPI_MTX_Parser", + "ACPI_MTX_Dispatcher", + "ACPI_MTX_Interpreter", + "ACPI_MTX_Execute", + "ACPI_MTX_Namespace", + "ACPI_MTX_Events", + "ACPI_MTX_Op_regions", + "ACPI_MTX_Debug_cmd_ready", + "ACPI_MTX_Debug_cmd_complete" +}; + +#endif +#endif + + +/* Table for the global mutexes */ + +typedef struct acpi_mutex_info +{ + ACPI_MUTEX mutex; + u32 use_count; + u8 locked; + +} ACPI_MUTEX_INFO; + + +/* Lock flag parameter for various interfaces */ + +#define ACPI_MTX_DO_NOT_LOCK 0 +#define ACPI_MTX_LOCK 1 + + +typedef u16 ACPI_OWNER_ID; +#define OWNER_TYPE_TABLE 0x0 +#define OWNER_TYPE_METHOD 0x1 +#define FIRST_METHOD_ID 0x0000 +#define FIRST_TABLE_ID 0x8000 + +/* TBD: [Restructure] get rid of the need for this! */ + +#define TABLE_ID_DSDT (ACPI_OWNER_ID) 0xD1D1 + +/***************************************************************************** + * + * Namespace typedefs and structs + * + ****************************************************************************/ + + +/* Operational modes of the AML interpreter/scanner */ + +typedef enum +{ + IMODE_LOAD_PASS1 = 0x01, + IMODE_LOAD_PASS2 = 0x02, + IMODE_EXECUTE = 0x0E + +} OPERATING_MODE; + + +/* + * The Acpi_named_object describes a named object that appears in the AML + * An Acpi_name_table is used to store Acpi_named_objects. + * + * Data_type is used to differentiate between internal descriptors, and MUST + * be the first byte in this structure. + */ + +typedef struct acpi_named_object +{ + u8 data_type; + u8 type; /* Type associated with this name */ + u8 this_index; /* Entry number */ + u8 flags; + u32 name; /* ACPI Name, always 4 chars per ACPI spec */ + + + void *object; /* Pointer to attached ACPI object (optional) */ + struct acpi_name_table *child_table; /* Scope owned by this name (optional) */ + ACPI_OWNER_ID owner_id; /* ID of owner - either an ACPI table or a method */ + u16 reference_count; /* Current count of references and children */ + +#ifdef _IA64 + u32 fill1; /* 64-bit alignment */ +#endif + +} ACPI_NAMED_OBJECT; + + +typedef struct acpi_name_table +{ + struct acpi_name_table *next_table; + struct acpi_name_table *parent_table; + ACPI_NAMED_OBJECT *parent_entry; + ACPI_NAMED_OBJECT entries[1]; + +} ACPI_NAME_TABLE; + + +#define ENTRY_NOT_FOUND NULL + + +/* NTE flags */ + +#define NTE_AML_ATTACHMENT 0x1 + + +/* + * ACPI Table Descriptor. One per ACPI table + */ +typedef struct acpi_table_desc +{ + struct acpi_table_desc *prev; + struct acpi_table_desc *next; + struct acpi_table_desc *installed_desc; + ACPI_TABLE_HEADER *pointer; + void *base_pointer; + u8 *aml_pointer; + u32 aml_length; + u32 length; + u32 count; + ACPI_OWNER_ID table_id; + u8 type; + u8 allocation; + u8 loaded_into_namespace; + +} ACPI_TABLE_DESC; + + +typedef struct +{ + char *search_for; + ACPI_HANDLE *list; + s32 *count; + +} FIND_CONTEXT; + + +typedef struct +{ + ACPI_NAME_TABLE *name_table; + u32 position; + u8 table_full; + +} NS_SEARCH_DATA; + + +/* + * Predefined Namespace items + */ +#define ACPI_MAX_ADDRESS_SPACE 255 +#define ACPI_NUM_ADDRESS_SPACES 256 + + +typedef struct +{ + char *name; + ACPI_OBJECT_TYPE type; + char *val; + +} PREDEFINED_NAMES; + + +/***************************************************************************** + * + * Event typedefs and structs + * + ****************************************************************************/ + + +/* Status bits. */ + +#define ACPI_STATUS_PMTIMER 0x0001 +#define ACPI_STATUS_GLOBAL 0x0020 +#define ACPI_STATUS_POWER_BUTTON 0x0100 +#define ACPI_STATUS_SLEEP_BUTTON 0x0200 +#define ACPI_STATUS_RTC_ALARM 0x0400 + +/* Enable bits. */ + +#define ACPI_ENABLE_PMTIMER 0x0001 +#define ACPI_ENABLE_GLOBAL 0x0020 +#define ACPI_ENABLE_POWER_BUTTON 0x0100 +#define ACPI_ENABLE_SLEEP_BUTTON 0x0200 +#define ACPI_ENABLE_RTC_ALARM 0x0400 + + +/* + * Entry in the Address_space (AKA Operation Region) table + */ + +typedef struct +{ + ADDRESS_SPACE_HANDLER handler; + void *context; + +} ACPI_ADDRESS_SPACE_INFO; + + +/* Values and addresses of the GPE registers (both banks) */ + +typedef struct +{ + u8 status; /* Current value of status reg */ + u8 enable; /* Current value of enable reg */ + u16 status_addr; /* Address of status reg */ + u16 enable_addr; /* Address of enable reg */ + u8 gpe_base; /* Base GPE number */ + +} ACPI_GPE_REGISTERS; + + +#define ACPI_GPE_LEVEL_TRIGGERED 1 +#define ACPI_GPE_EDGE_TRIGGERED 2 + + +/* Information about each particular GPE level */ + +typedef struct +{ + u8 type; /* Level or Edge */ + + ACPI_HANDLE method_handle; /* Method handle for direct (fast) execution */ + GPE_HANDLER handler; /* Address of handler, if any */ + void *context; /* Context to be passed to handler */ + +} ACPI_GPE_LEVEL_INFO; + + +/* Information about each particular fixed event */ + +typedef struct +{ + FIXED_EVENT_HANDLER handler; /* Address of handler. */ + void *context; /* Context to be passed to handler */ + +} ACPI_FIXED_EVENT_INFO; + + +/* Information used during field processing */ + +typedef struct +{ + u8 skip_field; + u8 field_flag; + u32 pkg_length; + +} ACPI_FIELD_INFO; + + +/***************************************************************************** + * + * Parser typedefs and structs + * + ****************************************************************************/ + + +#define OP_INFO_TYPE 0x1F +#define OP_INFO_HAS_ARGS 0x20 +#define OP_INFO_CHILD_LOCATION 0xC0 + +/* + * AML opcode, name, and argument layout + */ +typedef struct acpi_op_info +{ + u16 opcode; /* AML opcode */ + u8 flags; /* Opcode type, Has_args flag */ + u32 parse_args; /* Grammar/Parse time arguments */ + u32 runtime_args; /* Interpret time arguments */ + + DEBUG_ONLY_MEMBERS ( + char *name) /* op name (debug only) */ + +} ACPI_OP_INFO; + + +typedef union acpi_op_value +{ + u32 integer; /* integer constant */ + u32 size; /* bytelist or field size */ + char *string; /* NULL terminated string */ + u8 *buffer; /* buffer or string */ + char *name; /* NULL terminated string */ + struct acpi_generic_op *arg; /* arguments and contained ops */ + ACPI_NAMED_OBJECT *entry; /* entry in interpreter namespace tbl */ + +} ACPI_OP_VALUE; + + +#define ACPI_COMMON_OP \ + u8 data_type; /* To differentiate various internal objs */\ + u8 flags; /* Type of Op */\ + u16 opcode; /* AML opcode */\ + u32 aml_offset; /* offset of declaration in AML */\ + struct acpi_generic_op *parent; /* parent op */\ + struct acpi_generic_op *next; /* next op */\ + DEBUG_ONLY_MEMBERS (\ + char op_name[16]) /* op name (debug only) */\ + /* NON-DEBUG members below: */\ + void *acpi_named_object;/* for use by interpreter */\ + ACPI_OP_VALUE value; /* Value or args associated with the opcode */\ + + +/* + * generic operation (eg. If, While, Store) + */ +typedef struct acpi_generic_op +{ + ACPI_COMMON_OP +} ACPI_GENERIC_OP; + + +/* + * operation with a name (eg. Scope, Method, Name, Named_field, ...) + */ +typedef struct acpi_named_op +{ + ACPI_COMMON_OP + u32 name; /* 4-byte name or zero if no name */ + +} ACPI_NAMED_OP; + + +/* + * special operation for methods and regions (parsing must be deferred + * until a first pass parse is completed) + */ +typedef struct acpi_deferred_op +{ + ACPI_COMMON_OP + u32 name; /* 4-byte name or 0 if none */ + u32 body_length; /* AML body size */ + u8 *body; /* AML body */ + u16 thread_count; /* Count of threads currently executing a method */ + +} ACPI_DEFERRED_OP; + + +/* + * special operation for bytelists (Byte_list only) + */ +typedef struct acpi_bytelist_op +{ + ACPI_COMMON_OP + u8 *data; /* bytelist data */ + +} ACPI_BYTELIST_OP; + + +/* + * Parse state - one state per parser invocation and each control + * method. + */ + +typedef struct acpi_parse_state +{ + u8 *aml_start; /* first AML byte */ + u8 *aml; /* next AML byte */ + u8 *aml_end; /* (last + 1) AML byte */ + u8 *pkg_end; /* current package end */ + ACPI_GENERIC_OP *start_op; /* root of parse tree */ + struct acpi_parse_scope *scope; /* current scope */ + struct acpi_parse_scope *scope_avail; /* unused (extra) scope structs */ + struct acpi_parse_state *next; + +} ACPI_PARSE_STATE; + + +/* + * Parse scope - one per ACPI scope + */ + +typedef struct acpi_parse_scope +{ + ACPI_GENERIC_OP *op; /* current op being parsed */ + u8 *arg_end; /* current argument end */ + u8 *pkg_end; /* current package end */ + struct acpi_parse_scope *parent; /* parent scope */ + u32 arg_list; /* next argument to parse */ + u32 arg_count; /* Number of fixed arguments */ + +} ACPI_PARSE_SCOPE; + + +/***************************************************************************** + * + * Generic "state" object for stacks + * + ****************************************************************************/ + + +#define CONTROL_NORMAL 0xC0 +#define CONTROL_CONDITIONAL_EXECUTING 0xC1 +#define CONTROL_PREDICATE_EXECUTING 0xC2 +#define CONTROL_PREDICATE_FALSE 0xC3 +#define CONTROL_PREDICATE_TRUE 0xC4 + + +#define ACPI_STATE_COMMON /* Two 32-bit fields and a pointer */\ + u8 data_type; /* To differentiate various internal objs */\ + u8 flags; \ + u16 value; \ + u16 state; \ + u16 acpi_eval; \ + void *next; \ + +typedef struct acpi_common_state +{ + ACPI_STATE_COMMON +} ACPI_COMMON_STATE; + + +/* + * Update state - used to traverse complex objects such as packages + */ +typedef struct acpi_update_state +{ + ACPI_STATE_COMMON + union acpi_obj_internal *object; + +} ACPI_UPDATE_STATE; + +/* + * Control state - one per if/else and while constructs. + * Allows nesting of these constructs + */ +typedef struct acpi_control_state +{ + ACPI_STATE_COMMON + ACPI_GENERIC_OP *predicate_op; /* Start of if/while predicate */ + +} ACPI_CONTROL_STATE; + + +/* + * Scope state - current scope during namespace lookups + */ + +typedef struct acpi_scope_state +{ + ACPI_STATE_COMMON + ACPI_NAME_TABLE *name_table; + +} ACPI_SCOPE_STATE; + + +typedef union acpi_gen_state +{ + ACPI_COMMON_STATE common; + ACPI_CONTROL_STATE control; + ACPI_UPDATE_STATE update; + ACPI_SCOPE_STATE scope; + +} ACPI_GENERIC_STATE; + + +/***************************************************************************** + * + * Tree walking typedefs and structs + * + ****************************************************************************/ + + +/* + * Walk state - current state of a parse tree walk. Used for both a leisurely stroll through + * the tree (for whatever reason), and for control method execution. + */ + +#define NEXT_OP_DOWNWARD 1 +#define NEXT_OP_UPWARD 2 + +typedef struct acpi_walk_state +{ + u8 data_type; /* To differentiate various internal objs */\ + ACPI_OWNER_ID owner_id; /* Owner of objects created during the walk */ + u8 last_predicate; /* Result of last predicate */ + u8 next_op_info; /* Info about Next_op */ + u8 num_operands; /* Stack pointer for Operands[] array */ + u8 num_results; /* Stack pointer for Results[] array */ + u8 current_result; /* */ + + struct acpi_walk_state *next; /* Next Walk_state in list */ + ACPI_GENERIC_OP *origin; /* Start of walk */ + ACPI_GENERIC_OP *prev_op; /* Last op that was processed */ + ACPI_GENERIC_OP *next_op; /* next op to be processed */ + ACPI_GENERIC_STATE *control_state; /* List of control states (nested IFs) */ + ACPI_GENERIC_STATE *scope_info; /* Stack of nested scopes */ + union acpi_obj_internal *return_desc; /* Return object, if any */ + union acpi_obj_internal *method_desc; /* Method descriptor if running a method */ + ACPI_GENERIC_OP *method_call_op; /* Method_call Op if running a method */ + union acpi_obj_internal *operands[OBJ_NUM_OPERANDS]; /* Operands passed to the interpreter */ + union acpi_obj_internal *results[OBJ_NUM_OPERANDS]; /* Accumulated results */ + struct acpi_named_object arguments[MTH_NUM_ARGS]; /* Control method arguments */ + struct acpi_named_object local_variables[MTH_NUM_LOCALS]; /* Control method locals */ + + +} ACPI_WALK_STATE; + + +/* + * Walk list - head of a tree of walk states. Multiple walk states are created when there + * are nested control methods executing. + */ +typedef struct acpi_walk_list +{ + + ACPI_WALK_STATE *walk_state; + +} ACPI_WALK_LIST; + + +typedef +ACPI_STATUS (*INTERPRETER_CALLBACK) ( + ACPI_WALK_STATE *state, + ACPI_GENERIC_OP *op); + + +/* Info used by Acpi_ps_init_objects */ + +typedef struct init_walk_info +{ + u32 method_count; + u32 op_region_count; + ACPI_TABLE_DESC *table_desc; + +} INIT_WALK_INFO; + + +/* TBD: [Restructure] Merge with struct above */ + +typedef struct acpi_walk_info +{ + u32 debug_level; + u32 owner_id; + +} ACPI_WALK_INFO; + + +/***************************************************************************** + * + * Hardware and PNP + * + ****************************************************************************/ + + +/* Sleep states */ + +#define SLWA_DEBUG_LEVEL 4 +#define GTS_CALL 0 +#define GTS_WAKE 1 + +/* Cx States */ + +#define MAX_CX_STATE_LATENCY 0xFFFFFFFF +#define MAX_CX_STATES 4 + +/* + * The #define's and enum below establish an abstract way of identifying what + * register block and register is to be accessed. Do not change any of the + * values as they are used in switch statements and offset calculations. + */ + +#define REGISTER_BLOCK_MASK 0xFF00 +#define BIT_IN_REGISTER_MASK 0x00FF +#define PM1_EVT 0x0100 +#define PM1_CONTROL 0x0200 +#define PM2_CONTROL 0x0300 +#define PM_TIMER 0x0400 +#define PROCESSOR_BLOCK 0x0500 +#define GPE0_STS_BLOCK 0x0600 +#define GPE0_EN_BLOCK 0x0700 +#define GPE1_STS_BLOCK 0x0800 +#define GPE1_EN_BLOCK 0x0900 + +enum +{ + /* PM1 status register ids */ + + TMR_STS = (PM1_EVT | 0x01), + BM_STS, + GBL_STS, + PWRBTN_STS, + SLPBTN_STS, + RTC_STS, + WAK_STS, + + /* PM1 enable register ids */ + + TMR_EN, + /* need to skip 1 enable number since there's no bus master enable register */ + GBL_EN = (PM1_EVT | 0x0A), + PWRBTN_EN, + SLPBTN_EN, + RTC_EN, + + /* PM1 control register ids */ + + SCI_EN = (PM1_CONTROL | 0x01), + BM_RLD, + GBL_RLS, + SLP_TYPE_A, + SLP_TYPE_B, + SLP_EN, + + /* PM2 control register ids */ + + ARB_DIS = (PM2_CONTROL | 0x01), + + /* PM Timer register ids */ + + TMR_VAL = (PM_TIMER | 0x01), + + GPE0_STS = (GPE0_STS_BLOCK | 0x01), + GPE0_EN = (GPE0_EN_BLOCK | 0x01), + + GPE1_STS = (GPE1_STS_BLOCK | 0x01), + GPE1_EN = (GPE0_EN_BLOCK | 0x01), + + /* Last register value is one less than LAST_REG */ + + LAST_REG +}; + + +#define TMR_STS_MASK 0x0001 +#define BM_STS_MASK 0x0010 +#define GBL_STS_MASK 0x0020 +#define PWRBTN_STS_MASK 0x0100 +#define SLPBTN_STS_MASK 0x0200 +#define RTC_STS_MASK 0x0400 +#define WAK_STS_MASK 0x8000 + +#define ALL_FIXED_STS_BITS (TMR_STS_MASK | BM_STS_MASK | GBL_STS_MASK | PWRBTN_STS_MASK | \ + SLPBTN_STS_MASK | RTC_STS_MASK | WAK_STS_MASK) + +#define TMR_EN_MASK 0x0001 +#define GBL_EN_MASK 0x0020 +#define PWRBTN_EN_MASK 0x0100 +#define SLPBTN_EN_MASK 0x0200 +#define RTC_EN_MASK 0x0400 + +#define SCI_EN_MASK 0x0001 +#define BM_RLD_MASK 0x0002 +#define GBL_RLS_MASK 0x0004 +#define SLP_TYPE_X_MASK 0x1C00 +#define SLP_EN_MASK 0x2000 + +#define ARB_DIS_MASK 0x0001 + +#define GPE0_STS_MASK +#define GPE0_EN_MASK + +#define GPE1_STS_MASK +#define GPE1_EN_MASK + + +#define ACPI_READ 1 +#define ACPI_WRITE 2 + +#define LOW_BYTE 0x00FF +#define ONE_BYTE 0x08 + +#ifndef SET + #define SET 1 +#endif +#ifndef CLEAR + #define CLEAR 0 +#endif + + +/* Plug and play */ + +/* Pnp and ACPI data */ + +#define VERSION_NO 0x01 +#define LOGICAL_DEVICE_ID 0x02 +#define COMPATIBLE_DEVICE_ID 0x03 +#define IRQ_FORMAT 0x04 +#define DMA_FORMAT 0x05 +#define START_DEPENDENT_TAG 0x06 +#define END_DEPENDENT_TAG 0x07 +#define IO_PORT_DESCRIPTOR 0x08 +#define FIXED_LOCATION_IO_DESCRIPTOR 0x09 +#define RESERVED_TYPE0 0x0A +#define RESERVED_TYPE1 0x0B +#define RESERVED_TYPE2 0x0C +#define RESERVED_TYPE3 0x0D +#define SMALL_VENDOR_DEFINED 0x0E +#define END_TAG 0x0F + +/* Pnp and ACPI data */ + +#define MEMORY_RANGE_24 0x81 +#define ISA_MEMORY_RANGE 0x81 +#define LARGE_VENDOR_DEFINED 0x84 +#define EISA_MEMORY_RANGE 0x85 +#define MEMORY_RANGE_32 0x85 +#define FIXED_EISA_MEMORY_RANGE 0x86 +#define FIXED_MEMORY_RANGE_32 0x86 + +/* ACPI only data */ + +#define DWORD_ADDRESS_SPACE 0x87 +#define WORD_ADDRESS_SPACE 0x88 +#define EXTENDED_IRQ 0x89 + +/* MUST HAVES */ + + +typedef enum +{ + DWORD_DEVICE_ID, + STRING_PTR_DEVICE_ID, + STRING_DEVICE_ID + +} DEVICE_ID_TYPE; + +typedef struct +{ + DEVICE_ID_TYPE type; + union + { + u32 number; + char *string_ptr; + char buffer[9]; + } data; + +} DEVICE_ID; + + +/***************************************************************************** + * + * Debug + * + ****************************************************************************/ + + +/* Entry for a memory allocation (debug only) */ + +#ifdef ACPI_DEBUG + +#define MEM_MALLOC 0 +#define MEM_CALLOC 1 +#define MAX_MODULE_NAME 16 + +typedef struct allocation_info +{ + struct allocation_info *previous; + struct allocation_info *next; + void *address; + u32 size; + u32 component; + u32 line; + char module[MAX_MODULE_NAME]; + u8 alloc_type; + +} ALLOCATION_INFO; + +#endif + +#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/interp.h linux/drivers/acpi/include/interp.h --- v2.4.0-test2/linux/drivers/acpi/include/interp.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/interp.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,660 @@ + +/****************************************************************************** + * + * Name: interp.h - Interpreter subcomponent prototypes and defines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __INTERP_H__ +#define __INTERP_H__ + + +#include "actypes.h" +#include "acobject.h" + + +#define WALK_OPERANDS &(walk_state->operands [walk_state->num_operands -1]) + + +/* Interpreter constants */ + +#define AML_END_OF_BLOCK -1 +#define PUSH_PKG_LENGTH 1 +#define DO_NOT_PUSH_PKG_LENGTH 0 + + +#define STACK_TOP 0 +#define STACK_BOTTOM (u32) -1 + +/* Constants for global "When_to_parse_methods" */ + +#define METHOD_PARSE_AT_INIT 0x0 +#define METHOD_PARSE_JUST_IN_TIME 0x1 +#define METHOD_DELETE_AT_COMPLETION 0x2 + + +ACPI_STATUS +acpi_aml_resolve_operands ( + u16 opcode, + ACPI_OBJECT_INTERNAL **stack_ptr); + + +/* + * amxface - External interpreter interfaces + */ + +ACPI_STATUS +acpi_aml_load_table ( + ACPI_TABLE_TYPE table_id); + +ACPI_STATUS +acpi_aml_execute_method ( + ACPI_NAMED_OBJECT *method_entry, + ACPI_OBJECT_INTERNAL **params, + ACPI_OBJECT_INTERNAL **return_obj_desc); + + +/* + * amcopy - Interpreter object copy support + */ + +ACPI_STATUS +acpi_aml_build_copy_internal_package_object ( + ACPI_OBJECT_INTERNAL *source_obj, + ACPI_OBJECT_INTERNAL *dest_obj); + + +/* + * amfield - ACPI AML (p-code) execution - field manipulation + */ + + +ACPI_STATUS +acpi_aml_read_field ( + ACPI_OBJECT_INTERNAL *obj_desc, + void *buffer, + u32 buffer_length, + u32 byte_length, + u32 datum_length, + u32 bit_granularity, + u32 byte_granularity); + +ACPI_STATUS +acpi_aml_write_field ( + ACPI_OBJECT_INTERNAL *obj_desc, + void *buffer, + u32 buffer_length, + u32 byte_length, + u32 datum_length, + u32 bit_granularity, + u32 byte_granularity); + +ACPI_STATUS +acpi_aml_setup_field ( + ACPI_OBJECT_INTERNAL *obj_desc, + ACPI_OBJECT_INTERNAL *rgn_desc, + s32 field_bit_width); + +ACPI_STATUS +acpi_aml_read_field_data ( + ACPI_OBJECT_INTERNAL *obj_desc, + u32 field_byte_offset, + u32 field_bit_width, + u32 *value); + +ACPI_STATUS +acpi_aml_access_named_field ( + s32 mode, + ACPI_HANDLE named_field, + void *buffer, + u32 length); + +ACPI_STATUS +acpi_aml_set_named_field_value ( + ACPI_HANDLE named_field, + void *buffer, + u32 length); + +ACPI_STATUS +acpi_aml_get_named_field_value ( + ACPI_HANDLE named_field, + void *buffer, + u32 length); + + +/* + * ammisc - ACPI AML (p-code) execution - specific opcodes + */ + +ACPI_STATUS +acpi_aml_exec_create_field ( + u16 opcode, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_reconfiguration ( + u16 opcode, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_fatal ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_index ( + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL **return_desc); + +ACPI_STATUS +acpi_aml_exec_match ( + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL **return_desc); + +ACPI_STATUS +acpi_aml_exec_create_mutex ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_create_processor ( + ACPI_GENERIC_OP *op, + ACPI_HANDLE processor_nTE); + +ACPI_STATUS +acpi_aml_exec_create_power_resource ( + ACPI_GENERIC_OP *op, + ACPI_HANDLE processor_nTE); + +ACPI_STATUS +acpi_aml_exec_create_region ( + u8 *aml_ptr, + u32 acpi_aml_length, + u32 region_space, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_create_event ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_create_alias ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_create_method ( + u8 *aml_ptr, + u32 acpi_aml_length, + u32 method_flags, + ACPI_HANDLE method); + + +/* + * amprep - ACPI AML (p-code) execution - prep utilities + */ + +ACPI_STATUS +acpi_aml_prep_def_field_value ( + ACPI_NAMED_OBJECT *this_entry, + ACPI_HANDLE region, + u8 field_flags, + u8 field_attribute, + u32 field_position, + u32 field_length); + +ACPI_STATUS +acpi_aml_prep_bank_field_value ( + ACPI_NAMED_OBJECT *this_entry, + ACPI_HANDLE region, + ACPI_HANDLE bank_reg, + u32 bank_val, + u8 field_flags, + u8 field_attribute, + u32 field_position, + u32 field_length); + +ACPI_STATUS +acpi_aml_prep_index_field_value ( + ACPI_NAMED_OBJECT *this_entry, + ACPI_HANDLE index_reg, + ACPI_HANDLE data_reg, + u8 field_flags, + u8 field_attribute, + u32 field_position, + u32 field_length); + +ACPI_STATUS +acpi_aml_prep_operands ( + char *types, + ACPI_OBJECT_INTERNAL **stack_ptr); + + +/* + * iepstack - package stack utilities + */ + +/* +u32 +Acpi_aml_pkg_stack_level ( + void); + +void +Acpi_aml_clear_pkg_stack ( + void); + +ACPI_STATUS +Acpi_aml_pkg_push_length ( + u32 Length, + OPERATING_MODE Load_exec_mode); + +ACPI_STATUS +Acpi_aml_pkg_push_exec_length ( + u32 Length); + +ACPI_STATUS +Acpi_aml_pkg_push_exec ( + u8 *Code, + u32 Len); + +ACPI_STATUS +Acpi_aml_pkg_pop_length ( + s32 No_err_under, + OPERATING_MODE Load_exec_mode); + +ACPI_STATUS +Acpi_aml_pkg_pop_exec_length ( + void); + +ACPI_STATUS +Acpi_aml_pkg_pop_exec ( + void); + +*/ + +/* + * amsystem - Interface to OS services + */ + +u16 +acpi_aml_system_thread_id ( + void); + +ACPI_STATUS +acpi_aml_system_do_notify_op ( + ACPI_OBJECT_INTERNAL *value, + ACPI_OBJECT_INTERNAL *obj_desc); + +void +acpi_aml_system_do_suspend( + u32 time); + +void +acpi_aml_system_do_stall ( + u32 time); + +ACPI_STATUS +acpi_aml_system_acquire_mutex( + ACPI_OBJECT_INTERNAL *time, + ACPI_OBJECT_INTERNAL *obj_desc); + +ACPI_STATUS +acpi_aml_system_release_mutex( + ACPI_OBJECT_INTERNAL *obj_desc); + +ACPI_STATUS +acpi_aml_system_signal_event( + ACPI_OBJECT_INTERNAL *obj_desc); + +ACPI_STATUS +acpi_aml_system_wait_event( + ACPI_OBJECT_INTERNAL *time, + ACPI_OBJECT_INTERNAL *obj_desc); + +ACPI_STATUS +acpi_aml_system_reset_event( + ACPI_OBJECT_INTERNAL *obj_desc); + +ACPI_STATUS +acpi_aml_system_wait_semaphore ( + ACPI_HANDLE semaphore, + u32 timeout); + + +/* + * ammonadic - ACPI AML (p-code) execution, monadic operators + */ + +ACPI_STATUS +acpi_aml_exec_monadic1 ( + u16 opcode, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_monadic2 ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL **return_desc); + +ACPI_STATUS +acpi_aml_exec_monadic2_r ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL **return_desc); + + +/* + * amdyadic - ACPI AML (p-code) execution, dyadic operators + */ + +ACPI_STATUS +acpi_aml_exec_dyadic1 ( + u16 opcode, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_dyadic2 ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL **return_desc); + +ACPI_STATUS +acpi_aml_exec_dyadic2_r ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL **return_desc); + +ACPI_STATUS +acpi_aml_exec_dyadic2_s ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL **return_desc); + + +/* + * amresolv - Object resolution and get value functions + */ + +ACPI_STATUS +acpi_aml_resolve_to_value ( + ACPI_OBJECT_INTERNAL **stack_ptr); + +ACPI_STATUS +acpi_aml_resolve_entry_to_value ( + ACPI_NAMED_OBJECT **stack_ptr); + +ACPI_STATUS +acpi_aml_resolve_object_to_value ( + ACPI_OBJECT_INTERNAL **stack_ptr); + +ACPI_STATUS +acpi_aml_get_field_unit_value ( + ACPI_OBJECT_INTERNAL *field_desc, + ACPI_OBJECT_INTERNAL *result_desc); + + +/* + * amcode - Scanner AML code manipulation routines + */ + +s32 +acpi_aml_avail ( + ACPI_SIZE n); + +s32 +acpi_aml_peek ( + void); + +s32 +acpi_aml_get_pcode_byte ( + u8 *pcode); + +u16 +acpi_aml_peek_op ( + void); + +u8 * +acpi_aml_consume_bytes ( + ACPI_SIZE bytes); + +ACPI_SIZE +acpi_aml_consume_stream_bytes ( + ACPI_SIZE bytes_to_get, + u8 *aml_buffer); + +void +acpi_aml_consume_package ( + OPERATING_MODE load_exec_mode); + +void +acpi_aml_set_pcode_input ( + u8 *base, + u32 length); + +ACPI_STATUS +acpi_aml_set_method ( + void *object); + +ACPI_STATUS +acpi_aml_prep_exec ( + u8 *pcode, + u32 pcode_length); + +ACPI_HANDLE +acpi_aml_get_pcode_handle ( + void); + +void +acpi_aml_get_current_location ( + ACPI_OBJECT_INTERNAL *method_desc); + +void +acpi_aml_set_current_location ( + ACPI_OBJECT_INTERNAL *method_desc); + + +/* + * amdump - Scanner debug output routines + */ + +void +acpi_aml_show_hex_value ( + s32 byte_count, + u8 *aml_ptr, + s32 lead_space); + +void +acpi_aml_dump_buffer ( + ACPI_SIZE length); + + +ACPI_STATUS +acpi_aml_dump_operand ( + ACPI_OBJECT_INTERNAL *entry_desc); + +void +acpi_aml_dump_operands ( + ACPI_OBJECT_INTERNAL **operands, + OPERATING_MODE interpreter_mode, + char *ident, + s32 num_levels, + char *note, + char *module_name, + s32 line_number); + +void +acpi_aml_dump_object_descriptor ( + ACPI_OBJECT_INTERNAL *object, + u32 flags); + + +void +acpi_aml_dump_acpi_named_object ( + ACPI_NAMED_OBJECT *entry, + u32 flags); + + +/* + * amnames - interpreter/scanner name load/execute + */ + +char * +acpi_aml_allocate_name_string ( + u32 prefix_count, + u32 num_name_segs); + +s32 +acpi_aml_good_char ( + s32 character); + +ACPI_STATUS +acpi_aml_exec_name_segment ( + u8 **in_aml_address, + char *name_string); + +ACPI_STATUS +acpi_aml_get_name_string ( + OBJECT_TYPE_INTERNAL data_type, + u8 *in_aml_address, + char **out_name_string, + u32 *out_name_length); + +u32 +acpi_aml_decode_package_length ( + u32 last_pkg_len); + + +ACPI_STATUS +acpi_aml_do_name ( + ACPI_OBJECT_TYPE data_type, + OPERATING_MODE load_exec_mode); + + +/* + * amstore - Object store support + */ + +ACPI_STATUS +acpi_aml_exec_store ( + ACPI_OBJECT_INTERNAL *op1, + ACPI_OBJECT_INTERNAL *res); + +ACPI_STATUS +acpi_aml_store_object_to_object ( + ACPI_OBJECT_INTERNAL *val_desc, + ACPI_OBJECT_INTERNAL *dest_desc); + +ACPI_STATUS +acpi_aml_store_object_to_nte ( + ACPI_OBJECT_INTERNAL *val_desc, + ACPI_NAMED_OBJECT *entry); + + +/* + * amutils - interpreter/scanner utilities + */ + +void +acpi_aml_enter_interpreter ( + void); + +void +acpi_aml_exit_interpreter ( + void); + +u8 +acpi_aml_validate_object_type ( + ACPI_OBJECT_TYPE type); + +u8 +acpi_aml_acquire_global_lock ( + u32 rule); + +ACPI_STATUS +acpi_aml_release_global_lock ( + u8 locked); + +void +acpi_aml_append_operand_diag( + char *name, + s32 line, + u16 op_code, + ACPI_OBJECT_INTERNAL **operands, + s32 Noperands); + +u32 +acpi_aml_buf_seq ( + void); + +s32 +acpi_aml_digits_needed ( + s32 value, + s32 base); + +ACPI_STATUS +acpi_aml_eisa_id_to_string ( + u32 numeric_id, + char *out_string); + + +/* + * amregion - default Op_region handlers + */ + +ACPI_STATUS +acpi_aml_system_memory_space_handler ( + u32 function, + u32 address, + u32 bit_width, + u32 *value, + void *context); + +ACPI_STATUS +acpi_aml_system_io_space_handler ( + u32 function, + u32 address, + u32 bit_width, + u32 *value, + void *context); + +ACPI_STATUS +acpi_aml_pci_config_space_handler ( + u32 function, + u32 address, + u32 bit_width, + u32 *value, + void *context); + +ACPI_STATUS +acpi_aml_embedded_controller_space_handler ( + u32 function, + u32 address, + u32 bit_width, + u32 *value, + void *context); + +ACPI_STATUS +acpi_aml_sm_bus_space_handler ( + u32 function, + u32 address, + u32 bit_width, + u32 *value, + void *context); + + +#endif /* __INTERP_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/macros.h linux/drivers/acpi/include/macros.h --- v2.4.0-test2/linux/drivers/acpi/include/macros.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/macros.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,423 @@ + +/****************************************************************************** + * + * Name: macros.h - C macros for the entire subsystem. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MACROS_H__ +#define __MACROS_H__ + +/* + * Data manipulation macros + */ + +#ifndef LOWORD +#define LOWORD(l) ((u16)(NATIVE_UINT)(l)) +#endif + +#ifndef HIWORD +#define HIWORD(l) ((u16)((((NATIVE_UINT)(l)) >> 16) & 0xFFFF)) +#endif + +#ifndef LOBYTE +#define LOBYTE(l) ((u8)(u16)(l)) +#endif + +#ifndef HIBYTE +#define HIBYTE(l) ((u8)((((u16)(l)) >> 8) & 0xFF)) +#endif + +#define BIT0(x) ((((x) & 0x01) > 0) ? 1 : 0) +#define BIT1(x) ((((x) & 0x02) > 0) ? 1 : 0) +#define BIT2(x) ((((x) & 0x04) > 0) ? 1 : 0) + +#define BIT3(x) ((((x) & 0x08) > 0) ? 1 : 0) +#define BIT4(x) ((((x) & 0x10) > 0) ? 1 : 0) +#define BIT5(x) ((((x) & 0x20) > 0) ? 1 : 0) +#define BIT6(x) ((((x) & 0x40) > 0) ? 1 : 0) +#define BIT7(x) ((((x) & 0x80) > 0) ? 1 : 0) + +#define LOW_BASE(w) ((u16) ((w) & 0x0000FFFF)) +#define MID_BASE(b) ((u8) (((b) & 0x00FF0000) >> 16)) +#define HI_BASE(b) ((u8) (((b) & 0xFF000000) >> 24)) +#define LOW_LIMIT(w) ((u16) ((w) & 0x0000FFFF)) +#define HI_LIMIT(b) ((u8) (((b) & 0x00FF0000) >> 16)) + + + /* + * Extract a byte of data using a pointer. Any more than a byte and we + * get into potential aligment issues -- see the STORE macros below + */ +#define GET8(addr) (*(u8*)(addr)) + + +/* + * Macros for moving data around to/from buffers that are possibly unaligned. + * If the hardware supports the transfer of unaligned data, just do the store. + * Otherwise, we have to move one byte at a time. + */ + +#ifdef _HW_ALIGNMENT_SUPPORT + +/* The hardware supports unaligned transfers, just do the move */ + +#define MOVE_UNALIGNED16_TO_16(d,s) *(u16*)(d) = *(u16*)(s) +#define MOVE_UNALIGNED32_TO_32(d,s) *(u32*)(d) = *(u32*)(s) +#define MOVE_UNALIGNED16_TO_32(d,s) *(u32*)(d) = *(u16*)(s) + +#else +/* + * The hardware does not support unaligned transfers. We must move the + * data one byte at a time. These macros work whether the source or + * the destination (or both) is/are unaligned. + */ + +#define MOVE_UNALIGNED16_TO_16(d,s) {((char *)(d))[0] = ((char *)(s))[0];\ + ((char *)(d))[1] = ((char *)(s))[1];} + +#define MOVE_UNALIGNED32_TO_32(d,s) {((char *)(d))[0] = ((char *)(s))[0];\ + ((char *)(d))[1] = ((char *)(s))[1];\ + ((char *)(d))[2] = ((char *)(s))[2];\ + ((char *)(d))[3] = ((char *)(s))[3];} + +#define MOVE_UNALIGNED16_TO_32(d,s) {(*(u32*)(d)) = 0; MOVE_UNALIGNED16_TO_16(d,s);} + +#endif + + +/* + * Fast power-of-two math macros for non-optimized compilers + */ + +#define _DIV(value,power_of2) ((value) >> (power_of2)) +#define _MUL(value,power_of2) ((value) << (power_of2)) +#define _MOD(value,divisor) ((value) & ((divisor) -1)) + +#define DIV_2(a) _DIV(a,1) +#define MUL_2(a) _MUL(a,1) +#define MOD_2(a) _MOD(a,2) + +#define DIV_4(a) _DIV(a,2) +#define MUL_4(a) _MUL(a,2) +#define MOD_4(a) _MOD(a,4) + +#define DIV_8(a) _DIV(a,3) +#define MUL_8(a) _MUL(a,3) +#define MOD_8(a) _MOD(a,8) + +#define DIV_16(a) _DIV(a,4) +#define MUL_16(a) _MUL(a,4) +#define MOD_16(a) _MOD(a,16) + + +/* + * Rounding macros (Power of two boundaries only) + */ + +#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) +#define ROUND_UP(value,boundary) (((value) + ((boundary)-1)) & (~((boundary)-1))) + +#define ROUND_DOWN_TO_32_BITS(a) ROUND_DOWN(a,4) +#define ROUND_DOWN_TO_NATIVE_WORD(a) ROUND_DOWN(a,ALIGNED_ADDRESS_BOUNDARY) + +#define ROUND_UP_TO_32_bITS(a) ROUND_UP(a,4) +#define ROUND_UP_TO_NATIVE_WORD(a) ROUND_UP(a,ALIGNED_ADDRESS_BOUNDARY) + + +#ifdef DEBUG_ASSERT +#undef DEBUG_ASSERT +#endif + + +/* + * An ACPI_HANDLE (which is actually an ACPI_NAMED_OBJECT*) can appear in some contexts, + * such as on ap_obj_stack, where a pointer to an ACPI_OBJECT_INTERNAL can also + * appear. This macro is used to distinguish them. + * + * The Data_type field is the first field in both structures. + */ + +#define VALID_DESCRIPTOR_TYPE(d,t) (((ACPI_NAMED_OBJECT*)d)->data_type == t) + + +/* Macro to test the object type */ + +#define IS_THIS_OBJECT_TYPE(d,t) (((ACPI_OBJECT_INTERNAL *)d)->common.type == (u8)t) + + +/* + * Macro to check if a pointer is within an ACPI table. + * Parameter (a) is the pointer to check. Parameter (b) must be defined + * as a pointer to an ACPI_TABLE_HEADER. (b+1) then points past the header, + * and ((u8 *)b+b->Length) points one byte past the end of the table. + */ + +#ifndef _IA16 +#define IS_IN_ACPI_TABLE(a,b) (((u8 *)(a) >= (u8 *)(b + 1)) &&\ + ((u8 *)(a) < ((u8 *)b + b->length))) + +#else +#define IS_IN_ACPI_TABLE(a,b) (_segment)(a) == (_segment)(b) &&\ + (((u8 *)(a) >= (u8 *)(b + 1)) &&\ + ((u8 *)(a) < ((u8 *)b + b->length))) +#endif + +/* + * Macros for the master AML opcode table + */ + +#ifdef ACPI_DEBUG +#define OP_INFO_ENTRY(opcode,flags,name,Pargs,Iargs) {opcode,flags,Pargs,Iargs,name} +#else +#define OP_INFO_ENTRY(opcode,flags,name,Pargs,Iargs) {opcode,flags,Pargs,Iargs} +#endif + +#define ARG_TYPE_WIDTH 5 +#define ARG_1(x) ((u32)(x)) +#define ARG_2(x) ((u32)(x) << (1 * ARG_TYPE_WIDTH)) +#define ARG_3(x) ((u32)(x) << (2 * ARG_TYPE_WIDTH)) +#define ARG_4(x) ((u32)(x) << (3 * ARG_TYPE_WIDTH)) +#define ARG_5(x) ((u32)(x) << (4 * ARG_TYPE_WIDTH)) +#define ARG_6(x) ((u32)(x) << (5 * ARG_TYPE_WIDTH)) + +#define ARGI_LIST1(a) (ARG_1(a)) +#define ARGI_LIST2(a,b) (ARG_1(b)|ARG_2(a)) +#define ARGI_LIST3(a,b,c) (ARG_1(c)|ARG_2(b)|ARG_3(a)) +#define ARGI_LIST4(a,b,c,d) (ARG_1(d)|ARG_2(c)|ARG_3(b)|ARG_4(a)) +#define ARGI_LIST5(a,b,c,d,e) (ARG_1(e)|ARG_2(d)|ARG_3(c)|ARG_4(b)|ARG_5(a)) +#define ARGI_LIST6(a,b,c,d,e,f) (ARG_1(f)|ARG_2(e)|ARG_3(d)|ARG_4(c)|ARG_5(b)|ARG_6(a)) + +#define ARGP_LIST1(a) (ARG_1(a)) +#define ARGP_LIST2(a,b) (ARG_1(a)|ARG_2(b)) +#define ARGP_LIST3(a,b,c) (ARG_1(a)|ARG_2(b)|ARG_3(c)) +#define ARGP_LIST4(a,b,c,d) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)) +#define ARGP_LIST5(a,b,c,d,e) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)|ARG_5(e)) +#define ARGP_LIST6(a,b,c,d,e,f) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)|ARG_5(e)|ARG_6(f)) + +#define GET_CURRENT_ARG_TYPE(list) (list & 0x1F) +#define INCREMENT_ARG_LIST(list) (list >>= ARG_TYPE_WIDTH) + + +/* + * Reporting macros that are never compiled out + */ + +/* + * Error reporting. These versions add callers module and line#. Since + * _THIS_MODULE gets compiled out when ACPI_DEBUG isn't defined, only + * use it in debug mode. + */ + +#ifdef ACPI_DEBUG + +#define REPORT_INFO(a) _report_info(_THIS_MODULE,__LINE__,_COMPONENT,a) +#define REPORT_ERROR(a) _report_error(_THIS_MODULE,__LINE__,_COMPONENT,a) +#define REPORT_WARNING(a) _report_warning(_THIS_MODULE,__LINE__,_COMPONENT,a) +#define REPORT_SUCCESS(a) _report_success(_THIS_MODULE,__LINE__,_COMPONENT,a) + +#else + +#define REPORT_INFO(a) _report_info("",__LINE__,_COMPONENT,a) +#define REPORT_ERROR(a) _report_error("",__LINE__,_COMPONENT,a) +#define REPORT_WARNING(a) _report_warning("",__LINE__,_COMPONENT,a) +#define REPORT_SUCCESS(a) _report_success("",__LINE__,_COMPONENT,a) + +#endif + +/* Error reporting. These versions pass thru the module and line# */ + +#define _REPORT_INFO(a,b,c,d) _report_info(a,b,c,d) +#define _REPORT_ERROR(a,b,c,d) _report_error(a,b,c,d) +#define _REPORT_WARNING(a,b,c,d) _report_warning(a,b,c,d) + +/* Buffer dump macros */ + +#define DUMP_BUFFER(a,b) acpi_cm_dump_buffer((char *)a,b,DB_BYTE_DISPLAY,_COMPONENT) + +/* + * Debug macros that are conditionally compiled + */ + +#ifdef ACPI_DEBUG + +#define MODULE_NAME(name) static char *_THIS_MODULE = name + +/* + * Function entry tracing. + * The first parameter should be the procedure name as a quoted string. This is declared + * as a local string ("_Proc_name) so that it can be also used by the function exit macros below. + */ + +#define FUNCTION_TRACE(a) char * _proc_name = a;\ + function_trace(_THIS_MODULE,__LINE__,_COMPONENT,a) +#define FUNCTION_TRACE_PTR(a,b) char * _proc_name = a;\ + function_trace_ptr(_THIS_MODULE,__LINE__,_COMPONENT,a,(void *)b) +#define FUNCTION_TRACE_U32(a,b) char * _proc_name = a;\ + function_trace_u32(_THIS_MODULE,__LINE__,_COMPONENT,a,(u32)b) +#define FUNCTION_TRACE_STR(a,b) char * _proc_name = a;\ + function_trace_str(_THIS_MODULE,__LINE__,_COMPONENT,a,(char *)b) +/* + * Function exit tracing. + * WARNING: These macros include a return statement. This is usually considered + * bad form, but having a separate exit macro is very ugly and difficult to maintain. + * One of the FUNCTION_TRACE macros above must be used in conjunction with these macros + * so that "_Proc_name" is defined. + */ +#define return_VOID {function_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name);return;} +#define return_ACPI_STATUS(s) {function_status_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,s);return(s);} +#define return_VALUE(s) {function_value_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,(NATIVE_UINT)s);return(s);} +#define return_PTR(s) {function_ptr_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,(char *)s);return(s);} + + +/* Conditional execution */ + +#define DEBUG_EXEC(a) a; +#define NORMAL_EXEC(a) + +#define DEBUG_DEFINE(a) a; +#define DEBUG_ONLY_MEMBERS(a) a; + + +/* Stack and buffer dumping */ + +#define DUMP_STACK_ENTRY(a) acpi_aml_dump_operand(a) +#define DUMP_OPERANDS(a,b,c,d,e) acpi_aml_dump_operands(a,b,c,d,e,_THIS_MODULE,__LINE__) + + +#define DUMP_ENTRY(a,b) acpi_ns_dump_entry (a,b) +#define DUMP_TABLES(a,b) acpi_ns_dump_tables(a,b) +#define DUMP_PATHNAME(a,b,c,d) acpi_ns_dump_pathname(a,b,c,d) +#define BREAK_MSG(a) acpi_os_breakpoint (a) + +/* + * Generate INT3 on ACPI_ERROR (Debug only!) + */ + +#define ERROR_BREAK +#ifdef ERROR_BREAK +#define BREAK_ON_ERROR(lvl) if ((lvl)&ACPI_ERROR) acpi_os_breakpoint("Fatal error encountered\n") +#else +#define BREAK_ON_ERROR(lvl) +#endif + +/* + * Master debug print macros + * Print iff: + * 1) Debug print for the current component is enabled + * 2) Debug error level or trace level for the print statement is enabled + * + */ + +#define PARAM_LIST(pl) pl + +#define TEST_DEBUG_SWITCH(lvl) if (((lvl) & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer)) + +#define DEBUG_PRINT(lvl,fp) TEST_DEBUG_SWITCH(lvl) {\ + debug_print_prefix (_THIS_MODULE,__LINE__);\ + debug_print_raw PARAM_LIST(fp);\ + BREAK_ON_ERROR(lvl);} + +#define DEBUG_PRINT_RAW(lvl,fp) TEST_DEBUG_SWITCH(lvl) {\ + debug_print_raw PARAM_LIST(fp);} + + +/* Assert macros */ + +#define ACPI_ASSERT(exp) if(!(exp)) \ + acpi_os_dbg_assert(#exp, __FILE__, __LINE__, "Failed Assertion") + +#define DEBUG_ASSERT(msg, exp) if(!(exp)) \ + acpi_os_dbg_assert(#exp, __FILE__, __LINE__, msg) + + +#else +/* + * This is the non-debug case -- make everything go away, + * leaving no executable debug code! + */ + +#define MODULE_NAME(name) +#define _THIS_MODULE "" + +#define DEBUG_EXEC(a) +#define NORMAL_EXEC(a) a; + +#define DEBUG_DEFINE(a) +#define DEBUG_ONLY_MEMBERS(a) +#define FUNCTION_TRACE(a) +#define FUNCTION_TRACE_PTR(a,b) +#define FUNCTION_TRACE_U32(a,b) +#define FUNCTION_TRACE_STR(a,b) +#define FUNCTION_EXIT +#define FUNCTION_STATUS_EXIT(s) +#define FUNCTION_VALUE_EXIT(s) +#define DUMP_STACK_ENTRY(a) +#define DUMP_OPERANDS(a,b,c,d,e) +#define DUMP_ENTRY(a,b) +#define DUMP_TABLES(a,b) +#define DUMP_PATHNAME(a,b,c,d) +#define DEBUG_PRINT(l,f) +#define DEBUG_PRINT_RAW(l,f) +#define BREAK_MSG(a) + +#define return_VOID return +#define return_ACPI_STATUS(s) return(s) +#define return_VALUE(s) return(s) +#define return_PTR(s) return(s) + +#define ACPI_ASSERT(exp) +#define DEBUG_ASSERT(msg, exp) + +#endif + + +/* + * For 16-bit code, we want to shrink some things even though + * we are using ACPI_DEBUG to get the debug output + */ +#ifdef _IA16 +#undef DEBUG_ONLY_MEMBERS +#define DEBUG_ONLY_MEMBERS(a) +#undef OP_INFO_ENTRY +#define OP_INFO_ENTRY(opcode,flags,name,Pargs,Iargs) {opcode,flags,Pargs,Iargs} +#endif + + +#ifndef ACPI_DEBUG + +#define ADD_OBJECT_NAME(a,b) + +#else + + +/* + * 1) Set name to blanks + * 2) Copy the object name + */ + +#define ADD_OBJECT_NAME(a,b) MEMSET (a->common.name, ' ', sizeof (a->common.name));\ + STRNCPY (a->common.name, acpi_gbl_ns_type_names[b], sizeof (a->common.name)) + +#endif + + +#endif /* MACROS_H */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/namesp.h linux/drivers/acpi/include/namesp.h --- v2.4.0-test2/linux/drivers/acpi/include/namesp.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/namesp.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,424 @@ + +/****************************************************************************** + * + * Name: namesp.h - Namespace subcomponent prototypes and defines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __NAMESPACE_H__ +#define __NAMESPACE_H__ + +#include "actables.h" + + +/* To search the entire name space, pass this as Search_base */ + +#define NS_ALL ((ACPI_HANDLE)0) + +/* + * Elements of Acpi_ns_properties are bit significant + * and should be one-to-one with values of ACPI_OBJECT_TYPE + */ +#define NSP_NORMAL 0 +#define NSP_NEWSCOPE 1 /* a definition of this type opens a name scope */ +#define NSP_LOCAL 2 /* suppress search of enclosing scopes */ + + +/* Definitions of the predefined namespace names */ + +#define ACPI_UNKNOWN_NAME (u32) 0x3F3F3F3F /* Unknown name is "????" */ +#define ACPI_ROOT_NAME (u32) 0x2F202020 /* Root name is "/ " */ +#define ACPI_SYS_BUS_NAME (u32) 0x5F53425F /* Sys bus name is "_SB_" */ + +#define NS_ROOT_PATH "/" +#define NS_SYSTEM_BUS "_SB_" + + +/* Flags for Acpi_ns_lookup, Acpi_ns_search_and_enter */ + +#define NS_NO_UPSEARCH 0 +#define NS_SEARCH_PARENT 0x01 +#define NS_DONT_OPEN_SCOPE 0x02 +#define NS_NO_PEER_SEARCH 0x04 + +#define NS_WALK_UNLOCK TRUE +#define NS_WALK_NO_UNLOCK FALSE + + +ACPI_STATUS +acpi_ns_walk_namespace ( + OBJECT_TYPE_INTERNAL type, + ACPI_HANDLE start_object, + u32 max_depth, + u8 unlock_before_callback, + WALK_CALLBACK user_function, + void *context, + void **return_value); + + +ACPI_NAMED_OBJECT* +acpi_ns_get_next_object ( + OBJECT_TYPE_INTERNAL type, + ACPI_NAMED_OBJECT *parent, + ACPI_NAMED_OBJECT *child); + + +ACPI_STATUS +acpi_ns_delete_namespace_by_owner ( + u16 table_id); + +void +acpi_ns_free_table_entry ( + ACPI_NAMED_OBJECT *entry); + + +/* Namespace loading - nsload */ + +ACPI_STATUS +acpi_ns_parse_table ( + ACPI_TABLE_DESC *table_desc, + ACPI_NAME_TABLE *scope); + +ACPI_STATUS +acpi_ns_load_table ( + ACPI_TABLE_DESC *table_desc, + ACPI_NAMED_OBJECT *entry); + +ACPI_STATUS +acpi_ns_load_table_by_type ( + ACPI_TABLE_TYPE table_type); + + +/* + * Top-level namespace access - nsaccess + */ + + +ACPI_STATUS +acpi_ns_root_initialize ( + void); + +ACPI_STATUS +acpi_ns_lookup ( + ACPI_GENERIC_STATE *scope_info, + char *name, + OBJECT_TYPE_INTERNAL type, + OPERATING_MODE interpreter_mode, + u32 flags, + ACPI_WALK_STATE *walk_state, + ACPI_NAMED_OBJECT **ret_entry); + + +/* + * Table allocation/deallocation - nsalloc + */ + +ACPI_NAME_TABLE * +acpi_ns_allocate_name_table ( + u32 num_entries); + +ACPI_STATUS +acpi_ns_delete_namespace_subtree ( + ACPI_NAMED_OBJECT *parent_handle); + +void +acpi_ns_detach_object ( + ACPI_HANDLE object); + +void +acpi_ns_delete_name_table ( + ACPI_NAME_TABLE *name_table); + + +/* + * Namespace modification - nsmodify + */ + +ACPI_STATUS +acpi_ns_unload_namespace ( + ACPI_HANDLE handle); + +ACPI_STATUS +acpi_ns_delete_subtree ( + ACPI_HANDLE start_handle); + + +/* + * Namespace dump/print utilities - nsdump + */ + +void +acpi_ns_dump_tables ( + ACPI_HANDLE search_base, + s32 max_depth); + +void +acpi_ns_dump_entry ( + ACPI_HANDLE handle, + u32 debug_level); + +ACPI_STATUS +acpi_ns_dump_pathname ( + ACPI_HANDLE handle, + char *msg, + u32 level, + u32 component); + +void +acpi_ns_dump_root_devices ( + void); + +void +acpi_ns_dump_objects ( + OBJECT_TYPE_INTERNAL type, + u32 max_depth, + u32 ownder_id, + ACPI_HANDLE start_handle); + + +/* + * Namespace evaluation functions - nseval + */ + +ACPI_STATUS +acpi_ns_evaluate_by_handle ( + ACPI_NAMED_OBJECT *object_nte, + ACPI_OBJECT_INTERNAL **params, + ACPI_OBJECT_INTERNAL **return_object); + +ACPI_STATUS +acpi_ns_evaluate_by_name ( + char *pathname, + ACPI_OBJECT_INTERNAL **params, + ACPI_OBJECT_INTERNAL **return_object); + +ACPI_STATUS +acpi_ns_evaluate_relative ( + ACPI_NAMED_OBJECT *object_nte, + char *pathname, + ACPI_OBJECT_INTERNAL **params, + ACPI_OBJECT_INTERNAL **return_object); + +ACPI_STATUS +acpi_ns_execute_control_method ( + ACPI_NAMED_OBJECT *method_entry, + ACPI_OBJECT_INTERNAL **params, + ACPI_OBJECT_INTERNAL **return_obj_desc); + +ACPI_STATUS +acpi_ns_get_object_value ( + ACPI_NAMED_OBJECT *object_entry, + ACPI_OBJECT_INTERNAL **return_obj_desc); + + +/* + * Parent/Child/Peer utility functions - nsfamily + */ + +ACPI_NAME +acpi_ns_find_parent_name ( + ACPI_NAMED_OBJECT *entry_to_search); + +u8 +acpi_ns_exist_downstream_sibling ( + ACPI_NAMED_OBJECT *this_entry); + + +/* + * Scope manipulation - nsscope + */ + +s32 +acpi_ns_opens_scope ( + OBJECT_TYPE_INTERNAL type); + +char * +acpi_ns_name_of_scope ( + ACPI_NAME_TABLE *scope); + +char * +acpi_ns_name_of_current_scope ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ns_handle_to_pathname ( + ACPI_HANDLE obj_handle, + u32 *buf_size, + char *user_buffer); + +u8 +acpi_ns_pattern_match ( + ACPI_NAMED_OBJECT *obj_entry, + char *search_for); + +ACPI_STATUS +acpi_ns_name_compare ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value); + +void +acpi_ns_low_find_names ( + ACPI_NAMED_OBJECT *this_entry, + char *search_for, + s32 *count, + ACPI_HANDLE list[], + s32 max_depth); + +ACPI_HANDLE * +acpi_ns_find_names ( + char *search_for, + ACPI_HANDLE search_base, + s32 max_depth); + +ACPI_STATUS +acpi_ns_get_named_object ( + char *pathname, + ACPI_NAME_TABLE *in_scope, + ACPI_NAMED_OBJECT **out_nte); + +/* + * Object management for NTEs - nsobject + */ + +ACPI_STATUS +acpi_ns_attach_method ( + ACPI_HANDLE obj_handle, + u8 *pcode_addr, + u32 pcode_length); + +ACPI_STATUS +acpi_ns_attach_object ( + ACPI_HANDLE obj_handle, + ACPI_HANDLE value, + OBJECT_TYPE_INTERNAL type); + + +void * +acpi_ns_compare_value ( + ACPI_HANDLE obj_handle, + u32 level, + void *obj_desc); + +ACPI_HANDLE +acpi_ns_find_attached_object ( + ACPI_OBJECT_INTERNAL *obj_desc, + ACPI_HANDLE search_base, + s32 max_depth); + + +/* + * Namespace searching and entry - nssearch + */ + +ACPI_STATUS +acpi_ns_search_and_enter ( + u32 entry_name, + ACPI_WALK_STATE *walk_state, + ACPI_NAME_TABLE *name_table, + OPERATING_MODE interpreter_mode, + OBJECT_TYPE_INTERNAL type, + u32 flags, + ACPI_NAMED_OBJECT **ret_entry); + +void +acpi_ns_initialize_table ( + ACPI_NAME_TABLE *new_table, + ACPI_NAME_TABLE *parent_scope, + ACPI_NAMED_OBJECT *parent_entry); + +ACPI_STATUS +acpi_ns_search_one_scope ( + u32 entry_name, + ACPI_NAME_TABLE *name_table, + OBJECT_TYPE_INTERNAL type, + ACPI_NAMED_OBJECT **ret_entry, + NS_SEARCH_DATA *ret_info); + + +/* + * Utility functions - nsutils + */ + +u8 +acpi_ns_valid_root_prefix ( + char prefix); + +u8 +acpi_ns_valid_path_separator ( + char sep); + +OBJECT_TYPE_INTERNAL +acpi_ns_get_type ( + ACPI_HANDLE obj_handle); + +void * +acpi_ns_get_attached_object ( + ACPI_HANDLE obj_handle); + +s32 +acpi_ns_local ( + OBJECT_TYPE_INTERNAL type); + +ACPI_STATUS +acpi_ns_internalize_name ( + char *dotted_name, + char **converted_name); + +ACPI_STATUS +acpi_ns_externalize_name ( + u32 internal_name_length, + char *internal_name, + u32 *converted_name_length, + char **converted_name); + +s32 +is_ns_object ( + ACPI_OBJECT_INTERNAL *p_oD); + +s32 +acpi_ns_mark_nS( + void); + +ACPI_NAMED_OBJECT* +acpi_ns_convert_handle_to_entry ( + ACPI_HANDLE handle); + +ACPI_HANDLE +acpi_ns_convert_entry_to_handle( + ACPI_NAMED_OBJECT*nte); + +void +acpi_ns_terminate ( + void); + +ACPI_NAMED_OBJECT * +acpi_ns_get_parent_entry ( + ACPI_NAMED_OBJECT *this_entry); + + +ACPI_NAMED_OBJECT * +acpi_ns_get_next_valid_entry ( + ACPI_NAMED_OBJECT *this_entry); + + +#endif /* __NAMESPACE_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/output.h linux/drivers/acpi/include/output.h --- v2.4.0-test2/linux/drivers/acpi/include/output.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/output.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,124 @@ + +/****************************************************************************** + * + * Name: output.h -- debug output + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _OUTPUT_H +#define _OUTPUT_H + +/* + * Debug levels and component IDs. These are used to control the + * granularity of the output of the DEBUG_PRINT macro -- on a per- + * component basis and a per-exception-type basis. + */ + +/* Component IDs -- used in the global "Debug_layer" */ + +#define GLOBAL 0x00000001 +#define COMMON 0x00000002 +#define PARSER 0x00000004 +#define DISPATCHER 0x00000008 +#define INTERPRETER 0x00000010 +#define NAMESPACE 0x00000020 +#define RESOURCE_MANAGER 0x00000040 +#define TABLE_MANAGER 0x00000080 +#define EVENT_HANDLING 0x00000100 +#define HARDWARE 0x00000200 +#define MISCELLANEOUS 0x00000400 +#define OS_DEPENDENT 0x00000800 + +#define BUS_MANAGER 0x00001000 + +#define PROCESSOR_CONTROL 0x00002000 +#define SYSTEM_CONTROL 0x00004000 +#define THERMAL_CONTROL 0x00008000 +#define POWER_CONTROL 0x00010000 + +#define EMBEDDED_CONTROLLER 0x00020000 +#define BATTERY 0x00040000 + +#define DEBUGGER 0x00100000 +#define ALL_COMPONENTS 0x001FFFFF + + +/* Exception level -- used in the global "Debug_level" */ + +#define ACPI_OK 0x00000001 +#define ACPI_INFO 0x00000002 +#define ACPI_WARN 0x00000004 +#define ACPI_ERROR 0x00000008 +#define ACPI_FATAL 0x00000010 +#define ACPI_DEBUG_OBJECT 0x00000020 +#define ACPI_ALL 0x0000003F + + +/* Trace level -- also used in the global "Debug_level" */ + +#define TRACE_PARSE 0x00000100 +#define TRACE_DISPATCH 0x00000200 +#define TRACE_LOAD 0x00000400 +#define TRACE_EXEC 0x00000800 +#define TRACE_NAMES 0x00001000 +#define TRACE_OPREGION 0x00002000 +#define TRACE_BFIELD 0x00004000 +#define TRACE_TRASH 0x00008000 +#define TRACE_TABLES 0x00010000 +#define TRACE_FUNCTIONS 0x00020000 +#define TRACE_VALUES 0x00040000 +#define TRACE_OBJECTS 0x00080000 +#define TRACE_ALLOCATIONS 0x00100000 +#define TRACE_RESOURCES 0x00200000 +#define TRACE_IO 0x00400000 +#define TRACE_INTERRUPTS 0x00800000 +#define TRACE_USER_REQUESTS 0x01000000 +#define TRACE_PACKAGE 0x02000000 +#define TRACE_MUTEX 0x04000000 + +#define TRACE_ALL 0x0FFFFF00 + + +/* Exceptionally verbose output -- also used in the global "Debug_level" */ + +#define VERBOSE_AML_DISASSEMBLE 0x10000000 +#define VERBOSE_INFO 0x20000000 +#define VERBOSE_TABLES 0x40000000 +#define VERBOSE_EVENTS 0x80000000 + +#define VERBOSE_ALL 0x70000000 + + +/* Defaults for Debug_level, debug and normal */ + +#define DEBUG_DEFAULT (ACPI_OK | ACPI_WARN | ACPI_ERROR | ACPI_DEBUG_OBJECT | TRACE_TABLES | TRACE_IO) +#define NORMAL_DEFAULT (ACPI_OK | ACPI_WARN | ACPI_ERROR | ACPI_DEBUG_OBJECT) +#define DEBUG_ALL (VERBOSE_AML_DISASSEMBLE | TRACE_ALL | ACPI_ALL) + +/* Misc defines */ + +#define HEX 0x01 +#define ASCII 0x02 +#define FULL_ADDRESS 0x04 +#define CHARS_PER_LINE 16 /* used in Dump_buf function */ + + +#endif /* _OUTPUT_H */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/parser.h linux/drivers/acpi/include/parser.h --- v2.4.0-test2/linux/drivers/acpi/include/parser.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/parser.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,327 @@ +/****************************************************************************** + * + * Module Name: parser.h - AML Parser subcomponent prototypes and defines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PARSER_H_ +#define _PARSER_H_ + + +#define OP_HAS_RETURN_VALUE 1 + +/* variable # arguments */ + +#define ACPI_VAR_ARGS ACPI_UINT32_MAX + +/* maximum virtual address */ + +#define ACPI_MAX_AML ((u8 *)(~0UL)) + + +#define PARSE_DELETE_TREE 1 + + +/* psapi - Parser external interfaces */ + +ACPI_STATUS +acpi_psx_load_table ( + u8 *pcode_addr, + s32 pcode_length); + +ACPI_STATUS +acpi_psx_execute ( + ACPI_NAMED_OBJECT *method_entry, + ACPI_OBJECT_INTERNAL **params, + ACPI_OBJECT_INTERNAL **return_obj_desc); + + +u8 +acpi_ps_is_namespace_object_op ( + u16 opcode); +u8 +acpi_ps_is_namespace_op ( + u16 opcode); + + +/****************************************************************************** + * + * Parser interfaces + * + *****************************************************************************/ + + +/* psargs - Parse AML opcode arguments */ + +u8 * +acpi_ps_get_next_package_end ( + ACPI_PARSE_STATE *parser_state); + +char * +acpi_ps_get_next_namestring ( + ACPI_PARSE_STATE *parser_state); + +void +acpi_ps_get_next_simple_arg ( + ACPI_PARSE_STATE *parser_state, + s32 arg_type, /* type of argument */ + ACPI_GENERIC_OP *arg); /* (OUT) argument data */ + +void +acpi_ps_get_next_namepath ( + ACPI_PARSE_STATE *parser_state, + ACPI_GENERIC_OP *arg, + u32 *arg_count, + u8 method_call); + +ACPI_GENERIC_OP * +acpi_ps_get_next_field ( + ACPI_PARSE_STATE *parser_state); + +ACPI_GENERIC_OP * +acpi_ps_get_next_arg ( + ACPI_PARSE_STATE *parser_state, + s32 arg_type, + u32 *arg_count); + + +/* psopcode - AML Opcode information */ + +ACPI_OP_INFO * +acpi_ps_get_opcode_info ( + u16 opcode); + +char * +acpi_ps_get_opcode_name ( + u16 opcode); + + +/* psparse - top level parsing routines */ + +void +acpi_ps_delete_parse_tree ( + ACPI_GENERIC_OP *root); + +ACPI_STATUS +acpi_ps_parse_loop ( + ACPI_PARSE_STATE *parser_state, + ACPI_WALK_STATE *walk_state, + u32 parse_flags); + + +ACPI_STATUS +acpi_ps_parse_aml ( + ACPI_GENERIC_OP *start_scope, + u8 *aml, + u32 acpi_aml_size, + u32 parse_flags); + +ACPI_STATUS +acpi_ps_parse_table ( + u8 *aml, + s32 aml_size, + INTERPRETER_CALLBACK descending_callback, + INTERPRETER_CALLBACK ascending_callback, + ACPI_GENERIC_OP **root_object); + +u16 +acpi_ps_peek_opcode ( + ACPI_PARSE_STATE *state); + + +/* psscope - Scope stack management routines */ + + +ACPI_STATUS +acpi_ps_init_scope ( + ACPI_PARSE_STATE *parser_state, + ACPI_GENERIC_OP *root); + +ACPI_GENERIC_OP * +acpi_ps_get_parent_scope ( + ACPI_PARSE_STATE *state); + +u8 +acpi_ps_has_completed_scope ( + ACPI_PARSE_STATE *parser_state); + +void +acpi_ps_pop_scope ( + ACPI_PARSE_STATE *parser_state, + ACPI_GENERIC_OP **op, + u32 *arg_list); + +ACPI_STATUS +acpi_ps_push_scope ( + ACPI_PARSE_STATE *parser_state, + ACPI_GENERIC_OP *op, + u32 remaining_args, + u32 arg_count); + +void +acpi_ps_cleanup_scope ( + ACPI_PARSE_STATE *state); + + +/* pstree - parse tree manipulation routines */ + +void +acpi_ps_append_arg( + ACPI_GENERIC_OP *op, + ACPI_GENERIC_OP *arg); + +ACPI_GENERIC_OP* +acpi_ps_find ( + ACPI_GENERIC_OP *scope, + char *path, + u16 opcode, + u32 create); + +ACPI_GENERIC_OP * +acpi_ps_get_arg( + ACPI_GENERIC_OP *op, + u32 argn); + +ACPI_GENERIC_OP * +acpi_ps_get_child ( + ACPI_GENERIC_OP *op); + +ACPI_GENERIC_OP * +acpi_ps_get_depth_next ( + ACPI_GENERIC_OP *origin, + ACPI_GENERIC_OP *op); + + +/* pswalk - parse tree walk routines */ + +ACPI_STATUS +acpi_ps_walk_parsed_aml ( + ACPI_GENERIC_OP *start_op, + ACPI_GENERIC_OP *end_op, + ACPI_OBJECT_INTERNAL *mth_desc, + ACPI_NAME_TABLE *start_scope, + ACPI_OBJECT_INTERNAL **params, + ACPI_OBJECT_INTERNAL **caller_return_desc, + ACPI_OWNER_ID owner_id, + INTERPRETER_CALLBACK descending_callback, + INTERPRETER_CALLBACK ascending_callback); + +ACPI_STATUS +acpi_ps_get_next_walk_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op, + INTERPRETER_CALLBACK ascending_callback); + + +/* psutils - parser utilities */ + +void +acpi_ps_init_op ( + ACPI_GENERIC_OP *op, + u16 opcode); + +ACPI_GENERIC_OP * +acpi_ps_alloc_op ( + u16 opcode); + +void +acpi_ps_free_op ( + ACPI_GENERIC_OP *op); + +void +acpi_ps_delete_parse_cache ( + void); + +u8 +acpi_ps_is_leading_char ( + s32 c); + +u8 +acpi_ps_is_prefix_char ( + s32 c); + +u8 +acpi_ps_is_named_op ( + u16 opcode); + +u8 +acpi_ps_is_named_object_op ( + u16 opcode); + +u8 +acpi_ps_is_deferred_op ( + u16 opcode); + +u8 +acpi_ps_is_bytelist_op( + u16 opcode); + +u8 +acpi_ps_is_field_op( + u16 opcode); + +u8 +acpi_ps_is_create_field_op ( + u16 opcode); + +ACPI_NAMED_OP* +acpi_ps_to_named_op( + ACPI_GENERIC_OP *op); + +ACPI_DEFERRED_OP * +acpi_ps_to_deferred_op ( + ACPI_GENERIC_OP *op); + +ACPI_BYTELIST_OP* +acpi_ps_to_bytelist_op( + ACPI_GENERIC_OP *op); + +u32 +acpi_ps_get_name( + ACPI_GENERIC_OP *op); + +void +acpi_ps_set_name( + ACPI_GENERIC_OP *op, + u32 name); + + +/* psdump - display parser tree */ + +s32 +acpi_ps_sprint_path ( + char *buffer_start, + u32 buffer_size, + ACPI_GENERIC_OP *op); + +s32 +acpi_ps_sprint_op ( + char *buffer_start, + u32 buffer_size, + ACPI_GENERIC_OP *op); + +void +acpi_ps_show ( + ACPI_GENERIC_OP *op); + + +#endif /* _PARSER_H_ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/resource.h linux/drivers/acpi/include/resource.h --- v2.4.0-test2/linux/drivers/acpi/include/resource.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/resource.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,300 @@ +/****************************************************************************** + * + * Name: resource.h - Resource Manager function prototypes + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __RESOURCE_H__ +#define __RESOURCE_H__ + +#include "actypes.h" +#include "acobject.h" + +/* + * Function prototypes called from Acpi* APIs + */ + +ACPI_STATUS +acpi_rs_get_prt_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *ret_buffer); + + +ACPI_STATUS +acpi_rs_get_crs_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_rs_get_prs_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_rs_set_srs_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_rs_create_resource_list ( + ACPI_OBJECT_INTERNAL *byte_stream_buffer, + u8 *output_buffer, + u32 *output_buffer_length); + +ACPI_STATUS +acpi_rs_create_byte_stream ( + RESOURCE *linked_list_buffer, + u8 *output_buffer, + u32 *output_buffer_length); + +ACPI_STATUS +acpi_rs_create_pci_routing_table ( + ACPI_OBJECT_INTERNAL *method_return_object, + u8 *output_buffer, + u32 *output_buffer_length); + + +/* + *Function prototypes called from Acpi_rs_create*APIs + */ + +void +acpi_rs_dump_resource_list ( + RESOURCE *resource); + +void +acpi_rs_dump_irq_list ( + u8 *route_table); + +ACPI_STATUS +acpi_rs_get_byte_stream_start ( + u8 *byte_stream_buffer, + u8 **byte_stream_start, + u32 *size); + +ACPI_STATUS +acpi_rs_calculate_list_length ( + u8 *byte_stream_buffer, + u32 byte_stream_buffer_length, + u32 *size_needed); + +ACPI_STATUS +acpi_rs_calculate_byte_stream_length ( + RESOURCE *linked_list_buffer, + u32 *size_needed); + +ACPI_STATUS +acpi_rs_byte_stream_to_list ( + u8 *byte_stream_buffer, + u32 byte_stream_buffer_length, + u8 **output_buffer); + +ACPI_STATUS +acpi_rs_list_to_byte_stream ( + RESOURCE *linked_list, + u32 byte_stream_size_needed, + u8 **output_buffer); + +ACPI_STATUS +acpi_rs_io_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_fixed_io_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_io_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_fixed_io_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_irq_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_irq_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_dma_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_dma_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_address16_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_address16_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_address32_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_address32_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_start_dependent_functions_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_end_dependent_functions_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_start_dependent_functions_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_end_dependent_functions_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_memory24_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_memory24_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_memory32_range_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size +); + +ACPI_STATUS +acpi_rs_fixed_memory32_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_memory32_range_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_fixed_memory32_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_extended_irq_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_extended_irq_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_end_tag_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_end_tag_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_vendor_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_vendor_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + + +#endif /*__RESOURCE_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/include/tables.h linux/drivers/acpi/include/tables.h --- v2.4.0-test2/linux/drivers/acpi/include/tables.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/tables.h Wed Jul 5 11:23:12 2000 @@ -0,0 +1,168 @@ + +/****************************************************************************** + * + * Name: tables.h - ACPI table management + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __TABLES_H__ +#define __TABLES_H__ + +#include "actypes.h" +#include "actables.h" + + +/* Used in Acpi_tb_map_acpi_table for size parameter if table header is to be used */ + +#define SIZE_IN_HEADER 0 + + +ACPI_STATUS +acpi_tb_handle_to_object ( + u16 table_id, + ACPI_TABLE_DESC **table_desc); + + +/* + * Acpi_tbfac - FACP, FACS utilities + */ + +ACPI_STATUS +acpi_tb_get_table_facs ( + char *buffer_ptr, + ACPI_TABLE_DESC *table_info); + + +/* + * Acpi_tbget - Table "get" routines + */ + +ACPI_STATUS +acpi_tb_get_table_ptr ( + ACPI_TABLE_TYPE table_type, + u32 instance, + ACPI_TABLE_HEADER **table_ptr_loc); + +ACPI_STATUS +acpi_tb_get_table ( + void *physical_address, + char *buffer_ptr, + ACPI_TABLE_DESC *table_info); + + +/* + * Acpi_tbgetall - Get all firmware ACPI tables + */ + +ACPI_STATUS +acpi_tb_get_all_tables ( + u32 number_of_tables, + char *buffer_ptr); + + +/* + * Acpi_tbinstall - Table installation + */ + +ACPI_STATUS +acpi_tb_install_table ( + char *table_ptr, + ACPI_TABLE_DESC *table_info); + +ACPI_STATUS +acpi_tb_recognize_table ( + char *table_ptr, + ACPI_TABLE_DESC *table_info); + +ACPI_STATUS +acpi_tb_init_table_descriptor ( + ACPI_TABLE_TYPE table_type, + ACPI_TABLE_DESC *table_info); + + +/* + * Acpi_tbremove - Table removal and deletion + */ + +void +acpi_tb_delete_acpi_tables ( + void); + +void +acpi_tb_delete_acpi_table ( + ACPI_TABLE_TYPE type); + +ACPI_TABLE_DESC * +acpi_tb_delete_single_table ( + ACPI_TABLE_DESC *table_desc); + +void +acpi_tb_free_acpi_tables_of_type ( + ACPI_TABLE_DESC *table_info); + + +/* + * Acpi_tbrsd - RSDP, RSDT utilities + */ + +ACPI_STATUS +acpi_tb_get_table_rsdt ( + u32 *number_of_tables); + +char * +acpi_tb_scan_memory_for_rsdp ( + char *start_address, + u32 length); + +ACPI_STATUS +acpi_tb_find_rsdp ( + ACPI_TABLE_DESC *table_info); + + +/* + * Acpi_tbutils - common table utilities + */ + +u8 +acpi_tb_system_table_pointer ( + void *where); + +ACPI_STATUS +acpi_tb_map_acpi_table ( + void *physical_address, + u32 *size, + void **logical_address); + +ACPI_STATUS +acpi_tb_verify_table_checksum ( + ACPI_TABLE_HEADER *table_header); + +u8 +acpi_tb_checksum ( + void *buffer, + u32 length); + +ACPI_STATUS +acpi_tb_validate_table_header ( + ACPI_TABLE_HEADER *table_header); + + +#endif /* __TABLES_H__ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amconfig.c linux/drivers/acpi/interpreter/amconfig.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amconfig.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amconfig.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,303 @@ + +/****************************************************************************** + * + * Module Name: amconfig - Namespace reconfiguration (Load/Unload opcodes) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "interp.h" +#include "amlcode.h" +#include "namesp.h" +#include "events.h" +#include "tables.h" +#include "dispatch.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amconfig"); + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_load_table + * + * PARAMETERS: Rgn_desc - Op region where the table will be obtained + * Ddb_handle - Where a handle to the table will be returned + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_load_table ( + ACPI_OBJECT_INTERNAL *rgn_desc, + ACPI_HANDLE *ddb_handle) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL *table_desc = NULL; + char *table_ptr; + char *table_data_ptr; + ACPI_TABLE_HEADER table_header; + ACPI_TABLE_DESC table_info; + u32 i; + + + /* TBD: [Unhandled] Object can be either a field or an opregion */ + + + /* Get the table header */ + + table_header.length = 0; + for (i = 0; i < sizeof (ACPI_TABLE_HEADER); i++) { + status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ, + i, 8, (u32 *) ((char *) &table_header + i)); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* Allocate a buffer for the entire table */ + + table_ptr = acpi_cm_allocate (table_header.length); + if (!table_ptr) { + return (AE_NO_MEMORY); + } + + /* Copy the header to the buffer */ + + MEMCPY (table_ptr, &table_header, sizeof (ACPI_TABLE_HEADER)); + table_data_ptr = table_ptr + sizeof (ACPI_TABLE_HEADER); + + + /* Get the table from the op region */ + + for (i = 0; i < table_header.length; i++) { + status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ, + i, 8, (u32 *) (table_data_ptr + i)); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + } + + + /* Table must be either an SSDT or a PSDT */ + + if ((!STRNCMP (table_header.signature, + acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].signature, + acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].sig_length)) && + (!STRNCMP (table_header.signature, + acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].signature, + acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].sig_length))) + { + status = AE_BAD_SIGNATURE; + goto cleanup; + } + + /* Create an object to be the table handle */ + + table_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE); + if (!table_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + + /* Install the new table into the local data structures */ + + table_info.pointer = (ACPI_TABLE_HEADER *) table_ptr; + table_info.length = table_header.length; + table_info.allocation = ACPI_MEM_ALLOCATED; + table_info.base_pointer = table_ptr; + + status = acpi_tb_install_table (NULL, &table_info); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* Add the table to the namespace */ + + status = acpi_load_namespace (); + if (ACPI_FAILURE (status)) { + /* TBD: [Errors] Unload the table on failure ? */ + + goto cleanup; + } + + /* TBD: [Investigate] we need a pointer to the table desc */ + + /* Init the table handle */ + + table_desc->reference.op_code = AML_LOAD_OP; + table_desc->reference.object = table_info.installed_desc; + + *ddb_handle = table_desc; + + return (status); + + +cleanup: + + acpi_cm_free (table_desc); + acpi_cm_free (table_ptr); + return (status); + +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_unload_table + * + * PARAMETERS: Ddb_handle - Handle to a previously loaded table + * + * RETURN: Status + * + * DESCRIPTION: Unload an ACPI table + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_unload_table ( + ACPI_HANDLE ddb_handle) +{ + ACPI_STATUS status = AE_NOT_IMPLEMENTED; + ACPI_OBJECT_INTERNAL *table_desc = (ACPI_OBJECT_INTERNAL *) ddb_handle; + ACPI_TABLE_DESC *table_info; + + + /* Validate the handle */ + /* TBD: [Errors] Wasn't this done earlier? */ + + if ((!ddb_handle) || + (!VALID_DESCRIPTOR_TYPE (ddb_handle, ACPI_DESC_TYPE_INTERNAL)) || + (((ACPI_OBJECT_INTERNAL *)ddb_handle)->common.type != + INTERNAL_TYPE_REFERENCE)) + { + return (AE_BAD_PARAMETER); + } + + + /* Get the actual table descriptor from the Ddb_handle */ + + table_info = (ACPI_TABLE_DESC *) table_desc->reference.object; + + /* + * Delete the entire namespace under this table NTE + * (Offset contains the Table_id) + */ + + status = acpi_ns_delete_namespace_by_owner (table_info->table_id); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Delete the table itself */ + + acpi_tb_delete_single_table (table_info->installed_desc); + + /* Delete the table descriptor (Ddb_handle) */ + + acpi_cm_remove_reference (table_desc); + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_reconfiguration + * + * PARAMETERS: Opcode - The opcode to be executed + * Walk_state - Current state of the parse tree walk + * + * RETURN: Status + * + * DESCRIPTION: Reconfiguration opcodes such as LOAD and UNLOAD + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_reconfiguration ( + u16 opcode, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL *region_desc = NULL; + ACPI_HANDLE *ddb_handle; + + + /* Resolve the operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS); + /* Get the table handle, common for both opcodes */ + + status |= acpi_ds_obj_stack_pop_object ((ACPI_OBJECT_INTERNAL **) &ddb_handle, + walk_state); + + switch (opcode) + { + + case AML_LOAD_OP: + + /* Get the region or field descriptor */ + + status |= acpi_ds_obj_stack_pop_object (®ion_desc, walk_state); + if (status != AE_OK) { + acpi_aml_append_operand_diag (_THIS_MODULE, __LINE__, opcode, + WALK_OPERANDS, 2); + goto cleanup2; + } + + status = acpi_aml_exec_load_table (region_desc, ddb_handle); + break; + + + case AML_UN_LOAD_OP: + + if (status != AE_OK) { + acpi_aml_append_operand_diag (_THIS_MODULE, __LINE__, opcode, + WALK_OPERANDS, 1); + goto cleanup1; + } + + status = acpi_aml_exec_unload_table (ddb_handle); + break; + + + default: + + status = AE_AML_BAD_OPCODE; + break; + } + + +cleanup2: + acpi_cm_remove_reference (region_desc); + +cleanup1: + return (status); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amcreate.c linux/drivers/acpi/interpreter/amcreate.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amcreate.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amcreate.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,871 @@ + +/****************************************************************************** + * + * Module Name: amcreate - Named object creation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "interp.h" +#include "amlcode.h" +#include "namesp.h" +#include "events.h" +#include "dispatch.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amcreate"); + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_field + * + * PARAMETERS: Opcode - The opcode to be executed + * Operands - List of operands for the opcode + * + * RETURN: Status + * + * DESCRIPTION: Execute Create_field operators: Create_bit_field_op, + * Create_byte_field_op, Create_word_field_op, Create_dWord_field_op, + * Create_field_op (which define fields in buffers) + * + * ALLOCATION: Deletes Create_field_op's count operand descriptor + * + * + * ACPI SPECIFICATION REFERENCES: + * Def_create_bit_field := Create_bit_field_op Src_buf Bit_idx Name_string + * Def_create_byte_field := Create_byte_field_op Src_buf Byte_idx Name_string + * Def_create_dWord_field := Create_dWord_field_op Src_buf Byte_idx Name_string + * Def_create_field := Create_field_op Src_buf Bit_idx Num_bits Name_string + * Def_create_word_field := Create_word_field_op Src_buf Byte_idx Name_string + * Bit_index := Term_arg=>Integer + * Byte_index := Term_arg=>Integer + * Num_bits := Term_arg=>Integer + * Source_buff := Term_arg=>Buffer + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_field ( + u16 opcode, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OBJECT_INTERNAL *res_desc = NULL; + ACPI_OBJECT_INTERNAL *cnt_desc = NULL; + ACPI_OBJECT_INTERNAL *off_desc = NULL; + ACPI_OBJECT_INTERNAL *src_desc = NULL; + ACPI_OBJECT_INTERNAL *field_desc; + ACPI_OBJECT_INTERNAL *obj_desc; + OBJECT_TYPE_INTERNAL res_type; + ACPI_STATUS status; + u32 num_operands = 3; + u32 offset; + u32 bit_offset; + u16 bit_count; + u8 type_found; + + + /* Resolve the operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS); + + /* Get the operands */ + + status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); + if (AML_CREATE_FIELD_OP == opcode) { + num_operands = 4; + status |= acpi_ds_obj_stack_pop_object (&cnt_desc, walk_state); + } + + status |= acpi_ds_obj_stack_pop_object (&off_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&src_desc, walk_state); + + if (status != AE_OK) { + /* Invalid parameters on object stack */ + + acpi_aml_append_operand_diag (_THIS_MODULE, __LINE__, opcode, + WALK_OPERANDS, 3); + goto cleanup; + } + + + offset = off_desc->number.value; + + + /* + * If Res_desc is a Name, it will be a direct name pointer after + * Acpi_aml_resolve_operands() + */ + + if (!VALID_DESCRIPTOR_TYPE (res_desc, ACPI_DESC_TYPE_NAMED)) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + + /* + * Setup the Bit offsets and counts, according to the opcode + */ + + switch (opcode) + { + + /* Def_create_bit_field */ + + case AML_BIT_FIELD_OP: + + /* Offset is in bits, Field is a bit */ + + bit_offset = offset; + bit_count = 1; + break; + + + /* Def_create_byte_field */ + + case AML_BYTE_FIELD_OP: + + /* Offset is in bytes, field is a byte */ + + bit_offset = 8 * offset; + bit_count = 8; + break; + + + /* Def_create_word_field */ + + case AML_WORD_FIELD_OP: + + /* Offset is in bytes, field is a word */ + + bit_offset = 8 * offset; + bit_count = 16; + break; + + + /* Def_create_dWord_field */ + + case AML_DWORD_FIELD_OP: + + /* Offset is in bytes, field is a dword */ + + bit_offset = 8 * offset; + bit_count = 32; + break; + + + /* Def_create_field */ + + case AML_CREATE_FIELD_OP: + + /* Offset is in bits, count is in bits */ + + bit_offset = offset; + bit_count = (u16) cnt_desc->number.value; + break; + + + default: + + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + + /* + * Setup field according to the object type + */ + + switch (src_desc->common.type) + { + + /* Source_buff := Term_arg=>Buffer */ + + case ACPI_TYPE_BUFFER: + + if (bit_offset + (u32) bit_count > + (8 * (u32) src_desc->buffer.length)) + { + status = AE_AML_BUFFER_LIMIT; + goto cleanup; + } + + + /* Allocate an object for the field */ + + field_desc = acpi_cm_create_internal_object (ACPI_TYPE_FIELD_UNIT); + if (!field_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Construct the field object */ + + field_desc->field_unit.access = (u8) ACCESS_ANY_ACC; + field_desc->field_unit.lock_rule = (u8) GLOCK_NEVER_LOCK; + field_desc->field_unit.update_rule = (u8) UPDATE_PRESERVE; + field_desc->field_unit.length = bit_count; + field_desc->field_unit.bit_offset = (u8) (bit_offset % 8); + field_desc->field_unit.offset = DIV_8 (bit_offset); + field_desc->field_unit.container = src_desc; + field_desc->field_unit.sequence = src_desc->buffer.sequence; + + /* An additional reference for Src_desc */ + + acpi_cm_add_reference (src_desc); + + break; + + + /* Improper object type */ + + default: + + type_found = src_desc->common.type; + + if ((type_found > (u8) INTERNAL_TYPE_REFERENCE) || + !acpi_cm_valid_object_type (type_found)) + + + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + + if (AML_CREATE_FIELD_OP == opcode) { + /* Delete object descriptor unique to Create_field */ + + acpi_cm_remove_reference (cnt_desc); + cnt_desc = NULL; + } + + /* + * This operation is supposed to cause the destination Name to refer + * to the defined Field_unit -- it must not store the constructed + * Field_unit object (or its current value) in some location that the + * Name may already be pointing to. So, if the Name currently contains + * a reference which would cause Acpi_aml_exec_store() to perform an indirect + * store rather than setting the value of the Name itself, clobber that + * reference before calling Acpi_aml_exec_store(). + */ + + res_type = acpi_ns_get_type (res_desc); + + /* Type of Name's existing value */ + + switch (res_type) + { + + case ACPI_TYPE_FIELD_UNIT: + + case INTERNAL_TYPE_ALIAS: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_DEF_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + + obj_desc = acpi_ns_get_attached_object (res_desc); + if (obj_desc) { + /* + * There is an existing object here; delete it and zero out the + * NTE + */ + + acpi_cm_remove_reference (obj_desc); + acpi_ns_attach_object (res_desc, NULL, ACPI_TYPE_ANY); + } + + /* Set the type to ANY (or the store below will fail) */ + + ((ACPI_NAMED_OBJECT*) res_desc)->type = ACPI_TYPE_ANY; + + break; + + + default: + + break; + } + + + /* Store constructed field descriptor in result location */ + + status = acpi_aml_exec_store (field_desc, res_desc); + + /* + * If the field descriptor was not physically stored (or if a failure + * above), we must delete it + */ + if (field_desc->common.reference_count <= 1) { + acpi_cm_remove_reference (field_desc); + } + + +cleanup: + + /* Always delete the operands */ + + acpi_cm_remove_reference (off_desc); + acpi_cm_remove_reference (src_desc); + + if (AML_CREATE_FIELD_OP == opcode) { + acpi_cm_remove_reference (cnt_desc); + } + + /* On failure, delete the result descriptor */ + + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (res_desc); /* Result descriptor */ + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_alias + * + * PARAMETERS: Operands - List of operands for the opcode + * + * RETURN: Status + * + * DESCRIPTION: Create a new named alias + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_alias ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_NAMED_OBJECT *src_entry; + ACPI_NAMED_OBJECT *alias_entry; + ACPI_STATUS status; + + + /* Get the source/alias operands (both NTEs) */ + + status = acpi_ds_obj_stack_pop_object ((ACPI_OBJECT_INTERNAL **) &src_entry, + walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Don't pop it, it gets popped later */ + + alias_entry = acpi_ds_obj_stack_get_value (0, walk_state); + + /* Add an additional reference to the object */ + + acpi_cm_add_reference (src_entry->object); + + /* + * Attach the original source NTE to the new Alias NTE. + */ + status = acpi_ns_attach_object (alias_entry, src_entry->object, + src_entry->type); + + + /* + * The new alias assumes the type of the source, but it points + * to the same object. The reference count of the object has two + * additional references to prevent deletion out from under either the + * source or the alias NTE + */ + + /* Since both operands are NTEs, we don't need to delete them */ + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_event + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create a new event object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_event ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL *obj_desc; + + + BREAKPOINT3; + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_EVENT); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Create the actual OS semaphore */ + + /* TBD: [Investigate] should be created with 0 or 1 units? */ + + status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 1, + &obj_desc->event.semaphore); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (obj_desc); + goto cleanup; + } + + /* Attach object to the NTE */ + + status = acpi_ns_attach_object (acpi_ds_obj_stack_get_value (0, walk_state), + obj_desc, (u8) ACPI_TYPE_EVENT); + if (ACPI_FAILURE (status)) { + acpi_os_delete_semaphore (obj_desc->event.semaphore); + acpi_cm_remove_reference (obj_desc); + goto cleanup; + } + + +cleanup: + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_mutex + * + * PARAMETERS: Interpreter_mode - Current running mode (load1/Load2/Exec) + * Operands - List of operands for the opcode + * + * RETURN: Status + * + * DESCRIPTION: Create a new mutex object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_mutex ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + ACPI_OBJECT_INTERNAL *sync_desc; + ACPI_OBJECT_INTERNAL *obj_desc; + + + /* Get the operand */ + + status = acpi_ds_obj_stack_pop_object (&sync_desc, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Attempt to allocate a new object */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_MUTEX); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Create the actual OS semaphore */ + + status = acpi_os_create_semaphore (1, 1, &obj_desc->mutex.semaphore); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (obj_desc); + goto cleanup; + } + + obj_desc->mutex.sync_level = (u8) sync_desc->number.value; + + /* Obj_desc was on the stack top, and the name is below it */ + + status = acpi_ns_attach_object (acpi_ds_obj_stack_get_value (0, walk_state), + obj_desc, (u8) ACPI_TYPE_MUTEX); + if (ACPI_FAILURE (status)) { + acpi_os_delete_semaphore (obj_desc->mutex.semaphore); + acpi_cm_remove_reference (obj_desc); + goto cleanup; + } + + +cleanup: + + /* Always delete the operand */ + + acpi_cm_remove_reference (sync_desc); + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_region + * + * PARAMETERS: Aml_ptr - Pointer to the region declaration AML + * Aml_length - Max length of the declaration AML + * Operands - List of operands for the opcode + * Interpreter_mode - Load1/Load2/Execute + * + * RETURN: Status + * + * DESCRIPTION: Create a new operation region object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_region ( + u8 *aml_ptr, + u32 aml_length, + u32 region_space, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL *obj_desc_region; + ACPI_HANDLE *entry; + + + if (region_space >= NUM_REGION_TYPES) { + /* TBD: [Errors] should this return an error, or should we just keep + * going? */ + + REPORT_WARNING ("Unable to decode the Region_space"); + } + + + /* Get the NTE from the object stack */ + + entry = acpi_ds_obj_stack_get_value (0, walk_state); + + + /* Create the region descriptor */ + + obj_desc_region = acpi_cm_create_internal_object (ACPI_TYPE_REGION); + if (!obj_desc_region) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Allocate a method object for this region. + */ + obj_desc_region->region.method = acpi_cm_create_internal_object ( + ACPI_TYPE_METHOD); + if (!obj_desc_region->region.method) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Init the region from the operands */ + + obj_desc_region->region.space_id = (u16) region_space; + obj_desc_region->region.address = 0; + obj_desc_region->region.length = 0; + obj_desc_region->region.region_flags = 0; + + /* + * Remember location in AML stream of address & length + * operands since they need to be evaluated at run time. + */ + obj_desc_region->region.method->method.pcode = aml_ptr; + obj_desc_region->region.method->method.pcode_length = aml_length; + + + /* Install the new region object in the parent NTE */ + + obj_desc_region->region.nte = (ACPI_NAMED_OBJECT*) entry; + + status = acpi_ns_attach_object (entry, obj_desc_region, + (u8) ACPI_TYPE_REGION); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + +cleanup: + + if (status != AE_OK) { + /* Delete region object and method subobject */ + + if (obj_desc_region) { + /* Remove deletes both objects! */ + + acpi_cm_remove_reference (obj_desc_region); + obj_desc_region = NULL; + } + } + + + /* + * If we have a valid region, initialize it + */ + if (obj_desc_region) { + /* + * TBD: [Errors] Is there anything we can or could do when this + * fails? + * We need to do something useful with a failure. + */ + /* Namespace IS locked */ + + (void *) acpi_ev_initialize_region (obj_desc_region, TRUE); + + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_processor + * + * PARAMETERS: Op - Op containing the Processor definition and + * args + * Processor_nTE - NTE for the containing NTE + * + * RETURN: Status + * + * DESCRIPTION: Create a new processor object and populate the fields + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_processor ( + ACPI_GENERIC_OP *op, + ACPI_HANDLE processor_nTE) +{ + ACPI_STATUS status; + ACPI_GENERIC_OP *arg; + ACPI_OBJECT_INTERNAL *obj_desc; + + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_PROCESSOR); + if (!obj_desc) { + status = AE_NO_MEMORY; + return (status); + } + + /* Install the new processor object in the parent NTE */ + + status = acpi_ns_attach_object (processor_nTE, obj_desc, + (u8) ACPI_TYPE_PROCESSOR); + if (ACPI_FAILURE (status)) { + return(status); + } + + arg = op->value.arg; + + /* check existence */ + + if (!arg) { + status = AE_AML_NO_OPERAND; + return (status); + } + + /* First arg is the Processor ID */ + + obj_desc->processor.proc_id = (u8) arg->value.integer; + + /* Move to next arg and check existence */ + + arg = arg->next; + if (!arg) { + status = AE_AML_NO_OPERAND; + return (status); + } + + /* Second arg is the PBlock Address */ + + obj_desc->processor.pblk_address = (ACPI_IO_ADDRESS) arg->value.integer; + + /* Move to next arg and check existence */ + + arg = arg->next; + if (!arg) { + status = AE_AML_NO_OPERAND; + return (status); + } + + /* Third arg is the PBlock Length */ + + obj_desc->processor.pblk_length = (u8) arg->value.integer; + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_power_resource + * + * PARAMETERS: Op - Op containing the Power_resource definition + * and args + * Power_res_nTE - NTE for the containing NTE + * + * RETURN: Status + * + * DESCRIPTION: Create a new Power_resource object and populate the fields + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_power_resource ( + ACPI_GENERIC_OP *op, + ACPI_HANDLE power_res_nTE) +{ + ACPI_STATUS status; + ACPI_GENERIC_OP *arg; + ACPI_OBJECT_INTERNAL *obj_desc; + + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_POWER); + if (!obj_desc) { + status = AE_NO_MEMORY; + return (status); + } + + /* Install the new power resource object in the parent NTE */ + + status = acpi_ns_attach_object (power_res_nTE, obj_desc, + (u8) ACPI_TYPE_POWER); + if (ACPI_FAILURE (status)) { + return(status); + } + + arg = op->value.arg; + + /* check existence */ + + if (!arg) { + status = AE_AML_NO_OPERAND; + return (status); + } + + /* First arg is the System_level */ + + obj_desc->power_resource.system_level = (u8) arg->value.integer; + + /* Move to next arg and check existence */ + + arg = arg->next; + if (!arg) { + status = AE_AML_NO_OPERAND; + return (status); + } + + /* Second arg is the PBlock Address */ + + obj_desc->power_resource.resource_order = (u16) arg->value.integer; + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_method + * + * PARAMETERS: Interpreter_mode - Current running mode (load1/Load2/Exec) + * + * RETURN: Status + * + * DESCRIPTION: Create a new mutex object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_method ( + u8 *aml_ptr, + u32 aml_length, + u32 method_flags, + ACPI_HANDLE method) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_STATUS status; + + + /* Create a new method object */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_METHOD); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Get the method's AML pointer/length from the Op */ + + obj_desc->method.pcode = aml_ptr; + obj_desc->method.pcode_length = aml_length; + + /* + * First argument is the Method Flags (contains parameter count for the + * method) + */ + + obj_desc->method.method_flags = (u8) method_flags; + obj_desc->method.param_count = (u8) (method_flags & + METHOD_FLAGS_ARG_COUNT); + + /* + * Get the concurrency count + * If required, a semaphore will be created for this method when it is + * parsed. + * + * TBD: [Future] for APCI 2.0, there will be a Sync_level value, not + * just a flag + * Concurrency = Sync_level + 1;. + */ + + if (method_flags & METHOD_FLAGS_SERIALIZED) { + obj_desc->method.concurrency = 1; + } + else { + obj_desc->method.concurrency = INFINITE_CONCURRENCY; + } + + /* Mark the Method as not parsed yet */ + + obj_desc->method.parser_op = NULL; + + /* + * Another +1 gets added when Acpi_psx_execute is called, + * no need for: Obj_desc->Method.Pcode++; + */ + + obj_desc->method.acpi_table = NULL; /* TBD: [Restructure] was (u8 *) Pcode_addr; */ + obj_desc->method.table_length = 0; /* TBD: [Restructure] needed? (u32) (Walk_state->aml_end - Pcode_addr); */ + + /* Attach the new object to the method NTE */ + + status = acpi_ns_attach_object (method, obj_desc, (u8) ACPI_TYPE_METHOD); + if (ACPI_FAILURE (status)) { + acpi_cm_free (obj_desc); + } + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amdyadic.c linux/drivers/acpi/interpreter/amdyadic.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amdyadic.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amdyadic.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,750 @@ + +/****************************************************************************** + * + * Module Name: amdyadic - ACPI AML (p-code) execution for dyadic operators + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "namesp.h" +#include "interp.h" +#include "events.h" +#include "amlcode.h" +#include "dispatch.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amdyadic"); + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_dyadic1 + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 1 dyadic operator with numeric operands: + * Notify_op + * + * ALLOCATION: Deletes both operands + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_dyadic1 ( + u16 opcode, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OBJECT_INTERNAL *obj_desc = NULL; + ACPI_OBJECT_INTERNAL *val_desc = NULL; + ACPI_NAMED_OBJECT *entry; + ACPI_STATUS status = AE_OK; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS); + /* Get the operands */ + + status |= acpi_ds_obj_stack_pop_object (&val_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + acpi_aml_append_operand_diag (_THIS_MODULE, __LINE__, opcode, + WALK_OPERANDS, 2); + goto cleanup; + } + + + /* Examine the opcode */ + + switch (opcode) + { + + /* Def_notify := Notify_op Notify_object Notify_value */ + + case AML_NOTIFY_OP: + + /* The Obj_desc is actually an NTE */ + + entry = (ACPI_NAMED_OBJECT*) obj_desc; + obj_desc = NULL; + + /* Object must be a device or thermal zone */ + + if (entry && val_desc) { + switch (entry->type) + { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + + /* + * Requires that Device and Thermal_zone be compatible + * mappings + */ + + /* Dispatch the notify to the appropriate handler */ + + acpi_ev_notify_dispatch (entry, val_desc->number.value); + break; + + default: + status = AE_AML_OPERAND_TYPE; + } + } + break; + + default: + status = AE_AML_BAD_OPCODE; + } + + +cleanup: + + /* Always delete both operands */ + + acpi_cm_remove_reference (val_desc); + acpi_cm_remove_reference (obj_desc); + + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_dyadic2_r + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 dyadic operator with numeric operands and + * one or two result operands. + * + * ALLOCATION: Deletes one operand descriptor -- other remains on stack + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_dyadic2_r ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL **return_desc) +{ + ACPI_OBJECT_INTERNAL *obj_desc = NULL; + ACPI_OBJECT_INTERNAL *obj_desc2 = NULL; + ACPI_OBJECT_INTERNAL *res_desc = NULL; + ACPI_OBJECT_INTERNAL *res_desc2 = NULL; + ACPI_OBJECT_INTERNAL *ret_desc = NULL; + ACPI_OBJECT_INTERNAL *ret_desc2 = NULL; + ACPI_STATUS status = AE_OK; + u32 remainder; + s32 num_operands = 3; + char *new_buf; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS); + /* Get all operands */ + + if (AML_DIVIDE_OP == opcode) { + num_operands = 4; + status |= acpi_ds_obj_stack_pop_object (&res_desc2, walk_state); + } + + status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc2, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (status != AE_OK) { + acpi_aml_append_operand_diag (_THIS_MODULE, __LINE__, opcode, + &(walk_state->operands [walk_state->num_operands -1]), + num_operands); + goto cleanup; + } + + + /* Create an internal return object if necessary */ + + switch (opcode) + { + case AML_ADD_OP: + case AML_BIT_AND_OP: + case AML_BIT_NAND_OP: + case AML_BIT_OR_OP: + case AML_BIT_NOR_OP: + case AML_BIT_XOR_OP: + case AML_DIVIDE_OP: + case AML_MULTIPLY_OP: + case AML_SHIFT_LEFT_OP: + case AML_SHIFT_RIGHT_OP: + case AML_SUBTRACT_OP: + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + break; + } + + + /* + * Execute the opcode + */ + + switch (opcode) + { + + /* Def_add := Add_op Operand1 Operand2 Result */ + + case AML_ADD_OP: + + ret_desc->number.value = obj_desc->number.value + + obj_desc2->number.value; + break; + + + /* Def_and := And_op Operand1 Operand2 Result */ + + case AML_BIT_AND_OP: + + ret_desc->number.value = obj_desc->number.value & + obj_desc2->number.value; + break; + + + /* Def_nAnd := NAnd_op Operand1 Operand2 Result */ + + case AML_BIT_NAND_OP: + + ret_desc->number.value = ~(obj_desc->number.value & + obj_desc2->number.value); + break; + + + /* Def_or := Or_op Operand1 Operand2 Result */ + + case AML_BIT_OR_OP: + + ret_desc->number.value = obj_desc->number.value | + obj_desc2->number.value; + break; + + + /* Def_nOr := NOr_op Operand1 Operand2 Result */ + + case AML_BIT_NOR_OP: + + ret_desc->number.value = ~(obj_desc->number.value | + obj_desc2->number.value); + break; + + + /* Def_xOr := XOr_op Operand1 Operand2 Result */ + + case AML_BIT_XOR_OP: + + ret_desc->number.value = obj_desc->number.value ^ + obj_desc2->number.value; + break; + + + /* Def_divide := Divide_op Dividend Divisor Remainder Quotient */ + + case AML_DIVIDE_OP: + + if ((u32) 0 == obj_desc2->number.value) { + REPORT_ERROR ("Aml_exec_dyadic2_r/Divide_op: Divide by zero"); + + status = AE_AML_DIVIDE_BY_ZERO; + goto cleanup; + } + + ret_desc2 = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER); + if (!ret_desc2) { + status = AE_NO_MEMORY; + goto cleanup; + } + + remainder = obj_desc->number.value % + obj_desc2->number.value; + ret_desc->number.value = remainder; + + /* Result (what we used to call the quotient) */ + + ret_desc2->number.value = obj_desc->number.value / + obj_desc2->number.value; + break; + + + /* Def_multiply := Multiply_op Operand1 Operand2 Result */ + + case AML_MULTIPLY_OP: + + ret_desc->number.value = obj_desc->number.value * + obj_desc2->number.value; + break; + + + /* Def_shift_left := Shift_left_op Operand Shift_count Result */ + + case AML_SHIFT_LEFT_OP: + + ret_desc->number.value = obj_desc->number.value << + obj_desc2->number.value; + break; + + + /* Def_shift_right := Shift_right_op Operand Shift_count Result */ + + case AML_SHIFT_RIGHT_OP: + + ret_desc->number.value = obj_desc->number.value >> + obj_desc2->number.value; + break; + + + /* Def_subtract := Subtract_op Operand1 Operand2 Result */ + + case AML_SUBTRACT_OP: + + ret_desc->number.value = obj_desc->number.value - + obj_desc2->number.value; + break; + + + /* Def_concat := Concat_op Data1 Data2 Result */ + + case AML_CONCAT_OP: + + if (obj_desc2->common.type != obj_desc->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + /* Both operands are now known to be the same */ + + if (ACPI_TYPE_STRING == obj_desc->common.type) { + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Operand1 is string */ + + new_buf = acpi_cm_allocate (obj_desc->string.length + + obj_desc2->string.length + 1); + if (!new_buf) { + REPORT_ERROR + ("Aml_exec_dyadic2_r/Concat_op: String allocation failure"); + status = AE_NO_MEMORY; + goto cleanup; + } + + STRCPY (new_buf, (char *) obj_desc->string.pointer); + STRCPY (new_buf + obj_desc->string.length, + (char *) obj_desc2->string.pointer); + + /* Point the return object to the new string */ + + ret_desc->string.pointer = new_buf; + ret_desc->string.length = obj_desc->string.length += + obj_desc2->string.length; + } + + else { + /* Operand1 is not a string ==> must be a buffer */ + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + new_buf = acpi_cm_allocate (obj_desc->buffer.length + + obj_desc2->buffer.length); + if (!new_buf) { + /* Only bail out if the buffer is small */ + + /* TBD: [Investigate] what is the point of this code? */ + + if (obj_desc->buffer.length + obj_desc2->buffer.length < 1024) { + REPORT_ERROR + ("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure"); + return (AE_NO_MEMORY); + } + + status = AE_NO_MEMORY; + goto cleanup; + } + + MEMCPY (new_buf, obj_desc->buffer.pointer, + obj_desc->buffer.length); + MEMCPY (new_buf + obj_desc->buffer.length, obj_desc2->buffer.pointer, + obj_desc2->buffer.length); + + /* + * Point the return object to the new buffer + */ + + ret_desc->buffer.pointer = (u8 *) new_buf; + ret_desc->buffer.length = obj_desc->buffer.length + + obj_desc2->buffer.length; + } + break; + + + default: + + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + + /* + * Store the result of the operation (which is now in Obj_desc) into + * the result descriptor, or the location pointed to by the result + * descriptor (Res_desc). + */ + + if ((status = acpi_aml_exec_store (ret_desc, res_desc)) != AE_OK) { + goto cleanup; + } + + if (AML_DIVIDE_OP == opcode) { + status = acpi_aml_exec_store (ret_desc2, res_desc2); + + /* + * Since the remainder is not returned, remove a reference to + * the object we created earlier + */ + + acpi_cm_remove_reference (ret_desc2); + } + + +cleanup: + + /* Always delete the operands */ + + acpi_cm_remove_reference (obj_desc); + acpi_cm_remove_reference (obj_desc2); + + + /* Delete return object on error */ + + if (ACPI_FAILURE (status)) { + /* On failure, delete the result ops */ + + acpi_cm_remove_reference (res_desc); + acpi_cm_remove_reference (res_desc2); + + if (ret_desc) { + /* And delete the internal return object */ + + acpi_cm_remove_reference (ret_desc); + ret_desc = NULL; + } + } + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_dyadic2_s + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 dyadic synchronization operator + * + * ALLOCATION: Deletes one operand descriptor -- other remains on stack + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_dyadic2_s ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL **return_desc) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_OBJECT_INTERNAL *time_desc; + ACPI_OBJECT_INTERNAL *ret_desc = NULL; + ACPI_STATUS status; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&time_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (status != AE_OK) { + /* Invalid parameters on object stack */ + + acpi_aml_append_operand_diag (_THIS_MODULE, __LINE__, opcode, + WALK_OPERANDS, 2); + goto cleanup; + } + + + /* Create the internal return object */ + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Default return value is FALSE, operation did not time out */ + + ret_desc->number.value = 0; + + + /* Examine the opcode */ + + switch (opcode) + { + + /* Def_acquire := Acquire_op Mutex_object Timeout */ + + case AML_ACQUIRE_OP: + + status = acpi_aml_system_acquire_mutex (time_desc, obj_desc); + break; + + + /* Def_wait := Wait_op Acpi_event_object Timeout */ + + case AML_WAIT_OP: + + status = acpi_aml_system_wait_event (time_desc, obj_desc); + break; + + + default: + + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + + /* + * Return a boolean indicating if operation timed out + * (TRUE) or not (FALSE) + */ + + if (status == AE_TIME) { + ret_desc->number.value = (u32)(-1); /* TRUE, op timed out */ + status = AE_OK; + } + + +cleanup: + + /* Delete params */ + + acpi_cm_remove_reference (time_desc); + acpi_cm_remove_reference (obj_desc); + + /* Delete return object on error */ + + if (ACPI_FAILURE (status) && + (ret_desc)) + { + acpi_cm_remove_reference (ret_desc); + ret_desc = NULL; + } + + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_dyadic2 + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 dyadic operator with numeric operands and + * no result operands + * + * ALLOCATION: Deletes one operand descriptor -- other remains on stack + * containing result value + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_dyadic2 ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL **return_desc) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_OBJECT_INTERNAL *obj_desc2; + ACPI_OBJECT_INTERNAL *ret_desc = NULL; + ACPI_STATUS status; + u8 lboolean; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&obj_desc2, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (status != AE_OK) { + /* Invalid parameters on object stack */ + + acpi_aml_append_operand_diag (_THIS_MODULE, __LINE__, opcode, + WALK_OPERANDS, 2); + goto cleanup; + } + + + /* Create the internal return object */ + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Execute the Opcode + */ + + lboolean = FALSE; + switch (opcode) + { + + /* Def_lAnd := LAnd_op Operand1 Operand2 */ + + case AML_LAND_OP: + + lboolean = (u8) (obj_desc->number.value && + obj_desc2->number.value); + break; + + + /* Def_lEqual := LEqual_op Operand1 Operand2 */ + + case AML_LEQUAL_OP: + + lboolean = (u8) (obj_desc->number.value == + obj_desc2->number.value); + break; + + + /* Def_lGreater := LGreater_op Operand1 Operand2 */ + + case AML_LGREATER_OP: + + lboolean = (u8) (obj_desc->number.value > + obj_desc2->number.value); + break; + + + /* Def_lLess := LLess_op Operand1 Operand2 */ + + case AML_LLESS_OP: + + lboolean = (u8) (obj_desc->number.value < + obj_desc2->number.value); + break; + + + /* Def_lOr := LOr_op Operand1 Operand2 */ + + case AML_LOR_OP: + + lboolean = (u8) (obj_desc->number.value || + obj_desc2->number.value); + break; + + + default: + + status = AE_AML_BAD_OPCODE; + goto cleanup; + break; + } + + + /* Set return value to logical TRUE (all ones) or FALSE (zero) */ + + if (lboolean) { + ret_desc->number.value = 0xffffffff; + } + else { + ret_desc->number.value = 0; + } + + +cleanup: + + /* Always delete operands */ + + acpi_cm_remove_reference (obj_desc); + acpi_cm_remove_reference (obj_desc2); + + + /* Delete return object on error */ + + if (ACPI_FAILURE (status) && + (ret_desc)) + { + acpi_cm_remove_reference (ret_desc); + ret_desc = NULL; + } + + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amfield.c linux/drivers/acpi/interpreter/amfield.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amfield.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amfield.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,327 @@ +/****************************************************************************** + * + * Module Name: amfield - ACPI AML (p-code) execution - field manipulation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "dispatch.h" +#include "interp.h" +#include "amlcode.h" +#include "namesp.h" +#include "hardware.h" +#include "events.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amfield"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_setup_field + * + * PARAMETERS: *Obj_desc - Field to be read or written + * *Rgn_desc - Region containing field + * Field_bit_width - Field Width in bits (8, 16, or 32) + * + * RETURN: Status + * + * DESCRIPTION: Common processing for Acpi_aml_read_field and Acpi_aml_write_field + * + * ACPI SPECIFICATION REFERENCES: + * Each of the Type1_opcodes is defined as specified in in-line + * comments below. For each one, use the following definitions. + * + * Def_bit_field := Bit_field_op Src_buf Bit_idx Destination + * Def_byte_field := Byte_field_op Src_buf Byte_idx Destination + * Def_create_field := Create_field_op Src_buf Bit_idx Num_bits Name_string + * Def_dWord_field := DWord_field_op Src_buf Byte_idx Destination + * Def_word_field := Word_field_op Src_buf Byte_idx Destination + * Bit_index := Term_arg=>Integer + * Byte_index := Term_arg=>Integer + * Destination := Name_string + * Num_bits := Term_arg=>Integer + * Source_buf := Term_arg=>Buffer + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_setup_field ( + ACPI_OBJECT_INTERNAL *obj_desc, + ACPI_OBJECT_INTERNAL *rgn_desc, + s32 field_bit_width) +{ + ACPI_STATUS status = AE_OK; + s32 field_byte_width; + + + /* Parameter validation */ + + if (!obj_desc || !rgn_desc) { + return (AE_AML_NO_OPERAND); + } + + if (ACPI_TYPE_REGION != rgn_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + + /* + * Init and validate Field width + * Possible values are 1, 2, 4 + */ + + field_byte_width = DIV_8 (field_bit_width); + + if ((field_bit_width != 8) && + (field_bit_width != 16) && + (field_bit_width != 32)) + { + return (AE_AML_OPERAND_VALUE); + } + + + /* + * If the address and length have not been previously evaluated, + * evaluate them and save the results. + */ + if (!(rgn_desc->region.region_flags & REGION_AGRUMENT_DATA_VALID)) { + + status = acpi_ds_get_region_arguments (rgn_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + + /* + * If (offset rounded up to next multiple of field width) + * exceeds region length, indicate an error. + */ + + if (rgn_desc->region.length < + (obj_desc->field.offset & ~((u32) field_byte_width - 1)) + + field_byte_width) + { + /* + * Offset rounded up to next multiple of field width + * exceeds region length, indicate an error + */ + + return (AE_AML_REGION_LIMIT); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_access_named_field + * + * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE + * Named_field - Handle for field to be accessed + * *Buffer - Value(s) to be read or written + * Buffer_length - Number of bytes to transfer + * + * RETURN: Status + * + * DESCRIPTION: Read or write a named field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_access_named_field ( + s32 mode, + ACPI_HANDLE named_field, + void *buffer, + u32 buffer_length) +{ + ACPI_OBJECT_INTERNAL *obj_desc = NULL; + ACPI_STATUS status = AE_OK; + u8 locked = FALSE; + u32 bit_granularity = 0; + u32 byte_granularity; + u32 datum_length; + u32 actual_byte_length; + u32 byte_field_length; + + + /* Get the attached field object */ + + obj_desc = acpi_ns_get_attached_object (named_field); + if (!obj_desc) { + return (AE_AML_INTERNAL); + } + + /* Check the type */ + + if (INTERNAL_TYPE_DEF_FIELD != acpi_ns_get_type (named_field)) { + return (AE_AML_OPERAND_TYPE); + } + + /* Obj_desc valid and Named_field is a defined field */ + + + /* Double-check that the attached object is also a field */ + + if (INTERNAL_TYPE_DEF_FIELD != obj_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + + /* + * Granularity was decoded from the field access type + * (Any_acc will be the same as Byte_acc) + */ + + bit_granularity = obj_desc->field_unit.granularity; + byte_granularity = DIV_8 (bit_granularity); + + /* + * Check if request is too large for the field, and silently truncate + * if necessary + */ + + /* TBD: [Errors] should an error be returned in this case? */ + + byte_field_length = (u32) DIV_8 (obj_desc->field_unit.length + 7); + + + actual_byte_length = buffer_length; + if (buffer_length > byte_field_length) { + actual_byte_length = byte_field_length; + + } + + + /* Convert byte count to datum count, round up if necessary */ + + datum_length = (actual_byte_length + (byte_granularity-1)) / byte_granularity; + + + /* Get the global lock if needed */ + + locked = acpi_aml_acquire_global_lock (obj_desc->field_unit.lock_rule); + + + /* Perform the actual read or write of the buffer */ + + switch (mode) + { + case ACPI_READ: + + status = acpi_aml_read_field (obj_desc, buffer, buffer_length, + actual_byte_length, datum_length, + bit_granularity, byte_granularity); + break; + + + case ACPI_WRITE: + + status = acpi_aml_write_field (obj_desc, buffer, buffer_length, + actual_byte_length, datum_length, + bit_granularity, byte_granularity); + break; + + + default: + + status = AE_BAD_PARAMETER; + break; + } + + + /* Release global lock if we acquired it earlier */ + + acpi_aml_release_global_lock (locked); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_set_named_field_value + * + * PARAMETERS: Named_field - Handle for field to be set + * Buffer - Bytes to be stored + * Buffer_length - Number of bytes to be stored + * + * RETURN: Status + * + * DESCRIPTION: Store the given value into the field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_set_named_field_value ( + ACPI_HANDLE named_field, + void *buffer, + u32 buffer_length) +{ + ACPI_STATUS status; + + + if (!named_field) { + return (AE_AML_INTERNAL); + } + + status = acpi_aml_access_named_field (ACPI_WRITE, named_field, buffer, + buffer_length); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_get_named_field_value + * + * PARAMETERS: Named_field - Handle for field to be read + * *Buffer - Where to store value read from field + * Buffer_length - Max length to read + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value of the given field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_get_named_field_value ( + ACPI_HANDLE named_field, + void *buffer, + u32 buffer_length) +{ + ACPI_STATUS status; + + + if ((!named_field) || (!buffer)) { + return (AE_AML_INTERNAL); + } + + status = acpi_aml_access_named_field (ACPI_READ, named_field, buffer, + buffer_length); + return (status); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amfldio.c linux/drivers/acpi/interpreter/amfldio.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amfldio.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amfldio.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,654 @@ +/****************************************************************************** + * + * Module Name: amfldio - Aml Field I/O + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" +#include "amlcode.h" +#include "namesp.h" +#include "hardware.h" +#include "events.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amfldio"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_read_field_data + * + * PARAMETERS: *Obj_desc - Field to be read + * *Value - Where to store value + * Field_bit_width - Field Width in bits (8, 16, or 32) + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value of the given field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_read_field_data ( + ACPI_OBJECT_INTERNAL *obj_desc, + u32 field_byte_offset, + u32 field_bit_width, + u32 *value) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL *rgn_desc = NULL; + u32 address; + u32 local_value = 0; + s32 field_byte_width; + + + /* Obj_desc is validated by callers */ + + if (obj_desc) { + rgn_desc = obj_desc->field.container; + } + + + field_byte_width = DIV_8 (field_bit_width); + status = acpi_aml_setup_field (obj_desc, rgn_desc, field_bit_width); + if (AE_OK != status) { + return (status); + } + + /* Setup_field validated Rgn_desc and Field_bit_width */ + + if (!value) { + value = &local_value; /* support reads without saving value */ + } + + + /* + * Round offset down to next multiple of + * field width, add region base address and offset within the field + */ + + address = rgn_desc->region.address + + (obj_desc->field.offset & ~((u32) field_byte_width - 1)) + + field_byte_offset; + + + + + /* Invoke the appropriate Address_space/Op_region handler */ + + status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ, + address, field_bit_width, value); + + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_read_field + * + * PARAMETERS: *Obj_desc - Field to be read + * *Value - Where to store value + * Field_bit_width - Field Width in bits (8, 16, or 32) + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value of the given field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_read_field ( + ACPI_OBJECT_INTERNAL *obj_desc, + void *buffer, + u32 buffer_length, + u32 byte_length, + u32 datum_length, + u32 bit_granularity, + u32 byte_granularity) +{ + ACPI_STATUS status; + u32 this_field_byte_offset; + u32 this_field_datum_offset; + u32 previous_raw_datum; + u32 this_raw_datum; + u32 valid_field_bits; + u32 mask; + u32 merged_datum = 0; + + + /* + * Clear the caller's buffer (the whole buffer length as given) + * This is very important, especially in the cases where a byte is read, + * but the buffer is really a u32 (4 bytes). + */ + + MEMSET (buffer, 0, buffer_length); + + /* Read the first raw datum to prime the loop */ + + this_field_byte_offset = 0; + this_field_datum_offset= 0; + + status = acpi_aml_read_field_data (obj_desc, this_field_byte_offset, bit_granularity, + &previous_raw_datum); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* We might actually be done if the request fits in one datum */ + + if ((datum_length == 1) && + ((obj_desc->field.bit_offset + obj_desc->field_unit.length) <= + (u16) bit_granularity)) + { + merged_datum = previous_raw_datum; + + merged_datum = (merged_datum >> obj_desc->field.bit_offset); + + valid_field_bits = obj_desc->field_unit.length % bit_granularity; + if (valid_field_bits) { + mask = (((u32) 1 << valid_field_bits) - (u32) 1); + merged_datum &= mask; + } + + + /* + * Place the Merged_datum into the proper format and return buffer + * field + */ + + switch (byte_granularity) + { + case 1: + ((u8 *) buffer) [this_field_datum_offset] = (u8) merged_datum; + break; + + case 2: + MOVE_UNALIGNED16_TO_16 (&(((u16 *) buffer)[this_field_datum_offset]), &merged_datum); + break; + + case 4: + MOVE_UNALIGNED32_TO_32 (&(((u32 *) buffer)[this_field_datum_offset]), &merged_datum); + break; + } + + this_field_byte_offset = 1; + this_field_datum_offset = 1; + } + + else { + /* We need to get more raw data to complete one or more field data */ + + while (this_field_datum_offset < datum_length) { + /* + * Get the next raw datum, it contains bits of the current + * field datum + */ + + status = acpi_aml_read_field_data (obj_desc, + this_field_byte_offset + byte_granularity, + bit_granularity, &this_raw_datum); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* Before merging the data, make sure the unused bits are clear */ + + switch (byte_granularity) + { + case 1: + this_raw_datum &= 0x000000FF; + previous_raw_datum &= 0x000000FF; + break; + + case 2: + this_raw_datum &= 0x0000FFFF; + previous_raw_datum &= 0x0000FFFF; + break; + } + + /* + * Put together bits of the two raw data to make a complete + * field datum + */ + + if (obj_desc->field.bit_offset != 0) { + merged_datum = + (previous_raw_datum >> obj_desc->field.bit_offset) | + (this_raw_datum << (bit_granularity - obj_desc->field.bit_offset)); + } + + else { + merged_datum = previous_raw_datum; + } + + /* + * Now store the datum in the caller's buffer, according to + * the data type + */ + + switch (byte_granularity) + { + case 1: + ((u8 *) buffer) [this_field_datum_offset] = (u8) merged_datum; + break; + + case 2: + MOVE_UNALIGNED16_TO_16 (&(((u16 *) buffer) [this_field_datum_offset]), &merged_datum); + break; + + case 4: + MOVE_UNALIGNED32_TO_32 (&(((u32 *) buffer) [this_field_datum_offset]), &merged_datum); + break; + } + + + /* + * Save the most recent datum since it contains bits of + * the *next* field datum + */ + + previous_raw_datum = this_raw_datum; + + this_field_byte_offset += byte_granularity; + this_field_datum_offset++; + + } /* while */ + } + +cleanup: + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_write_field_data + * + * PARAMETERS: *Obj_desc - Field to be set + * Value - Value to store + * Field_bit_width - Field Width in bits (8, 16, or 32) + * + * RETURN: Status + * + * DESCRIPTION: Store the value into the given field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_write_field_data ( + ACPI_OBJECT_INTERNAL *obj_desc, + u32 field_byte_offset, + u32 field_bit_width, + u32 value) +{ + ACPI_STATUS status = AE_OK; + ACPI_OBJECT_INTERNAL *rgn_desc = NULL; + u32 address; + s32 field_byte_width; + + + /* Obj_desc is validated by callers */ + + if (obj_desc) { + rgn_desc = obj_desc->field.container; + } + + field_byte_width = DIV_8 (field_bit_width); + status = acpi_aml_setup_field (obj_desc, rgn_desc, field_bit_width); + if (AE_OK != status) { + return (status); + } + + + /* + * Round offset down to next multiple of + * field width, add region base address and offset within the field + */ + + address = rgn_desc->region.address + + (obj_desc->field.offset & ~((u32) field_byte_width - 1)) + + field_byte_offset; + + + /* Invoke the appropriate Address_space/Op_region handler */ + + status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_WRITE, + address, field_bit_width, &value); + + + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_write_field_data_with_update_rule + * + * PARAMETERS: *Obj_desc - Field to be set + * Value - Value to store + * Field_bit_width - Field Width in bits (8, 16, or 32) + * + * RETURN: Status + * + * DESCRIPTION: Apply the field update rule to a field write + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_write_field_data_with_update_rule ( + ACPI_OBJECT_INTERNAL *obj_desc, + u32 mask, + u32 field_value, + u32 this_field_byte_offset, + u32 bit_granularity) +{ + ACPI_STATUS status = AE_OK; + u32 merged_value; + u32 current_value; + + + /* Start with the new bits */ + + merged_value = field_value; + + /* Check if update rule needs to be applied (not if mask is all ones) */ + + + /* Decode the update rule */ + + switch (obj_desc->field.update_rule) + { + + case UPDATE_PRESERVE: + + /* + * Read the current contents of the byte/word/dword containing + * the field, and merge with the new field value. + */ + status = acpi_aml_read_field_data (obj_desc, this_field_byte_offset, + bit_granularity, ¤t_value); + merged_value |= (current_value & ~mask); + break; + + + case UPDATE_WRITE_AS_ONES: + + /* Set positions outside the field to all ones */ + + merged_value |= ~mask; + break; + + + case UPDATE_WRITE_AS_ZEROS: + + /* Set positions outside the field to all zeros */ + + merged_value &= mask; + break; + + + default: + status = AE_AML_OPERAND_VALUE; + } + + + /* Write the merged value */ + + if (ACPI_SUCCESS (status)) { + status = acpi_aml_write_field_data (obj_desc, this_field_byte_offset, + bit_granularity, merged_value); + } + + return status; +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_write_field + * + * PARAMETERS: *Obj_desc - Field to be set + * Value - Value to store + * Field_bit_width - Field Width in bits (8, 16, or 32) + * + * RETURN: Status + * + * DESCRIPTION: Store the value into the given field + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_write_field ( + ACPI_OBJECT_INTERNAL *obj_desc, + void *buffer, + u32 buffer_length, + u32 byte_length, + u32 datum_length, + u32 bit_granularity, + u32 byte_granularity) +{ + ACPI_STATUS status; + u32 this_field_byte_offset; + u32 this_field_datum_offset; + u32 mask; + u32 merged_datum; + u32 previous_raw_datum; + u32 this_raw_datum; + u32 field_value; + u32 valid_field_bits; + + + /* + * Break the request into up to three parts: + * non-aligned part at start, aligned part in middle, non-aligned part + * at end --- Just like an I/O request --- + */ + + this_field_byte_offset = 0; + this_field_datum_offset= 0; + + /* Get a datum */ + + switch (byte_granularity) + { + case 1: + previous_raw_datum = ((u8 *) buffer) [this_field_datum_offset]; + break; + + case 2: + MOVE_UNALIGNED16_TO_32 (&previous_raw_datum, &(((u16 *) buffer) [this_field_datum_offset])); + break; + + case 4: + MOVE_UNALIGNED32_TO_32 (&previous_raw_datum, &(((u32 *) buffer) [this_field_datum_offset])); + break; + + default: + status = AE_AML_OPERAND_VALUE; + goto cleanup; + } + + + /* + * Write a partial field datum if field does not begin on a datum boundary + * + * Construct Mask with 1 bits where the field is, 0 bits elsewhere + * + * 1) Bits above the field + */ + + mask = (((u32)(-1)) << (u32)obj_desc->field.bit_offset); + + /* 2) Only the bottom 5 bits are valid for a shift operation. */ + + if ((obj_desc->field.bit_offset + obj_desc->field_unit.length) < 32) { + /* Bits above the field */ + + mask &= (~(((u32)(-1)) << ((u32)obj_desc->field.bit_offset + + (u32)obj_desc->field_unit.length))); + } + + /* 3) Shift and mask the value into the field position */ + + field_value = (previous_raw_datum << obj_desc->field.bit_offset) & mask; + + status = acpi_aml_write_field_data_with_update_rule (obj_desc, mask, field_value, + this_field_byte_offset, + bit_granularity); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* If the field fits within one datum, we are done. */ + + if ((datum_length == 1) && + ((obj_desc->field.bit_offset + obj_desc->field_unit.length) <= + (u16) bit_granularity)) + { + goto cleanup; + } + + /* + * We don't need to worry about the update rule for these data, because + * all of the bits are part of the field. + * + * Can't write the last datum, however, because it might contain bits that + * are not part of the field -- the update rule must be applied. + */ + + while (this_field_datum_offset < (datum_length - 1)) { + this_field_datum_offset++; + + /* Get the next raw datum, it contains bits of the current field datum... */ + + switch (byte_granularity) + { + case 1: + this_raw_datum = ((u8 *) buffer) [this_field_datum_offset]; + break; + + case 2: + MOVE_UNALIGNED16_TO_32 (&this_raw_datum, &(((u16 *) buffer) [this_field_datum_offset])); + break; + + case 4: + MOVE_UNALIGNED32_TO_32 (&this_raw_datum, &(((u32 *) buffer) [this_field_datum_offset])); + break; + + default: + status = AE_AML_OPERAND_VALUE; + goto cleanup; + } + + /* + * Put together bits of the two raw data to make a complete field + * datum + */ + + if (obj_desc->field.bit_offset != 0) { + merged_datum = + (previous_raw_datum >> (bit_granularity - obj_desc->field.bit_offset)) | + (this_raw_datum << obj_desc->field.bit_offset); + } + + else { + merged_datum = this_raw_datum; + } + + /* Now write the completed datum */ + + + status = acpi_aml_write_field_data (obj_desc, + this_field_byte_offset + byte_granularity, + bit_granularity, merged_datum); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* + * Save the most recent datum since it contains bits of + * the *next* field datum + */ + + previous_raw_datum = this_raw_datum; + + this_field_byte_offset += byte_granularity; + + } /* while */ + + + /* Write a partial field datum if field does not end on a datum boundary */ + + if ((obj_desc->field_unit.length + obj_desc->field_unit.bit_offset) % + bit_granularity) + { + switch (byte_granularity) + { + case 1: + this_raw_datum = ((u8 *) buffer) [this_field_datum_offset]; + break; + + case 2: + MOVE_UNALIGNED16_TO_32 (&this_raw_datum, &(((u16 *) buffer) [this_field_datum_offset])); + break; + + case 4: + MOVE_UNALIGNED32_TO_32 (&this_raw_datum, &(((u32 *) buffer) [this_field_datum_offset])); + break; + } + + /* Construct Mask with 1 bits where the field is, 0 bits elsewhere */ + + valid_field_bits = ((obj_desc->field_unit.length % bit_granularity) + + obj_desc->field.bit_offset); + + mask = (((u32) 1 << valid_field_bits) - (u32) 1); + + /* Shift and mask the value into the field position */ + + field_value = (previous_raw_datum >> + (bit_granularity - obj_desc->field.bit_offset)) & mask; + + status = acpi_aml_write_field_data_with_update_rule (obj_desc, mask, field_value, this_field_byte_offset + 1, + bit_granularity); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + } + + +cleanup: + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/ammisc.c linux/drivers/acpi/interpreter/ammisc.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/ammisc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/ammisc.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,533 @@ + +/****************************************************************************** + * + * Module Name: ammisc - ACPI AML (p-code) execution - specific opcodes + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "interp.h" +#include "amlcode.h" +#include "dispatch.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("ammisc"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_fatal + * + * PARAMETERS: none + * + * RETURN: Status. If the OS returns from the OSD call, we just keep + * on going. + * + * DESCRIPTION: Execute Fatal operator + * + * ACPI SPECIFICATION REFERENCES: + * Def_fatal := Fatal_op Fatal_type Fatal_code Fatal_arg + * Fatal_type := Byte_data + * Fatal_code := DWord_data + * Fatal_arg := Term_arg=>Integer + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_fatal ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_OBJECT_INTERNAL *type_desc; + ACPI_OBJECT_INTERNAL *code_desc; + ACPI_OBJECT_INTERNAL *arg_desc; + ACPI_STATUS status; + + + /* Resolve operands */ + + status = acpi_aml_resolve_operands (AML_FATAL_OP, WALK_OPERANDS); + /* Get operands */ + + status |= acpi_ds_obj_stack_pop_object (&arg_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&code_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&type_desc, walk_state); + if (status != AE_OK) { + /* invalid parameters on object stack */ + + acpi_aml_append_operand_diag (_THIS_MODULE, __LINE__, + (u16) AML_FATAL_OP, WALK_OPERANDS, 3); + goto cleanup; + } + + + /* Def_fatal := Fatal_op Fatal_type Fatal_code Fatal_arg */ + + + /* + * TBD: [Unhandled] call OSD interface to notify OS of fatal error + * requiring shutdown! + */ + + +cleanup: + + /* Free the operands */ + + acpi_cm_remove_reference (arg_desc); + acpi_cm_remove_reference (code_desc); + acpi_cm_remove_reference (type_desc); + + + /* If we get back from the OS call, we might as well keep going. */ + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_index + * + * PARAMETERS: none + * + * RETURN: Status + * + * DESCRIPTION: Execute Index operator + * + * ALLOCATION: Deletes one operand descriptor -- other remains on stack + * + * ACPI SPECIFICATION REFERENCES: + * Def_index := Index_op Buff_pkg_obj Index_value Result + * Index_value := Term_arg=>Integer + * Name_string := | + * Result := Super_name + * Super_name := Name_string | Arg_obj | Local_obj | Debug_obj | Def_index + * Local4_op | Local5_op | Local6_op | Local7_op + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_index ( + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL **return_desc) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_OBJECT_INTERNAL *idx_desc; + ACPI_OBJECT_INTERNAL *res_desc; + ACPI_OBJECT_INTERNAL *ret_desc = NULL; + ACPI_OBJECT_INTERNAL *tmp_desc; + ACPI_STATUS status; + + + /* Resolve operands */ + /* First operand can be either a package or a buffer */ + + status = acpi_aml_resolve_operands (AML_INDEX_OP, WALK_OPERANDS); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&idx_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (status != AE_OK) { + /* Invalid parameters on object stack */ + + acpi_aml_append_operand_diag (_THIS_MODULE, __LINE__, + (u16) AML_INDEX_OP, WALK_OPERANDS, 3); + goto cleanup; + } + + + /* Create the internal return object */ + + ret_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + + /* + * At this point, the Obj_desc operand is either a Package or a Buffer + */ + + if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { + /* Object to be indexed is a Package */ + + if (idx_desc->number.value >= obj_desc->package.count) { + status = AE_AML_PACKAGE_LIMIT; + goto cleanup; + } + + if ((res_desc->common.type == INTERNAL_TYPE_REFERENCE) && + (res_desc->reference.op_code == AML_ZERO_OP)) + { + /* + * There is no actual result descriptor (the Zero_op Result + * descriptor is a placeholder), so just delete the placeholder and + * return a reference to the package element + */ + + acpi_cm_remove_reference (res_desc); + } + + else { + /* + * Each element of the package is an internal object. Get the one + * we are after. + */ + + tmp_desc = obj_desc->package.elements[idx_desc->number.value]; + ret_desc->reference.op_code = AML_INDEX_OP; + ret_desc->reference.target_type = tmp_desc->common.type; + ret_desc->reference.object = tmp_desc; + + status = acpi_aml_exec_store (ret_desc, res_desc); + ret_desc->reference.object = NULL; + } + + /* + * The local return object must always be a reference to the package element, + * not the element itself. + */ + ret_desc->reference.op_code = AML_INDEX_OP; + ret_desc->reference.target_type = ACPI_TYPE_PACKAGE; + ret_desc->reference.where = &obj_desc->package.elements[idx_desc->number.value]; + } + + else { + /* Object to be indexed is a Buffer */ + + if (idx_desc->number.value >= obj_desc->buffer.length) { + status = AE_AML_BUFFER_LIMIT; + goto cleanup; + } + + ret_desc->reference.op_code = AML_INDEX_OP; + ret_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD; + ret_desc->reference.object = obj_desc; + ret_desc->reference.offset = idx_desc->number.value; + + status = acpi_aml_exec_store (ret_desc, res_desc); + } + + +cleanup: + + /* Always delete operands */ + + acpi_cm_remove_reference (obj_desc); + acpi_cm_remove_reference (idx_desc); + + /* Delete return object on error */ + + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (res_desc); + + if (ret_desc) { + acpi_cm_remove_reference (ret_desc); + ret_desc = NULL; + } + } + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_match + * + * PARAMETERS: none + * + * RETURN: Status + * + * DESCRIPTION: Execute Match operator + * + * ACPI SPECIFICATION REFERENCES: + * Def_match := Match_op Search_pkg Opcode1 Operand1 + * Opcode2 Operand2 Start_index + * Opcode1 := Byte_data: MTR, MEQ, MLE, MLT, MGE, or MGT + * Opcode2 := Byte_data: MTR, MEQ, MLE, MLT, MGE, or MGT + * Operand1 := Term_arg=>Integer + * Operand2 := Term_arg=>Integer + * Search_pkg := Term_arg=>Package_object + * Start_index := Term_arg=>Integer + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_match ( + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL **return_desc) +{ + ACPI_OBJECT_INTERNAL *pkg_desc; + ACPI_OBJECT_INTERNAL *op1_desc; + ACPI_OBJECT_INTERNAL *V1_desc; + ACPI_OBJECT_INTERNAL *op2_desc; + ACPI_OBJECT_INTERNAL *V2_desc; + ACPI_OBJECT_INTERNAL *start_desc; + ACPI_OBJECT_INTERNAL *ret_desc = NULL; + ACPI_STATUS status; + u32 index; + u32 match_value = (u32) -1; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (AML_MATCH_OP, WALK_OPERANDS); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&start_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&V2_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&op2_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&V1_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&op1_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&pkg_desc, walk_state); + + if (status != AE_OK) { + /* Invalid parameters on object stack */ + + acpi_aml_append_operand_diag (_THIS_MODULE, __LINE__, + (u16) AML_MATCH_OP, WALK_OPERANDS, 6); + goto cleanup; + } + + /* Validate match comparison sub-opcodes */ + + if ((op1_desc->number.value > MAX_MATCH_OPERATOR) || + (op2_desc->number.value > MAX_MATCH_OPERATOR)) + { + status = AE_AML_OPERAND_VALUE; + goto cleanup; + } + + index = start_desc->number.value; + if (index >= (u32) pkg_desc->package.count) { + status = AE_AML_PACKAGE_LIMIT; + goto cleanup; + } + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + + } + + /* + * Examine each element until a match is found. Within the loop, + * "continue" signifies that the current element does not match + * and the next should be examined. + * Upon finding a match, the loop will terminate via "break" at + * the bottom. If it terminates "normally", Match_value will be -1 + * (its initial value) indicating that no match was found. When + * returned as a Number, this will produce the Ones value as specified. + */ + + for ( ; index < pkg_desc->package.count; ++index) { + /* + * Treat any NULL or non-numeric elements as non-matching. + * TBD [Unhandled] - if an element is a Name, + * should we examine its value? + */ + if (!pkg_desc->package.elements[index] || + ACPI_TYPE_NUMBER != pkg_desc->package.elements[index]->common.type) + { + continue; + } + + /* + * Within these switch statements: + * "break" (exit from the switch) signifies a match; + * "continue" (proceed to next iteration of enclosing + * "for" loop) signifies a non-match. + */ + switch (op1_desc->number.value) + { + + case MATCH_MTR: /* always true */ + + break; + + + case MATCH_MEQ: /* true if equal */ + + if (pkg_desc->package.elements[index]->number.value + != V1_desc->number.value) + { + continue; + } + break; + + + case MATCH_MLE: /* true if less than or equal */ + + if (pkg_desc->package.elements[index]->number.value + > V1_desc->number.value) + { + continue; + } + break; + + + case MATCH_MLT: /* true if less than */ + + if (pkg_desc->package.elements[index]->number.value + >= V1_desc->number.value) + { + continue; + } + break; + + + case MATCH_MGE: /* true if greater than or equal */ + + if (pkg_desc->package.elements[index]->number.value + < V1_desc->number.value) + { + continue; + } + break; + + + case MATCH_MGT: /* true if greater than */ + + if (pkg_desc->package.elements[index]->number.value + <= V1_desc->number.value) + { + continue; + } + break; + + + default: /* undefined */ + + continue; + } + + + switch(op2_desc->number.value) + { + + case MATCH_MTR: + + break; + + + case MATCH_MEQ: + + if (pkg_desc->package.elements[index]->number.value + != V2_desc->number.value) + { + continue; + } + break; + + + case MATCH_MLE: + + if (pkg_desc->package.elements[index]->number.value + > V2_desc->number.value) + { + continue; + } + break; + + + case MATCH_MLT: + + if (pkg_desc->package.elements[index]->number.value + >= V2_desc->number.value) + { + continue; + } + break; + + + case MATCH_MGE: + + if (pkg_desc->package.elements[index]->number.value + < V2_desc->number.value) + { + continue; + } + break; + + + case MATCH_MGT: + + if (pkg_desc->package.elements[index]->number.value + <= V2_desc->number.value) + { + continue; + } + break; + + + default: + + continue; + } + + /* Match found: exit from loop */ + + match_value = index; + break; + } + + /* Match_value is the return value */ + + ret_desc->number.value = match_value; + + +cleanup: + + /* Free the operands */ + + acpi_cm_remove_reference (start_desc); + acpi_cm_remove_reference (V2_desc); + acpi_cm_remove_reference (op2_desc); + acpi_cm_remove_reference (V1_desc); + acpi_cm_remove_reference (op1_desc); + acpi_cm_remove_reference (pkg_desc); + + + /* Delete return object on error */ + + if (ACPI_FAILURE (status) && + (ret_desc)) + { + acpi_cm_remove_reference (ret_desc); + ret_desc = NULL; + } + + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/ammonad.c linux/drivers/acpi/interpreter/ammonad.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/ammonad.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/ammonad.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,954 @@ + +/****************************************************************************** + * + * Module Name: ammonad - ACPI AML (p-code) execution for monadic operators + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "dispatch.h" +#include "interp.h" +#include "amlcode.h" +#include "namesp.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("ammonad"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_get_object_reference + * + * PARAMETERS: Obj_desc - Create a reference to this object + * Ret_desc - Where to store the reference + * + * RETURN: Status + * + * DESCRIPTION: Obtain and return a "reference" to the target object + * Common code for the Ref_of_op and the Cond_ref_of_op. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_get_object_reference ( + ACPI_OBJECT_INTERNAL *obj_desc, + ACPI_OBJECT_INTERNAL **ret_desc) +{ + ACPI_STATUS status = AE_OK; + + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { + if (obj_desc->common.type != INTERNAL_TYPE_REFERENCE) { + *ret_desc = NULL; + status = AE_TYPE; + goto cleanup; + } + + /* + * Not a Name -- an indirect name pointer would have + * been converted to a direct name pointer in Acpi_aml_resolve_operands + */ + switch (obj_desc->reference.op_code) + { + case AML_LOCAL_OP: + + *ret_desc = (void *) acpi_ds_method_data_get_nte (MTH_TYPE_LOCAL, + (obj_desc->reference.offset)); + break; + + + case AML_ARG_OP: + + *ret_desc = (void *) acpi_ds_method_data_get_nte (MTH_TYPE_ARG, + (obj_desc->reference.offset)); + break; + + + default: + + *ret_desc = NULL; + status = AE_AML_INTERNAL; + goto cleanup; + } + + } + + else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + /* Must be a named object; Just return the NTE */ + + *ret_desc = obj_desc; + } + + else { + *ret_desc = NULL; + status = AE_TYPE; + } + + +cleanup: + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_monadic1 + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on + * object stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_monadic1 ( + u16 opcode, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_STATUS status; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (status != AE_OK) { + acpi_aml_append_operand_diag (_THIS_MODULE, __LINE__, + opcode, WALK_OPERANDS, 1); + goto cleanup; + } + + + /* Examine the opcode */ + + switch (opcode) + { + + /* Def_release := Release_op Mutex_object */ + + case AML_RELEASE_OP: + + status = acpi_aml_system_release_mutex (obj_desc); + break; + + + /* Def_reset := Reset_op Acpi_event_object */ + + case AML_RESET_OP: + + status = acpi_aml_system_reset_event (obj_desc); + break; + + + /* Def_signal := Signal_op Acpi_event_object */ + + case AML_SIGNAL_OP: + + status = acpi_aml_system_signal_event (obj_desc); + break; + + + /* Def_sleep := Sleep_op Msec_time */ + + case AML_SLEEP_OP: + + acpi_aml_system_do_suspend (obj_desc->number.value); + break; + + + /* Def_stall := Stall_op Usec_time */ + + case AML_STALL_OP: + + acpi_aml_system_do_stall (obj_desc->number.value); + break; + + + /* Unknown opcode */ + + default: + + status = AE_AML_BAD_OPCODE; + break; + + } /* switch */ + + +cleanup: + + /* Always delete the operand */ + + acpi_cm_remove_reference (obj_desc); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_monadic2_r + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 monadic operator with numeric operand and + * result operand on operand stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_monadic2_r ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL **return_desc) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_OBJECT_INTERNAL *res_desc; + ACPI_OBJECT_INTERNAL *ret_desc = NULL; + ACPI_OBJECT_INTERNAL *ret_desc2 = NULL; + u32 res_val; + ACPI_STATUS status; + s32 d0; + s32 d1; + s32 d2; + s32 d3; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (status != AE_OK) { + acpi_aml_append_operand_diag (_THIS_MODULE, __LINE__, + opcode, WALK_OPERANDS, 2); + goto cleanup; + } + + + /* Create a return object of type NUMBER for most opcodes */ + + switch (opcode) + { + case AML_BIT_NOT_OP: + case AML_FIND_SET_LEFT_BIT_OP: + case AML_FIND_SET_RIGHT_BIT_OP: + case AML_FROM_BCDOP: + case AML_TO_BCDOP: + case AML_COND_REF_OF_OP: + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + break; + } + + + switch (opcode) + { + /* Def_not := Not_op Operand Result */ + + case AML_BIT_NOT_OP: + + ret_desc->number.value = ~obj_desc->number.value; + break; + + + /* Def_find_set_left_bit := Find_set_left_bit_op Operand Result */ + + case AML_FIND_SET_LEFT_BIT_OP: + + ret_desc->number.value = obj_desc->number.value; + for (res_val = 0; ret_desc->number.value && res_val < 33; ++res_val) { + ret_desc->number.value >>= 1; + } + + ret_desc->number.value = res_val; + break; + + + /* Def_find_set_right_bit := Find_set_right_bit_op Operand Result */ + + case AML_FIND_SET_RIGHT_BIT_OP: + + ret_desc->number.value = obj_desc->number.value; + for (res_val = 0; ret_desc->number.value && res_val < 33; ++res_val) { + ret_desc->number.value <<= 1; + } + + ret_desc->number.value = res_val == 0 ? 0 : 33 - res_val; + break; + + + /* Def_from_bDC := From_bCDOp BCDValue Result */ + + case AML_FROM_BCDOP: + + d0 = (s32) (obj_desc->number.value & 15); + d1 = (s32) (obj_desc->number.value >> 4 & 15); + d2 = (s32) (obj_desc->number.value >> 8 & 15); + d3 = (s32) (obj_desc->number.value >> 12 & 15); + + if (d0 > 9 || d1 > 9 || d2 > 9 || d3 > 9) { + status = AE_AML_NUMERIC_OVERFLOW; + goto cleanup; + } + + ret_desc->number.value = d0 + d1 * 10 + d2 * 100 + d3 * 1000; + break; + + + /* Def_to_bDC := To_bCDOp Operand Result */ + + case AML_TO_BCDOP: + + + if (obj_desc->number.value > 9999) { + status = AE_AML_NUMERIC_OVERFLOW; + goto cleanup; + } + + ret_desc->number.value + = obj_desc->number.value % 10 + + (obj_desc->number.value / 10 % 10 << 4) + + (obj_desc->number.value / 100 % 10 << 8) + + (obj_desc->number.value / 1000 % 10 << 12); + + break; + + + /* Def_cond_ref_of := Cond_ref_of_op Source_object Result */ + + case AML_COND_REF_OF_OP: + + /* + * This op is a little strange because the internal return value is + * different than the return value stored in the result descriptor + * (There are really two return values) + */ + + if ((ACPI_NAMED_OBJECT*) obj_desc == acpi_gbl_root_object) { + /* + * This means that the object does not exist in the namespace, + * return FALSE + */ + + ret_desc->number.value = 0; + + /* + * Must delete the result descriptor since there is no reference + * being returned + */ + + acpi_cm_remove_reference (res_desc); + goto cleanup; + } + + /* Get the object reference and store it */ + + status = acpi_aml_get_object_reference (obj_desc, &ret_desc2); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + status = acpi_aml_exec_store (ret_desc2, res_desc); + + /* The object exists in the namespace, return TRUE */ + + ret_desc->number.value = (u32) -1; + goto cleanup; + break; + + + case AML_STORE_OP: + + /* + * A store operand is typically a number, string, buffer or lvalue + * TBD: [Unhandled] What about a store to a package? + */ + + /* + * Do the store, and be careful about deleting the source object, + * since the object itself may have been stored. + */ + + status = acpi_aml_exec_store (obj_desc, res_desc); + if (ACPI_FAILURE (status)) { + /* On failure, just delete the Obj_desc */ + + acpi_cm_remove_reference (obj_desc); + } + + else { + /* + * Normally, we would remove a reference on the Obj_desc parameter; + * But since it is being used as the internal return object + * (meaning we would normally increment it), the two cancel out, + * and we simply don't do anything. + */ + *return_desc = obj_desc; + } + + obj_desc = NULL; + return (status); + + break; + + + case AML_DEBUG_OP: + + /* Reference, returning an Reference */ + + return (AE_OK); + break; + + + /* + * These are obsolete opcodes + */ + + /* Def_shift_left_bit := Shift_left_bit_op Source Bit_num */ + /* Def_shift_right_bit := Shift_right_bit_op Source Bit_num */ + + case AML_SHIFT_LEFT_BIT_OP: + case AML_SHIFT_RIGHT_BIT_OP: + + status = AE_SUPPORT; + goto cleanup; + break; + + + default: + + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + + status = acpi_aml_exec_store (ret_desc, res_desc); + + +cleanup: + /* Always delete the operand object */ + + acpi_cm_remove_reference (obj_desc); + + /* Delete return object(s) on error */ + + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (res_desc); /* Result descriptor */ + if (ret_desc) { + acpi_cm_remove_reference (ret_desc); + ret_desc = NULL; + } + } + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_monadic2 + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 monadic operator with numeric operand: + * Deref_of_op, Ref_of_op, Size_of_op, Type_op, Increment_op, + * Decrement_op, LNot_op, + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_monadic2 ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OBJECT_INTERNAL **return_desc) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_OBJECT_INTERNAL *tmp_desc; + ACPI_OBJECT_INTERNAL *ret_desc = NULL; + ACPI_STATUS status; + u32 type; + u32 value; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (status != AE_OK) { + acpi_aml_append_operand_diag (_THIS_MODULE, __LINE__, + opcode, WALK_OPERANDS, 1); + goto cleanup; + } + + + /* Get the operand and decode the opcode */ + + + switch (opcode) + { + + /* Def_lNot := LNot_op Operand */ + + case AML_LNOT_OP: + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + ret_desc->number.value = !obj_desc->number.value; + break; + + + /* Def_decrement := Decrement_op Target */ + /* Def_increment := Increment_op Target */ + + case AML_DECREMENT_OP: + case AML_INCREMENT_OP: + + /* + * Since we are expecting an Reference on the top of the stack, it + * can be either an NTE or an internal object. + * + * TBD: [Future] This may be the prototype code for all cases where + * an Reference is expected!! 10/99 + */ + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + ret_desc = obj_desc; + } + + else { + /* + * Duplicate the Reference in a new object so that we can resolve it + * without destroying the original Reference object + */ + + ret_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + ret_desc->reference.op_code = obj_desc->reference.op_code; + ret_desc->reference.offset = obj_desc->reference.offset; + ret_desc->reference.object = obj_desc->reference.object; + } + + + /* + * Convert the Ret_desc Reference to a Number + * (This deletes the original Ret_desc) + */ + + status = acpi_aml_resolve_operands (AML_LNOT_OP, &ret_desc); + if (status != AE_OK) { + acpi_aml_append_operand_diag (_THIS_MODULE, __LINE__, + opcode, WALK_OPERANDS, 1); + goto cleanup; + } + + /* Do the actual increment or decrement */ + + if (AML_INCREMENT_OP == opcode) { + ret_desc->number.value++; + } + else { + ret_desc->number.value--; + } + + /* Store the result back in the original descriptor */ + + status = acpi_aml_exec_store (ret_desc, obj_desc); + + /* Objdesc was just deleted (because it is an Reference) */ + + obj_desc = NULL; + + break; + + + /* Def_object_type := Object_type_op Source_object */ + + case AML_TYPE_OP: + + if (INTERNAL_TYPE_REFERENCE == obj_desc->common.type) { + /* + * Not a Name -- an indirect name pointer would have + * been converted to a direct name pointer in Resolve_operands + */ + switch (obj_desc->reference.op_code) + { + case AML_ZERO_OP: + case AML_ONE_OP: + case AML_ONES_OP: + + /* Constants are of type Number */ + + type = ACPI_TYPE_NUMBER; + break; + + + case AML_DEBUG_OP: + + /* Per 1.0b spec, Debug object is of type Debug_object */ + + type = ACPI_TYPE_DEBUG_OBJECT; + break; + + + case AML_INDEX_OP: + + /* Get the type of this reference (index into another object) */ + + type = obj_desc->reference.target_type; + if (type == ACPI_TYPE_PACKAGE) { + /* + * The main object is a package, we want to get the type + * of the individual package element that is referenced by + * the index. + */ + type = (*(obj_desc->reference.where))->common.type; + } + + break; + + + case AML_LOCAL_OP: + + type = acpi_ds_method_data_get_type (MTH_TYPE_LOCAL, + (obj_desc->reference.offset)); + break; + + + case AML_ARG_OP: + + type = acpi_ds_method_data_get_type (MTH_TYPE_ARG, + (obj_desc->reference.offset)); + break; + + + default: + + status = AE_AML_INTERNAL; + goto cleanup; + } + } + + else { + /* + * Since we passed Acpi_aml_resolve_operands("l") and it's not a + * Reference, it must be a direct name pointer. + */ + type = acpi_ns_get_type ((ACPI_HANDLE) obj_desc); + } + + /* Allocate a descriptor to hold the type. */ + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + ret_desc->number.value = type; + break; + + + /* Def_size_of := Size_of_op Source_object */ + + case AML_SIZE_OF_OP: + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + obj_desc = acpi_ns_get_attached_object (obj_desc); + } + + if (!obj_desc) { + value = 0; + } + + else { + switch (obj_desc->common.type) + { + + case ACPI_TYPE_BUFFER: + + value = obj_desc->buffer.length; + break; + + + case ACPI_TYPE_STRING: + + value = obj_desc->string.length; + break; + + + case ACPI_TYPE_PACKAGE: + + value = obj_desc->package.count; + break; + + case INTERNAL_TYPE_REFERENCE: + + value = 4; + break; + + default: + + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + } + + /* + * Now that we have the size of the object, create a result + * object to hold the value + */ + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + ret_desc->number.value = value; + break; + + + /* Def_ref_of := Ref_of_op Source_object */ + + case AML_REF_OF_OP: + + status = acpi_aml_get_object_reference (obj_desc, &ret_desc); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + break; + + + /* Def_deref_of := Deref_of_op Obj_reference */ + + case AML_DEREF_OF_OP: + + + /* Check for a method local or argument */ + + if (!VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + /* + * Must resolve/dereference the local/arg reference first + */ + switch (obj_desc->reference.op_code) + { + /* Set Obj_desc to the value of the local/arg */ + + case AML_LOCAL_OP: + + acpi_ds_method_data_get_value (MTH_TYPE_LOCAL, + (obj_desc->reference.offset), &tmp_desc); + + /* + * Delete our reference to the input object and + * point to the object just retrieved + */ + acpi_cm_remove_reference (obj_desc); + obj_desc = tmp_desc; + break; + + + case AML_ARG_OP: + + acpi_ds_method_data_get_value (MTH_TYPE_ARG, + (obj_desc->reference.offset), &tmp_desc); + + /* + * Delete our reference to the input object and + * point to the object just retrieved + */ + acpi_cm_remove_reference (obj_desc); + obj_desc = tmp_desc; + break; + + default: + + /* Index op - handled below */ + break; + } + } + + + /* Obj_desc may have changed from the code above */ + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + /* Get the actual object from the NTE (This is the dereference) */ + + ret_desc = ((ACPI_NAMED_OBJECT*) obj_desc)->object; + + /* Returning a pointer to the object, add another reference! */ + + acpi_cm_add_reference (ret_desc); + } + + else { + /* + * This must be a reference object produced by the Index + * ASL operation -- check internal opcode + */ + + if ((obj_desc->reference.op_code != AML_INDEX_OP) && + (obj_desc->reference.op_code != AML_REF_OF_OP)) + { + status = AE_TYPE; + goto cleanup; + } + + + switch (obj_desc->reference.op_code) + { + case AML_INDEX_OP: + + /* + * Supported target types for the Index operator are + * 1) A Buffer + * 2) A Package + */ + + if (obj_desc->reference.target_type == ACPI_TYPE_BUFFER_FIELD) { + /* + * The target is a buffer, we must create a new object that + * contains one element of the buffer, the element pointed + * to by the index. + * + * NOTE: index into a buffer is NOT a pointer to a + * sub-buffer of the main buffer, it is only a pointer to a + * single element (byte) of the buffer! + */ + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + tmp_desc = obj_desc->reference.object; + ret_desc->number.value = + tmp_desc->buffer.pointer[obj_desc->reference.offset]; + + /* TBD: [Investigate] (see below) Don't add an additional + * ref! + */ + } + + else if (obj_desc->reference.target_type == ACPI_TYPE_PACKAGE) { + /* + * The target is a package, we want to return the referenced + * element of the package. We must add another reference to + * this object, however. + */ + + ret_desc = *(obj_desc->reference.where); + if (!ret_desc) { + /* + * We can't return a NULL dereferenced value. This is + * an uninitialized package element and is thus a + * severe error. + */ + + status = AE_AML_UNINITIALIZED_ELEMENT; + goto cleanup; + } + + acpi_cm_add_reference (ret_desc); + } + + else { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + break; + + + case AML_REF_OF_OP: + + ret_desc = obj_desc->reference.object; + + /* Add another reference to the object! */ + + acpi_cm_add_reference (ret_desc); + break; + } + } + + break; + + + default: + + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + +cleanup: + + if (obj_desc) { + acpi_cm_remove_reference (obj_desc); + } + + /* Delete return object on error */ + + if (ACPI_FAILURE (status) && + (ret_desc)) + { + acpi_cm_remove_reference (ret_desc); + ret_desc = NULL; + } + + *return_desc = ret_desc; + return (status); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amnames.c linux/drivers/acpi/interpreter/amnames.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amnames.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amnames.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,440 @@ + +/****************************************************************************** + * + * Module Name: amnames - interpreter/scanner name load/execute + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" +#include "amlcode.h" +#include "namesp.h" + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amnames"); + + +/* AML Package Length encodings */ + +#define ACPI_AML_PACKAGE_TYPE1 0x40 +#define ACPI_AML_PACKAGE_TYPE2 0x4000 +#define ACPI_AML_PACKAGE_TYPE3 0x400000 +#define ACPI_AML_PACKAGE_TYPE4 0x40000000 + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_allocate_name_string + * + * PARAMETERS: Prefix_count - Count of parent levels. Special cases: + * (-1) = root, 0 = none + * Num_name_segs - count of 4-character name segments + * + * RETURN: A pointer to the allocated string segment. This segment must + * be deleted by the caller. + * + * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name + * string is long enough, and set up prefix if any. + * + ******************************************************************************/ + +char * +acpi_aml_allocate_name_string ( + u32 prefix_count, + u32 num_name_segs) +{ + char *temp_ptr; + char *name_string; + u32 size_needed; + + + /* + * Allow room for all \ and ^ prefixes, all segments, and a Multi_name_prefix. + * Also, one byte for the null terminator. + * This may actually be somewhat longer than needed. + */ + + if (prefix_count == (u32) -1) { + /* Special case for root */ + + size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; + } + else { + size_needed = prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; + } + + /* + * Allocate a buffer for the name. + * This buffer must be deleted by the caller! + */ + + name_string = acpi_cm_allocate ((ACPI_SIZE) size_needed); + if (!name_string) { + REPORT_ERROR ("Aml_allocate_name_string: name allocation failure"); + return (NULL); + } + + temp_ptr = name_string; + + /* Set up Root or Parent prefixes if needed */ + + if (prefix_count == (u32) -1) { + *temp_ptr++ = AML_ROOT_PREFIX; + } + + else { + while (prefix_count--) { + *temp_ptr++ = AML_PARENT_PREFIX; + } + } + + + /* Set up Dual or Multi prefixes if needed */ + + if (num_name_segs > 2) { + /* Set up multi prefixes */ + + *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP; + *temp_ptr++ = (char) num_name_segs; + } + + else if (2 == num_name_segs) { + /* Set up dual prefixes */ + + *temp_ptr++ = AML_DUAL_NAME_PREFIX; + } + + /* + * Terminate string following prefixes. Acpi_aml_exec_name_segment() will + * append the segment(s) + */ + + *temp_ptr = 0; + + return (name_string); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_decode_package_length + * + * PARAMETERS: Last_pkg_len - latest value decoded by Do_pkg_length() for + * most recently examined package or field + * + * RETURN: Number of bytes contained in package length encoding + * + * DESCRIPTION: Decodes the Package Length. Upper 2 bits are are used to + * tell if type 1, 2, 3, or 4. + * 0x3F = Max 1 byte encoding, + * 0xFFF = Max 2 byte encoding, + * 0xFFFFF = Max 3 Byte encoding, + * 0xFFFFFFFFF = Max 4 Byte encoding. + * + ******************************************************************************/ + +u32 +acpi_aml_decode_package_length ( + u32 last_pkg_len) +{ + u32 num_bytes = 0; + + + if (last_pkg_len < ACPI_AML_PACKAGE_TYPE1) { + num_bytes = 1; + } + + else if (last_pkg_len < ACPI_AML_PACKAGE_TYPE2) { + num_bytes = 2; + } + + else if (last_pkg_len < ACPI_AML_PACKAGE_TYPE3) { + num_bytes = 3; + } + + else if (last_pkg_len < ACPI_AML_PACKAGE_TYPE4) { + num_bytes = 4; + } + + return (num_bytes); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_name_segment + * + * PARAMETERS: Interpreter_mode - Current running mode (load1/Load2/Exec) + * + * RETURN: Status + * + * DESCRIPTION: Execute a name segment (4 bytes) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_name_segment ( + u8 **in_aml_address, + char *name_string) +{ + u8 *aml_address = *in_aml_address; + ACPI_STATUS status = AE_OK; + s32 index; + char char_buf[5]; + + + /* + * If first character is a digit, then we know that we aren't looking at a + * valid name segment + */ + + char_buf[0] = *aml_address; + + if ('0' <= char_buf[0] && char_buf[0] <= '9') { + return (AE_CTRL_PENDING); + } + + for (index = 4; + (index > 0) && (acpi_cm_valid_acpi_character (*aml_address)); + --index) + { + char_buf[4 - index] = *aml_address++; + } + + + /* Valid name segment */ + + if (0 == index) { + /* Found 4 valid characters */ + + char_buf[4] = '\0'; + + if (name_string) { + STRCAT (name_string, char_buf); + } + + } + + else if (4 == index) { + /* + * First character was not a valid name character, + * so we are looking at something other than a name. + */ + status = AE_CTRL_PENDING; + } + + else { + /* Segment started with one or more valid characters, but fewer than 4 */ + + status = AE_AML_BAD_NAME; + } + + *in_aml_address = aml_address; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_get_name_string + * + * PARAMETERS: Data_type - Data type to be associated with this name + * + * RETURN: Status + * + * DESCRIPTION: Get a name, including any prefixes. + * + ******************************************************************************/ + + +ACPI_STATUS +acpi_aml_get_name_string ( + OBJECT_TYPE_INTERNAL data_type, + u8 *in_aml_address, + char **out_name_string, + u32 *out_name_length) +{ + ACPI_STATUS status = AE_OK; + u8 *aml_address = in_aml_address; + char *name_string = NULL; + s32 num_segments; + s32 prefix_count = 0; + u8 prefix = 0; + + + if (INTERNAL_TYPE_DEF_FIELD == data_type || + INTERNAL_TYPE_BANK_FIELD == data_type || + INTERNAL_TYPE_INDEX_FIELD == data_type) + { + /* Disallow prefixes for types associated with field names */ + + name_string = acpi_aml_allocate_name_string (0, 1); + if (!name_string) { + status = AE_NO_MEMORY; + } + else { + status = acpi_aml_exec_name_segment (&aml_address, name_string); + } + } + + else { + /* + * Data_type is not a field name. + * Examine first character of name for root or parent prefix operators + */ + + switch (*aml_address) + { + + case AML_ROOT_PREFIX: + + prefix = *aml_address++; + /* + * Remember that we have a Root_prefix -- + * see comment in Acpi_aml_allocate_name_string() + */ + prefix_count = -1; + break; + + + case AML_PARENT_PREFIX: + + /* Increment past possibly multiple parent prefixes */ + + do + { + prefix = *aml_address++; + ++prefix_count; + + } while (*aml_address == AML_PARENT_PREFIX); + + break; + + + default: + + break; + } + + + /* Examine first character of name for name segment prefix operator */ + + switch (*aml_address) + { + + case AML_DUAL_NAME_PREFIX: + + prefix = *aml_address++; + name_string = acpi_aml_allocate_name_string (prefix_count, 2); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + /* Ensure Prefix_count != 0 to remember processing a prefix */ + + prefix_count += 2; + + status = acpi_aml_exec_name_segment (&aml_address, name_string); + if (ACPI_SUCCESS (status)) { + status = acpi_aml_exec_name_segment (&aml_address, name_string); + } + break; + + + case AML_MULTI_NAME_PREFIX_OP: + + prefix = *aml_address++; + /* Fetch count of segments remaining in name path */ + + num_segments = *aml_address++; + + name_string = acpi_aml_allocate_name_string (prefix_count, num_segments); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + /* Ensure Prefix_count != 0 to remember processing a prefix */ + + prefix_count += 2; + + while (num_segments && + (status = acpi_aml_exec_name_segment (&aml_address, name_string)) == AE_OK) + { + --num_segments; + } + + break; + + + case 0: + + /* Null_name valid as of 8-12-98 ASL/AML Grammar Update */ + + + /* Consume the NULL byte */ + + aml_address++; + name_string = acpi_aml_allocate_name_string (prefix_count, 0); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + break; + + + default: + + /* Name segment string */ + + name_string = acpi_aml_allocate_name_string (prefix_count, 1); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + status = acpi_aml_exec_name_segment (&aml_address, name_string); + break; + + } /* Switch (Peek_op ()) */ + } + + + if (AE_CTRL_PENDING == status && prefix_count != 0) { + /* Ran out of segments after processing a prefix */ + + REPORT_ERROR ("Ran out of segments after processing a prefix"); + + status = AE_AML_BAD_NAME; + } + + + *out_name_string = name_string; + *out_name_length = (u32) (aml_address - in_aml_address); + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amprep.c linux/drivers/acpi/interpreter/amprep.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amprep.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amprep.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,392 @@ + +/****************************************************************************** + * + * Module Name: amprep - ACPI AML (p-code) execution - field prep utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" +#include "amlcode.h" +#include "namesp.h" +#include "parser.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amprep"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_decode_field_access_type + * + * PARAMETERS: Access - Encoded field access bits + * + * RETURN: Field granularity (8, 16, or 32) + * + * DESCRIPTION: Decode the Access_type bits of a field definition. + * + ******************************************************************************/ + +u32 +acpi_aml_decode_field_access_type ( + u32 access) +{ + + switch (access) + { + case ACCESS_ANY_ACC: + return 8; + break; + + case ACCESS_BYTE_ACC: + return 8; + break; + + case ACCESS_WORD_ACC: + return 16; + break; + + case ACCESS_DWORD_ACC: + return 32; + break; + + default: + /* Invalid field access type */ + + return 0; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_prep_common_field_objec + * + * PARAMETERS: Obj_desc - The field object + * Field_flags - Access, Lock_rule, or Update_rule. + * The format of a Field_flag is described + * in the ACPI specification + * Field_position - Field position + * Field_length - Field length + * + * RETURN: Status + * + * DESCRIPTION: Initialize the areas of the field object that are common + * to the various types of fields. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_prep_common_field_object ( + ACPI_OBJECT_INTERNAL *obj_desc, + u8 field_flags, + u8 field_attribute, + u32 field_position, + u32 field_length) +{ + u32 granularity; + + + /* + * Note: the structure being initialized is the + * ACPI_COMMON_FIELD_INFO; Therefore, we can just use the Field union to + * access this common area. No structure fields outside of the common area + * are initialized by this procedure. + */ + + /* Decode the Field_flags */ + + obj_desc->field.access = (u8) ((field_flags & ACCESS_TYPE_MASK) + >> ACCESS_TYPE_SHIFT); + obj_desc->field.lock_rule = (u8) ((field_flags & LOCK_RULE_MASK) + >> LOCK_RULE_SHIFT); + obj_desc->field.update_rule = (u8) ((field_flags & UPDATE_RULE_MASK) + >> UPDATE_RULE_SHIFT); + + /* Other misc fields */ + + obj_desc->field.length = (u16) field_length; + obj_desc->field.access_attribute = field_attribute; + + /* Decode the access type so we can compute offsets */ + + granularity = acpi_aml_decode_field_access_type (obj_desc->field.access); + if (!granularity) { + return (AE_AML_OPERAND_VALUE); + } + + /* Access granularity based fields */ + + obj_desc->field.granularity = (u8) granularity; + obj_desc->field.bit_offset = (u8) (field_position % granularity); + obj_desc->field.offset = (u32) field_position / granularity; + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_prep_def_field_value + * + * PARAMETERS: This_entry - Owning NTE + * Region - Region in which field is being defined + * Field_flags - Access, Lock_rule, or Update_rule. + * The format of a Field_flag is described + * in the ACPI specification + * Field_position - Field position + * Field_length - Field length + * + * RETURN: Status + * + * DESCRIPTION: Construct an ACPI_OBJECT_INTERNAL of type Def_field and + * connect it to the parent NTE. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_prep_def_field_value ( + ACPI_NAMED_OBJECT *this_entry, + ACPI_HANDLE region, + u8 field_flags, + u8 field_attribute, + u32 field_position, + u32 field_length) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + s32 type; + ACPI_STATUS status; + + + /* Parameter validation */ + + if (!region) { + return (AE_AML_NO_OPERAND); + } + + type = acpi_ns_get_type (region); + if (type != ACPI_TYPE_REGION) { + return (AE_AML_OPERAND_TYPE); + } + + /* Allocate a new object */ + + obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_DEF_FIELD); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + + /* Obj_desc and Region valid */ + + /* Initialize areas of the object that are common to all fields */ + + status = acpi_aml_prep_common_field_object (obj_desc, field_flags, field_attribute, + field_position, field_length); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Initialize areas of the object that are specific to this field type */ + + obj_desc->field.container = acpi_ns_get_attached_object (region); + + /* An additional reference for the container */ + + acpi_cm_add_reference (obj_desc->field.container); + + + /* Debug info */ + + /* + * Store the constructed descriptor (Obj_desc) into the nte whose + * handle is on TOS, preserving the current type of that nte. + */ + status = acpi_ns_attach_object ((ACPI_HANDLE) this_entry, obj_desc, + (u8) acpi_ns_get_type ((ACPI_HANDLE) this_entry)); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_prep_bank_field_value + * + * PARAMETERS: This_entry - Owning NTE + * Region - Region in which field is being defined + * Bank_reg - Bank selection register + * Bank_val - Value to store in selection register + * Field_flags - Access, Lock_rule, or Update_rule + * Field_position - Field position + * Field_length - Field length + * + * RETURN: Status + * + * DESCRIPTION: Construct an ACPI_OBJECT_INTERNAL of type Bank_field and + * connect it to the parent NTE. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_prep_bank_field_value ( + ACPI_NAMED_OBJECT *this_entry, + ACPI_HANDLE region, + ACPI_HANDLE bank_reg, + u32 bank_val, + u8 field_flags, + u8 field_attribute, + u32 field_position, + u32 field_length) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + s32 type; + ACPI_STATUS status; + + + /* Parameter validation */ + + if (!region) { + return (AE_AML_NO_OPERAND); + } + + type = acpi_ns_get_type (region); + if (type != ACPI_TYPE_REGION) { + return (AE_AML_OPERAND_TYPE); + } + + /* Allocate a new object */ + + obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_BANK_FIELD); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Obj_desc and Region valid */ + + /* Initialize areas of the object that are common to all fields */ + + status = acpi_aml_prep_common_field_object (obj_desc, field_flags, field_attribute, + field_position, field_length); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Initialize areas of the object that are specific to this field type */ + + obj_desc->bank_field.value = bank_val; + obj_desc->bank_field.container = acpi_ns_get_attached_object (region); + obj_desc->bank_field.bank_select = acpi_ns_get_attached_object (bank_reg); + + /* An additional reference for the container and bank select */ + /* TBD: [Restructure] is "Bank_select" ever a real internal object?? */ + + acpi_cm_add_reference (obj_desc->bank_field.container); + acpi_cm_add_reference (obj_desc->bank_field.bank_select); + + /* Debug info */ + + /* + * Store the constructed descriptor (Obj_desc) into the nte whose + * handle is on TOS, preserving the current type of that nte. + */ + status = acpi_ns_attach_object ((ACPI_HANDLE) this_entry, obj_desc, + (u8) acpi_ns_get_type ((ACPI_HANDLE) this_entry)); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_prep_index_field_value + * + * PARAMETERS: This_entry - Owning NTE + * Index_reg - Index register + * Data_reg - Data register + * Field_flags - Access, Lock_rule, or Update_rule + * Field_position - Field position + * Field_length - Field length + * + * RETURN: Status + * + * DESCRIPTION: Construct an ACPI_OBJECT_INTERNAL of type Index_field and + * connect it to the parent NTE. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_prep_index_field_value ( + ACPI_NAMED_OBJECT *this_entry, + ACPI_HANDLE index_reg, + ACPI_HANDLE data_reg, + u8 field_flags, + u8 field_attribute, + u32 field_position, + u32 field_length) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_STATUS status; + + + /* Parameter validation */ + + if (!index_reg || !data_reg) { + return (AE_AML_NO_OPERAND); + } + + /* Allocate a new object descriptor */ + + obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_INDEX_FIELD); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Initialize areas of the object that are common to all fields */ + + status = acpi_aml_prep_common_field_object (obj_desc, field_flags, field_attribute, + field_position, field_length); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Initialize areas of the object that are specific to this field type */ + + obj_desc->index_field.value = (u32) (field_position / + obj_desc->field.granularity); + obj_desc->index_field.index = index_reg; + obj_desc->index_field.data = data_reg; + + /* Debug info */ + + /* + * Store the constructed descriptor (Obj_desc) into the nte whose + * handle is on TOS, preserving the current type of that nte. + */ + status = acpi_ns_attach_object ((ACPI_HANDLE) this_entry, obj_desc, + (u8) acpi_ns_get_type ((ACPI_HANDLE) this_entry)); + + return (status); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amregion.c linux/drivers/acpi/interpreter/amregion.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amregion.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amregion.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,406 @@ +/****************************************************************************** + * + * Module Name: amregion - ACPI default Op_region (address space) handlers + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" +#include "amlcode.h" +#include "namesp.h" +#include "hardware.h" +#include "events.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amregion"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_memory_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * Bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * Context - Context pointer + * + * RETURN: Status + * + * DESCRIPTION: Handler for the System Memory address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_memory_space_handler ( + u32 function, + u32 address, /* TBD: [Future] Should this be A POINTER for 64-bit support? */ + u32 bit_width, + u32 *value, + void *context) +{ + ACPI_STATUS status = AE_OK; + void *logical_addr_ptr = NULL; + MEM_HANDLER_CONTEXT *mem_info = context; + u32 length; + + + /* Validate and translate the bit width */ + + switch (bit_width) + { + case 8: + length = 1; + break; + + case 16: + length = 2; + break; + + case 32: + length = 4; + break; + + default: + return (AE_AML_OPERAND_VALUE); + break; + } + + + /* + * Does the request fit into the cached memory mapping? + * Is 1) Address below the current mapping? OR + * 2) Address beyond the current mapping? + */ + + if (((char *) address < mem_info->mapped_physical_address) || + (((char *) address + length) > + (mem_info->mapped_physical_address + mem_info->mapped_length))) + { + /* + * The request cannot be resolved by the current memory mapping; + * Delete the existing mapping and create a new one. + */ + + if (mem_info->mapped_length) { + /* Valid mapping, delete it */ + + acpi_os_unmap_memory (mem_info->mapped_logical_address, + mem_info->mapped_length); + } + + mem_info->mapped_length = 0; /* In case of failure below */ + + /* Create a new mapping starting at the address given */ + + status = acpi_os_map_memory ((void *) address, SYSMEM_REGION_WINDOW_SIZE, + (void **) &mem_info->mapped_logical_address); + if (ACPI_FAILURE (status)) { + return (status); + } + + mem_info->mapped_physical_address = (char *) address; + mem_info->mapped_length = SYSMEM_REGION_WINDOW_SIZE; + } + + + /* + * Generate a logical pointer corresponding to the address we want to + * access + */ + + logical_addr_ptr = mem_info->mapped_logical_address + + ((char *) address - mem_info->mapped_physical_address); + + /* Perform the memory read or write */ + + switch (function) + { + + case ADDRESS_SPACE_READ: + + switch (bit_width) + { + case 8: + *value = (u32)* (u8 *) logical_addr_ptr; + break; + + case 16: + MOVE_UNALIGNED16_TO_32 (value, logical_addr_ptr); + break; + + case 32: + MOVE_UNALIGNED32_TO_32 (value, logical_addr_ptr); + break; + } + + break; + + + case ADDRESS_SPACE_WRITE: + + switch (bit_width) + { + case 8: + *(u8 *) logical_addr_ptr = (u8) *value; + break; + + case 16: + MOVE_UNALIGNED16_TO_16 (logical_addr_ptr, value); + break; + + case 32: + MOVE_UNALIGNED32_TO_32 (logical_addr_ptr, value); + break; + } + + break; + + + default: + status = AE_BAD_PARAMETER; + break; + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_io_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * Bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * Context - Context pointer + * + * RETURN: Status + * + * DESCRIPTION: Handler for the System IO address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_io_space_handler ( + u32 function, + u32 address, + u32 bit_width, + u32 *value, + void *context) +{ + ACPI_STATUS status = AE_OK; + + + /* Decode the function parameter */ + + switch (function) + { + + case ADDRESS_SPACE_READ: + + switch (bit_width) + { + /* I/O Port width */ + + case 8: + *value = (u32) acpi_os_in8 ((ACPI_IO_ADDRESS) address); + break; + + case 16: + *value = (u32) acpi_os_in16 ((ACPI_IO_ADDRESS) address); + break; + + case 32: + *value = acpi_os_in32 ((ACPI_IO_ADDRESS) address); + break; + + default: + status = AE_AML_OPERAND_VALUE; + } + + break; + + + case ADDRESS_SPACE_WRITE: + + switch (bit_width) + { + /* I/O Port width */ + case 8: + acpi_os_out8 ((ACPI_IO_ADDRESS) address, (u8) *value); + break; + + case 16: + acpi_os_out16 ((ACPI_IO_ADDRESS) address, (u16) *value); + break; + + case 32: + acpi_os_out32 ((ACPI_IO_ADDRESS) address, *value); + break; + + default: + status = AE_AML_OPERAND_VALUE; + } + + break; + + + default: + status = AE_BAD_PARAMETER; + break; + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_pci_config_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * Bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * Context - Context pointer + * + * RETURN: Status + * + * DESCRIPTION: Handler for the PCI Config address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_pci_config_space_handler ( + u32 function, + u32 address, + u32 bit_width, + u32 *value, + void *context) +{ + ACPI_STATUS status = AE_OK; + u32 pci_bus; + u32 dev_func; + u8 pci_reg; + PCI_HANDLER_CONTEXT *PCIcontext; + + + /* + * The arguments to Acpi_os(Read|Write)Pci_cfg(Byte|Word|Dword) are: + * + * Seg_bus - 0xSSSSBBBB - SSSS is the PCI bus segment + * BBBB is the PCI bus number + * + * Dev_func - 0xDDDDFFFF - DDDD is the PCI device number + * FFFF is the PCI device function number + * + * Reg_num - Config space register must be < 40h + * + * Value - input value for write, output for read + * + */ + + PCIcontext = (PCI_HANDLER_CONTEXT *) context; + + pci_bus = LOWORD(PCIcontext->seg) << 16; + pci_bus |= LOWORD(PCIcontext->bus); + + dev_func = PCIcontext->dev_func; + + pci_reg = (u8) address; + + switch (function) + { + + case ADDRESS_SPACE_READ: + + *value = 0; + + switch (bit_width) + { + /* PCI Register width */ + + case 8: + status = acpi_os_read_pci_cfg_byte (pci_bus, dev_func, pci_reg, + (u8 *) value); + break; + + case 16: + status = acpi_os_read_pci_cfg_word (pci_bus, dev_func, pci_reg, + (u16 *) value); + break; + + case 32: + status = acpi_os_read_pci_cfg_dword (pci_bus, dev_func, pci_reg, + value); + break; + + default: + status = AE_AML_OPERAND_VALUE; + + } /* Switch bit_width */ + + break; + + + case ADDRESS_SPACE_WRITE: + + + switch (bit_width) + { + /* PCI Register width */ + + case 8: + status = acpi_os_write_pci_cfg_byte (pci_bus, dev_func, pci_reg, + *(u8 *) value); + break; + + case 16: + status = acpi_os_write_pci_cfg_word (pci_bus, dev_func, pci_reg, + *(u16 *) value); + break; + + case 32: + status = acpi_os_write_pci_cfg_dword (pci_bus, dev_func, pci_reg, + *value); + break; + + default: + status = AE_AML_OPERAND_VALUE; + + } /* Switch bit_width */ + + break; + + + default: + + status = AE_BAD_PARAMETER; + break; + + } + + return (status); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amresnte.c linux/drivers/acpi/interpreter/amresnte.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amresnte.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amresnte.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,555 @@ + +/****************************************************************************** + * + * Module Name: amresnte - AML Interpreter object resolution + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "parser.h" +#include "dispatch.h" +#include "interp.h" +#include "namesp.h" +#include "tables.h" +#include "events.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amresnte"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_resolve_entry_to_value + * + * PARAMETERS: Stack_ptr - Pointer to a location on a stack that contains + * a ptr to an NTE + * + * RETURN: Status + * + * DESCRIPTION: Resolve a ACPI_NAMED_OBJECT(nte, A.K.A. a "direct name pointer") + * + * Note: for some of the data types, the pointer attached to the NTE can be + * either a pointer to an actual internal object or a pointer into the AML + * stream itself. These types are currently: + * + * ACPI_TYPE_NUMBER + * ACPI_TYPE_STRING + * ACPI_TYPE_BUFFER + * ACPI_TYPE_MUTEX + * ACPI_TYPE_PACKAGE + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_resolve_entry_to_value ( + ACPI_NAMED_OBJECT **stack_ptr) +{ + ACPI_STATUS status = AE_OK; + ACPI_OBJECT_INTERNAL *val_desc = NULL; + ACPI_OBJECT_INTERNAL *obj_desc = NULL; + ACPI_NAMED_OBJECT *stack_entry; + u8 *aml_pointer = NULL; + OBJECT_TYPE_INTERNAL entry_type; + u8 locked; + u8 attached_aml_pointer = FALSE; + u8 aml_opcode = 0; + u32 temp_val; + OBJECT_TYPE_INTERNAL object_type; + + + stack_entry = *stack_ptr; + + + /* + * The stack pointer is a "Direct name ptr", and points to a + * a ACPI_NAMED_OBJECT(nte). Get the pointer that is attached to + * the nte. + */ + + val_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) stack_entry); + entry_type = acpi_ns_get_type ((ACPI_HANDLE) stack_entry); + + /* + * The Val_desc attached to the NTE can be either: + * 1) An internal ACPI object + * 2) A pointer into the AML stream (into one of the ACPI system tables) + */ + + if (acpi_tb_system_table_pointer (val_desc)) { + attached_aml_pointer = TRUE; + aml_opcode = *((u8 *) val_desc); + aml_pointer = ((u8 *) val_desc) + 1; + + } + + + /* + * Action is based on the type of the NTE, which indicates the type + * of the attached object or pointer + */ + switch (entry_type) + { + + case ACPI_TYPE_PACKAGE: + + /* + * Val_desc should point to either an ACPI_OBJECT_INTERNAL of + * type Package, or an initialization in the AML stream. + */ + if (!val_desc) { + return (AE_AML_NO_OPERAND); + } + + + if (attached_aml_pointer) { + /* + * This means that the package initialization is not parsed + * -- should not happen + */ + return (AE_NOT_IMPLEMENTED); + } + + /* Val_desc is an internal object in all cases by the time we get here */ + + if (!val_desc || (ACPI_TYPE_PACKAGE != val_desc->common.type)) { + return (AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_cm_add_reference (obj_desc); + break; + + + case ACPI_TYPE_BUFFER: + + if (!val_desc) { + return (AE_AML_NO_OPERAND); + } + + if (attached_aml_pointer) { + /* + * This means that the buffer initialization is not parsed + * -- should not happen + */ + return (AE_NOT_IMPLEMENTED); + } + + /* Val_desc is an internal object in all cases by the time we get here */ + + if (!val_desc || (ACPI_TYPE_BUFFER != val_desc->common.type)) { + return (AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_cm_add_reference (obj_desc); + + break; + + + case ACPI_TYPE_STRING: + + if (attached_aml_pointer) { + /* Allocate a new string object */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Init the internal object */ + + obj_desc->string.pointer = (char *) aml_pointer; + obj_desc->string.length = STRLEN (aml_pointer); + } + + else { + if (ACPI_TYPE_STRING != val_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_cm_add_reference (obj_desc); + } + + break; + + + case ACPI_TYPE_NUMBER: + + if (!val_desc) { + return (AE_AML_NO_OPERAND); + } + + + /* + * An ACPI_TYPE_NUMBER can be either an object or an AML pointer + */ + + if (attached_aml_pointer) { + /* + * The attachment points into the AML stream, get the number from + * there. The actual number is based upon the AML opcode + * + * Note: Word_op and DWord_op will not work properly if the + * processor's endianness does not match the AML's. + */ + + switch (aml_opcode) + { + + case AML_ZERO_OP: + + temp_val = 0; + break; + + + case AML_ONE_OP: + + temp_val = 1; + break; + + + case AML_ONES_OP: + + temp_val = 0xFFFFFFFF; + break; + + + case AML_BYTE_OP: + + temp_val = (u32) ((u8 *) val_desc)[1]; + break; + + + case AML_WORD_OP: + + MOVE_UNALIGNED16_TO_32 (&temp_val, &((u8 *) val_desc)[1]); + break; + + + case AML_DWORD_OP: + + MOVE_UNALIGNED32_TO_32 (&temp_val, &((u8 *) val_desc)[1]); + break; + + + default: + + return (AE_AML_BAD_OPCODE); + + } /* switch */ + + + /* Create and initialize a new object */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + obj_desc->number.value = temp_val; + } + + else { + /* + * The NTE has an attached internal object, make sure that it's a + * number + */ + + if (ACPI_TYPE_NUMBER != val_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_cm_add_reference (obj_desc); + } + + break; + + + case INTERNAL_TYPE_DEF_FIELD: + + /* + * TBD: [Investigate] Is this the correct solution? + * + * This section was extended to convert to generic buffer if + * the return length is greater than 32 bits, but still allows + * for returning a type Number for smaller values because the + * caller can then apply arithmetic operators on those fields. + * + * XXX - Implementation limitation: Fields are implemented as type + * XXX - Number, but they really are supposed to be type Buffer. + * XXX - The two are interchangeable only for lengths <= 32 bits. + */ + if(val_desc->field.length > 32) { + object_type = ACPI_TYPE_BUFFER; + } + else { + object_type = ACPI_TYPE_NUMBER; + } + + /* + * Create the destination buffer object and the buffer space. + */ + obj_desc = acpi_cm_create_internal_object (object_type); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* + * Fill in the object specific details + */ + if (ACPI_TYPE_BUFFER == object_type) { + obj_desc->buffer.pointer = acpi_cm_callocate(val_desc->field.length); + if (!obj_desc->buffer.pointer) { + acpi_cm_remove_reference(obj_desc); + return (AE_NO_MEMORY); + } + + obj_desc->buffer.length = val_desc->field.length; + + status = acpi_aml_get_named_field_value ((ACPI_HANDLE) stack_entry, + obj_desc->buffer.pointer, obj_desc->buffer.length); + + if (AE_OK != status) { + return (status); + } + } + else { + status = acpi_aml_get_named_field_value ((ACPI_HANDLE) stack_entry, + &temp_val, sizeof (temp_val)); + + if (AE_OK != status) { + return (status); + } + + obj_desc->number.value = temp_val; + } + + + break; + + + case INTERNAL_TYPE_BANK_FIELD: + + if (!val_desc) { + return (AE_AML_NO_OPERAND); + } + + if (attached_aml_pointer) { + return (AE_AML_OPERAND_TYPE); + } + + if (INTERNAL_TYPE_BANK_FIELD != val_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + + /* Get the global lock if needed */ + + obj_desc = (ACPI_OBJECT_INTERNAL *) *stack_ptr; + locked = acpi_aml_acquire_global_lock (obj_desc->field_unit.lock_rule); + { + + /* Set Index value to select proper Data register */ + /* perform the update */ + + status = acpi_aml_set_named_field_value (val_desc->bank_field.bank_select, + &val_desc->bank_field.value, + sizeof (val_desc->bank_field.value)); + } + acpi_aml_release_global_lock (locked); + + + if (AE_OK != status) { + return (status); + } + + /* Read Data value */ + + status = acpi_aml_get_named_field_value ( + (ACPI_HANDLE) val_desc->bank_field.container, + &temp_val, sizeof (temp_val)); + if (AE_OK != status) { + return (status); + } + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + obj_desc->number.value = temp_val; + break; + + + case INTERNAL_TYPE_INDEX_FIELD: + + if (!val_desc) { + return (AE_AML_NO_OPERAND); + } + + if (attached_aml_pointer) { + return (AE_AML_OPERAND_TYPE); + } + + if (INTERNAL_TYPE_INDEX_FIELD != val_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + + /* Set Index value to select proper Data register */ + /* Get the global lock if needed */ + + obj_desc = (ACPI_OBJECT_INTERNAL *) *stack_ptr; + locked = acpi_aml_acquire_global_lock (obj_desc->field_unit.lock_rule); + { + /* Perform the update */ + + status = acpi_aml_set_named_field_value (val_desc->index_field.index, + &val_desc->index_field.value, + sizeof (val_desc->index_field.value)); + } + acpi_aml_release_global_lock (locked); + + if (AE_OK != status) { + return (status); + } + + /* Read Data value */ + + status = acpi_aml_get_named_field_value (val_desc->index_field.data, &temp_val, sizeof (temp_val)); + if (AE_OK != status) { + return (status); + } + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + obj_desc->number.value = temp_val; + break; + + + case ACPI_TYPE_FIELD_UNIT: + + if (!val_desc) { + return (AE_AML_NO_OPERAND); + } + + if (attached_aml_pointer) { + return (AE_AML_OPERAND_TYPE); + } + + if (val_desc->common.type != (u8) entry_type) { + return (AE_AML_OPERAND_TYPE); + break; + } + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_ANY); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + if ((status = acpi_aml_get_field_unit_value (val_desc, obj_desc)) != AE_OK) { + acpi_cm_remove_reference (obj_desc); + return (status); + } + + break; + + + /* + * For these objects, just return the object attached to the NTE + */ + + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_METHOD: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_REGION: + + + /* There must be an object attached to this NTE */ + + if (!val_desc) { + return (AE_AML_INTERNAL); + } + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_cm_add_reference (obj_desc); + break; + + + /* Devices rarely have an attached object, return the NTE */ + + case ACPI_TYPE_DEVICE: + + + /* Method locals and arguments have a pseudo-NTE, just return it */ + + case INTERNAL_TYPE_METHOD_ARGUMENT: + case INTERNAL_TYPE_METHOD_LOCAL_VAR: + + return (AE_OK); + break; + + + /* TYPE_Any is untyped, and thus there is no object associated with it */ + + case ACPI_TYPE_ANY: + + return (AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */ + + + /* Default case is for unknown types */ + + default: + + return (AE_AML_OPERAND_TYPE); + + } /* switch (Entry_type) */ + + + /* Put the object descriptor on the stack */ + + *stack_ptr = (void *) obj_desc; + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amresolv.c linux/drivers/acpi/interpreter/amresolv.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amresolv.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amresolv.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,452 @@ + +/****************************************************************************** + * + * Module Name: amresolv - AML Interpreter object resolution + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "parser.h" +#include "dispatch.h" +#include "interp.h" +#include "namesp.h" +#include "tables.h" +#include "events.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amresolv"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_get_field_unit_value + * + * PARAMETERS: *Field_desc - Pointer to a Field_unit + * *Result_desc - Pointer to an empty descriptor + * which will become a Number + * containing the field's value. + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value from a Field_unit + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_get_field_unit_value ( + ACPI_OBJECT_INTERNAL *field_desc, + ACPI_OBJECT_INTERNAL *result_desc) +{ + ACPI_STATUS status = AE_OK; + u32 mask; + u8 *location = NULL; + u8 locked = FALSE; + + + if (!field_desc) { + status = AE_AML_NO_OPERAND; + } + + else if (!field_desc->field_unit.container) { + status = AE_AML_INTERNAL; + } + + else if (ACPI_TYPE_BUFFER != field_desc->field_unit.container->common.type) { + status = AE_AML_OPERAND_TYPE; + } + + else if (field_desc->field_unit.sequence + != field_desc->field_unit.container->buffer.sequence) + { + status = AE_AML_INTERNAL; + } + + else if (!result_desc) { + status = AE_AML_INTERNAL; + } + + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* Get the global lock if needed */ + + locked = acpi_aml_acquire_global_lock (field_desc->field_unit.lock_rule); + + /* Field location is (base of buffer) + (byte offset) */ + + location = field_desc->field_unit.container->buffer.pointer + + field_desc->field_unit.offset; + + /* + * Construct Mask with as many 1 bits as the field width + * + * NOTE: Only the bottom 5 bits are valid for a shift operation, so + * special care must be taken for any shift greater than 31 bits. + * + * TBD: [Unhandled] Fields greater than 32-bits will not work. + */ + + if (field_desc->field_unit.length < 32) { + mask = ((u32) 1 << field_desc->field_unit.length) - (u32) 1; + } + else { + mask = 0xFFFFFFFF; + } + + result_desc->number.type = (u8) ACPI_TYPE_NUMBER; + + /* Get the 32 bit value at the location */ + + MOVE_UNALIGNED32_TO_32 (&result_desc->number.value, location); + + /* + * Shift the 32-bit word containing the field, and mask off the + * resulting value + */ + + result_desc->number.value = + (result_desc->number.value >> field_desc->field_unit.bit_offset) & mask; + + /* Release global lock if we acquired it earlier */ + + acpi_aml_release_global_lock (locked); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_resolve_to_value + * + * PARAMETERS: **Stack_ptr - Points to entry on Obj_stack, which can + * be either an (ACPI_OBJECT_INTERNAL *) + * or an ACPI_HANDLE. + * + * RETURN: Status + * + * DESCRIPTION: Convert Reference entries on Obj_stack to Rvalues + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_resolve_to_value ( + ACPI_OBJECT_INTERNAL **stack_ptr) +{ + ACPI_STATUS status = AE_OK; + + + if (!stack_ptr || !*stack_ptr) { + return (AE_AML_NO_OPERAND); + } + + + /* + * The entity pointed to by the Stack_ptr can be either + * 1) A valid ACPI_OBJECT_INTERNAL, or + * 2) A ACPI_NAMED_OBJECT(nte) + */ + + if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_INTERNAL)) { + + status = acpi_aml_resolve_object_to_value (stack_ptr); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* + * Object on the stack may have changed if Acpi_aml_resolve_object_to_value() + * was called (i.e., we can't use an _else_ here.) + */ + + if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_NAMED)) { + status = acpi_aml_resolve_entry_to_value ((ACPI_NAMED_OBJECT**) stack_ptr); + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_resolve_object_to_value + * + * PARAMETERS: Stack_ptr - Pointer to a stack location that contains a + * ptr to an internal object. + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value from an internal object. The Reference type + * uses the associated AML opcode to determine the value. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_resolve_object_to_value ( + ACPI_OBJECT_INTERNAL **stack_ptr) +{ + ACPI_OBJECT_INTERNAL *stack_desc; + ACPI_STATUS status = AE_OK; + ACPI_HANDLE temp_handle = NULL; + ACPI_OBJECT_INTERNAL *obj_desc = NULL; + u32 index = 0; + u16 opcode; + + + stack_desc = *stack_ptr; + + /* This is an ACPI_OBJECT_INTERNAL */ + + switch (stack_desc->common.type) + { + + case INTERNAL_TYPE_REFERENCE: + + opcode = stack_desc->reference.op_code; + + switch (opcode) + { + + case AML_NAME_OP: + + /* + * Convert indirect name ptr to a direct name ptr. + * Then, Acpi_aml_resolve_entry_to_value can be used to get the value + */ + + temp_handle = stack_desc->reference.object; + + /* Delete the Reference Object */ + + acpi_cm_remove_reference (stack_desc); + + /* Put direct name pointer onto stack and exit */ + + (*stack_ptr) = temp_handle; + status = AE_OK; + break; + + + case AML_LOCAL_OP: + + index = stack_desc->reference.offset; + + /* Delete the Reference Object */ + + acpi_cm_remove_reference (stack_desc); + + /* + * Get the local from the method's state info + * Note: this increments the object reference count + */ + + status = acpi_ds_method_data_get_value (MTH_TYPE_LOCAL, index, + stack_ptr); + if (ACPI_FAILURE (status)) { + return (status); + } + + stack_desc = *stack_ptr; + + if (ACPI_TYPE_NUMBER == stack_desc->common.type) { + /* Value is a Number */ + + } + + break; + + + case AML_ARG_OP: + + index = stack_desc->reference.offset; + + /* Delete the Reference Object*/ + + acpi_cm_remove_reference (stack_desc); + + /* + * Get the argument from the method's state info + * Note: this increments the object reference count + */ + + status = acpi_ds_method_data_get_value (MTH_TYPE_ARG, index, + stack_ptr); + if (ACPI_FAILURE (status)) { + return (status); + } + + stack_desc = *stack_ptr; + + if (ACPI_TYPE_NUMBER == stack_desc->common.type) { + /* Value is a Number */ + + } + + break; + + + /* + * TBD: [Restructure] These next three opcodes change the type of + * the object, which is actually a no-no. + */ + + case AML_ZERO_OP: + + stack_desc->common.type = (u8) ACPI_TYPE_NUMBER; + stack_desc->number.value = 0; + break; + + + case AML_ONE_OP: + + stack_desc->common.type = (u8) ACPI_TYPE_NUMBER; + stack_desc->number.value = 1; + break; + + + case AML_ONES_OP: + + stack_desc->common.type = (u8) ACPI_TYPE_NUMBER; + stack_desc->number.value = 0xFFFFFFFF; + break; + + + case AML_INDEX_OP: + + switch (stack_desc->reference.target_type) + { + case ACPI_TYPE_BUFFER_FIELD: + + /* Just return - leave the Reference on the stack */ + break; + + + case ACPI_TYPE_PACKAGE: + obj_desc = *stack_desc->reference.where; + if (obj_desc) { + /* + * Valid obj descriptor, copy pointer to return value + * (i.e., dereference the package index) + * Delete the ref object, increment the returned object + */ + acpi_cm_remove_reference (stack_desc); + acpi_cm_add_reference (obj_desc); + *stack_ptr = obj_desc; + } + + else { + /* + * A NULL object descriptor means an unitialized element of + * the package, can't deref it + */ + + status = AE_AML_UNINITIALIZED_ELEMENT; + } + break; + + default: + /* Invalid reference OBJ*/ + + status = AE_AML_INTERNAL; + break; + } + + break; + + + case AML_DEBUG_OP: + + /* Just leave the object as-is */ + break; + + + default: + + status = AE_AML_INTERNAL; + + } /* switch (Opcode) */ + + + if (AE_OK != status) { + return (status); + } + + break; /* case INTERNAL_TYPE_REFERENCE */ + + + case ACPI_TYPE_FIELD_UNIT: + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_ANY); + if (!obj_desc) { + /* Descriptor allocation failure */ + + return (AE_NO_MEMORY); + } + + status = acpi_aml_get_field_unit_value (stack_desc, obj_desc); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (obj_desc); + obj_desc = NULL; + } + + *stack_ptr = (void *) obj_desc; + break; + + + case INTERNAL_TYPE_BANK_FIELD: + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_ANY); + if (!obj_desc) { + /* Descriptor allocation failure */ + + return (AE_NO_MEMORY); + } + + status = acpi_aml_get_field_unit_value (stack_desc, obj_desc); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (obj_desc); + obj_desc = NULL; + } + + *stack_ptr = (void *) obj_desc; + break; + + + /* TBD: [Future] - may need to handle Index_field, and Def_field someday */ + + default: + + break; + + } /* switch (Stack_desc->Common.Type) */ + + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amresop.c linux/drivers/acpi/interpreter/amresop.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amresop.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amresop.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,429 @@ + +/****************************************************************************** + * + * Module Name: amresop - AML Interpreter operand/object resolution + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "parser.h" +#include "dispatch.h" +#include "interp.h" +#include "namesp.h" +#include "tables.h" +#include "events.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amresop"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_resolve_operands + * + * PARAMETERS: Opcode Opcode being interpreted + * Stack_ptr Top of operand stack + * + * RETURN: Status + * + * DESCRIPTION: Convert stack entries to required types + * + * Each nibble in Arg_types represents one required operand + * and indicates the required Type: + * + * The corresponding stack entry will be converted to the + * required type if possible, else return an exception + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_resolve_operands ( + u16 opcode, + ACPI_OBJECT_INTERNAL **stack_ptr) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_STATUS status = AE_OK; + u8 object_type; + ACPI_HANDLE temp_handle; + u32 arg_types; + ACPI_OP_INFO *op_info; + u32 this_arg_type; + + + op_info = acpi_ps_get_opcode_info (opcode); + if (!op_info) { + return (AE_AML_BAD_OPCODE); + } + + + arg_types = op_info->runtime_args; + if (arg_types == ARGI_INVALID_OPCODE) { + status = AE_AML_INTERNAL; + goto cleanup; + } + + + /* + * Normal exit is with *Types == '\0' at end of string. + * Function will return an exception from within the loop upon + * finding an entry which is not, and cannot be converted + * to, the required type; if stack underflows; or upon + * finding a NULL stack entry (which "should never happen"). + */ + + while (GET_CURRENT_ARG_TYPE (arg_types)) { + if (!stack_ptr || !*stack_ptr) { + status = AE_AML_INTERNAL; + goto cleanup; + } + + /* Extract useful items */ + + obj_desc = *stack_ptr; + + /* Decode the descriptor type */ + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + /* NTE */ + + object_type = ((ACPI_NAMED_OBJECT*) obj_desc)->type; + } + + else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { + /* ACPI internal object */ + + object_type = obj_desc->common.type; + + /* Check for bad ACPI_OBJECT_TYPE */ + + if (!acpi_aml_validate_object_type (object_type)) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + if (object_type == (u8) INTERNAL_TYPE_REFERENCE) { + /* + * Decode the Reference + */ + + op_info = acpi_ps_get_opcode_info (opcode); + if (!op_info) { + return (AE_AML_BAD_OPCODE); + } + + + switch (obj_desc->reference.op_code) + { + case AML_ZERO_OP: + case AML_ONE_OP: + case AML_ONES_OP: + case AML_DEBUG_OP: + case AML_NAME_OP: + case AML_INDEX_OP: + case AML_ARG_OP: + case AML_LOCAL_OP: + + break; + + default: + status = AE_AML_OPERAND_TYPE; + goto cleanup; + break; + } + } + + } + + else { + /* Invalid descriptor */ + + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + + /* + * Decode a character from the type string + */ + + this_arg_type = GET_CURRENT_ARG_TYPE (arg_types); + INCREMENT_ARG_LIST (arg_types); + + + switch (this_arg_type) + { + + case ARGI_REFERENCE: /* Reference */ + case ARGI_TARGETREF: + + /* Need an operand of type INTERNAL_TYPE_REFERENCE */ + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) /* direct name ptr OK as-is */ { + break; + } + + if (INTERNAL_TYPE_REFERENCE != object_type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + if (AML_NAME_OP == obj_desc->reference.op_code) { + /* + * Convert an indirect name ptr to direct name ptr and put + * it on the stack + */ + + temp_handle = obj_desc->reference.object; + acpi_cm_remove_reference (obj_desc); + (*stack_ptr) = temp_handle; + } + break; + + + case ARGI_NUMBER: /* Number */ + + /* Need an operand of type ACPI_TYPE_NUMBER */ + + if ((status = acpi_aml_resolve_to_value (stack_ptr)) != AE_OK) { + goto cleanup; + } + + if (ACPI_TYPE_NUMBER != (*stack_ptr)->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + break; + + + case ARGI_STRING: + + /* Need an operand of type ACPI_TYPE_STRING or ACPI_TYPE_BUFFER */ + + if ((status = acpi_aml_resolve_to_value (stack_ptr)) != AE_OK) { + goto cleanup; + } + + if ((ACPI_TYPE_STRING != (*stack_ptr)->common.type) && + (ACPI_TYPE_BUFFER != (*stack_ptr)->common.type)) + { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + break; + + + case ARGI_BUFFER: + + /* Need an operand of type ACPI_TYPE_BUFFER */ + + if ((status = acpi_aml_resolve_to_value(stack_ptr)) != AE_OK) { + goto cleanup; + } + + if (ACPI_TYPE_BUFFER != (*stack_ptr)->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + break; + + + case ARGI_MUTEX: + + /* Need an operand of type ACPI_TYPE_MUTEX */ + + if ((status = acpi_aml_resolve_to_value(stack_ptr)) != AE_OK) { + goto cleanup; + } + + if (ACPI_TYPE_MUTEX != (*stack_ptr)->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + break; + + + case ARGI_EVENT: + + /* Need an operand of type ACPI_TYPE_EVENT */ + + if ((status = acpi_aml_resolve_to_value(stack_ptr)) != AE_OK) { + goto cleanup; + } + + if (ACPI_TYPE_EVENT != (*stack_ptr)->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + break; + + + case ARGI_REGION: + + /* Need an operand of type ACPI_TYPE_REGION */ + + if ((status = acpi_aml_resolve_to_value(stack_ptr)) != AE_OK) { + goto cleanup; + } + + if (ACPI_TYPE_REGION != (*stack_ptr)->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + break; + + + case ARGI_IF: /* If */ + + /* Need an operand of type INTERNAL_TYPE_IF */ + + if (INTERNAL_TYPE_IF != (*stack_ptr)->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + break; + + + case ARGI_PACKAGE: /* Package */ + + /* Need an operand of type ACPI_TYPE_PACKAGE */ + + if ((status = acpi_aml_resolve_to_value (stack_ptr)) != AE_OK) { + goto cleanup; + } + + if (ACPI_TYPE_PACKAGE != (*stack_ptr)->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + break; + + + case ARGI_ANYTYPE: + + + /* + * We don't want to resolve Index_op reference objects during + * a store because this would be an implicit De_ref_of operation. + * Instead, we just want to store the reference object. + */ + + if ((opcode == AML_STORE_OP) && + ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) && + ((*stack_ptr)->reference.op_code == AML_INDEX_OP)) + { + break; + } + + /* All others must be resolved */ + + if ((status = acpi_aml_resolve_to_value (stack_ptr)) != AE_OK) { + goto cleanup; + } + + /* All types OK, so we don't perform any typechecks */ + + break; + + + case ARGI_DATAOBJECT: + /* + * ARGI_DATAOBJECT is only used by the Size_of operator. + * + * The ACPI specification allows Size_of to return the size of + * a Buffer, String or Package. However, the MS ACPI.SYS AML + * Interpreter also allows an NTE reference to return without + * error with a size of 4. + */ + + if ((status = acpi_aml_resolve_to_value (stack_ptr)) != AE_OK) { + goto cleanup; + } + + /* Need a buffer, string, package or NTE reference */ + + if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) && + ((*stack_ptr)->common.type != ACPI_TYPE_STRING) && + ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE) && + ((*stack_ptr)->common.type != INTERNAL_TYPE_REFERENCE)) + { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + /* + * If this is a reference, only allow a reference to an NTE. + */ + if ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) { + if (!(*stack_ptr)->reference.nte) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + } + + break; + + + case ARGI_COMPLEXOBJ: + + if ((status = acpi_aml_resolve_to_value (stack_ptr)) != AE_OK) { + goto cleanup; + } + + /* Need a buffer or package */ + + if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) && + ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE)) + { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + break; + + + /* Unknown abbreviation passed in */ + + default: + status = AE_BAD_PARAMETER; + goto cleanup; + + } /* switch (*Types++) */ + + + /* + * If more operands needed, decrement Stack_ptr to point + * to next operand on stack (after checking for underflow). + */ + if (GET_CURRENT_ARG_TYPE (arg_types)) { + stack_ptr--; + } + + } /* while (*Types) */ + + +cleanup: + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amstore.c linux/drivers/acpi/interpreter/amstore.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amstore.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amstore.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,374 @@ + +/****************************************************************************** + * + * Module Name: amstore - AML Interpreter object store support + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "dispatch.h" +#include "interp.h" +#include "amlcode.h" +#include "namesp.h" +#include "tables.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amstore"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_store + * + * PARAMETERS: *Val_desc - Value to be stored + * *Dest_desc - Where to store it 0 Must be (ACPI_HANDLE) + * or an ACPI_OBJECT_INTERNAL of type + * Reference; if the latter the descriptor + * will be either reused or deleted. + * + * RETURN: Status + * + * DESCRIPTION: Store the value described by Val_desc into the location + * described by Dest_desc. Called by various interpreter + * functions to store the result of an operation into + * the destination operand. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_store ( + ACPI_OBJECT_INTERNAL *val_desc, + ACPI_OBJECT_INTERNAL *dest_desc) +{ + ACPI_STATUS status = AE_OK; + ACPI_OBJECT_INTERNAL *delete_dest_desc = NULL; + ACPI_OBJECT_INTERNAL *tmp_desc; + ACPI_NAMED_OBJECT *entry = NULL; + u8 value = 0; + u32 length; + u32 i; + + + /* Validate parameters */ + + if (!val_desc || !dest_desc) { + return (AE_AML_NO_OPERAND); + } + + /* Examine the datatype of the Dest_desc */ + + if (VALID_DESCRIPTOR_TYPE (dest_desc, ACPI_DESC_TYPE_NAMED)) { + /* Dest is an ACPI_HANDLE, create a new object */ + + entry = (ACPI_NAMED_OBJECT*) dest_desc; + dest_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE); + if (!dest_desc) { + /* Allocation failure */ + + return (AE_NO_MEMORY); + } + + /* Build a new Reference wrapper around the handle */ + + dest_desc->reference.op_code = AML_NAME_OP; + dest_desc->reference.object = entry; + } + + + /* Destination object must be of type Reference */ + + if (dest_desc->common.type != INTERNAL_TYPE_REFERENCE) { + /* Destination is not an Reference */ + + return (AE_AML_OPERAND_TYPE); + } + + /* Examine the Reference opcode */ + + switch (dest_desc->reference.op_code) + { + + case AML_NAME_OP: + + /* + * Storing into a Name + */ + delete_dest_desc = dest_desc; + status = acpi_aml_store_object_to_nte (val_desc, dest_desc->reference.object); + + break; /* Case Name_op */ + + + case AML_INDEX_OP: + + delete_dest_desc = dest_desc; + + /* + * Valid source value and destination reference pointer. + * + * ACPI Specification 1.0B section 15.2.3.4.2.13: + * Destination should point to either a buffer or a package + */ + + /* + * Actually, storing to a package is not so simple. The source must be + * evaluated and converted to the type of the destination and then the + * source is copied into the destination - we can't just point to the + * source object. + */ + if (dest_desc->reference.target_type == ACPI_TYPE_PACKAGE) { + /* + * The object at *(Dest_desc->Reference.Where) is the + * element within the package that is to be modified. + */ + tmp_desc = *(dest_desc->reference.where); + if (tmp_desc) { + /* + * If the Destination element is a package, we will delete + * that object and construct a new one. + * + * TBD: [Investigate] Should both the src and dest be required + * to be packages? + * && (Val_desc->Common.Type == ACPI_TYPE_PACKAGE) + */ + if (tmp_desc->common.type == ACPI_TYPE_PACKAGE) { + /* + * Take away the reference for being part of a package and + * delete + */ + acpi_cm_remove_reference (tmp_desc); + acpi_cm_remove_reference (tmp_desc); + + tmp_desc = NULL; + } + } + + if (!tmp_desc) { + /* + * If the Tmp_desc is NULL, that means an uninitialized package + * has been used as a destination, therefore, we must create + * the destination element to match the type of the source + * element NOTE: Val_desc can be of any type. + */ + tmp_desc = acpi_cm_create_internal_object (val_desc->common.type); + if (!tmp_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * If the source is a package, copy the source to the new dest + */ + if (ACPI_TYPE_PACKAGE == tmp_desc->common.type) { + status = acpi_aml_build_copy_internal_package_object ( + val_desc, tmp_desc); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (tmp_desc); + tmp_desc = NULL; + goto cleanup; + } + } + + /* + * Install the new descriptor into the package and add a + * reference to the newly created descriptor for now being + * part of the parent package + */ + + *(dest_desc->reference.where) = tmp_desc; + acpi_cm_add_reference (tmp_desc); + } + + if (ACPI_TYPE_PACKAGE != tmp_desc->common.type) { + /* + * The destination element is not a package, so we need to + * convert the contents of the source (Val_desc) and copy into + * the destination (Tmp_desc) + */ + status = acpi_aml_store_object_to_object(val_desc, tmp_desc); + if (ACPI_FAILURE (status)) { + /* + * An error occurrered when copying the internal object + * so delete the reference. + */ + status = AE_AML_OPERAND_TYPE; + } + } + + break; + } + + /* + * Check that the destination is a Buffer Field type + */ + if (dest_desc->reference.target_type != ACPI_TYPE_BUFFER_FIELD) { + status = AE_AML_OPERAND_TYPE; + break; + } + + /* + * Storing into a buffer at a location defined by an Index. + * + * Each 8-bit element of the source object is written to the + * 8-bit Buffer Field of the Index destination object. + */ + + /* + * Set the Tmp_desc to the destination object and type check. + */ + tmp_desc = dest_desc->reference.object; + + if (tmp_desc->common.type != ACPI_TYPE_BUFFER) { + status = AE_AML_OPERAND_TYPE; + break; + } + + /* + * The assignment of the individual elements will be slightly + * different for each source type. + */ + + switch (val_desc->common.type) + { + /* + * If the type is Integer, the Length is 4. + * This loop to assign each of the elements is somewhat + * backward because of the Big Endian-ness of IA-64 + */ + case ACPI_TYPE_NUMBER: + length = 4; + for (i = length; i != 0; i--) { + value = (u8)(val_desc->number.value >> (MUL_8 (i - 1))); + tmp_desc->buffer.pointer[dest_desc->reference.offset] = value; + } + break; + + /* + * If the type is Buffer, the Length is in the structure. + * Just loop through the elements and assign each one in turn. + */ + case ACPI_TYPE_BUFFER: + length = val_desc->buffer.length; + for (i = 0; i < length; i++) { + value = *(val_desc->buffer.pointer + i); + tmp_desc->buffer.pointer[dest_desc->reference.offset] = value; + } + break; + + /* + * If the type is String, the Length is in the structure. + * Just loop through the elements and assign each one in turn. + */ + case ACPI_TYPE_STRING: + length = val_desc->string.length; + for (i = 0; i < length; i++) { + value = *(val_desc->string.pointer + i); + tmp_desc->buffer.pointer[dest_desc->reference.offset] = value; + } + break; + + /* + * If source is not a valid type so return an error. + */ + default: + status = AE_AML_OPERAND_TYPE; + break; + } + + /* + * If we had an error, break out of this case statement. + */ + if(AE_OK != status) { + break; + } + + /* + * Set the return pointer + */ + dest_desc = tmp_desc; + + break; + + case AML_ZERO_OP: + case AML_ONE_OP: + case AML_ONES_OP: + + /* + * Storing to a constant is a no-op -- see spec sec 15.2.3.3.1. + * Delete the result descriptor. + */ + + delete_dest_desc = dest_desc; + break; + + + case AML_LOCAL_OP: + + status = acpi_ds_method_data_set_value (MTH_TYPE_LOCAL, + (dest_desc->reference.offset), val_desc); + delete_dest_desc = dest_desc; + break; + + + case AML_ARG_OP: + + status = acpi_ds_method_data_set_value (MTH_TYPE_ARG, + (dest_desc->reference.offset), val_desc); + delete_dest_desc = dest_desc; + break; + + + case AML_DEBUG_OP: + + /* + * Storing to the Debug object causes the value stored to be + * displayed and otherwise has no effect -- see sec. 15.2.3.3.3. + */ + + delete_dest_desc = dest_desc; + break; + + + default: + + /* TBD: [Restructure] use object dump routine !! */ + + delete_dest_desc = dest_desc; + status = AE_AML_INTERNAL; + + } /* switch(Dest_desc->Reference.Op_code) */ + + +cleanup: + + /* Cleanup and exit*/ + + if (delete_dest_desc) { + acpi_cm_remove_reference (delete_dest_desc); + } + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amstoren.c linux/drivers/acpi/interpreter/amstoren.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amstoren.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amstoren.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,518 @@ + +/****************************************************************************** + * + * Module Name: amstoren - AML Interpreter object store support, store to NTE + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "dispatch.h" +#include "interp.h" +#include "amlcode.h" +#include "namesp.h" +#include "tables.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amstoren"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_store_object_to_nte + * + * PARAMETERS: *Val_desc - Value to be stored + * *Entry - Named object to recieve the value + * + * RETURN: Status + * + * DESCRIPTION: Store the object to the named object. + * + * The Assignment of an object to a named object is handled here + * The val passed in will replace the current value (if any) + * with the input value. + * + * When storing into an object the data is converted to the + * target object type then stored in the object. This means + * that the target object type (for an initialized target) will + * not be changed by a store operation. + * + * NOTE: the global lock is acquired early. This will result + * in the global lock being held a bit longer. Also, if the + * function fails during set up we may get the lock when we + * don't really need it. I don't think we care. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_store_object_to_nte ( + ACPI_OBJECT_INTERNAL *val_desc, + ACPI_NAMED_OBJECT *entry) +{ + ACPI_STATUS status = AE_OK; + u8 *buffer = NULL; + u32 length = 0; + u32 mask; + u32 new_value; + u8 locked = FALSE; + u8 *location=NULL; + ACPI_OBJECT_INTERNAL *dest_desc; + OBJECT_TYPE_INTERNAL destination_type = ACPI_TYPE_ANY; + + + /* + * Assuming the parameters are valid!!! + */ + ACPI_ASSERT((entry) && (val_desc)); + + destination_type = acpi_ns_get_type (entry); + + /* + * First ensure we have a value that can be stored in the target + */ + switch (destination_type) + { + /* Type of Name's existing value */ + + case INTERNAL_TYPE_ALIAS: + + /* + * Aliases are resolved by Acpi_aml_prep_operands + */ + + status = AE_AML_INTERNAL; + break; + + + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + case ACPI_TYPE_FIELD_UNIT: + case ACPI_TYPE_NUMBER: + + /* + * These cases all require only number values or values that + * can be converted to numbers. + * + * If value is not a Number, try to resolve it to one. + */ + + if (val_desc->common.type != ACPI_TYPE_NUMBER) { + /* + * Initially not a number, convert + */ + status = acpi_aml_resolve_to_value (&val_desc); + if ((status == AE_OK) && + (val_desc->common.type != ACPI_TYPE_NUMBER)) + { + /* + * Conversion successful but still not a number + */ + status = AE_AML_OPERAND_TYPE; + } + } + + break; + + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + case INTERNAL_TYPE_DEF_FIELD: + + /* + * Storing into a Field in a region or into a buffer or into + * a string all is essentially the same. + * + * If value is not a valid type, try to resolve it to one. + */ + + if ((val_desc->common.type != ACPI_TYPE_NUMBER) && + (val_desc->common.type != ACPI_TYPE_BUFFER) && + (val_desc->common.type != ACPI_TYPE_STRING)) + { + /* + * Initially not a valid type, convert + */ + status = acpi_aml_resolve_to_value (&val_desc); + if ((status == AE_OK) && + (val_desc->common.type != ACPI_TYPE_NUMBER) && + (val_desc->common.type != ACPI_TYPE_BUFFER) && + (val_desc->common.type != ACPI_TYPE_STRING)) + { + /* + * Conversion successful but still not a valid type + */ + status = AE_AML_OPERAND_TYPE; + } + } + break; + + + case ACPI_TYPE_PACKAGE: + + /* + * TBD: [Unhandled] Not real sure what to do here + */ + status = AE_NOT_IMPLEMENTED; + break; + + + default: + + /* + * All other types than Alias and the various Fields come here. + * Store Val_desc as the new value of the Name, and set + * the Name's type to that of the value being stored in it. + * Val_desc reference count is incremented by Attach_object. + */ + + status = acpi_ns_attach_object (entry, val_desc, val_desc->common.type); + + goto clean_up_and_bail_out; + break; + } + + /* Exit now if failure above */ + + if (status != AE_OK) { + goto clean_up_and_bail_out; + } + + /* + * Get descriptor for object attached to NTE + */ + dest_desc = acpi_ns_get_attached_object (entry); + if (!dest_desc) { + /* + * There is no existing object attached to this NTE + */ + status = AE_AML_INTERNAL; + goto clean_up_and_bail_out; + } + + /* + * Make sure the destination Object is the same as the NTE + */ + if (dest_desc->common.type != (u8) destination_type) { + status = AE_AML_INTERNAL; + goto clean_up_and_bail_out; + } + + /* + * Acpi_everything is ready to execute now, We have + * a value we can handle, just perform the update + */ + + switch (destination_type) + { + /* Type of Name's existing value */ + + case INTERNAL_TYPE_BANK_FIELD: + + /* + * Get the global lock if needed + */ + locked = acpi_aml_acquire_global_lock (dest_desc->bank_field.lock_rule); + + /* + * Set Bank value to select proper Bank + * Perform the update (Set Bank Select) + */ + + status = acpi_aml_set_named_field_value (dest_desc->bank_field.bank_select, + &dest_desc->bank_field.value, + sizeof (dest_desc->bank_field.value)); + if (status == AE_OK) { + /* Set bank select successful, set data value */ + + status = acpi_aml_set_named_field_value (dest_desc->bank_field.bank_select, + &val_desc->bank_field.value, + sizeof (val_desc->bank_field.value)); + } + + break; + + + case INTERNAL_TYPE_DEF_FIELD: + + /* + * Get the global lock if needed + */ + locked = acpi_aml_acquire_global_lock (val_desc->field.lock_rule); + + /* + * Perform the update + */ + + switch (val_desc->common.type) + { + case ACPI_TYPE_NUMBER: + buffer = (u8 *) &val_desc->number.value; + length = sizeof (val_desc->number.value); + break; + + case ACPI_TYPE_BUFFER: + buffer = (u8 *) val_desc->buffer.pointer; + length = val_desc->buffer.length; + break; + + case ACPI_TYPE_STRING: + buffer = (u8 *) val_desc->string.pointer; + length = val_desc->string.length; + break; + } + + status = acpi_aml_set_named_field_value (entry, buffer, length); + break; /* Global Lock released below */ + + + case ACPI_TYPE_STRING: + + /* + * Perform the update + */ + + switch (val_desc->common.type) + { + case ACPI_TYPE_NUMBER: + buffer = (u8 *) &val_desc->number.value; + length = sizeof (val_desc->number.value); + break; + + case ACPI_TYPE_BUFFER: + buffer = (u8 *) val_desc->buffer.pointer; + length = val_desc->buffer.length; + break; + + case ACPI_TYPE_STRING: + buffer = (u8 *) val_desc->string.pointer; + length = val_desc->string.length; + break; + } + + /* + * Setting a string value replaces the old string + */ + + if (length < dest_desc->string.length) { + /* + * Zero fill, not willing to do pointer arithmetic for + * archetecture independance. Just clear the whole thing + */ + MEMSET(dest_desc->string.pointer, 0, dest_desc->string.length); + MEMCPY(dest_desc->string.pointer, buffer, length); + } + else { + /* + * Free the current buffer, then allocate a buffer + * large enough to hold the value + */ + if ( dest_desc->string.pointer && + !acpi_tb_system_table_pointer (dest_desc->string.pointer)) + { + /* + * Only free if not a pointer into the DSDT + */ + + acpi_cm_free(dest_desc->string.pointer); + } + + dest_desc->string.pointer = acpi_cm_allocate (length + 1); + dest_desc->string.length = length; + + if (!dest_desc->string.pointer) { + status = AE_NO_MEMORY; + goto clean_up_and_bail_out; + } + + MEMCPY(dest_desc->string.pointer, buffer, length); + } + break; + + + case ACPI_TYPE_BUFFER: + + /* + * Perform the update to the buffer + */ + + switch (val_desc->common.type) + { + case ACPI_TYPE_NUMBER: + buffer = (u8 *) &val_desc->number.value; + length = sizeof (val_desc->number.value); + break; + + case ACPI_TYPE_BUFFER: + buffer = (u8 *) val_desc->buffer.pointer; + length = val_desc->buffer.length; + break; + + case ACPI_TYPE_STRING: + buffer = (u8 *) val_desc->string.pointer; + length = val_desc->string.length; + break; + } + + /* + * Buffer is a static allocation, + * only place what will fit in the buffer. + */ + if (length <= dest_desc->buffer.length) { + /* + * Zero fill first, not willing to do pointer arithmetic for + * archetecture independence. Just clear the whole thing + */ + MEMSET(dest_desc->buffer.pointer, 0, dest_desc->buffer.length); + MEMCPY(dest_desc->buffer.pointer, buffer, length); + } + else { + /* + * truncate, copy only what will fit + */ + MEMCPY(dest_desc->buffer.pointer, buffer, dest_desc->buffer.length); + } + break; + + + case INTERNAL_TYPE_INDEX_FIELD: + + /* + * Get the global lock if needed + */ + locked = acpi_aml_acquire_global_lock (dest_desc->index_field.lock_rule); + + /* + * Set Index value to select proper Data register + * perform the update (Set index) + */ + + status = acpi_aml_set_named_field_value (dest_desc->index_field.index, + &dest_desc->index_field.value, + sizeof (dest_desc->index_field.value)); + + if (AE_OK == status) { + /* set index successful, next set Data value */ + + status = acpi_aml_set_named_field_value (dest_desc->index_field.data, + &val_desc->number.value, + sizeof (val_desc->number.value)); + } + break; + + + case ACPI_TYPE_FIELD_UNIT: + + if ((!dest_desc->field_unit.container || + ACPI_TYPE_BUFFER != dest_desc->field_unit.container->common.type || + dest_desc->field_unit.sequence != + dest_desc->field_unit.container->buffer.sequence)) + { + status = AE_AML_INTERNAL; + goto clean_up_and_bail_out; + } + + /* + * Get the global lock if needed + */ + locked = acpi_aml_acquire_global_lock (dest_desc->field_unit.lock_rule); + + /* + * TBD: [Unhandled] REMOVE this limitation + * Make sure the operation is within the limits of our implementation + * this is not a Spec limitation!! + */ + if (dest_desc->field_unit.length + dest_desc->field_unit.bit_offset > 32) { + status = AE_NOT_IMPLEMENTED; + goto clean_up_and_bail_out; + } + + /* Field location is (base of buffer) + (byte offset) */ + + location = dest_desc->field_unit.container->buffer.pointer + + dest_desc->field_unit.offset; + + /* + * Construct Mask with 1 bits where the field is, + * 0 bits elsewhere + */ + mask = ((u32) 1 << dest_desc->field_unit.length) - ((u32)1 + << dest_desc->field_unit.bit_offset); + + /* Zero out the field in the buffer */ + + MOVE_UNALIGNED32_TO_32 (&new_value, location); + new_value &= ~mask; + + /* + * Shift and mask the new value into position, + * and or it into the buffer. + */ + new_value |= (val_desc->number.value << dest_desc->field_unit.bit_offset) & + mask; + + /* Store back the value */ + + MOVE_UNALIGNED32_TO_32 (location, &new_value); + + break; + + + case ACPI_TYPE_NUMBER: + + dest_desc->number.value = val_desc->number.value; + break; + + + case ACPI_TYPE_PACKAGE: + + /* + * TBD: [Unhandled] Not real sure what to do here + */ + status = AE_NOT_IMPLEMENTED; + break; + + + default: + + /* + * All other types than Alias and the various Fields come here. + * Store Val_desc as the new value of the Name, and set + * the Name's type to that of the value being stored in it. + * Val_desc reference count is incremented by Attach_object. + */ + + status = AE_NOT_IMPLEMENTED; + break; + } + + +clean_up_and_bail_out: + + /* + * Release global lock if we acquired it earlier + */ + acpi_aml_release_global_lock (locked); + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amstorob.c linux/drivers/acpi/interpreter/amstorob.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amstorob.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amstorob.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,314 @@ + +/****************************************************************************** + * + * Module Name: amstorob - AML Interpreter object store support, store to object + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "dispatch.h" +#include "interp.h" +#include "amlcode.h" +#include "namesp.h" +#include "tables.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amstorob"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_store_object_to_object + * + * PARAMETERS: *Val_desc - Value to be stored + * *Dest_desc - Object to receive the value + * + * RETURN: Status + * + * DESCRIPTION: Store an object to another object. + * + * The Assignment of an object to another (not named) object + * is handled here. + * The val passed in will replace the current value (if any) + * with the input value. + * + * When storing into an object the data is converted to the + * target object type then stored in the object. This means + * that the target object type (for an initialized target) will + * not be changed by a store operation. + * + * This module allows destination types of Number, String, + * and Buffer. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_store_object_to_object ( + ACPI_OBJECT_INTERNAL *val_desc, + ACPI_OBJECT_INTERNAL *dest_desc) +{ + ACPI_STATUS status = AE_OK; + u8 *buffer = NULL; + u32 length = 0; + OBJECT_TYPE_INTERNAL destination_type = dest_desc->common.type; + + + /* + * Assuming the parameters are valid!!! + */ + ACPI_ASSERT((dest_desc) && (val_desc)); + + /* + * First ensure we have a value that can be stored in the target + */ + switch (destination_type) + { + /* Type of Name's existing value */ + + case ACPI_TYPE_NUMBER: + + /* + * These cases all require only number values or values that + * can be converted to numbers. + * + * If value is not a Number, try to resolve it to one. + */ + + if (val_desc->common.type != ACPI_TYPE_NUMBER) { + /* + * Initially not a number, convert + */ + status = acpi_aml_resolve_to_value (&val_desc); + if ((status == AE_OK) && + (val_desc->common.type != ACPI_TYPE_NUMBER)) + { + /* + * Conversion successful but still not a number + */ + status = AE_AML_OPERAND_TYPE; + } + } + + break; + + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* + * Storing into a Field in a region or into a buffer or into + * a string all is essentially the same. + * + * If value is not a valid type, try to resolve it to one. + */ + + if ((val_desc->common.type != ACPI_TYPE_NUMBER) && + (val_desc->common.type != ACPI_TYPE_BUFFER) && + (val_desc->common.type != ACPI_TYPE_STRING)) + { + /* + * Initially not a valid type, convert + */ + status = acpi_aml_resolve_to_value (&val_desc); + if ((status == AE_OK) && + (val_desc->common.type != ACPI_TYPE_NUMBER) && + (val_desc->common.type != ACPI_TYPE_BUFFER) && + (val_desc->common.type != ACPI_TYPE_STRING)) + { + /* + * Conversion successful but still not a valid type + */ + status = AE_AML_OPERAND_TYPE; + } + } + break; + + + default: + + /* + * TBD: [Unhandled] What other combinations must be implemented? + */ + status = AE_NOT_IMPLEMENTED; + break; + } + + /* Exit now if failure above */ + + if (status != AE_OK) { + goto clean_up_and_bail_out; + } + + /* + * Acpi_everything is ready to execute now, We have + * a value we can handle, just perform the update + */ + + switch (destination_type) + { + + case ACPI_TYPE_STRING: + + /* + * Perform the update + */ + + switch (val_desc->common.type) + { + case ACPI_TYPE_NUMBER: + buffer = (u8 *) &val_desc->number.value; + length = sizeof (val_desc->number.value); + break; + + case ACPI_TYPE_BUFFER: + buffer = (u8 *) val_desc->buffer.pointer; + length = val_desc->buffer.length; + break; + + case ACPI_TYPE_STRING: + buffer = (u8 *) val_desc->string.pointer; + length = val_desc->string.length; + break; + } + + /* + * Setting a string value replaces the old string + */ + + if (length < dest_desc->string.length) { + /* + * Zero fill, not willing to do pointer arithmetic for + * architecture independence. Just clear the whole thing + */ + MEMSET(dest_desc->string.pointer, 0, dest_desc->string.length); + MEMCPY(dest_desc->string.pointer, buffer, length); + } + else { + /* + * Free the current buffer, then allocate a buffer + * large enough to hold the value + */ + if ( dest_desc->string.pointer && + !acpi_tb_system_table_pointer (dest_desc->string.pointer)) + { + /* + * Only free if not a pointer into the DSDT + */ + + acpi_cm_free(dest_desc->string.pointer); + } + + dest_desc->string.pointer = acpi_cm_allocate (length + 1); + dest_desc->string.length = length; + + if (!dest_desc->string.pointer) { + status = AE_NO_MEMORY; + goto clean_up_and_bail_out; + } + + MEMCPY(dest_desc->string.pointer, buffer, length); + } + break; + + + case ACPI_TYPE_BUFFER: + + /* + * Perform the update to the buffer + */ + + switch (val_desc->common.type) + { + case ACPI_TYPE_NUMBER: + buffer = (u8 *) &val_desc->number.value; + length = sizeof (val_desc->number.value); + break; + + case ACPI_TYPE_BUFFER: + buffer = (u8 *) val_desc->buffer.pointer; + length = val_desc->buffer.length; + break; + + case ACPI_TYPE_STRING: + buffer = (u8 *) val_desc->string.pointer; + length = val_desc->string.length; + break; + } + + /* + * If the buffer is uninitialized, + * memory needs to be allocated for the copy. + */ + if(0 == dest_desc->buffer.length) { + dest_desc->buffer.pointer = acpi_cm_callocate(length); + dest_desc->buffer.length = length; + + if (!dest_desc->buffer.pointer) { + status = AE_NO_MEMORY; + goto clean_up_and_bail_out; + } + } + + /* + * Buffer is a static allocation, + * only place what will fit in the buffer. + */ + if (length <= dest_desc->buffer.length) { + /* + * Zero fill first, not willing to do pointer arithmetic for + * architecture independence. Just clear the whole thing + */ + MEMSET(dest_desc->buffer.pointer, 0, dest_desc->buffer.length); + MEMCPY(dest_desc->buffer.pointer, buffer, length); + } + else { + /* + * truncate, copy only what will fit + */ + MEMCPY(dest_desc->buffer.pointer, buffer, dest_desc->buffer.length); + } + break; + + case ACPI_TYPE_NUMBER: + + dest_desc->number.value = val_desc->number.value; + break; + + default: + + /* + * All other types than Alias and the various Fields come here. + * Store Val_desc as the new value of the Name, and set + * the Name's type to that of the value being stored in it. + * Val_desc reference count is incremented by Attach_object. + */ + + status = AE_NOT_IMPLEMENTED; + break; + } + +clean_up_and_bail_out: + + return (status); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amsystem.c linux/drivers/acpi/interpreter/amsystem.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amsystem.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amsystem.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,343 @@ + +/****************************************************************************** + * + * Module Name: amsystem - Interface to OS services + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" +#include "namesp.h" +#include "hardware.h" +#include "events.h" + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amsystem"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_thread_id + * + * PARAMETERS: None + * + * RETURN: Current Thread ID (for this implementation a 1 is returned) + * + * DESCRIPTION: An invocation is identified by its Thread ID. In a single + * threaded OS the Thread ID is undefined so a 1 will be + * returned. + * + ******************************************************************************/ + +u16 +acpi_aml_system_thread_id (void) +{ + return (1); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_wait_semaphore + * + * PARAMETERS: Semaphore - OSD semaphore to wait on + * Timeout - Max time to wait + * + * RETURN: Status + * + * DESCRIPTION: Implements a semaphore wait with a check to see if the + * semaphore is available immediately. If it is not, the + * interpreter is released. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_wait_semaphore ( + ACPI_HANDLE semaphore, + u32 timeout) +{ + ACPI_STATUS status; + + + status = acpi_os_wait_semaphore (semaphore, 1, 0); + if (ACPI_SUCCESS (status)) { + return (status); + } + + if (status == AE_TIME) { + /* We must wait, so unlock the interpreter */ + + acpi_aml_exit_interpreter (); + + status = acpi_os_wait_semaphore (semaphore, 1, timeout); + + /* Reacquire the interpreter */ + + acpi_aml_enter_interpreter (); + + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_do_stall + * + * PARAMETERS: How_long - The amount of time to stall + * + * RETURN: None + * + * DESCRIPTION: Suspend running thread for specified amount of time. + * + ******************************************************************************/ + +void +acpi_aml_system_do_stall ( + u32 how_long) +{ + + if (how_long > 1000) /* 1 millisecond */ { + /* Since this thread will sleep, we must release the interpreter */ + + acpi_aml_exit_interpreter (); + + acpi_os_sleep_usec (how_long); + + /* And now we must get the interpreter again */ + + acpi_aml_enter_interpreter (); + } + + else { + acpi_os_sleep_usec (how_long); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_do_suspend + * + * PARAMETERS: How_long - The amount of time to suspend + * + * RETURN: None + * + * DESCRIPTION: Suspend running thread for specified amount of time. + * + ******************************************************************************/ + +void +acpi_aml_system_do_suspend ( + u32 how_long) +{ + /* Since this thread will sleep, we must release the interpreter */ + + acpi_aml_exit_interpreter (); + + acpi_os_sleep ((u16) (how_long / (u32) 1000), + (u16) (how_long % (u32) 1000)); + + /* And now we must get the interpreter again */ + + acpi_aml_enter_interpreter (); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_acquire_mutex + * + * PARAMETERS: *Time_desc - The 'time to delay' object descriptor + * *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. This function will cause a lock to be generated + * for the Mutex pointed to by Obj_desc. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_acquire_mutex ( + ACPI_OBJECT_INTERNAL *time_desc, + ACPI_OBJECT_INTERNAL *obj_desc) +{ + ACPI_STATUS status = AE_OK; + + + if (!obj_desc) { + return (AE_BAD_PARAMETER); + } + + /* + * Support for the _GL_ Mutex object -- go get the global lock + */ + + if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) { + status = acpi_ev_acquire_global_lock (); + return (status); + } + + status = acpi_aml_system_wait_semaphore (obj_desc->mutex.semaphore, + time_desc->number.value); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_release_mutex + * + * PARAMETERS: *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. This operation is a request to release a + * previously acquired Mutex. If the Mutex variable is set then + * it will be decremented. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_release_mutex ( + ACPI_OBJECT_INTERNAL *obj_desc) +{ + ACPI_STATUS status = AE_OK; + + + if (!obj_desc) { + return (AE_BAD_PARAMETER); + } + + /* + * Support for the _GL_ Mutex object -- release the global lock + */ + if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) { + acpi_ev_release_global_lock (); + return (AE_OK); + } + + status = acpi_os_signal_semaphore (obj_desc->mutex.semaphore, 1); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_signal_event + * + * PARAMETERS: *Obj_desc - The object descriptor for this op + * + * RETURN: AE_OK + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_signal_event ( + ACPI_OBJECT_INTERNAL *obj_desc) +{ + ACPI_STATUS status = AE_OK; + + + if (obj_desc) { + status = acpi_os_signal_semaphore (obj_desc->event.semaphore, 1); + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_wait_event + * + * PARAMETERS: *Time_desc - The 'time to delay' object descriptor + * *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. This operation is a request to wait for an + * event. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_wait_event ( + ACPI_OBJECT_INTERNAL *time_desc, + ACPI_OBJECT_INTERNAL *obj_desc) +{ + ACPI_STATUS status = AE_OK; + + + if (obj_desc) { + status = acpi_aml_system_wait_semaphore (obj_desc->event.semaphore, + time_desc->number.value); + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_reset_event + * + * PARAMETERS: *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_reset_event ( + ACPI_OBJECT_INTERNAL *obj_desc) +{ + ACPI_STATUS status = AE_OK; + void *temp_semaphore; + + + /* + * We are going to simply delete the existing semaphore and + * create a new one! + */ + + status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore); + if (ACPI_SUCCESS (status)) { + acpi_os_delete_semaphore (obj_desc->mutex.semaphore); + obj_desc->mutex.semaphore = temp_semaphore; + } + + return (status); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amutils.c linux/drivers/acpi/interpreter/amutils.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amutils.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amutils.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,522 @@ + +/****************************************************************************** + * + * Module Name: amutils - interpreter/scanner utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "interp.h" +#include "amlcode.h" +#include "namesp.h" +#include "events.h" + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amutils"); + + +typedef struct internal_search_st +{ + ACPI_OBJECT_INTERNAL *dest_obj; + u32 index; + ACPI_OBJECT_INTERNAL *source_obj; + +} INTERNAL_PKG_SEARCH_INFO; + + +/* Used to traverse nested packages when copying*/ + +INTERNAL_PKG_SEARCH_INFO copy_level[MAX_PACKAGE_DEPTH]; + + +static char hex[] = + {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_enter_interpreter + * + * PARAMETERS: None + * + * DESCRIPTION: Enter the interpreter execution region + * + ******************************************************************************/ + +void +acpi_aml_enter_interpreter (void) +{ + + acpi_cm_acquire_mutex (ACPI_MTX_EXECUTE); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exit_interpreter + * + * PARAMETERS: None + * + * DESCRIPTION: Exit the interpreter execution region + * + * Cases where the interpreter is unlocked: + * 1) Completion of the execution of a control method + * 2) Method blocked on a Sleep() AML opcode + * 3) Method blocked on an Acquire() AML opcode + * 4) Method blocked on a Wait() AML opcode + * 5) Method blocked to acquire the global lock + * 6) Method blocked to execute a serialized control method that is + * already executing + * 7) About to invoke a user-installed opregion handler + * + ******************************************************************************/ + +void +acpi_aml_exit_interpreter (void) +{ + + acpi_cm_release_mutex (ACPI_MTX_EXECUTE); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_validate_object_type + * + * PARAMETERS: Type Object type to validate + * + * DESCRIPTION: Determine if a type is a valid ACPI object type + * + ******************************************************************************/ + +u8 +acpi_aml_validate_object_type ( + ACPI_OBJECT_TYPE type) +{ + + if ((type > ACPI_TYPE_MAX && type < INTERNAL_TYPE_BEGIN) || + (type > INTERNAL_TYPE_MAX)) + { + return FALSE; + } + + return TRUE; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_append_operand_diag + * + * PARAMETERS: *File_name - Name of source file + * Line_num - Line Number in file + * Op_code - Op_code being executed + * Num_operands - Number of operands Prep_stack tried to check + * + * DESCRIPTION: Print diagnostic information about operands. + * This function is intended to be called after Prep_stack + * has returned S_ERROR. + * + ******************************************************************************/ + +void +acpi_aml_append_operand_diag ( + char *file_name, + s32 line_num, + u16 op_code, + ACPI_OBJECT_INTERNAL **operands, + s32 num_operands) +{ + + /* + * This function outputs debug information only + */ + +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_buf_seq + * + * RETURN: The next buffer descriptor sequence number + * + * DESCRIPTION: Provide a unique sequence number for each Buffer descriptor + * allocated during the interpreter's existence. These numbers + * are used to relate Field_unit descriptors to the Buffers + * within which the fields are defined. + * + * Just increment the global counter and return it. + * + ******************************************************************************/ + +u32 +acpi_aml_buf_seq (void) +{ + + return ++acpi_gbl_buf_seq; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_acquire_global_lock + * + * PARAMETERS: Rule - Lock rule: Always_lock, Never_lock + * + * RETURN: TRUE/FALSE indicating whether the lock was actually acquired + * + * DESCRIPTION: Obtain the global lock and keep track of this fact via two + * methods. A global variable keeps the state of the lock, and + * the state is returned to the caller. + * + ******************************************************************************/ + +u8 +acpi_aml_acquire_global_lock ( + u32 rule) +{ + u8 locked = FALSE; + ACPI_STATUS status; + + + /* Only attempt lock if the Rule says so */ + + if (rule == (u32) GLOCK_ALWAYS_LOCK) { + /* OK to get the lock */ + + status = acpi_ev_acquire_global_lock (); + + if (ACPI_SUCCESS (status)) { + acpi_gbl_global_lock_set = TRUE; + locked = TRUE; + } + } + + return (locked); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_release_global_lock + * + * PARAMETERS: Locked_by_me - Return value from corresponding call to + * Acquire_global_lock. + * + * RETURN: Status + * + * DESCRIPTION: Release the global lock if it is locked. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_release_global_lock ( + u8 locked_by_me) +{ + + + /* Only attempt unlock if the caller locked it */ + + if (locked_by_me) { + /* Double check against the global flag */ + + if (acpi_gbl_global_lock_set) { + /* OK, now release the lock */ + + acpi_ev_release_global_lock (); + acpi_gbl_global_lock_set = FALSE; + } + + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_digits_needed + * + * PARAMETERS: val - Value to be represented + * base - Base of representation + * + * RETURN: the number of digits needed to represent val in base + * + ******************************************************************************/ + +s32 +acpi_aml_digits_needed ( + s32 val, + s32 base) +{ + s32 num_digits = 0; + + + if (base < 1) { + /* impossible base */ + + REPORT_ERROR ("Aml_digits_needed: Impossible base"); + } + + else { + for (num_digits = 1 + (val < 0) ; val /= base ; ++num_digits) { ; } + } + + return (num_digits); +} + + +/******************************************************************************* + * + * FUNCTION: ntohl + * + * PARAMETERS: Value - Value to be converted + * + * RETURN: Convert a 32-bit value to big-endian (swap the bytes) + * + ******************************************************************************/ + +u32 +_ntohl ( + u32 value) +{ + union + { + u32 value; + char bytes[4]; + } out; + + union + { + u32 value; + char bytes[4]; + } in; + + + in.value = value; + + out.bytes[0] = in.bytes[3]; + out.bytes[1] = in.bytes[2]; + out.bytes[2] = in.bytes[1]; + out.bytes[3] = in.bytes[0]; + + return out.value; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_eisa_id_to_string + * + * PARAMETERS: Numeric_id - EISA ID to be converted + * Out_string - Where to put the converted string (8 bytes) + * + * RETURN: Convert a numeric EISA ID to string representation + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_eisa_id_to_string ( + u32 numeric_id, + char *out_string) +{ + u32 id; + + /* swap to big-endian to get contiguous bits */ + + id = _ntohl (numeric_id); + + out_string[0] = (char) ('@' + ((id >> 26) & 0x1f)); + out_string[1] = (char) ('@' + ((id >> 21) & 0x1f)); + out_string[2] = (char) ('@' + ((id >> 16) & 0x1f)); + out_string[3] = hex[(id >> 12) & 0xf]; + out_string[4] = hex[(id >> 8) & 0xf]; + out_string[5] = hex[(id >> 4) & 0xf]; + out_string[6] = hex[id & 0xf]; + out_string[7] = 0; + + return AE_OK; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_build_copy_internal_package_object + * + * PARAMETERS: *Source_obj - Pointer to the source package object + * *Dest_obj - Where the internal object is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to copy an internal package object + * into another internal package object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_build_copy_internal_package_object ( + ACPI_OBJECT_INTERNAL *source_obj, + ACPI_OBJECT_INTERNAL *dest_obj) +{ + u32 current_depth = 0; + ACPI_STATUS status = AE_OK; + u32 length = 0; + u32 this_index; + u32 object_space = 0; + ACPI_OBJECT_INTERNAL *this_dest_obj; + ACPI_OBJECT_INTERNAL *this_source_obj; + INTERNAL_PKG_SEARCH_INFO *level_ptr; + + + /* + * Initialize the working variables + */ + + MEMSET ((void *) copy_level, 0, sizeof(copy_level)); + + copy_level[0].dest_obj = dest_obj; + copy_level[0].source_obj = source_obj; + level_ptr = ©_level[0]; + current_depth = 0; + + dest_obj->common.type = source_obj->common.type; + dest_obj->package.count = source_obj->package.count; + + + /* + * Build an array of ACPI_OBJECTS in the buffer + * and move the free space past it + */ + + dest_obj->package.elements = acpi_cm_callocate ( + (dest_obj->package.count + 1) * + sizeof (void *)); + if (!dest_obj->package.elements) { + /* Package vector allocation failure */ + + REPORT_ERROR ("Aml_build_copy_internal_package_object: Package vector allocation failure"); + return (AE_NO_MEMORY); + } + + dest_obj->package.next_element = dest_obj->package.elements; + + + while (1) { + this_index = level_ptr->index; + this_dest_obj = (ACPI_OBJECT_INTERNAL *) level_ptr->dest_obj->package.elements[this_index]; + this_source_obj = (ACPI_OBJECT_INTERNAL *) level_ptr->source_obj->package.elements[this_index]; + + if (IS_THIS_OBJECT_TYPE (this_source_obj, ACPI_TYPE_PACKAGE)) { + /* + * If this object is a package then we go one deeper + */ + if (current_depth >= MAX_PACKAGE_DEPTH-1) { + /* + * Too many nested levels of packages for us to handle + */ + return (AE_LIMIT); + } + + /* + * Build the package object + */ + this_dest_obj = acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE); + level_ptr->dest_obj->package.elements[this_index] = this_dest_obj; + + + this_dest_obj->common.type = ACPI_TYPE_PACKAGE; + this_dest_obj->package.count = this_dest_obj->package.count; + + /* + * Save space for the array of objects (Package elements) + * update the buffer length counter + */ + object_space = this_dest_obj->package.count * + sizeof (ACPI_OBJECT_INTERNAL); + length += object_space; + current_depth++; + level_ptr = ©_level[current_depth]; + level_ptr->dest_obj = this_dest_obj; + level_ptr->source_obj = this_source_obj; + level_ptr->index = 0; + + } /* if object is a package */ + + else { + + this_dest_obj = acpi_cm_create_internal_object ( + this_source_obj->common.type); + level_ptr->dest_obj->package.elements[this_index] = this_dest_obj; + + status = acpi_aml_store_object_to_object(this_source_obj, this_dest_obj); + + if (status != AE_OK) { + /* + * Failure get out + */ + return (status); + } + + length +=object_space; + + level_ptr->index++; + while (level_ptr->index >= level_ptr->dest_obj->package.count) { + /* + * We've handled all of the objects at this level, This means + * that we have just completed a package. That package may + * have contained one or more packages itself + */ + if (current_depth == 0) { + /* + * We have handled all of the objects in the top level + * package just add the length of the package objects + * and exit + */ + return (AE_OK); + } + + /* + * Go back up a level and move the index past the just + * completed package object. + */ + current_depth--; + level_ptr = ©_level[current_depth]; + level_ptr->index++; + } + } /* else object is NOT a package */ + } /* while (1) */ + + + /* + * We'll never get here, but the compiler whines about return value + */ + return (AE_OK); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/interpreter/amxface.c linux/drivers/acpi/interpreter/amxface.c --- v2.4.0-test2/linux/drivers/acpi/interpreter/amxface.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/interpreter/amxface.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,94 @@ + +/****************************************************************************** + * + * Module Name: ixface - External interpreter interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" + + +#define _COMPONENT INTERPRETER + MODULE_NAME ("amxface"); + + +/* + * DEFINE_AML_GLOBALS is tested in amlcode.h + * to determine whether certain global names should be "defined" or only + * "declared" in the current compilation. This enhances maintainability + * by enabling a single header file to embody all knowledge of the names + * in question. + * + * Exactly one module of any executable should #define DEFINE_GLOBALS + * before #including the header files which use this convention. The + * names in question will be defined and initialized in that module, + * and declared as extern in all other modules which #include those + * header files. + */ + +#define DEFINE_AML_GLOBALS +#include "amlcode.h" +#include "parser.h" +#include "namesp.h" + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_execute_method + * + * PARAMETERS: Pcode - Pointer to the pcode stream + * Pcode_length - Length of pcode that comprises the method + * **Params - List of parameters to pass to method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_execute_method ( + ACPI_NAMED_OBJECT *method_entry, + ACPI_OBJECT_INTERNAL **params, + ACPI_OBJECT_INTERNAL **return_obj_desc) +{ + ACPI_STATUS status; + + + /* + * The point here is to lock the interpreter and call the low + * level execute. + */ + + acpi_aml_enter_interpreter (); + + status = acpi_psx_execute (method_entry, params, return_obj_desc); + + acpi_aml_exit_interpreter (); + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/namespace/nsaccess.c linux/drivers/acpi/namespace/nsaccess.c --- v2.4.0-test2/linux/drivers/acpi/namespace/nsaccess.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/namespace/nsaccess.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,647 @@ + +/****************************************************************************** + * + * Module Name: nsaccess - Top-level functions for accessing ACPI namespace + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "interp.h" +#include "namesp.h" +#include "dispatch.h" + + +#define _COMPONENT NAMESPACE + MODULE_NAME ("nsaccess"); + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_root_create_scope + * + * PARAMETERS: Entry - NTE for which a scope will be created + * + * RETURN: Status + * + * DESCRIPTION: Create a scope table for the given name table entry + * + * MUTEX: Expects namespace to be locked + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_root_create_scope ( + ACPI_NAMED_OBJECT *entry) +{ + + /* Allocate a scope table */ + + if (entry->child_table) { + return (AE_EXIST); + } + + entry->child_table = acpi_ns_allocate_name_table (NS_TABLE_SIZE); + if (!entry->child_table) { + /* root name table allocation failure */ + + REPORT_ERROR ("Root name table allocation failure"); + return (AE_NO_MEMORY); + } + + /* + * Init the scope first entry -- since it is the exemplar of + * the scope (Some fields are duplicated to new entries!) + */ + acpi_ns_initialize_table (entry->child_table, NULL, entry); + return (AE_OK); + +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_root_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Allocate and initialize the root name table + * + * MUTEX: Locks namespace for entire execution + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_root_initialize (void) +{ + ACPI_STATUS status = AE_OK; + PREDEFINED_NAMES *init_val = NULL; + ACPI_NAMED_OBJECT *new_entry; + ACPI_OBJECT_INTERNAL *obj_desc; + + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* + * Root is initially NULL, so a non-NULL value indicates + * that Acpi_ns_root_initialize() has already been called; just return. + */ + + if (acpi_gbl_root_object->child_table) { + status = AE_OK; + goto unlock_and_exit; + } + + + /* Create the root scope */ + + status = acpi_ns_root_create_scope (acpi_gbl_root_object); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + + /* Enter the pre-defined names in the name table */ + + for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) { + status = acpi_ns_lookup (NULL, init_val->name, + (OBJECT_TYPE_INTERNAL) init_val->type, + IMODE_LOAD_PASS2, NS_NO_UPSEARCH, + NULL, &new_entry); + + /* + * if name entered successfully + * && its entry in Pre_defined_names[] specifies an + * initial value + */ + + if ((status == AE_OK) && + new_entry && init_val->val) + { + /* + * Entry requests an initial value, allocate a + * descriptor for it. + */ + + obj_desc = + acpi_cm_create_internal_object ( + (OBJECT_TYPE_INTERNAL) init_val->type); + + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* + * Convert value string from table entry to + * internal representation. Only types actually + * used for initial values are implemented here. + */ + + switch (init_val->type) + { + + case ACPI_TYPE_NUMBER: + + obj_desc->number.value = + (u32) STRTOUL (init_val->val, NULL, 10); + break; + + + case ACPI_TYPE_STRING: + + obj_desc->string.length = + (u16) STRLEN (init_val->val); + + /* + * Allocate a buffer for the string. All + * String.Pointers must be allocated buffers! + * (makes deletion simpler) + */ + obj_desc->string.pointer = + acpi_cm_allocate ((ACPI_SIZE) + (obj_desc->string.length + 1)); + + if (!obj_desc->string.pointer) { + REPORT_ERROR ("Initial value string" + "allocation failure"); + + acpi_cm_remove_reference (obj_desc); + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + STRCPY ((char *) obj_desc->string.pointer, + init_val->val); + break; + + + case ACPI_TYPE_MUTEX: + + obj_desc->mutex.sync_level = + (u16) STRTOUL (init_val->val, NULL, 10); + + if (STRCMP (init_val->name, "_GL_") == 0) { + /* + * Create a counting semaphore for the + * global lock + */ + status = + acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, + 1, &obj_desc->mutex.semaphore); + + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + /* + * We just created the mutex for the + * global lock, save it + */ + + acpi_gbl_global_lock_semaphore = + obj_desc->mutex.semaphore; + } + + else { + /* Create a mutex */ + + status = acpi_os_create_semaphore (1, 1, + &obj_desc->mutex.semaphore); + + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + } + + /* TBD: [Restructure] These fields may be obsolete */ + + obj_desc->mutex.lock_count = 0; + obj_desc->mutex.thread_id = 0; + break; + + + default: + REPORT_ERROR ("Unsupported initial type value"); + acpi_cm_remove_reference (obj_desc); + obj_desc = NULL; + continue; + } + + /* Store pointer to value descriptor in nte */ + + acpi_ns_attach_object (new_entry, obj_desc, + obj_desc->common.type); + } + } + + +unlock_and_exit: + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_lookup + * + * PARAMETERS: Prefix_scope - Search scope if name is not fully qualified + * Pathname - Search pathname, in internal format + * (as represented in the AML stream) + * Type - Type associated with name + * Interpreter_mode - IMODE_LOAD_PASS2 => add name if not found + * Ret_entry - Where the new entry (NTE) is placed + * + * RETURN: Status + * + * DESCRIPTION: Find or enter the passed name in the name space. + * Log an error if name not found in Exec mode. + * + * MUTEX: Assumes namespace is locked. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_lookup ( + ACPI_GENERIC_STATE *scope_info, + char *pathname, + OBJECT_TYPE_INTERNAL type, + OPERATING_MODE interpreter_mode, + u32 flags, + ACPI_WALK_STATE *walk_state, + ACPI_NAMED_OBJECT **ret_entry) +{ + ACPI_STATUS status; + ACPI_NAME_TABLE *prefix_scope; + ACPI_NAME_TABLE *table_to_search = NULL; + ACPI_NAME_TABLE *scope_to_push = NULL; + ACPI_NAMED_OBJECT *this_entry = NULL; + u32 num_segments; + ACPI_NAME simple_name; + u8 null_name_path = FALSE; + OBJECT_TYPE_INTERNAL type_to_check_for; + OBJECT_TYPE_INTERNAL this_search_type; + + if (!ret_entry) { + return (AE_BAD_PARAMETER); + } + + + acpi_gbl_ns_lookup_count++; + + *ret_entry = ENTRY_NOT_FOUND; + if (!acpi_gbl_root_object->child_table) { + /* + * If the name space has not been initialized: + * - In Pass1 of Load mode, we need to initialize it + * before trying to define a name. + * - In Exec mode, there are no names to be found. + */ + + if (IMODE_LOAD_PASS1 == interpreter_mode) { + if ((status = acpi_ns_root_initialize ()) != AE_OK) { + return (status); + } + } + else { + return (AE_NOT_FOUND); + } + } + + + /* + * Get the prefix scope. + * A null scope means use the root scope + */ + + if ((!scope_info) || + (!scope_info->scope.name_table)) + { + prefix_scope = acpi_gbl_root_object->child_table; + } + else { + prefix_scope = scope_info->scope.name_table; + } + + + /* + * This check is explicitly split provide relax the Type_to_check_for + * conditions for Bank_field_defn. Originally, both Bank_field_defn and + * Def_field_defn caused Type_to_check_for to be set to ACPI_TYPE_REGION, + * but the Bank_field_defn may also check for a Field definition as well + * as an Operation_region. + */ + + if (INTERNAL_TYPE_DEF_FIELD_DEFN == type) { + /* Def_field_defn defines fields in a Region */ + + type_to_check_for = ACPI_TYPE_REGION; + } + + else if (INTERNAL_TYPE_BANK_FIELD_DEFN == type) { + /* Bank_field_defn defines data fields in a Field Object */ + + type_to_check_for = ACPI_TYPE_ANY; + } + + else { + type_to_check_for = type; + } + + + /* Examine the name pointer */ + + if (!pathname) { + /* 8-12-98 ASL Grammar Update supports null Name_path */ + + null_name_path = TRUE; + num_segments = 0; + this_entry = acpi_gbl_root_object; + + } + + else { + /* + * Valid name pointer (Internal name format) + * + * Check for prefixes. As represented in the AML stream, a + * Pathname consists of an optional scope prefix followed by + * a segment part. + * + * If present, the scope prefix is either a Root_prefix (in + * which case the name is fully qualified), or zero or more + * Parent_prefixes (in which case the name's scope is relative + * to the current scope). + * + * The segment part consists of either: + * - A single 4-byte name segment, or + * - A Dual_name_prefix followed by two 4-byte name segments, or + * - A Multi_name_prefix_op, followed by a byte indicating the + * number of segments and the segments themselves. + */ + + if (*pathname == AML_ROOT_PREFIX) { + /* Pathname is fully qualified, look in root name table */ + + table_to_search = acpi_gbl_root_object->child_table; + /* point to segment part */ + pathname++; + + /* Direct reference to root, "\" */ + + if (!(*pathname)) { + this_entry = acpi_gbl_root_object; + goto check_for_new_scope_and_exit; + } + } + + else { + /* Pathname is relative to current scope, start there */ + + table_to_search = prefix_scope; + + /* + * Handle up-prefix (carat). More than one prefix + * is supported + */ + + while (*pathname == AML_PARENT_PREFIX) { + + /* Point to segment part or next Parent_prefix */ + + pathname++; + + /* Backup to the parent's scope */ + + table_to_search = table_to_search->parent_table; + if (!table_to_search) { + /* Current scope has no parent scope */ + + REPORT_ERROR ("Ns_lookup: Too many parent" + "prefixes or scope has no parent"); + + + return (AE_NOT_FOUND); + } + } + } + + + /* + * Examine the name prefix opcode, if any, + * to determine the number of segments + */ + + if (*pathname == AML_DUAL_NAME_PREFIX) { + num_segments = 2; + /* point to first segment */ + pathname++; + + } + + else if (*pathname == AML_MULTI_NAME_PREFIX_OP) { + num_segments = (s32)* (u8 *) ++pathname; + /* point to first segment */ + pathname++; + + } + + else { + /* + * No Dual or Multi prefix, hence there is only one + * segment and Pathname is already pointing to it. + */ + num_segments = 1; + + } + + } + + + /* + * Search namespace for each segment of the name. + * Loop through and verify/add each name segment. + */ + + + while (num_segments-- && table_to_search) { + /* + * Search for the current segment in the table where + * it should be. + * Type is significant only at the last (topmost) level. + */ + this_search_type = ACPI_TYPE_ANY; + if (!num_segments) { + this_search_type = type; + } + + MOVE_UNALIGNED32_TO_32 (&simple_name, pathname); + status = acpi_ns_search_and_enter (simple_name, walk_state, + table_to_search, interpreter_mode, + this_search_type, flags, + &this_entry); + + if (status != AE_OK) { + if (status == AE_NOT_FOUND) { + /* Name not in ACPI namespace */ + + if (IMODE_LOAD_PASS1 == interpreter_mode || + IMODE_LOAD_PASS2 == interpreter_mode) + { + REPORT_ERROR ("Name table overflow"); + } + + } + + return (status); + } + + + /* + * If 1) last segment (Num_segments == 0) + * 2) and looking for a specific type + * (Not checking for TYPE_ANY) + * 3) which is not a local type (TYPE_DEF_ANY) + * 4) which is not a local type (TYPE_SCOPE) + * 5) which is not a local type (TYPE_INDEX_FIELD_DEFN) + * 6) and type of entry is known (not TYPE_ANY) + * 7) and entry does not match request + * + * Then we have a type mismatch. Just warn and ignore it. + */ + if ((num_segments == 0) && + (type_to_check_for != ACPI_TYPE_ANY) && + (type_to_check_for != INTERNAL_TYPE_DEF_ANY) && + (type_to_check_for != INTERNAL_TYPE_SCOPE) && + (type_to_check_for != INTERNAL_TYPE_INDEX_FIELD_DEFN) && + (this_entry->type != ACPI_TYPE_ANY) && + (this_entry->type != type_to_check_for)) + { + /* Complain about type mismatch */ + + REPORT_WARNING ("Type mismatch"); + } + + /* + * If last segment and not looking for a specific type, but type of + * found entry is known, use that type to see if it opens a scope. + */ + + if ((0 == num_segments) && (ACPI_TYPE_ANY == type)) { + type = this_entry->type; + } + + if ((num_segments || acpi_ns_opens_scope (type)) && + (this_entry->child_table == NULL)) + { + /* + * More segments or the type implies enclosed scope, + * and the next scope has not been allocated. + */ + + if ((IMODE_LOAD_PASS1 == interpreter_mode) || + (IMODE_LOAD_PASS2 == interpreter_mode)) + { + /* + * First or second pass load mode + * ==> locate the next scope + */ + + this_entry->child_table = + acpi_ns_allocate_name_table (NS_TABLE_SIZE); + + if (!this_entry->child_table) { + return (AE_NO_MEMORY); + } + } + + /* Now complain if there is no next scope */ + + if (this_entry->child_table == NULL) { + if (IMODE_LOAD_PASS1 == interpreter_mode || + IMODE_LOAD_PASS2 == interpreter_mode) + { + REPORT_ERROR ("Name Table allocation failure"); + return (AE_NOT_FOUND); + } + + return (AE_NOT_FOUND); + } + + + /* Scope table initialization */ + + if (IMODE_LOAD_PASS1 == interpreter_mode || + IMODE_LOAD_PASS2 == interpreter_mode) + { + /* Initialize the new table */ + + acpi_ns_initialize_table (this_entry->child_table, + table_to_search, + this_entry); + } + } + + table_to_search = this_entry->child_table; + /* point to next name segment */ + pathname += ACPI_NAME_SIZE; + } + + + /* + * Always check if we need to open a new scope + */ + +check_for_new_scope_and_exit: + + if (!(flags & NS_DONT_OPEN_SCOPE) && (walk_state)) { + /* + * If entry is a type which opens a scope, + * push the new scope on the scope stack. + */ + + if (acpi_ns_opens_scope (type_to_check_for)) { + /* 8-12-98 ASL Grammar Update supports null Name_path */ + + if (null_name_path) { + /* TBD: [Investigate] - is this the correct thing to do? */ + + scope_to_push = NULL; + } + else { + scope_to_push = this_entry->child_table; + } + + status = acpi_ds_scope_stack_push (scope_to_push, type, + walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + } + } + + *ret_entry = this_entry; + return (AE_OK); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/namespace/nsalloc.c linux/drivers/acpi/namespace/nsalloc.c --- v2.4.0-test2/linux/drivers/acpi/namespace/nsalloc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/namespace/nsalloc.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,411 @@ + +/****************************************************************************** + * + * Module Name: nsalloc - Namespace allocation and deletion utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "namesp.h" +#include "interp.h" + + +#define _COMPONENT NAMESPACE + MODULE_NAME ("nsalloc"); + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_allocate_name_table + * + * PARAMETERS: Nte_count - Count of NTEs to allocate + * + * RETURN: The address of the first nte in the array, or NULL + * + * DESCRIPTION: Allocate an array of nte, including prepended link space + * Array is set to all zeros via Acpi_os_callcate(). + * + ***************************************************************************/ + +ACPI_NAME_TABLE * +acpi_ns_allocate_name_table ( + u32 num_entries) +{ + ACPI_NAME_TABLE *name_table = NULL; + ACPI_SIZE alloc_size; + + + alloc_size = sizeof (ACPI_NAME_TABLE) + ((num_entries - 1) * + sizeof (ACPI_NAMED_OBJECT)); + + name_table = acpi_cm_callocate (alloc_size); + + + return (name_table); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_delete_namespace_subtree + * + * PARAMETERS: None. + * + * RETURN: None. + * + * DESCRIPTION: Delete a subtree of the namespace. This includes all objects stored + * within the subtree. Scope tables are deleted also + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_delete_namespace_subtree ( + ACPI_NAMED_OBJECT *parent_entry) +{ + ACPI_NAMED_OBJECT *child_entry; + u32 level; + ACPI_OBJECT_INTERNAL *obj_desc; + + + child_entry = 0; + level = 1; + + /* + * Traverse the tree of objects until we bubble back up + * to where we started. + */ + + while (level > 0) { + /* + * Get the next typed object in this scope. + * Null returned if not found + */ + + child_entry = acpi_ns_get_next_object (ACPI_TYPE_ANY, + parent_entry, + child_entry); + + if (child_entry) { + /* + * Found an object - delete the object within + * the Value field + */ + + obj_desc = acpi_ns_get_attached_object (child_entry); + if (obj_desc) { + acpi_ns_detach_object (child_entry); + acpi_cm_remove_reference (obj_desc); + } + + + /* + * Clear the NTE in case this scope is reused + * (e.g., a control method scope) + */ + + child_entry->type = ACPI_TYPE_ANY; + child_entry->name = 0; + + /* Check if this object has any children */ + + if (acpi_ns_get_next_object (ACPI_TYPE_ANY, child_entry, 0)) { + /* + * There is at least one child of this object, + * visit the object + */ + + level++; + parent_entry = child_entry; + child_entry = 0; + } + + else { + /* + * There may be a name table even if there are + * no children + */ + + acpi_ns_delete_name_table (child_entry->child_table); + child_entry->child_table = NULL; + + } + } + + else { + /* + * No more children in this object. + * We will move up to the grandparent. + */ + level--; + + /* + * Delete the scope (Name Table) associated with + * the parent object + */ + /* Don't delete the top level scope, this allows + * the dynamic deletion of objects created underneath + * control methods! + */ + + if (level != 0) { + acpi_ns_delete_name_table (parent_entry->child_table); + parent_entry->child_table = NULL; + } + + /* New "last child" is this parent object */ + + child_entry = parent_entry; + + /* Now we can move up the tree to the grandparent */ + + parent_entry = acpi_ns_get_parent_entry (parent_entry); + } + } + + + return (AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_remove_reference + * + * PARAMETERS: Entry - NTE whose reference count is to be decremented + * + * RETURN: None. + * + * DESCRIPTION: Remove an NTE reference. Decrements the reference count of + * all parent NTEs up to the root. Any NTE along the way that + * reaches zero references is freed. + * + ***************************************************************************/ + +void +acpi_ns_remove_reference ( + ACPI_NAMED_OBJECT *entry) +{ + ACPI_NAMED_OBJECT *this_entry; + + + /* There may be a name table even if there are no children */ + + acpi_ns_delete_name_table (entry->child_table); + entry->child_table = NULL; + + + /* + * Decrement the reference count(s) of all parents up to the root, + * And delete anything with zero remaining references. + */ + this_entry = entry; + while (this_entry) { + /* Decrement the reference */ + + this_entry->reference_count--; + + /* Delete entry if no more references */ + + if (!this_entry->reference_count) { + /* Delete the scope if present */ + + if (this_entry->child_table) { + acpi_ns_delete_name_table (this_entry->child_table); + this_entry->child_table = NULL; + } + + /* + * Mark the entry free + * (This doesn't deallocate anything) + */ + + acpi_ns_free_table_entry (this_entry); + + } + + /* Move up to parent */ + + this_entry = acpi_ns_get_parent_entry (this_entry); + } +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_delete_namespace_by_owner + * + * PARAMETERS: None. + * + * RETURN: None. + * + * DESCRIPTION: Delete entries within the namespace that are owned by a + * specific ID. Used to delete entire ACPI tables. All + * reference counts are updated. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_delete_namespace_by_owner ( + u16 owner_id) +{ + ACPI_NAMED_OBJECT *child_entry; + u32 level; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_NAMED_OBJECT *parent_entry; + + + parent_entry = acpi_gbl_root_object; + child_entry = 0; + level = 1; + + /* + * Traverse the tree of objects until we bubble back up + * to where we started. + */ + + while (level > 0) { + /* + * Get the next typed object in this scope. + * Null returned if not found + */ + + child_entry = acpi_ns_get_next_object (ACPI_TYPE_ANY, + parent_entry, + child_entry); + + if (child_entry) { + if (child_entry->owner_id == owner_id) { + /* + * Found an object - delete the object within + * the Value field + */ + + obj_desc = acpi_ns_get_attached_object (child_entry); + if (obj_desc) { + acpi_ns_detach_object (child_entry); + acpi_cm_remove_reference (obj_desc); + } + } + + /* Check if this object has any children */ + + if (acpi_ns_get_next_object (ACPI_TYPE_ANY, child_entry, 0)) { + /* + * There is at least one child of this object, + * visit the object + */ + + level++; + parent_entry = child_entry; + child_entry = 0; + } + + else if (child_entry->owner_id == owner_id) { + acpi_ns_remove_reference (child_entry); + } + } + + else { + /* + * No more children in this object. + * We will move up to the grandparent. + */ + level--; + + /* + * Delete the scope (Name Table) associated with + * the parent object + */ + /* Don't delete the top level scope, this allows + * the dynamic deletion of objects created underneath + * control methods! + */ + + + if (level != 0) { + if (parent_entry->owner_id == owner_id) { + acpi_ns_remove_reference (parent_entry); + } + } + + + /* New "last child" is this parent object */ + + child_entry = parent_entry; + + /* Now we can move up the tree to the grandparent */ + + parent_entry = acpi_ns_get_parent_entry (parent_entry); + } + } + + + return (AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_delete_name_table + * + * PARAMETERS: Scope - A handle to the scope to be deleted + * + * RETURN: None. + * + * DESCRIPTION: Delete a namespace Name Table with zero or + * more appendages. The table and all appendages are deleted. + * + ***************************************************************************/ + +void +acpi_ns_delete_name_table ( + ACPI_NAME_TABLE *name_table) +{ + ACPI_NAME_TABLE *this_table; + ACPI_NAME_TABLE *next_table; + + + if (!name_table) { + return; + } + + this_table = name_table; + + + /* + * Deallocate the name table and all appendages + */ + do + { + next_table = this_table->next_table; + + /* Now we can free the table */ + + acpi_cm_free (this_table); + this_table = next_table; + + } while (this_table); + + return; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/namespace/nseval.c linux/drivers/acpi/namespace/nseval.c --- v2.4.0-test2/linux/drivers/acpi/namespace/nseval.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/namespace/nseval.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,507 @@ + +/****************************************************************************** + * + * Module Name: nseval - Object evaluation interfaces -- includes control + * method lookup and execution. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "parser.h" +#include "interp.h" +#include "namesp.h" + + +#define _COMPONENT NAMESPACE + MODULE_NAME ("nseval"); + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_evaluate_relative + * + * PARAMETERS: Rel_obj_entry - NTE of the relative containing object + * *Pathname - Name of method to execute, If NULL, the + * handle is the object to execute + * **Params - List of parameters to pass to the method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * *Return_object - Where to put method's return value (if + * any). If NULL, no value is returned. + * + * RETURN: Status + * + * DESCRIPTION: Find and execute the requested method using the handle as a + * scope + * + * MUTEX: Locks Namespace + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ns_evaluate_relative ( + ACPI_NAMED_OBJECT *handle, + char *pathname, + ACPI_OBJECT_INTERNAL **params, + ACPI_OBJECT_INTERNAL **return_object) +{ + ACPI_NAMED_OBJECT *rel_obj_entry; + ACPI_STATUS status; + ACPI_NAMED_OBJECT *obj_entry = NULL; + char *internal_path = NULL; + ACPI_GENERIC_STATE scope_info; + + + /* + * Must have a valid object handle + */ + if (!handle) { + return (AE_BAD_PARAMETER); + } + + /* Build an internal name string for the method */ + + status = acpi_ns_internalize_name (pathname, &internal_path); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Get the prefix handle and NTE */ + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + rel_obj_entry = acpi_ns_convert_handle_to_entry (handle); + if (!rel_obj_entry) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + status = AE_BAD_PARAMETER; + goto cleanup; + } + + /* Lookup the name in the namespace */ + + scope_info.scope.name_table = rel_obj_entry->child_table; + status = acpi_ns_lookup (&scope_info, internal_path, ACPI_TYPE_ANY, + IMODE_EXECUTE, + NS_NO_UPSEARCH, NULL, + &obj_entry); + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + if (status != AE_OK) { + goto cleanup; + } + + /* + * Now that we have a handle to the object, we can attempt + * to evaluate it. + */ + + status = acpi_ns_evaluate_by_handle (obj_entry, params, return_object); + +cleanup: + + /* Cleanup */ + + acpi_cm_free (internal_path); + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_evaluate_by_name + * + * PARAMETERS: Pathname - Fully qualified pathname to the object + * *Return_object - Where to put method's return value (if + * any). If NULL, no value is returned. + * **Params - List of parameters to pass to the method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * + * RETURN: Status + * + * DESCRIPTION: Find and execute the requested method passing the given + * parameters + * + * MUTEX: Locks Namespace + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ns_evaluate_by_name ( + char *pathname, + ACPI_OBJECT_INTERNAL **params, + ACPI_OBJECT_INTERNAL **return_object) +{ + ACPI_STATUS status; + ACPI_NAMED_OBJECT *obj_entry = NULL; + char *internal_path = NULL; + + + /* Build an internal name string for the method */ + + if (pathname[0] != '\\' || pathname[1] != '/') { + status = acpi_ns_internalize_name (pathname, &internal_path); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* Lookup the name in the namespace */ + + status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY, + IMODE_EXECUTE, + NS_NO_UPSEARCH, NULL, + &obj_entry); + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + if (status != AE_OK) { + goto cleanup; + } + + /* + * Now that we have a handle to the object, we can attempt + * to evaluate it. + */ + + status = acpi_ns_evaluate_by_handle (obj_entry, params, return_object); + + +cleanup: + + /* Cleanup */ + + if (internal_path) { + acpi_cm_free (internal_path); + } + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_evaluate_by_handle + * + * PARAMETERS: Obj_entry - NTE of method to execute + * *Return_object - Where to put method's return value (if + * any). If NULL, no value is returned. + * **Params - List of parameters to pass to the method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * + * RETURN: Status + * + * DESCRIPTION: Execute the requested method passing the given parameters + * + * MUTEX: Locks Namespace + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ns_evaluate_by_handle ( + ACPI_NAMED_OBJECT *handle, + ACPI_OBJECT_INTERNAL **params, + ACPI_OBJECT_INTERNAL **return_object) +{ + ACPI_NAMED_OBJECT *obj_entry; + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL *local_return_object; + + + /* Check if namespace has been initialized */ + + if (!acpi_gbl_root_object->child_table) { + return (AE_NO_NAMESPACE); + } + + /* Parameter Validation */ + + if (!handle) { + return (AE_BAD_PARAMETER); + } + + if (return_object) { + /* Initialize the return value to an invalid object */ + + *return_object = NULL; + } + + /* Get the prefix handle and NTE */ + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + obj_entry = acpi_ns_convert_handle_to_entry (handle); + if (!obj_entry) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + + /* + * Two major cases here: + * 1) The object is an actual control method -- execute it. + * 2) The object is not a method -- just return it's current + * value + * + * In both cases, the namespace is unlocked by the + * Acpi_ns* procedure + */ + + if (acpi_ns_get_type (obj_entry) == ACPI_TYPE_METHOD) { + /* + * Case 1) We have an actual control method to execute + */ + + status = acpi_ns_execute_control_method (obj_entry, + params, + &local_return_object); + } + + else { + /* + * Case 2) Object is NOT a method, just return its + * current value + */ + + status = acpi_ns_get_object_value (obj_entry, + &local_return_object); + } + + + /* + * Check if there is a return value on the stack that must + * be dealt with + */ + + if (status == AE_CTRL_RETURN_VALUE) { + /* + * If the Method returned a value and the caller + * provided a place to store a returned value, Copy + * the returned value to the object descriptor provided + * by the caller. + */ + + if (return_object) { + /* + * Valid return object, copy the pointer to + * the returned object + */ + + *return_object = local_return_object; + } + + + /* Map AE_RETURN_VALUE to AE_OK, we are done with it */ + + if (status == AE_CTRL_RETURN_VALUE) { + status = AE_OK; + } + } + + /* + * Namespace was unlocked by the handling Acpi_ns* function, + * so we just return + */ + + return (status); + + +unlock_and_exit: + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_execute_control_method + * + * PARAMETERS: Method_entry - The Nte of the object/method + * **Params - List of parameters to pass to the method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * + * RETURN: Status + * + * DESCRIPTION: Execute the requested method passing the given parameters + * + * MUTEX: Assumes namespace is locked + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ns_execute_control_method ( + ACPI_NAMED_OBJECT *method_entry, + ACPI_OBJECT_INTERNAL **params, + ACPI_OBJECT_INTERNAL **return_obj_desc) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL *obj_desc; + + + /* Verify that there is a method associated with this object */ + + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) method_entry); + if (!obj_desc) { + return (AE_ERROR); + } + + /* + * Valid method, Set the current scope to that of the Method, + * and execute it. + */ + + + /* + * Unlock the namespace before execution. This allows namespace access + * via the external Acpi* interfaces while a method is being executed. + * However, any namespace deletion must acquire both the namespace and + * interpter locks to ensure that no thread is using the portion of the + * namespace that is being deleted. + */ + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + /* + * Excecute the method via the interpreter + */ + status = acpi_aml_execute_method (method_entry, params, return_obj_desc); + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_get_object_value + * + * PARAMETERS: Object_entry - The Nte of the object + * + * RETURN: Status + * + * DESCRIPTION: Return the current value of the object + * + * MUTEX: Assumes namespace is locked + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ns_get_object_value ( + ACPI_NAMED_OBJECT *object_entry, + ACPI_OBJECT_INTERNAL **return_obj_desc) +{ + ACPI_STATUS status = AE_OK; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_OBJECT_INTERNAL *val_desc; + + + /* + * We take the value from certain objects directly + */ + + if ((object_entry->type == ACPI_TYPE_PROCESSOR) || + (object_entry->type == ACPI_TYPE_POWER)) + { + + /* + * Create a Reference object to contain the object + */ + obj_desc = acpi_cm_create_internal_object (object_entry->type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* + * Get the attached object + */ + + val_desc = acpi_ns_get_attached_object (object_entry); + if (!val_desc) { + status = AE_NULL_OBJECT; + goto unlock_and_exit; + } + + /* + * Just copy from the original to the return object + */ + + MEMCPY (&obj_desc->common.first_non_common_byte, + &val_desc->common.first_non_common_byte, + (sizeof(ACPI_OBJECT_COMMON) - + sizeof(obj_desc->common.first_non_common_byte))); + } + + + /* + * Other objects require a reference object wrapper which we + * then attempt to resolve. + */ + else { + /* Create an Reference object to contain the object */ + + obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Construct a descriptor pointing to the name */ + + obj_desc->reference.op_code = (u8) AML_NAME_OP; + obj_desc->reference.object = (void *) object_entry; + + /* + * Use Acpi_aml_resolve_to_value() to get the associated value. + * The call to Acpi_aml_resolve_to_value causes + * Obj_desc (allocated above) to always be deleted. + */ + + status = acpi_aml_resolve_to_value (&obj_desc); + } + + /* + * If Acpi_aml_resolve_to_value() succeeded, the return value was + * placed in Obj_desc. + */ + + if (status == AE_OK) { + status = AE_CTRL_RETURN_VALUE; + + *return_obj_desc = obj_desc; + } + + +unlock_and_exit: + + /* Unlock the namespace */ + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/namespace/nsload.c linux/drivers/acpi/namespace/nsload.c --- v2.4.0-test2/linux/drivers/acpi/namespace/nsload.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/namespace/nsload.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,488 @@ + +/****************************************************************************** + * + * Module Name: nsload - namespace loading/expanding/contracting procedures + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" +#include "namesp.h" +#include "amlcode.h" +#include "parser.h" +#include "dispatch.h" +#include "debugger.h" + + +#define _COMPONENT NAMESPACE + MODULE_NAME ("nsload"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_parse_table + * + * PARAMETERS: Table_desc - An ACPI table descriptor for table to parse + * Scope - Where to enter the table into the namespace + * + * RETURN: Status + * + * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_parse_table ( + ACPI_TABLE_DESC *table_desc, + ACPI_NAME_TABLE *scope) +{ + ACPI_STATUS status; + + + /* Create the root object */ + + acpi_gbl_parsed_namespace_root = acpi_ps_alloc_op (AML_SCOPE_OP); + if (!acpi_gbl_parsed_namespace_root) { + return (AE_NO_MEMORY); + } + + /* Initialize the root object */ + + ((ACPI_NAMED_OP *) acpi_gbl_parsed_namespace_root)->name = ACPI_ROOT_NAME; + + /* Pass 1: Parse everything except control method bodies */ + + status = acpi_ps_parse_aml (acpi_gbl_parsed_namespace_root, + table_desc->aml_pointer, + table_desc->aml_length, 0); + + if (ACPI_FAILURE (status)) { + return (status); + } + + +#ifndef PARSER_ONLY + status = acpi_ps_walk_parsed_aml (acpi_ps_get_child (acpi_gbl_parsed_namespace_root), + acpi_gbl_parsed_namespace_root, NULL, + scope, NULL, NULL, + table_desc->table_id, + acpi_ds_load2_begin_op, + acpi_ds_load2_end_op); + + + /* + * Now that the internal namespace has been constructed, we can delete the + * parsed namespace, since it is no longer needed + */ + + acpi_ps_delete_parse_tree (acpi_gbl_parsed_namespace_root); + acpi_gbl_parsed_namespace_root = NULL; +#endif + + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ns_load_table + * + * PARAMETERS: *Pcode_addr - Address of pcode block + * Pcode_length - Length of pcode block + * + * RETURN: Status + * + * DESCRIPTION: Mainline of the AML load/dump subsystem. Sets up the + * input engine, calls handler for outermost object type. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ns_load_table ( + ACPI_TABLE_DESC *table_desc, + ACPI_NAMED_OBJECT *entry) +{ + ACPI_STATUS status; + + + if (!table_desc->aml_pointer) { + return (AE_BAD_PARAMETER); + } + + + if (!table_desc->aml_length) { + return (AE_BAD_PARAMETER); + } + + + /* + * Parse the table and load the namespace with all named + * objects found within. Control methods are NOT parsed + * at this time. In fact, the control methods cannot be + * parsed until the entire namespace is loaded, because + * if a control method makes a forward reference (call) + * to another control method, we can't continue parsing + * because we don't know how many arguments to parse next! + */ + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ns_parse_table (table_desc, entry->child_table); + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Now we can parse the control methods. We always parse + * them here for a sanity check, and if configured for + * just-in-time parsing, we delete the control method + * parse trees. + */ + + status = acpi_ds_initialize_objects (table_desc, entry); + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ns_load_table_by_type + * + * PARAMETERS: Table_type - Id of the table type to load + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table or tables into the namespace. All tables + * of the given type are loaded. The mechanism allows this + * routine to be called repeatedly. + * + *****************************************************************************/ + +ACPI_STATUS +acpi_ns_load_table_by_type ( + ACPI_TABLE_TYPE table_type) +{ + u32 i; + ACPI_STATUS status = AE_OK; + ACPI_TABLE_HEADER *table_ptr; + ACPI_TABLE_DESC *table_desc; + + + acpi_cm_acquire_mutex (ACPI_MTX_TABLES); + + + /* + * Table types supported are: + * DSDT (one), SSDT/PSDT (multiple) + */ + + switch (table_type) + { + + case ACPI_TABLE_DSDT: + + table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_DSDT]; + + /* If table already loaded into namespace, just return */ + + if (table_desc->loaded_into_namespace) { + goto unlock_and_exit; + } + + table_desc->table_id = TABLE_ID_DSDT; + + /* Initialize the root of the namespace tree */ + + status = acpi_ns_root_initialize (); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + + /* Now load the single DSDT */ + + status = acpi_ns_load_table (table_desc, acpi_gbl_root_object); + if (ACPI_SUCCESS (status)) { + table_desc->loaded_into_namespace = TRUE; + } + + break; + + + case ACPI_TABLE_SSDT: + + /* + * Traverse list of SSDT tables + */ + + table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_SSDT]; + for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count; i++) { + table_ptr = table_desc->pointer; + + /* + * Only attempt to load table if it is not + * already loaded! + */ + + if (!table_desc->loaded_into_namespace) { + status = acpi_ns_load_table (table_desc, + acpi_gbl_root_object); + if (ACPI_FAILURE (status)) { + break; + } + + table_desc->loaded_into_namespace = TRUE; + } + + table_desc = table_desc->next; + } + + break; + + + case ACPI_TABLE_PSDT: + + /* + * Traverse list of PSDT tables + */ + + table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_PSDT]; + + for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count; i++) { + table_ptr = table_desc->pointer; + + /* Only attempt to load table if it is not already loaded! */ + + if (!table_desc->loaded_into_namespace) { + status = acpi_ns_load_table (table_desc, + acpi_gbl_root_object); + if (ACPI_FAILURE (status)) { + break; + } + + table_desc->loaded_into_namespace = TRUE; + } + + table_desc = table_desc->next; + } + + break; + + + default: + status = AE_SUPPORT; + } + + +unlock_and_exit: + + acpi_cm_release_mutex (ACPI_MTX_TABLES); + + return (status); + +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ns_free_table_entry + * + * PARAMETERS: Entry - The entry to be deleted + * + * RETURNS None + * + * DESCRIPTION: Free an entry in a namespace table. Delete any objects contained + * in the entry, unlink the entry, then mark it unused. + * + ******************************************************************************/ + +void +acpi_ns_free_table_entry ( + ACPI_NAMED_OBJECT *entry) +{ + + if (!entry) { + return; + } + + /* + * Need to delete + * 1) The scope, if any + * 2) An attached object, if any + */ + + if (entry->child_table) { + acpi_cm_free (entry->child_table); + entry->child_table = NULL; + } + + if (entry->object) { + acpi_ns_detach_object (entry->object); + entry->object = NULL; + } + + /* Mark the entry unallocated */ + + entry->name = 0; + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ns_delete_subtree + * + * PARAMETERS: Start_handle - Handle in namespace where search begins + * + * RETURNS Status + * + * DESCRIPTION: Walks the namespace starting at the given handle and deletes + * all objects, entries, and scopes in the entire subtree. + * + * TBD: [Investigate] What if any part of this subtree is in use? + * (i.e. on one of the object stacks?) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_delete_subtree ( + ACPI_HANDLE start_handle) +{ + ACPI_STATUS status; + ACPI_HANDLE child_handle; + ACPI_HANDLE parent_handle; + ACPI_HANDLE next_child_handle; + ACPI_HANDLE dummy; + u32 level; + + + parent_handle = start_handle; + child_handle = 0; + level = 1; + + /* + * Traverse the tree of objects until we bubble back up + * to where we started. + */ + + while (level > 0) { + /* Attempt to get the next object in this scope */ + + status = acpi_get_next_object (ACPI_TYPE_ANY, parent_handle, + child_handle, + &next_child_handle); + + /* + * Regardless of the success or failure of the + * previous operation, we are done with the previous + * object (if there was one), and any children it + * may have had. So we can now safely delete it (and + * its scope, if any) + */ + + acpi_ns_free_table_entry (child_handle); + child_handle = next_child_handle; + + + /* Did we get a new object? */ + + if (ACPI_SUCCESS (status)) { + /* Check if this object has any children */ + + if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY, + child_handle, 0, + &dummy))) + { + /* + * There is at least one child of this object, + * visit the object + */ + + level++; + parent_handle = child_handle; + child_handle = 0; + } + } + + else { + /* + * No more children in this object, go back up to + * the object's parent + */ + level--; + child_handle = parent_handle; + acpi_get_parent (parent_handle, &parent_handle); + } + } + + /* Now delete the starting object, and we are done */ + + acpi_ns_free_table_entry ((ACPI_NAMED_OBJECT*) child_handle); + + + return (AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_unload_name_space + * + * PARAMETERS: Handle - Root of namespace subtree to be deleted + * + * RETURN: Status + * + * DESCRIPTION: Shrinks the namespace, typically in response to an undocking + * event. Deletes an entire subtree starting from (and + * including) the given handle. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ns_unload_namespace ( + ACPI_HANDLE handle) +{ + ACPI_STATUS status; + + + /* Parameter validation */ + + if (!acpi_gbl_root_object->child_table) { + return (AE_NO_NAMESPACE); + } + + if (!handle) { + return (AE_BAD_PARAMETER); + } + + + /* This function does the real work */ + + status = acpi_ns_delete_subtree (handle); + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/namespace/nsnames.c linux/drivers/acpi/namespace/nsnames.c --- v2.4.0-test2/linux/drivers/acpi/namespace/nsnames.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/namespace/nsnames.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,503 @@ + +/****************************************************************************** + * + * Module Name: nsnames - Name manipulation and search + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "interp.h" +#include "namesp.h" + + +#define _COMPONENT NAMESPACE + MODULE_NAME ("nsnames"); + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_name_of_scope + * + * PARAMETERS: Scope - Scope whose name is needed + * + * RETURN: Pointer to storage containing the fully qualified name of + * the scope, in Label format (all segments strung together + * with no separators) + * + * DESCRIPTION: Used via Acpi_ns_name_of_current_scope() and Acpi_ns_last_fQN() + * for label generation in the interpreter, and for debug + * printing in Acpi_ns_search_table(). + * + ***************************************************************************/ + +char * +acpi_ns_name_of_scope ( + ACPI_NAME_TABLE *scope) +{ + char *name_buffer; + ACPI_SIZE size; + ACPI_NAME name; + ACPI_NAMED_OBJECT *entry_to_search; + ACPI_NAMED_OBJECT *parent_entry; + + + if (!acpi_gbl_root_object->child_table || !scope) { + /* + * If the name space has not been initialized, + * this function should not have been called. + */ + return (NULL); + } + + entry_to_search = scope->entries; + + + /* Calculate required buffer size based on depth below root NT */ + + size = 1; + parent_entry = entry_to_search; + while (parent_entry) { + parent_entry = acpi_ns_get_parent_entry (parent_entry); + if (parent_entry) { + size += ACPI_NAME_SIZE; + } + } + + + /* Allocate the buffer */ + + name_buffer = acpi_cm_callocate (size + 1); + if (!name_buffer) { + REPORT_ERROR ("Ns_name_of_scope: allocation failure"); + return (NULL); + } + + + /* Store terminator byte, then build name backwards */ + + name_buffer[size] = '\0'; + while ((size > ACPI_NAME_SIZE) && + acpi_ns_get_parent_entry (entry_to_search)) + { + size -= ACPI_NAME_SIZE; + name = acpi_ns_find_parent_name (entry_to_search); + + /* Put the name into the buffer */ + + MOVE_UNALIGNED32_TO_32 ((name_buffer + size), &name); + entry_to_search = acpi_ns_get_parent_entry (entry_to_search); + } + + name_buffer[--size] = AML_ROOT_PREFIX; + + + return (name_buffer); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_name_of_current_scope + * + * PARAMETERS: none + * + * RETURN: pointer to storage containing the name of the current scope + * + ***************************************************************************/ + +char * +acpi_ns_name_of_current_scope ( + ACPI_WALK_STATE *walk_state) +{ + char *scope_name; + + + if (walk_state && walk_state->scope_info) { + scope_name = + acpi_ns_name_of_scope (walk_state->scope_info->scope.name_table); + + return (scope_name); + } + + REPORT_ERROR ("Current scope pointer is invalid"); + + return (NULL); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_handle_to_pathname + * + * PARAMETERS: Target_handle - Handle of nte whose name is to be found + * Buf_size - Size of the buffer provided + * User_buffer - Where the pathname is returned + * + * RETURN: Status, Buffer is filled with pathname if status == AE_OK + * + * DESCRIPTION: Build and return a full namespace pathname + * + * MUTEX: Locks Namespace + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_handle_to_pathname ( + ACPI_HANDLE target_handle, + u32 *buf_size, + char *user_buffer) +{ + ACPI_STATUS status = AE_OK; + ACPI_NAMED_OBJECT *entry_to_search = NULL; + ACPI_NAMED_OBJECT *temp = NULL; + ACPI_SIZE path_length = 0; + ACPI_SIZE size; + u32 user_buf_size; + ACPI_NAME name; + u8 namespace_was_locked; + + + if (!acpi_gbl_root_object->child_table || !target_handle) { + /* + * If the name space has not been initialized, + * this function should not have been called. + */ + + return (AE_NO_NAMESPACE); + } + + namespace_was_locked = acpi_gbl_acpi_mutex_info[ACPI_MTX_NAMESPACE].locked; + if (!namespace_was_locked) { + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + } + + entry_to_search = acpi_ns_convert_handle_to_entry (target_handle); + if (!entry_to_search) { + return (AE_BAD_PARAMETER); + } + + /* + * Compute length of pathname as 5 * number of name segments. + * Go back up the parent tree to the root + */ + for (size = 0, temp = entry_to_search; + acpi_ns_get_parent_entry (temp); + temp = acpi_ns_get_parent_entry (temp)) + { + size += PATH_SEGMENT_LENGTH; + } + + /* Set return length to the required path length */ + + path_length = size + 1; + user_buf_size = *buf_size; + *buf_size = path_length; + + /* Check if the user buffer is sufficiently large */ + + if (path_length > user_buf_size) { + status = AE_BUFFER_OVERFLOW; + goto unlock_and_exit; + } + + /* Store null terminator */ + + user_buffer[size] = 0; + size -= ACPI_NAME_SIZE; + + /* Put the original ACPI name at the end of the path */ + + MOVE_UNALIGNED32_TO_32 ((user_buffer + size), + &entry_to_search->name); + + user_buffer[--size] = PATH_SEPARATOR; + + /* Build name backwards, putting "." between segments */ + + while ((size > ACPI_NAME_SIZE) && entry_to_search) { + size -= ACPI_NAME_SIZE; + name = acpi_ns_find_parent_name (entry_to_search); + MOVE_UNALIGNED32_TO_32 ((user_buffer + size), &name); + + user_buffer[--size] = PATH_SEPARATOR; + entry_to_search = acpi_ns_get_parent_entry (entry_to_search); + } + + /* + * Overlay the "." preceding the first segment with + * the root name "\" + */ + + user_buffer[size] = '\\'; + + +unlock_and_exit: + + if (!namespace_was_locked) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + } + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_pattern_match + * + * PARAMETERS: Obj_entry - A namespace entry + * Search_for - Wildcard pattern string + * + * DESCRIPTION: Matches a namespace name against a wildcard pattern. Only + * a very simple pattern - 4 chars, either a valid char or a "?" + * to match any. + * + ***************************************************************************/ + +u8 +acpi_ns_pattern_match ( + ACPI_NAMED_OBJECT *obj_entry, + char *search_for) +{ + s32 i; + + + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (search_for[i] != '?' && + search_for[i] != ((char *) &obj_entry->name)[i]) + { + /* No match */ + + return FALSE; + } + } + + /* name matches pattern */ + + return TRUE; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_name_compare + * + * PARAMETERS: Obj_handle - A namespace entry + * Level - Current nesting level + * Context - A FIND_CONTEXT structure + * + * DESCRIPTION: A User_function called by Acpi_ns_walk_namespace(). It performs + * a pattern match for Acpi_ns_low_find_names(), and updates the list + * and count as required. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_name_compare ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value) +{ + FIND_CONTEXT *find = context; + + + /* Match, yes or no? */ + + if (acpi_ns_pattern_match ((ACPI_NAMED_OBJECT*) obj_handle, + find->search_for)) + { + /* Name matches pattern */ + + if (find->list) { + find->list[*(find->count)] = obj_handle; + } + + ++*(find->count); + } + + /* Don't terminate the walk */ + return AE_OK; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_low_find_names + * + * PARAMETERS: *This_entry - Table to be searched + * *Search_for - Pattern to be found. + * 4 bytes, ? matches any character. + * *Count - Output count of matches found. + * Outermost caller should preset to 0 + * List[] - Output array of handles. If + * null, only the count is obtained. + * Max_depth - Maximum depth of search. Use + * INT_MAX for an effectively + * unlimited depth. + * + * DESCRIPTION: Low-level find name. + * Traverse the name space finding names which match a search + * pattern, and return an array of handles in List[]. + * + ***************************************************************************/ + +void +acpi_ns_low_find_names ( + ACPI_NAMED_OBJECT *this_entry, + char *search_for, + s32 *count, + ACPI_HANDLE list[], + s32 max_depth) +{ + FIND_CONTEXT find; + + + if (0 == max_depth || !this_entry || !search_for || !count) { + /* + * Zero requested depth, nothing to search, + * nothing to search for, or count pointer bad + */ + + return; + } + + /* Init the context structure used by compare routine */ + + find.list = list; + find.count = count; + find.search_for = search_for; + + /* Walk the namespace and find all matches */ + + acpi_ns_walk_namespace (ACPI_TYPE_ANY, (ACPI_HANDLE) this_entry, + max_depth, NS_WALK_NO_UNLOCK, + acpi_ns_name_compare, &find, NULL); + + if (list) { + /* null-terminate the output array */ + + list[*count] = (ACPI_HANDLE) 0; + } + + return; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_find_names + + * + * PARAMETERS: *Search_for - pattern to be found. + * 4 bytes, ? matches any character. + * If NULL, "????" will be used. + * Start_handle - Root of subtree to be searched, or + * NS_ALL to search the entire namespace + * Max_depth - Maximum depth of search. Use INT_MAX + * for an effectively unlimited depth. + * + * DESCRIPTION: Traverse the name space finding names which match a search + * pattern, and return an array of handles. The end of the + * array is marked by the value (ACPI_HANDLE)0. A return value + * of (ACPI_HANDLE *)0 indicates that no matching names were + * found or that space for the list could not be allocated. + * if Start_handle is NS_ALL (null) search from the root, + * else it is a handle whose children are to be searched. + * + ***************************************************************************/ + +ACPI_HANDLE * +acpi_ns_find_names ( + char *search_for, + ACPI_HANDLE start_handle, + s32 max_depth) +{ + ACPI_HANDLE *list = NULL; + s32 count; + + + if (!acpi_gbl_root_object->child_table) { + /* + * If the name space has not been initialized, + * there surely are no matching names. + */ + return (NULL); + } + + if (NS_ALL == start_handle) { + /* base is root */ + + start_handle = acpi_gbl_root_object; + } + + else if (((ACPI_NAMED_OBJECT *) start_handle)->child_table) { + /* base has children to search */ + + start_handle = + ((ACPI_NAMED_OBJECT *) start_handle)->child_table->entries; + } + + else { + /* + * If base is not the root and has no children, + * there is nothing to search. + */ + return (NULL); + } + + if (!search_for) { + /* Search name not specified */ + + search_for = "????"; + } + + + /* Pass 1. Get required buffer size, don't try to build list */ + + count = 0; + acpi_ns_low_find_names (start_handle, search_for, &count, + NULL, max_depth); + + if (0 == count) { + return (NULL); + } + + /* Allow for trailing null */ + count++; + + list = acpi_cm_callocate (count * sizeof(ACPI_HANDLE)); + if (!list) { + REPORT_ERROR ("Ns_find_names: allocation failure"); + return (NULL); + } + + /* Pass 2. Fill buffer */ + + count = 0; + acpi_ns_low_find_names (start_handle, search_for, &count, list, max_depth); + + return (list); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/namespace/nsobject.c linux/drivers/acpi/namespace/nsobject.c --- v2.4.0-test2/linux/drivers/acpi/namespace/nsobject.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/namespace/nsobject.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,556 @@ + +/****************************************************************************** + * + * Module Name: nsobject - Utilities for objects attached to namespace + * table entries + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "namesp.h" +#include "interp.h" +#include "tables.h" + + +#define _COMPONENT NAMESPACE + MODULE_NAME ("nsobject"); + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_attach_object + * + * PARAMETERS: Handle - Handle of nte + * Object - Object to be attached + * Type - Type of object, or ACPI_TYPE_ANY if not + * known + * + * DESCRIPTION: Record the given object as the value associated with the + * name whose ACPI_HANDLE is passed. If Object is NULL + * and Type is ACPI_TYPE_ANY, set the name as having no value. + * + * MUTEX: Assumes namespace is locked + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_attach_object ( + ACPI_HANDLE handle, + ACPI_HANDLE object, + OBJECT_TYPE_INTERNAL type) +{ + ACPI_NAMED_OBJECT *this_entry = (ACPI_NAMED_OBJECT*) handle; + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_OBJECT_INTERNAL *previous_obj_desc; + OBJECT_TYPE_INTERNAL obj_type = ACPI_TYPE_ANY; + u8 flags; + u16 opcode; + + + /* + * Parameter validation + */ + + if (!acpi_gbl_root_object->child_table) { + /* Name space not initialized */ + + REPORT_ERROR ("Ns_attach_object: Name space not initialized"); + return (AE_NO_NAMESPACE); + } + + if (!handle) { + /* Invalid handle */ + + REPORT_ERROR ("Ns_attach_object: Null name handle"); + return (AE_BAD_PARAMETER); + } + + if (!object && (ACPI_TYPE_ANY != type)) { + /* Null object */ + + REPORT_ERROR ("Ns_attach_object: Null object, but type" + "not ACPI_TYPE_ANY"); + return (AE_BAD_PARAMETER); + } + + if (!VALID_DESCRIPTOR_TYPE (handle, ACPI_DESC_TYPE_NAMED)) { + /* Not a name handle */ + + REPORT_ERROR ("Ns_attach_object: Invalid handle"); + return (AE_BAD_PARAMETER); + } + + /* Check if this object is already attached */ + + if (this_entry->object == object) { + return (AE_OK); + } + + + /* Get the current flags field of the NTE */ + + flags = this_entry->flags; + flags &= ~NTE_AML_ATTACHMENT; + + + /* If null object, we will just install it */ + + if (!object) { + obj_desc = NULL; + obj_type = ACPI_TYPE_ANY; + } + + /* + * If the object is an NTE with an attached object, + * we will use that (attached) object + */ + + else if (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_NAMED) && + ((ACPI_NAMED_OBJECT*) object)->object) + { + /* + * Value passed is a name handle and that name has a + * non-null value. Use that name's value and type. + */ + + obj_desc = ((ACPI_NAMED_OBJECT*) object)->object; + obj_type = ((ACPI_NAMED_OBJECT*) object)->type; + + /* + * Copy appropriate flags + */ + + if (((ACPI_NAMED_OBJECT*) object)->flags & NTE_AML_ATTACHMENT) { + flags |= NTE_AML_ATTACHMENT; + } + } + + + /* + * Otherwise, we will use the parameter object, but we must type + * it first + */ + + else { + obj_desc = (ACPI_OBJECT_INTERNAL *) object; + + + /* If a valid type (non-ANY) was given, just use it */ + + if (ACPI_TYPE_ANY != type) { + obj_type = type; + } + + + /* + * Type is TYPE_Any, we must try to determinte the + * actual type of the object + */ + + /* + * Check if value points into the AML code + */ + else if (acpi_tb_system_table_pointer (object)) { + /* + * Object points into the AML stream. + * Set a flag bit in the NTE to indicate this + */ + + flags |= NTE_AML_ATTACHMENT; + + /* + * The next byte (perhaps the next two bytes) + * will be the AML opcode + */ + + MOVE_UNALIGNED16_TO_16 (&opcode, object); + + /* Check for a recognized Op_code */ + + switch ((u8) opcode) + { + + case AML_OP_PREFIX: + + if (opcode != AML_REVISION_OP) { + /* + * Op_prefix is unrecognized unless part + * of Revision_op + */ + + break; + } + + /* Else fall through to set type as Number */ + + + case AML_ZERO_OP: case AML_ONES_OP: case AML_ONE_OP: + case AML_BYTE_OP: case AML_WORD_OP: case AML_DWORD_OP: + + obj_type = ACPI_TYPE_NUMBER; + break; + + + case AML_STRING_OP: + + obj_type = ACPI_TYPE_STRING; + break; + + + case AML_BUFFER_OP: + + obj_type = ACPI_TYPE_BUFFER; + break; + + + case AML_MUTEX_OP: + + obj_type = ACPI_TYPE_MUTEX; + break; + + + case AML_PACKAGE_OP: + + obj_type = ACPI_TYPE_PACKAGE; + break; + + + default: + + return (AE_TYPE); + break; + } + } + + else { + /* + * Cannot figure out the type -- set to Def_any which + * will print as an error in the name table dump + */ + + + obj_type = INTERNAL_TYPE_DEF_ANY; + } + } + + + /* + * Must increment the new value's reference count + * (if it is an internal object) + */ + + acpi_cm_add_reference (obj_desc); + + /* Save the existing object (if any) for deletion later */ + + previous_obj_desc = this_entry->object; + + /* Install the object and set the type, flags */ + + this_entry->object = obj_desc; + this_entry->type = (u8) obj_type; + this_entry->flags = flags; + + + /* + * Delete an existing attached object. + */ + + if (previous_obj_desc) { + /* One for the attach to the NTE */ + acpi_cm_remove_reference (previous_obj_desc); + /* Now delete */ + acpi_cm_remove_reference (previous_obj_desc); + } + + return (AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_attach_method + * + * PARAMETERS: Handle - Handle of nte to be set + * Offset - Value to be set + * Length - Length associated with value + * + * DESCRIPTION: Record the given offset and p-code length of the method + * whose handle is passed + * + * MUTEX: Assumes namespace is locked + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_attach_method ( + ACPI_HANDLE handle, + u8 *pcode_addr, + u32 pcode_length) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_OBJECT_INTERNAL *previous_obj_desc; + ACPI_NAMED_OBJECT *this_entry = (ACPI_NAMED_OBJECT*) handle; + + + /* Parameter validation */ + + if (!acpi_gbl_root_object->child_table) { + /* Name space uninitialized */ + + REPORT_ERROR ("Ns_attach_method: name space uninitialized"); + return (AE_NO_NAMESPACE); + } + + if (!handle) { + /* Null name handle */ + + REPORT_ERROR ("Ns_attach_method: null name handle"); + return (AE_BAD_PARAMETER); + } + + + /* Allocate a method descriptor */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_METHOD); + if (!obj_desc) { + /* Method allocation failure */ + + REPORT_ERROR ("Ns_attach_method: allocation failure"); + return (AE_NO_MEMORY); + } + + /* Init the method info */ + + obj_desc->method.pcode = pcode_addr; + obj_desc->method.pcode_length = pcode_length; + + /* Update reference count and install */ + + acpi_cm_add_reference (obj_desc); + + previous_obj_desc = this_entry->object; + this_entry->object = obj_desc; + + + /* + * Delete an existing object. Don't try to re-use in case it is shared + */ + if (previous_obj_desc) { + acpi_cm_remove_reference (previous_obj_desc); + } + + return (AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_detach_object + * + * PARAMETERS: Object - An object whose Value will be deleted + * + * RETURN: None. + * + * DESCRIPTION: Delete the Value associated with a namespace object. If the + * Value is an allocated object, it is freed. Otherwise, the + * field is simply cleared. + * + ***************************************************************************/ + +void +acpi_ns_detach_object ( + ACPI_HANDLE object) +{ + ACPI_NAMED_OBJECT *entry = object; + ACPI_OBJECT_INTERNAL *obj_desc; + + + obj_desc = entry->object; + if (!obj_desc) { + return; + } + + /* Clear the entry in all cases */ + + entry->object = NULL; + + /* Found a valid value */ + + /* + * Not every value is an object allocated via Acpi_cm_callocate, + * - must check + */ + + if (!acpi_tb_system_table_pointer (obj_desc)) { + /* Attempt to delete the object (and all subobjects) */ + + acpi_cm_remove_reference (obj_desc); + } + + return; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_get_attached_object + * + * PARAMETERS: Handle - Handle of nte to be examined + * + * RETURN: Current value of the object field from nte whose handle is + * passed + * + ***************************************************************************/ + +void * +acpi_ns_get_attached_object ( + ACPI_HANDLE handle) +{ + + if (!handle) { + /* handle invalid */ + + REPORT_WARNING ("Ns_get_attached_object: Null handle"); + return (NULL); + } + + return (((ACPI_NAMED_OBJECT*) handle)->object); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_compare_object + * + * PARAMETERS: Obj_handle - A namespace entry + * Level - Current nesting level + * Obj_desc - The value to be compared + * + * DESCRIPTION: A User_function called by Acpi_ns_walk_namespace(). It performs + * a comparison for Acpi_ns_find_attached_object(). The comparison is against + * the value in the value field of the Obj_handle (an NTE). + * If a match is found, the handle is returned, which aborts + * Acpi_ns_walk_namespace. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_compare_object ( + ACPI_HANDLE obj_handle, + u32 level, + void *obj_desc, + void **return_value) +{ + + if (((ACPI_NAMED_OBJECT*) obj_handle)->object == obj_desc) { + if (return_value) { + *return_value = obj_handle; + } + + /* Stop the walk */ + return AE_CTRL_TERMINATE; + } + + /* Not found, continue the walk */ + return AE_OK; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_find_attached_object + * + * PARAMETERS: *Obj_desc - Value to be found in ptr_val field. + * Start_handle - Root of subtree to be searched, or + * NS_ALL to search the entire namespace + * Max_depth - Maximum depth of search. Use INT_MAX + * for an effectively unlimited depth. + * + * DESCRIPTION: Traverse the name space until finding a name whose Value field + * matches the Obj_desc parameter, and return a handle to that + * name, or (ACPI_HANDLE)0 if none exists. + * if Start_handle is NS_ALL (null) search from the root, + * else it is a handle whose children are to be searched. + * + ***************************************************************************/ + +ACPI_HANDLE +acpi_ns_find_attached_object ( + ACPI_OBJECT_INTERNAL *obj_desc, + ACPI_HANDLE start_handle, + s32 max_depth) +{ + ACPI_HANDLE ret_object; + ACPI_STATUS status; + + + /* Parameter validation */ + + if (!obj_desc) { + return (NULL); + } + + if (0 == max_depth) { + return (NULL); + } + + if (!acpi_gbl_root_object->child_table) { + /* + * If the name space has not been initialized, + * there surely are no matching values. + */ + return (NULL); + } + + if (NS_ALL == start_handle) { + start_handle = acpi_gbl_root_object; + } + + else { + /* + * If base is not the root and has no children, + * there is nothing to search. + */ + return (NULL); + } + + + /* + * Walk namespace until a match is found. + * Either the matching object is returned, or NULL in case + * of no match. + */ + status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, start_handle, + max_depth, NS_WALK_NO_UNLOCK, + acpi_ns_compare_object, + obj_desc, &ret_object); + + if (ACPI_FAILURE (status)) { + ret_object = NULL; + } + + return (ret_object); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/namespace/nssearch.c linux/drivers/acpi/namespace/nssearch.c --- v2.4.0-test2/linux/drivers/acpi/namespace/nssearch.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/namespace/nssearch.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,646 @@ + +/****************************************************************************** + * + * Module Name: nssearch - Namespace search + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "interp.h" +#include "namesp.h" + + +#define _COMPONENT NAMESPACE + MODULE_NAME ("nssearch"); + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_search_one_scope + * + * PARAMETERS: *Entry_name - Ascii ACPI name to search for + * *Name_table - Starting table where search will begin + * Type - Object type to match + * **Ret_entry - Where the matched NTE is returned + * *Ret_info - Where info about the search is returned + * + * RETURN: Status and return information via NS_SEARCH_DATA + * + * DESCRIPTION: Search a single namespace table. Performs a simple search, + * does not add entries or search parents. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_search_one_scope ( + u32 entry_name, + ACPI_NAME_TABLE *name_table, + OBJECT_TYPE_INTERNAL type, + ACPI_NAMED_OBJECT **ret_entry, + NS_SEARCH_DATA *ret_info) +{ + u32 position; + ACPI_NAME_TABLE *this_table; + ACPI_NAME_TABLE *previous_table = name_table; + ACPI_NAMED_OBJECT *entries; + u8 table_full = TRUE; + ACPI_NAME_TABLE *table_with_empty_slots = NULL; + u32 empty_slot_position = 0; + + + + /* + * Name tables are built (and subsequently dumped) in the + * order in which the names are encountered during the namespace load; + * + * All namespace searching will be linear; If a table overflows an + * additional segment will be allocated and added (chained). + * + * Start linear search at top of table + */ + position = 0; + this_table = name_table; + entries = this_table->entries; + + + /* Init return data */ + + if (ret_info) { + ret_info->name_table = this_table; + } + + + /* + * Search entire name table, including all linked appendages + */ + + while (this_table) { + /* + * Search for name in table, starting at Position. Stop + * searching upon examining all entries in the table. + * + */ + + entries = this_table->entries; + while (position < NS_TABLE_SIZE) { + /* Check for a valid entry */ + + if (!entries[position].name) { + if (table_full) { + /* + * There is room in the table for more + * entries, if necessary + */ + + table_full = FALSE; + table_with_empty_slots = this_table; + empty_slot_position = position; + } + } + + /* Search for name in table */ + + else if (entries[position].name == entry_name) { + /* + * Found matching entry. Capture type if + * appropriate before returning the entry. + */ + + /* + * The Def_field_defn and Bank_field_defn cases + * are actually looking up the Region in which + * the field will be defined + */ + + if ((INTERNAL_TYPE_DEF_FIELD_DEFN == type) || + (INTERNAL_TYPE_BANK_FIELD_DEFN == type)) + { + type = ACPI_TYPE_REGION; + } + + /* + * Scope, Def_any, and Index_field_defn are bogus + * "types" which do not actually have anything + * to do with the type of the name being looked + * up. For any other value of Type, if the type + * stored in the entry is Any (i.e. unknown), + * save the actual type. + */ + + if (type != INTERNAL_TYPE_SCOPE && + type != INTERNAL_TYPE_DEF_ANY && + type != INTERNAL_TYPE_INDEX_FIELD_DEFN && + entries[position].type == ACPI_TYPE_ANY) + { + entries[position].type = (u8) type; + } + + *ret_entry = &entries[position]; + return (AE_OK); + } + + + /* Didn't match name, move on to the next entry */ + + position++; + } + + + /* + * Just examined last slot in this table, move on + * to next appendate. + * All appendages, even to the root NT, contain + * NS_TABLE_SIZE entries. + */ + + previous_table = this_table; + this_table = this_table->next_table; + + position = 0; + } + + + /* Searched entire table, not found */ + + + if (ret_info) { + /* + * Save info on if/where a slot is available + * (name was not found) + */ + + ret_info->table_full = table_full; + if (table_full) { + ret_info->name_table = previous_table; + } + + else { + ret_info->position = empty_slot_position; + ret_info->name_table = table_with_empty_slots; + } + } + + return (AE_NOT_FOUND); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_search_parent_tree + * + * PARAMETERS: *Entry_name - Ascii ACPI name to search for + * *Name_table - Starting table where search will begin + * Type - Object type to match + * **Ret_entry - Where the matched NTE is returned + * + * RETURN: Status + * + * DESCRIPTION: Called when a name has not been found in the current namespace + * table. Before adding it or giving up, ACPI scope rules require + * searching enclosing scopes in cases identified by Acpi_ns_local(). + * + * "A name is located by finding the matching name in the current + * name space, and then in the parent name space. If the parent + * name space does not contain the name, the search continues + * recursively until either the name is found or the name space + * does not have a parent (the root of the name space). This + * indicates that the name is not found" (From ACPI Specification, + * section 5.3) + * + ***************************************************************************/ + + +ACPI_STATUS +acpi_ns_search_parent_tree ( + u32 entry_name, + ACPI_NAME_TABLE *name_table, + OBJECT_TYPE_INTERNAL type, + ACPI_NAMED_OBJECT **ret_entry) +{ + ACPI_STATUS status; + ACPI_NAMED_OBJECT *parent_entry; + ACPI_NAMED_OBJECT *entries; + + + entries = name_table->entries; + + /* + * If no parent or type is "local", we won't be searching the + * parent tree. + */ + + if (!acpi_ns_local (type) && + name_table->parent_entry) + { + parent_entry = name_table->parent_entry; + /* + * Search parents until found or we have backed up to + * the root + */ + + while (parent_entry) { + /* Search parent scope */ + /* TBD: [Investigate] Why ACPI_TYPE_ANY? */ + + status = acpi_ns_search_one_scope (entry_name, + parent_entry->child_table, + ACPI_TYPE_ANY, + ret_entry, NULL); + + if (status == AE_OK) { + return (status); + } + + /* + * Not found here, go up another level + * (until we reach the root) + */ + + parent_entry = acpi_ns_get_parent_entry (parent_entry); + } + + /* Not found in parent tree */ + } + + + return (AE_NOT_FOUND); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_create_and_link_new_table + * + * PARAMETERS: *Name_table - The table that is to be "extended" by + * the creation of an appendage table. + * + * RETURN: Status + * + * DESCRIPTION: Allocate a new namespace table, initialize it, and link it + * into the parent table. + * + * NOTE: We are in the first or second pass load mode, want to + * add a new table entry, and the current table is full. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_create_and_link_new_table ( + ACPI_NAME_TABLE *name_table) +{ + ACPI_NAME_TABLE *new_table; + ACPI_NAMED_OBJECT *parent_entry; + ACPI_STATUS status = AE_OK; + + + /* Sanity check on the data structure */ + + if (name_table->next_table) { + /* We should never get here (an appendage already allocated) */ + + return (AE_AML_INTERNAL); + } + + + /* + * We can use the parent entries from the current table + * Since the parent information remains the same. + */ + parent_entry = name_table->parent_entry; + + + /* Allocate and chain an appendage to the filled table */ + + new_table = acpi_ns_allocate_name_table (NS_TABLE_SIZE); + if (!new_table) { + REPORT_ERROR ("Name Table appendage allocation failure"); + return (AE_NO_MEMORY); + } + + /* + * Allocation successful. Init the new table. + */ + name_table->next_table = new_table; + acpi_ns_initialize_table (new_table, parent_entry->child_table, + parent_entry); + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_initialize_table + * + * PARAMETERS: New_table - The new table to be initialized + * Parent_table - The parent (owner) scope + * Parent_entry - The NTE for the parent + * + * RETURN: None + * + * DESCRIPTION: Initialize a new namespace table. Simple, but called + * from several places -- code should be kept in one place. + * + ***************************************************************************/ + +void +acpi_ns_initialize_table ( + ACPI_NAME_TABLE *new_table, + ACPI_NAME_TABLE *parent_table, + ACPI_NAMED_OBJECT *parent_entry) +{ + u8 i; + + + new_table->parent_entry = parent_entry; + new_table->parent_table = parent_table; + + + /* Init each named object entry in the table */ + + for (i = 0; i < NS_TABLE_SIZE; i++) { + new_table->entries[i].this_index = i; + new_table->entries[i].data_type = ACPI_DESC_TYPE_NAMED; + } + +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_initialize_entry + * + * PARAMETERS: Name_table - The containing table for the new NTE + * Position - Position (index) of the new NTE in the table + * Entry_name - ACPI name of the new entry + * Type - ACPI object type of the new entry + * Previous_entry - Link back to the previous entry (can span + * multiple tables) + * + * RETURN: None + * + * DESCRIPTION: Initialize a new entry within a namespace table. + * + ***************************************************************************/ + +void +acpi_ns_initialize_entry ( + ACPI_WALK_STATE *walk_state, + ACPI_NAME_TABLE *name_table, + u32 position, + u32 entry_name, + OBJECT_TYPE_INTERNAL type) +{ + ACPI_NAMED_OBJECT *new_entry; + u16 owner_id = TABLE_ID_DSDT; + ACPI_NAMED_OBJECT *entries; + + + /* + * Get the owner ID from the Walk state + * The owner ID is used to track table deletion and + * deletion of objects created by methods + */ + if (walk_state) { + owner_id = walk_state->owner_id; + } + + /* The new entry is given by two parameters */ + + entries = name_table->entries; + new_entry = &entries[position]; + + /* Init the new entry */ + + new_entry->data_type = ACPI_DESC_TYPE_NAMED; + new_entry->name = entry_name; + new_entry->owner_id = owner_id; + new_entry->reference_count = 1; + + + /* + * If adding a name with unknown type, or having to + * add the region in order to define fields in it, we + * have a forward reference. + */ + + if ((ACPI_TYPE_ANY == type) || + (INTERNAL_TYPE_DEF_FIELD_DEFN == type) || + (INTERNAL_TYPE_BANK_FIELD_DEFN == type)) + { + /* + * We don't want to abort here, however! + * We will fill in the actual type when the + * real definition is found later. + */ + + } + + /* + * The Def_field_defn and Bank_field_defn cases are actually + * looking up the Region in which the field will be defined + */ + + if ((INTERNAL_TYPE_DEF_FIELD_DEFN == type) || + (INTERNAL_TYPE_BANK_FIELD_DEFN == type)) + { + type = ACPI_TYPE_REGION; + } + + /* + * Scope, Def_any, and Index_field_defn are bogus "types" which do + * not actually have anything to do with the type of the name + * being looked up. Save any other value of Type as the type of + * the entry. + */ + + if ((type != INTERNAL_TYPE_SCOPE) && + (type != INTERNAL_TYPE_DEF_ANY) && + (type != INTERNAL_TYPE_INDEX_FIELD_DEFN)) + { + new_entry->type = (u8) type; + } + + return; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_search_and_enter + * + * PARAMETERS: Entry_name - Ascii ACPI name to search for (4 chars) + * *Name_table - Starting table where search will begin + * Interpreter_mode - Add names only in MODE_Load_pass_x. Otherwise, + * search only. + * Type - Object type to match + * **Ret_entry - Where the matched NTE is returned + * + * RETURN: Status + * + * DESCRIPTION: Search for a name segment in a single name table, + * optionally adding it if it is not found. If the passed + * Type is not Any and the type previously stored in the + * entry was Any (i.e. unknown), update the stored type. + * + * In IMODE_EXECUTE, search only. + * In other modes, search and add if not found. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_search_and_enter ( + u32 entry_name, + ACPI_WALK_STATE *walk_state, + ACPI_NAME_TABLE *name_table, + OPERATING_MODE interpreter_mode, + OBJECT_TYPE_INTERNAL type, + u32 flags, + ACPI_NAMED_OBJECT **ret_entry) +{ + u32 position; /* position in table */ + ACPI_STATUS status; + NS_SEARCH_DATA search_info; + ACPI_NAMED_OBJECT *entry; + ACPI_NAMED_OBJECT *entries; + + + /* Parameter validation */ + + if (!name_table || !entry_name || !ret_entry) { + REPORT_ERROR ("Ns_search_and_enter: bad parameter"); + return (AE_BAD_PARAMETER); + } + + + /* Name must consist of printable characters */ + + if (!acpi_cm_valid_acpi_name (entry_name)) { + return (AE_BAD_CHARACTER); + } + + + /* Try to find the name in the table specified by the caller */ + + *ret_entry = ENTRY_NOT_FOUND; + status = acpi_ns_search_one_scope (entry_name, name_table, + type, ret_entry, &search_info); + if (status != AE_NOT_FOUND) { + /* + * Either found it or there was an error + * -- finished either way + */ + + return (status); + } + + + /* + * Not found in the table. If we are NOT performing the + * first pass (name entry) of loading the namespace, search + * the parent tree (all the way to the root if necessary.) + * We don't want to perform the parent search when the + * namespace is actually being loaded. We want to perform + * the search when namespace references are being resolved + * (load pass 2) and during the execution phase. + */ + + if ((interpreter_mode != IMODE_LOAD_PASS1) && + (flags & NS_SEARCH_PARENT)) + { + /* + * Not found in table - search parent tree according + * to ACPI specification + */ + + status = acpi_ns_search_parent_tree (entry_name, name_table, + type, ret_entry); + + if (status == AE_OK) { + return (status); + } + } + + + /* + * In execute mode, just search, never add names. Exit now. + */ + + if (interpreter_mode == IMODE_EXECUTE) { + return (AE_NOT_FOUND); + } + + + /* + * Extract the pertinent info from the search result struct. + * Name_table and position might now point to an appendage + */ + name_table = search_info.name_table; + position = search_info.position; + + + /* + * This block handles the case where the existing table is full. + * we must allocate a new table before we can initialize a new entry + */ + + if (search_info.table_full) { + status = acpi_ns_create_and_link_new_table (name_table); + if (status != AE_OK) { + return (status); + } + + /* Point to the first slot in the new table */ + + name_table = name_table->next_table; + position = 0; + } + + + /* + * There is room in the table (or we have just allocated a new one.) + * Initialize the new entry + */ + + acpi_ns_initialize_entry (walk_state, name_table, position, + entry_name, type); + + + entries = name_table->entries; + *ret_entry = &entries[position]; + entry = &entries[position]; + + /* + * Increment the reference count(s) of all parents up to + * the root! + */ + + while (acpi_ns_get_parent_entry (entry)) { + entry = acpi_ns_get_parent_entry (entry); + entry->reference_count++; + } + + + return (AE_OK); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/namespace/nsutils.c linux/drivers/acpi/namespace/nsutils.c --- v2.4.0-test2/linux/drivers/acpi/namespace/nsutils.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/namespace/nsutils.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,886 @@ + +/****************************************************************************** + * + * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing + * parents and siblings and Scope manipulation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "namesp.h" +#include "interp.h" +#include "amlcode.h" +#include "tables.h" + +#define _COMPONENT NAMESPACE + MODULE_NAME ("nsutils"); + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_valid_root_prefix + * + * PARAMETERS: Prefix - Character to be checked + * + * RETURN: TRUE if a valid prefix + * + * DESCRIPTION: Check if a character is a valid ACPI Root prefix + * + ***************************************************************************/ + +u8 +acpi_ns_valid_root_prefix ( + char prefix) +{ + + return ((u8) (prefix == '\\')); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_valid_path_separator + * + * PARAMETERS: Sep - Character to be checked + * + * RETURN: TRUE if a valid path separator + * + * DESCRIPTION: Check if a character is a valid ACPI path separator + * + ***************************************************************************/ + +u8 +acpi_ns_valid_path_separator ( + char sep) +{ + + return ((u8) (sep == '.')); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_get_type + * + * PARAMETERS: Handle - Handle of nte to be examined + * + * RETURN: Type field from nte whose handle is passed + * + ***************************************************************************/ + +OBJECT_TYPE_INTERNAL +acpi_ns_get_type ( + ACPI_HANDLE handle) +{ + + if (!handle) { + /* Handle invalid */ + + REPORT_WARNING ("Ns_get_type: Null handle"); + return (ACPI_TYPE_ANY); + } + + return (((ACPI_NAMED_OBJECT*) handle)->type); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_local + * + * PARAMETERS: Type - A namespace object type + * + * RETURN: LOCAL if names must be found locally in objects of the + * passed type, 0 if enclosing scopes should be searched + * + ***************************************************************************/ + +s32 +acpi_ns_local ( + OBJECT_TYPE_INTERNAL type) +{ + + if (!acpi_cm_valid_object_type (type)) { + /* type code out of range */ + + REPORT_WARNING ("Ns_local: Invalid Object Type"); + return (NSP_NORMAL); + } + + return ((s32) acpi_gbl_ns_properties[type] & NSP_LOCAL); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_internalize_name + * + * PARAMETERS: *External_name - External representation of name + * **Converted Name - Where to return the resulting + * internal represention of the name + * + * RETURN: Status + * + * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0") + * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ns_internalize_name ( + char *external_name, + char **converted_name) +{ + char *result = NULL; + char *internal_name; + ACPI_SIZE num_segments; + u8 fully_qualified = FALSE; + u32 i; + + + if ((!external_name) || + (*external_name == 0) || + (!converted_name)) + { + return (AE_BAD_PARAMETER); + } + + + /* + * For the internal name, the required length is 4 bytes + * per segment, plus 1 each for Root_prefix, Multi_name_prefix_op, + * segment count, trailing null (which is not really needed, + * but no there's harm in putting it there) + * + * strlen() + 1 covers the first Name_seg, which has no + * path separator + */ + + if (acpi_ns_valid_root_prefix (external_name[0])) { + fully_qualified = TRUE; + external_name++; + } + + + /* + * Determine the number of ACPI name "segments" by counting + * the number of path separators within the string. Start + * with one segment since the segment count is (# separators) + * + 1, and zero separators is ok. + */ + + num_segments = 1; + for (i = 0; external_name[i]; i++) { + if (acpi_ns_valid_path_separator (external_name[i])) { + num_segments++; + } + } + + + /* We need a segment to store the internal version of the name */ + + internal_name = acpi_cm_callocate ((ACPI_NAME_SIZE * num_segments) + 4); + if (!internal_name) { + return (AE_NO_MEMORY); + } + + + /* Setup the correct prefixes, counts, and pointers */ + + if (fully_qualified) { + internal_name[0] = '\\'; + internal_name[1] = AML_MULTI_NAME_PREFIX_OP; + internal_name[2] = (char) num_segments; + result = &internal_name[3]; + } + else { + internal_name[0] = AML_MULTI_NAME_PREFIX_OP; + internal_name[1] = (char) num_segments; + result = &internal_name[2]; + } + + + /* Build the name (minus path separators) */ + + for (; num_segments; num_segments--) { + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (acpi_ns_valid_path_separator (*external_name) || + (*external_name == 0)) + { + /* + * Pad the segment with underscore(s) if + * segment is short + */ + + result[i] = '_'; + } + + else { + /* Convert char to uppercase and save it */ + + result[i] = (char) TOUPPER (*external_name); + external_name++; + } + + } + + /* Now we must have a path separator, or the pathname is bad */ + + if (!acpi_ns_valid_path_separator (*external_name) && + (*external_name != 0)) + { + acpi_cm_free (internal_name); + return (AE_BAD_PARAMETER); + } + + /* Move on the next segment */ + + external_name++; + result += ACPI_NAME_SIZE; + } + + + /* Return the completed name */ + + /* Terminate the string! */ + *result = 0; + *converted_name = internal_name; + + + + return (AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_externalize_name + * + * PARAMETERS: *Internal_name - Internal representation of name + * **Converted_name - Where to return the resulting + * external representation of name + * + * RETURN: Status + * + * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) + * to its external form (e.g. "\_PR_.CPU0") + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ns_externalize_name ( + u32 internal_name_length, + char *internal_name, + u32 *converted_name_length, + char **converted_name) +{ + u32 prefix_length = 0; + u32 names_index = 0; + u32 names_count = 0; + u32 i = 0; + u32 j = 0; + + if (internal_name_length < 0 || + !internal_name || + !converted_name_length || + !converted_name) + { + return (AE_BAD_PARAMETER); + } + + /* + * Check for a prefix (one '\' | one or more '^'). + */ + switch (internal_name[0]) + { + case '\\': + prefix_length = 1; + break; + + case '^': + for (i = 0; i < internal_name_length; i++) { + if (internal_name[i] != '^') { + prefix_length = i + 1; + } + } + + if (i == internal_name_length) { + prefix_length = i; + } + + break; + } + + /* + * Check for object names. Note that there could be 0-255 of these + * 4-byte elements. + */ + if (prefix_length < internal_name_length) { + switch (internal_name[prefix_length]) + { + + /* 4-byte names */ + + case AML_MULTI_NAME_PREFIX_OP: + names_index = prefix_length + 2; + names_count = (u32) internal_name[prefix_length + 1]; + break; + + + /* two 4-byte names */ + + case AML_DUAL_NAME_PREFIX: + names_index = prefix_length + 1; + names_count = 2; + break; + + + /* Null_name */ + + case 0: + names_index = 0; + names_count = 0; + break; + + + /* one 4-byte name */ + + default: + names_index = prefix_length; + names_count = 1; + break; + } + } + + /* + * Calculate the length of Converted_name, which equals the length + * of the prefix, length of all object names, length of any required + * punctuation ('.') between object names, plus the NULL terminator. + */ + *converted_name_length = prefix_length + (4 * names_count) + + ((names_count > 0) ? (names_count - 1) : 0) + 1; + + /* + * Check to see if we're still in bounds. If not, there's a problem + * with Internal_name (invalid format). + */ + if (*converted_name_length > internal_name_length) { + REPORT_ERROR ("Ns_externalize_name: Invalid internal name.\n"); + return (AE_BAD_PATHNAME); + } + + /* + * Build Converted_name... + */ + + (*converted_name) = acpi_cm_callocate (*converted_name_length); + if (!(*converted_name)) { + return (AE_NO_MEMORY); + } + + j = 0; + + for (i = 0; i < prefix_length; i++) { + (*converted_name)[j++] = internal_name[i]; + } + + if (names_count > 0) { + for (i = 0; i < names_count; i++) { + if (i > 0) { + (*converted_name)[j++] = '.'; + } + + (*converted_name)[j++] = internal_name[names_index++]; + (*converted_name)[j++] = internal_name[names_index++]; + (*converted_name)[j++] = internal_name[names_index++]; + (*converted_name)[j++] = internal_name[names_index++]; + } + } + + return (AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_convert_handle_to_entry + * + * PARAMETERS: Handle - Handle to be converted to an NTE + * + * RETURN: A Name table entry pointer + * + * DESCRIPTION: Convert a namespace handle to a real NTE + * + ****************************************************************************/ + +ACPI_NAMED_OBJECT* +acpi_ns_convert_handle_to_entry ( + ACPI_HANDLE handle) +{ + + /* + * Simple implementation for now; + * TBD: [Future] Real integer handles allow for more verification + * and keep all pointers within this subsystem! + */ + + if (!handle) { + return NULL; + } + + if (handle == ACPI_ROOT_OBJECT) { + return acpi_gbl_root_object; + } + + + /* We can at least attempt to verify the handle */ + + if (!VALID_DESCRIPTOR_TYPE (handle, ACPI_DESC_TYPE_NAMED)) { + return NULL; + } + + return (ACPI_NAMED_OBJECT*) handle; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_convert_entry_to_handle + * + * PARAMETERS: Nte - NTE to be converted to a Handle + * + * RETURN: An USER ACPI_HANDLE + * + * DESCRIPTION: Convert a real NTE to a namespace handle + * + ****************************************************************************/ + +ACPI_HANDLE +acpi_ns_convert_entry_to_handle(ACPI_NAMED_OBJECT*nte) +{ + + + /* + * Simple implementation for now; + * TBD: [Future] Real integer handles allow for more verification + * and keep all pointers within this subsystem! + */ + + return (ACPI_HANDLE) nte; + + +/* --------------------------------------------------- + + if (!Nte) { + return NULL; + } + + if (Nte == Acpi_gbl_Root_object) { + return ACPI_ROOT_OBJECT; + } + + + return (ACPI_HANDLE) Nte; +------------------------------------------------------*/ +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ns_terminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: free memory allocated for table storage. + * + ******************************************************************************/ + +void +acpi_ns_terminate (void) +{ + ACPI_OBJECT_INTERNAL *obj_desc; + ACPI_NAMED_OBJECT *entry; + + + entry = acpi_gbl_root_object; + + /* + * 1) Free the entire namespace -- all objects, tables, and stacks + */ + /* + * Delete all objects linked to the root + * (additional table descriptors) + */ + + acpi_ns_delete_namespace_subtree (entry); + + /* Detach any object(s) attached to the root */ + + obj_desc = acpi_ns_get_attached_object (entry); + if (obj_desc) { + acpi_ns_detach_object (entry); + acpi_cm_remove_reference (obj_desc); + } + + acpi_ns_delete_name_table (entry->child_table); + entry->child_table = NULL; + + + REPORT_SUCCESS ("Entire namespace and objects deleted"); + + /* + * 2) Now we can delete the ACPI tables + */ + + acpi_tb_delete_acpi_tables (); + + return; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_opens_scope + * + * PARAMETERS: Type - A valid namespace type + * + * RETURN: NEWSCOPE if the passed type "opens a name scope" according + * to the ACPI specification, else 0 + * + ***************************************************************************/ + +s32 +acpi_ns_opens_scope ( + OBJECT_TYPE_INTERNAL type) +{ + + if (!acpi_cm_valid_object_type (type)) { + /* type code out of range */ + + REPORT_WARNING ("Ns_opens_scope: Invalid Object Type"); + return (NSP_NORMAL); + } + + return (((s32) acpi_gbl_ns_properties[type]) & NSP_NEWSCOPE); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_get_named_object + * + * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The + * \ (backslash) and ^ (carat) prefixes, and the + * . (period) to separate segments are supported. + * In_scope - Root of subtree to be searched, or NS_ALL for the + * root of the name space. If Name is fully + * qualified (first char is '\'), the passed value + * of Scope will not be accessed. + * Out_nte - Where the Nte is returned + * + * DESCRIPTION: Look up a name relative to a given scope and return the + * corresponding NTE. NOTE: Scope can be null. + * + * MUTEX: Locks namespace + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_get_named_object ( + char *pathname, + ACPI_NAME_TABLE *in_scope, + ACPI_NAMED_OBJECT **out_nte) +{ + ACPI_GENERIC_STATE scope_info; + ACPI_STATUS status; + ACPI_NAMED_OBJECT *obj_entry = NULL; + char *internal_path = NULL; + + + scope_info.scope.name_table = in_scope; + + /* Ensure that the namespace has been initialized */ + + if (!acpi_gbl_root_object->child_table) { + return (AE_NO_NAMESPACE); + } + + if (!pathname) { + return (AE_BAD_PARAMETER); + } + + + /* Convert path to internal representation */ + + status = acpi_ns_internalize_name (pathname, &internal_path); + if (ACPI_FAILURE (status)) { + return (status); + } + + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* NS_ALL means start from the root */ + + if (NS_ALL == scope_info.scope.name_table) { + scope_info.scope.name_table = acpi_gbl_root_object->child_table; + } + + else { + scope_info.scope.name_table = in_scope; + if (!scope_info.scope.name_table) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + } + + /* Lookup the name in the namespace */ + + status = acpi_ns_lookup (&scope_info, internal_path, + ACPI_TYPE_ANY, IMODE_EXECUTE, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &obj_entry); + + + /* Return what was wanted - the NTE that matches the name */ + + *out_nte = obj_entry; + + +unlock_and_exit: + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + /* Cleanup */ + + acpi_cm_free (internal_path); + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_find_parent_name + * + * PARAMETERS: *Child_entry - nte whose name is to be found + * + * RETURN: The ACPI name + * + * DESCRIPTION: Search for the given nte in its parent scope and return the + * name segment, or "????" if the parent name can't be found + * (which "should not happen"). + * + ***************************************************************************/ + +ACPI_NAME +acpi_ns_find_parent_name ( + ACPI_NAMED_OBJECT *child_entry) +{ + ACPI_NAMED_OBJECT *parent_entry; + + + if (child_entry) { + /* Valid entry. Get the parent Nte */ + + parent_entry = acpi_ns_get_parent_entry (child_entry); + if (parent_entry) { + if (parent_entry->name) { + return (parent_entry->name); + } + } + + } + + + return (ACPI_UNKNOWN_NAME); +} + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_exist_downstream_sibling + * + * PARAMETERS: *This_entry - pointer to first nte to examine + * + * RETURN: TRUE if sibling is found, FALSE otherwise + * + * DESCRIPTION: Searches remainder of scope being processed to determine + * whether there is a downstream sibling to the current + * object. This function is used to determine what type of + * line drawing character to use when displaying namespace + * trees. + * + ***************************************************************************/ + +u8 +acpi_ns_exist_downstream_sibling ( + ACPI_NAMED_OBJECT *this_entry) +{ + + if (!this_entry) { + return FALSE; + } + + if (this_entry->name) { + return TRUE; + } + + +/* TBD: what did this really do? + if (This_entry->Next_entry) { + return TRUE; + } +*/ + return FALSE; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_get_owner_table + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ***************************************************************************/ + + +ACPI_NAME_TABLE * +acpi_ns_get_owner_table ( + ACPI_NAMED_OBJECT *this_entry) +{ + + /* + * Given an entry in the Name_table->Entries field of a name table, + * we can create a pointer to the beginning of the table as follows: + * + * 1) Starting with the the pointer to the entry, + * 2) Subtract the entry index * size of each entry to get a + * pointer to Entries[0] + * 3) Subtract the size of NAME_TABLE structure to get a pointer + * to the start. + * + * This saves having to put a pointer in every entry that points + * back to the beginning of the table and/or a pointer back to + * the parent. + */ + + return (ACPI_NAME_TABLE *) ((char *) this_entry - + (this_entry->this_index * + sizeof (ACPI_NAMED_OBJECT)) - + (sizeof (ACPI_NAME_TABLE) - + sizeof (ACPI_NAMED_OBJECT))); + +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_get_parent_entry + * + * PARAMETERS: This_entry - Current table entry + * + * RETURN: Parent entry of the given entry + * + * DESCRIPTION: Obtain the parent entry for a given entry in the namespace. + * + ***************************************************************************/ + + +ACPI_NAMED_OBJECT * +acpi_ns_get_parent_entry ( + ACPI_NAMED_OBJECT *this_entry) +{ + ACPI_NAME_TABLE *name_table; + + + name_table = acpi_ns_get_owner_table (this_entry); + + /* + * Now that we have a pointer to the name table, we can just pluck + * the parent + */ + + return (name_table->parent_entry); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_get_next_valid_entry + * + * PARAMETERS: This_entry - Current table entry + * + * RETURN: Next valid object in the table. NULL if no more valid + * objects + * + * DESCRIPTION: Find the next valid object within a name table. + * + ***************************************************************************/ + + +ACPI_NAMED_OBJECT * +acpi_ns_get_next_valid_entry ( + ACPI_NAMED_OBJECT *this_entry) +{ + ACPI_NAME_TABLE *name_table; + u32 index; + + + index = this_entry->this_index + 1; + name_table = acpi_ns_get_owner_table (this_entry); + + + while (name_table) { + if (index >= NS_TABLE_SIZE) { + /* We are at the end of this table */ + + name_table = name_table->next_table; + index = 0; + continue; + } + + + /* Is this a valid (occupied) slot? */ + + if (name_table->entries[index].name) { + /* Found a valid entry, all done */ + + return (&name_table->entries[index]); + } + + /* Go to the next slot */ + + index++; + } + + /* No more valid entries in this name table */ + + return NULL; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/namespace/nswalk.c linux/drivers/acpi/namespace/nswalk.c --- v2.4.0-test2/linux/drivers/acpi/namespace/nswalk.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/namespace/nswalk.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,279 @@ + +/****************************************************************************** + * + * Module Name: nswalk - Functions for walking the APCI namespace + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" +#include "namesp.h" + + +#define _COMPONENT NAMESPACE + MODULE_NAME ("nswalk"); + + +/**************************************************************************** + * + * FUNCTION: Acpi_get_next_object + * + * PARAMETERS: Type - Type of object to be searched for + * Parent - Parent object whose children we are getting + * Last_child - Previous child that was found. + * The NEXT child will be returned + * Ret_handle - Where handle to the next object is placed + * + * RETURN: Status + * + * DESCRIPTION: Return the next peer object within the namespace. If Handle is + * valid, Scope is ignored. Otherwise, the first object within + * Scope is returned. + * + ******************************************************************************/ + +ACPI_NAMED_OBJECT* +acpi_ns_get_next_object ( + OBJECT_TYPE_INTERNAL type, + ACPI_NAMED_OBJECT *parent, + ACPI_NAMED_OBJECT *child) +{ + ACPI_NAMED_OBJECT *this_entry = NULL; + + + if (!child) { + + /* It's really the parent's _scope_ that we want */ + + if (parent->child_table) { + this_entry = parent->child_table->entries; + } + } + + else { + /* Start search at the NEXT object */ + + this_entry = acpi_ns_get_next_valid_entry (child); + } + + + /* If any type is OK, we are done */ + + if (type == ACPI_TYPE_ANY) { + /* Make sure this is valid entry first */ + + if ((!this_entry) || + (!this_entry->name)) + { + return NULL; + } + + return (this_entry); + } + + + /* Must search for the object -- but within this scope only */ + + while (this_entry) { + /* If type matches, we are done */ + + if (this_entry->type == type) { + return (this_entry); + } + + /* Otherwise, move on to the next object */ + + this_entry = acpi_ns_get_next_valid_entry (this_entry); + } + + + /* Not found */ + + return NULL; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ns_walk_namespace + * + * PARAMETERS: Type - ACPI_OBJECT_TYPE to search for + * Start_object - Handle in namespace where search begins + * Max_depth - Depth to which search is to reach + * Unlock_before_callback- Whether to unlock the NS before invoking + * the callback routine + * User_function - Called when an object of "Type" is found + * Context - Passed to user function + * + * RETURNS Return value from the User_function if terminated early. + * Otherwise, returns NULL. + * + * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, + * starting (and ending) at the object specified by Start_handle. + * The User_function is called whenever an object that matches + * the type parameter is found. If the user function returns + * a non-zero value, the search is terminated immediately and this + * value is returned to the caller. + * + * The point of this procedure is to provide a generic namespace + * walk routine that can be called from multiple places to + * provide multiple services; the User Function can be tailored + * to each task, whether it is a print function, a compare + * function, etc. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_walk_namespace ( + OBJECT_TYPE_INTERNAL type, + ACPI_HANDLE start_object, + u32 max_depth, + u8 unlock_before_callback, + WALK_CALLBACK user_function, + void *context, + void **return_value) +{ + ACPI_STATUS status; + ACPI_NAMED_OBJECT *child_entry; + ACPI_NAMED_OBJECT *parent_entry; + OBJECT_TYPE_INTERNAL child_type; + u32 level; + + + /* Special case for the namespace root object */ + + if (start_object == ACPI_ROOT_OBJECT) { + start_object = acpi_gbl_root_object; + } + + + /* Null child means "get first object" */ + + parent_entry = start_object; + child_entry = 0; + child_type = ACPI_TYPE_ANY; + level = 1; + + /* + * Traverse the tree of objects until we bubble back up to where we + * started. When Level is zero, the loop is done because we have + * bubbled up to (and passed) the original parent handle (Start_entry) + */ + + while (level > 0) { + /* + * Get the next typed object in this scope. Null returned + * if not found + */ + + status = AE_OK; + child_entry = acpi_ns_get_next_object (ACPI_TYPE_ANY, + parent_entry, + child_entry); + + if (child_entry) { + /* + * Found an object, Get the type if we are not + * searching for ANY + */ + + if (type != ACPI_TYPE_ANY) { + child_type = child_entry->type; + } + + if (child_type == type) { + /* + * Found a matching object, invoke the user + * callback function + */ + + if (unlock_before_callback) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + } + + status = user_function (child_entry, level, + context, return_value); + + if (unlock_before_callback) { + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + } + + switch (status) + { + case AE_OK: + case AE_CTRL_DEPTH: + /* Just keep going */ + break; + + case AE_CTRL_TERMINATE: + /* Exit now, with OK status */ + return (AE_OK); + break; + + default: + /* All others are valid exceptions */ + return (status); + break; + } + } + + /* + * Depth first search: + * Attempt to go down another level in the namespace + * if we are allowed to. Don't go any further if we + * have reached the caller specified maximum depth + * or if the user function has specified that the + * maximum depth has been reached. + */ + + if ((level < max_depth) && (status != AE_CTRL_DEPTH)) { + if (acpi_ns_get_next_object (ACPI_TYPE_ANY, + child_entry, 0)) + { + /* + * There is at least one child of this + * object, visit the object + */ + level++; + parent_entry = child_entry; + child_entry = 0; + } + } + } + + else { + /* + * No more children in this object (Acpi_ns_get_next_object + * failed), go back upwards in the namespace tree to + * the object's parent. + */ + level--; + child_entry = parent_entry; + parent_entry = acpi_ns_get_parent_entry (parent_entry); + } + } + + /* Complete walk, not terminated by user function */ + return (AE_OK); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/namespace/nsxfname.c linux/drivers/acpi/namespace/nsxfname.c --- v2.4.0-test2/linux/drivers/acpi/namespace/nsxfname.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/namespace/nsxfname.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,372 @@ +/****************************************************************************** + * + * Module Name: nsxfname - Public interfaces to the ACPI subsystem + * ACPI Namespace oriented interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" +#include "namesp.h" +#include "amlcode.h" +#include "parser.h" +#include "dispatch.h" +#include "events.h" + + +#define _COMPONENT NAMESPACE + MODULE_NAME ("nsxfname"); + + +/****************************************************************************** + * + * FUNCTION: Acpi_load_namespace + * + * PARAMETERS: Display_aml_during_load + * + * RETURN: Status + * + * DESCRIPTION: Load the name space from what ever is pointed to by DSDT. + * (DSDT points to either the BIOS or a buffer.) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_load_namespace ( + void) +{ + ACPI_STATUS status; + + + /* There must be at least a DSDT installed */ + + if (acpi_gbl_DSDT == NULL) { + return (AE_NO_ACPI_TABLES); + } + + + /* Init the hardware */ + + /* + * TBD: [Restructure] Should this should be moved elsewhere, + * like Acpi_enable! ?? + */ + + /* we need to be able to call this interface repeatedly! */ + /* Does H/W require init before loading the namespace? */ + + status = acpi_cm_hardware_initialize (); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Load the namespace. The DSDT is required, + * but the SSDT and PSDT tables are optional. + */ + + status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Ignore exceptions from these */ + + acpi_ns_load_table_by_type (ACPI_TABLE_SSDT); + acpi_ns_load_table_by_type (ACPI_TABLE_PSDT); + + + /* + * Install the default Op_region handlers, ignore the return + * code right now. + */ + + acpi_ev_install_default_address_space_handlers (); + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_get_handle + * + * PARAMETERS: Parent - Object to search under (search scope). + * Path_name - Pointer to an asciiz string containing the + * name + * Ret_handle - Where the return handle is placed + * + * RETURN: Status + * + * DESCRIPTION: This routine will search for a caller specified name in the + * name space. The caller can restrict the search region by + * specifying a non NULL parent. The parent value is itself a + * namespace handle. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_handle ( + ACPI_HANDLE parent, + ACPI_STRING pathname, + ACPI_HANDLE *ret_handle) +{ + ACPI_STATUS status; + ACPI_NAMED_OBJECT *this_entry; + ACPI_NAME_TABLE *scope = NULL; + + + if (!ret_handle || !pathname) { + return AE_BAD_PARAMETER; + } + + if (parent) { + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + this_entry = acpi_ns_convert_handle_to_entry (parent); + if (!this_entry) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return AE_BAD_PARAMETER; + } + + scope = this_entry->child_table; + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + } + + /* Special case for root, since we can't search for it */ + /* TBD: [Investigate] Check for both forward and backslash?? */ + + if (STRCMP (pathname, NS_ROOT_PATH) == 0) { + *ret_handle = acpi_ns_convert_entry_to_handle (acpi_gbl_root_object); + return AE_OK; + } + + /* + * Find the Nte and convert to the user format + */ + this_entry = NULL; + status = acpi_ns_get_named_object (pathname, scope, &this_entry); + + *ret_handle = acpi_ns_convert_entry_to_handle (this_entry); + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_get_pathname + * + * PARAMETERS: Handle - Handle to be converted to a pathname + * Name_type - Full pathname or single segment + * Ret_path_ptr - Buffer for returned path + * + * RETURN: Pointer to a string containing the fully qualified Name. + * + * DESCRIPTION: This routine returns the fully qualified name associated with + * the Handle parameter. This and the Acpi_pathname_to_handle are + * complementary functions. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_name ( + ACPI_HANDLE handle, + u32 name_type, + ACPI_BUFFER *ret_path_ptr) +{ + ACPI_STATUS status; + ACPI_NAMED_OBJECT *obj_entry; + + + /* Buffer pointer must be valid always */ + + if (!ret_path_ptr || (name_type > ACPI_NAME_TYPE_MAX)) { + return AE_BAD_PARAMETER; + } + + /* Allow length to be zero and ignore the pointer */ + + if ((ret_path_ptr->length) && + (!ret_path_ptr->pointer)) + { + return AE_BAD_PARAMETER; + } + + if (name_type == ACPI_FULL_PATHNAME) { + /* Get the full pathname (From the namespace root) */ + + status = acpi_ns_handle_to_pathname (handle, &ret_path_ptr->length, + ret_path_ptr->pointer); + return status; + } + + /* + * Wants the single segment ACPI name. + * Validate handle and convert to an NTE + */ + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + obj_entry = acpi_ns_convert_handle_to_entry (handle); + if (!obj_entry) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Check if name will fit in buffer */ + + if (ret_path_ptr->length < PATH_SEGMENT_LENGTH) { + ret_path_ptr->length = PATH_SEGMENT_LENGTH; + status = AE_BUFFER_OVERFLOW; + goto unlock_and_exit; + } + + /* Just copy the ACPI name from the NTE and zero terminate it */ + + STRNCPY (ret_path_ptr->pointer, (char *) &obj_entry->name, + ACPI_NAME_SIZE); + ((char *) ret_path_ptr->pointer) [ACPI_NAME_SIZE] = 0; + status = AE_OK; + + +unlock_and_exit: + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return status; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_get_object_info + * + * PARAMETERS: Handle - Object Handle + * Info - Where the info is returned + * + * RETURN: Status + * + * DESCRIPTION: Returns information about an object as gleaned from running + * several standard control methods. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_object_info ( + ACPI_HANDLE device, + ACPI_DEVICE_INFO *info) +{ + DEVICE_ID hid; + DEVICE_ID uid; + ACPI_STATUS status; + u32 device_status = 0; + u32 address = 0; + ACPI_NAMED_OBJECT *device_entry; + + + /* Parameter validation */ + + if (!device || !info) { + return AE_BAD_PARAMETER; + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + device_entry = acpi_ns_convert_handle_to_entry (device); + if (!device_entry) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return AE_BAD_PARAMETER; + } + + info->type = device_entry->type; + info->name = device_entry->name; + info->parent = + acpi_ns_convert_entry_to_handle (acpi_ns_get_parent_entry (device_entry)); + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + /* + * If not a device, we are all done. + */ + if (info->type != ACPI_TYPE_DEVICE) { + return AE_OK; + } + + + /* Get extra info for ACPI devices */ + + info->valid = 0; + + /* Execute the _HID method and save the result */ + + status = acpi_cm_execute_HID (device_entry, &hid); + if (ACPI_SUCCESS (status)) { + if (hid.type == STRING_PTR_DEVICE_ID) { + STRCPY (info->hardware_id, hid.data.string_ptr); + } + else { + STRCPY (info->hardware_id, hid.data.buffer); + } + + info->valid |= ACPI_VALID_HID; + } + + /* Execute the _UID method and save the result */ + + status = acpi_cm_execute_UID (device_entry, &uid); + if (ACPI_SUCCESS (status)) { + if (hid.type == STRING_PTR_DEVICE_ID) { + STRCPY (info->unique_id, uid.data.string_ptr); + } + else { + STRCPY (info->unique_id, uid.data.buffer); + } + + info->valid |= ACPI_VALID_UID; + } + + /* + * Execute the _STA method and save the result + * _STA is not always present + */ + + status = acpi_cm_execute_STA (device_entry, &device_status); + if (ACPI_SUCCESS (status)) { + info->current_status = device_status; + info->valid |= ACPI_VALID_STA; + } + + /* + * Execute the _ADR method and save result if successful + * _ADR is not always present + */ + + status = acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR, + device_entry, &address); + + if (ACPI_SUCCESS (status)) { + info->address = address; + info->valid |= ACPI_VALID_ADR; + } + + return AE_OK; +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/namespace/nsxfobj.c linux/drivers/acpi/namespace/nsxfobj.c --- v2.4.0-test2/linux/drivers/acpi/namespace/nsxfobj.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/namespace/nsxfobj.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,554 @@ + +/****************************************************************************** + * + * Module Name: nsxfobj - Public interfaces to the ACPI subsystem + * ACPI Object oriented interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" +#include "namesp.h" + + +#define _COMPONENT NAMESPACE + MODULE_NAME ("nsxfobj"); + + +/**************************************************************************** + * + * FUNCTION: Acpi_evaluate_object + * + * PARAMETERS: Handle - Object handle (optional) + * *Pathname - Object pathname (optional) + * **Params - List of parameters to pass to + * method, terminated by NULL. + * Params itself may be NULL + * if no parameters are being + * passed. + * *Return_object - Where to put method's return value (if + * any). If NULL, no value is returned. + * + * RETURN: Status + * + * DESCRIPTION: Find and evaluate the given object, passing the given + * parameters if necessary. One of "Handle" or "Pathname" must + * be valid (non-null) + * + ****************************************************************************/ + +ACPI_STATUS +acpi_evaluate_object ( + ACPI_HANDLE handle, + ACPI_STRING pathname, + ACPI_OBJECT_LIST *param_objects, + ACPI_BUFFER *return_buffer) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL **param_ptr = NULL; + ACPI_OBJECT_INTERNAL *return_obj = NULL; + ACPI_OBJECT_INTERNAL *object_ptr = NULL; + u32 buffer_space_needed; + u32 user_buffer_length; + u32 count; + u32 i; + u32 param_length; + u32 object_length; + + + /* + * If there are parameters to be passed to the object + * (which must be a control method), the external objects + * must be converted to internal objects + */ + + if (param_objects && param_objects->count) { + /* + * Allocate a new parameter block for the internal objects + * Add 1 to count to allow for null terminated internal list + * TBD: [Restructure] merge into single allocation! + */ + + count = param_objects->count; + param_length = (count + 1) * sizeof (void *); + object_length = count * sizeof (ACPI_OBJECT_INTERNAL); + + param_ptr = acpi_cm_callocate (param_length + /* Parameter List part */ + object_length); /* Actual objects */ + if (!param_ptr) { + return (AE_NO_MEMORY); + } + + object_ptr = (ACPI_OBJECT_INTERNAL *) ((u8 *) param_ptr + + param_length); + + /* + * Init the param array of pointers and NULL terminate + * the list + */ + + for (i = 0; i < count; i++) { + param_ptr[i] = &object_ptr[i]; + acpi_cm_init_static_object (&object_ptr[i]); + } + param_ptr[count] = NULL; + + /* + * Convert each external object in the list to an + * internal object + */ + for (i = 0; i < count; i++) { + status = + acpi_cm_build_internal_object (¶m_objects->pointer[i], + param_ptr[i]); + + if (ACPI_FAILURE (status)) { + acpi_cm_delete_internal_object_list (param_ptr); + return (status); + } + } + } + + + /* + * Three major cases: + * 1) Fully qualified pathname + * 2) No handle, not fully qualified pathname (error) + * 3) Valid handle + */ + + if ((pathname) && + (acpi_ns_valid_root_prefix (pathname[0]))) + { + /* + * The path is fully qualified, just evaluate by name + */ + status = acpi_ns_evaluate_by_name (pathname, param_ptr, &return_obj); + } + + else if (!handle) { + /* + * A handle is optional iff a fully qualified pathname + * is specified. Since we've already handled fully + * qualified names above, this is an error + */ + + + + status = AE_BAD_PARAMETER; + } + + else { + /* + * We get here if we have a handle -- and if we have a + * pathname it is relative. The handle will be validated + * in the lower procedures + */ + + if (!pathname) { + /* + * The null pathname case means the handle is for + * the actual object to be evaluated + */ + status = acpi_ns_evaluate_by_handle (handle, + param_ptr, + &return_obj); + } + + else { + /* + * Both a Handle and a relative Pathname + */ + status = acpi_ns_evaluate_relative (handle, pathname, + param_ptr, + &return_obj); + } + } + + + /* + * If we are expecting a return value, and all went well above, + * copy the return value to an external object. + */ + + if (return_buffer) { + user_buffer_length = return_buffer->length; + return_buffer->length = 0; + + if (return_obj) { + if (VALID_DESCRIPTOR_TYPE (return_obj, + ACPI_DESC_TYPE_NAMED)) + { + /* + * If we got an NTE as a return object, + * this means the object we are evaluating + * has nothing interesting to return (such + * as a mutex, etc.) We return an error + * because these types are essentially + * unsupported by this interface. We + * don't check up front because this makes + * it easier to add support for various + * types at a later date if necessary. + */ + status = AE_TYPE; + return_obj = NULL; /* No need to delete an NTE */ + } + + if (ACPI_SUCCESS (status)) { + /* + * Find out how large a buffer is needed + * to contain the returned object + */ + status = acpi_cm_get_object_size (return_obj, + &buffer_space_needed); + if (ACPI_SUCCESS (status)) { + /* + * Check if there is enough room in the + * caller's buffer + */ + + if (user_buffer_length < buffer_space_needed) { + /* + * Caller's buffer is too small, can't + * give him partial results fail the call + * but return the buffer size needed + */ + + return_buffer->length = buffer_space_needed; + status = AE_BUFFER_OVERFLOW; + } + + else { + /* + * We have enough space for the object, build it + */ + status = + acpi_cm_build_external_object (return_obj, + return_buffer); + return_buffer->length = buffer_space_needed; + } + } + } + } + } + + + /* Delete the return and parameter objects */ + + if (return_obj) { + /* + * Delete the internal return object. (Or at least + * decrement the reference count by one) + */ + acpi_cm_remove_reference (return_obj); + } + + /* + * Free the input parameter list (if we created one), + */ + + if (param_ptr) { + /* Free the allocated parameter block */ + + acpi_cm_delete_internal_object_list (param_ptr); + } + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_get_next_object + * + * PARAMETERS: Type - Type of object to be searched for + * Parent - Parent object whose children we are getting + * Last_child - Previous child that was found. + * The NEXT child will be returned + * Ret_handle - Where handle to the next object is placed + * + * RETURN: Status + * + * DESCRIPTION: Return the next peer object within the namespace. If Handle is + * valid, Scope is ignored. Otherwise, the first object within + * Scope is returned. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_next_object ( + ACPI_OBJECT_TYPE type, + ACPI_HANDLE parent, + ACPI_HANDLE child, + ACPI_HANDLE *ret_handle) +{ + ACPI_STATUS status = AE_OK; + ACPI_NAMED_OBJECT *entry; + ACPI_NAMED_OBJECT *parent_entry = NULL; + ACPI_NAMED_OBJECT *child_entry = NULL; + + + /* Parameter validation */ + + if (type > ACPI_TYPE_MAX) { + return AE_BAD_PARAMETER; + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* If null handle, use the parent */ + + if (!child) { + /* Start search at the beginning of the specified scope */ + + parent_entry = acpi_ns_convert_handle_to_entry (parent); + if (!parent_entry) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + } + + /* Non-null handle, ignore the parent */ + + else { + /* Convert and validate the handle */ + + child_entry = acpi_ns_convert_handle_to_entry (child); + if (!child_entry) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + } + + + /* Internal function does the real work */ + + entry = acpi_ns_get_next_object ((OBJECT_TYPE_INTERNAL) type, + parent_entry, child_entry); + if (!entry) { + status = AE_NOT_FOUND; + goto unlock_and_exit; + } + + if (ret_handle) { + *ret_handle = acpi_ns_convert_entry_to_handle (entry); + } + + +unlock_and_exit: + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return status; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_get_type + * + * PARAMETERS: Handle - Handle of object whose type is desired + * *Ret_type - Where the type will be placed + * + * RETURN: Status + * + * DESCRIPTION: This routine returns the type associatd with a particular handle + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_type ( + ACPI_HANDLE handle, + ACPI_OBJECT_TYPE *ret_type) +{ + ACPI_NAMED_OBJECT *object; + + + /* Parameter Validation */ + + if (!ret_type) { + return AE_BAD_PARAMETER; + } + + /* + * Special case for the predefined Root Object + * (return type ANY) + */ + + if (handle == ACPI_ROOT_OBJECT) { + *ret_type = ACPI_TYPE_ANY; + return AE_OK; + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* Convert and validate the handle */ + + object = acpi_ns_convert_handle_to_entry (handle); + if (!object) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return AE_BAD_PARAMETER; + } + + *ret_type = object->type; + + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return AE_OK; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_get_parent + * + * PARAMETERS: Handle - Handle of object whose parent is desired + * Ret_handle - Where the parent handle will be placed + * + * RETURN: Status + * + * DESCRIPTION: Returns a handle to the parent of the object represented by + * Handle. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_parent ( + ACPI_HANDLE handle, + ACPI_HANDLE *ret_handle) +{ + ACPI_NAMED_OBJECT *object; + ACPI_STATUS status = AE_OK; + + + /* No trace macro, too verbose */ + + + if (!ret_handle) { + return AE_BAD_PARAMETER; + } + + /* Special case for the predefined Root Object (no parent) */ + + if (handle == ACPI_ROOT_OBJECT) { + return AE_NULL_ENTRY; + } + + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* Convert and validate the handle */ + + object = acpi_ns_convert_handle_to_entry (handle); + if (!object) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + + /* Get the parent entry */ + + *ret_handle = + acpi_ns_convert_entry_to_handle (acpi_ns_get_parent_entry (object)); + + /* Return exeption if parent is null */ + + if (!acpi_ns_get_parent_entry (object)) { + status = AE_NULL_ENTRY; + } + + +unlock_and_exit: + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return AE_OK; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_walk_namespace + * + * PARAMETERS: Type - ACPI_OBJECT_TYPE to search for + * Start_object - Handle in namespace where search begins + * Max_depth - Depth to which search is to reach + * User_function - Called when an object of "Type" is found + * Context - Passed to user function + * + * RETURNS Return value from the User_function if terminated early. + * Otherwise, returns NULL. + * + * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, + * starting (and ending) at the object specified by Start_handle. + * The User_function is called whenever an object that matches + * the type parameter is found. If the user function returns + * a non-zero value, the search is terminated immediately and this + * value is returned to the caller. + * + * The point of this procedure is to provide a generic namespace + * walk routine that can be called from multiple places to + * provide multiple services; the User Function can be tailored + * to each task, whether it is a print function, a compare + * function, etc. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_walk_namespace ( + ACPI_OBJECT_TYPE type, + ACPI_HANDLE start_object, + u32 max_depth, + WALK_CALLBACK user_function, + void *context, + void **return_value) +{ + ACPI_STATUS status; + + + /* Parameter validation */ + + if ((type > ACPI_TYPE_MAX) || + (!max_depth) || + (!user_function)) + { + return (AE_BAD_PARAMETER); + } + + /* + * Lock the namespace around the walk. + * The namespace will be unlocked/locked around each call + * to the user function - since this function + * must be allowed to make Acpi calls itself. + */ + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ns_walk_namespace ((OBJECT_TYPE_INTERNAL) type, + start_object, max_depth, + NS_WALK_UNLOCK, + user_function, context, + return_value); + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/osd.c linux/drivers/acpi/osd.c --- v2.4.0-test2/linux/drivers/acpi/osd.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/osd.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,1319 @@ +/* + * osd.c - Linux specific code + * + * Copyright (C) 2000 Andrew Henroid + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "acpi.h" + +#define ACPI_MAX_THROTTLE 10 +#define ACPI_INVALID ~0UL +#define ACPI_INFINITE ~0UL + +static struct acpi_facp *acpi_facp = NULL; + +static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED; +static volatile u32 acpi_event_status = 0; +static volatile acpi_sstate_t acpi_event_state = ACPI_S0; +static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait); +static int acpi_irq_irq = 0; +static OSD_HANDLER acpi_irq_handler = NULL; +static void *acpi_irq_context = NULL; + +static unsigned long acpi_pblk = ACPI_INVALID; +static unsigned long acpi_c2_exit_latency = ACPI_INFINITE; +static unsigned long acpi_c3_exit_latency = ACPI_INFINITE; +static unsigned long acpi_c2_enter_latency = ACPI_INFINITE; +static unsigned long acpi_c3_enter_latency = ACPI_INFINITE; +static int acpi_c2_tested = 0; +static int acpi_c3_tested = 0; + +struct acpi_intrp_entry +{ + int priority; + OSD_EXECUTION_CALLBACK callback; + void *context; + struct list_head list; +}; + +struct acpi_enter_sx_ctx +{ + wait_queue_head_t wait; + int state; +}; + +static volatile int acpi_intrp_pid = -1; +static DECLARE_WAIT_QUEUE_HEAD(acpi_intrp_wait); +static LIST_HEAD(acpi_intrp_exec); +static spinlock_t acpi_intrp_exec_lock = SPIN_LOCK_UNLOCKED; + +#define ACPI_SLP_TYP(typa, typb) (((int)(typa) << 8) | (int)(typb)) +#define ACPI_SLP_TYPA(value) \ + ((((value) >> 8) << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK) +#define ACPI_SLP_TYPB(value) \ + ((((value) & 0xff) << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK) + +static volatile acpi_sstate_t acpi_sleep_state = ACPI_S0; +static unsigned long acpi_slptyp[ACPI_S5 + 1] = {ACPI_INVALID,}; + +static struct ctl_table_header *acpi_sysctl = NULL; + +static int acpi_do_ulong(ctl_table * ctl, + int write, + struct file *file, + void *buffer, + size_t * len); +static int acpi_do_sleep(ctl_table * ctl, + int write, + struct file *file, + void *buffer, + size_t * len); +static int acpi_do_event(ctl_table * ctl, + int write, + struct file *file, + void *buffer, + size_t * len); + +static struct ctl_table acpi_table[] = +{ + {ACPI_P_LVL2_LAT, "c2_exit_latency", + &acpi_c2_exit_latency, sizeof(acpi_c2_exit_latency), + 0644, NULL, &acpi_do_ulong}, + + {ACPI_ENTER_LVL2_LAT, "c2_enter_latency", + &acpi_c2_enter_latency, sizeof(acpi_c2_enter_latency), + 0644, NULL, &acpi_do_ulong}, + + {ACPI_P_LVL3_LAT, "c3_exit_latency", + &acpi_c3_exit_latency, sizeof(acpi_c3_exit_latency), + 0644, NULL, &acpi_do_ulong}, + + {ACPI_ENTER_LVL3_LAT, "c3_enter_latency", + &acpi_c3_enter_latency, sizeof(acpi_c3_enter_latency), + 0644, NULL, &acpi_do_ulong}, + + {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep}, + + {ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event}, + + {0} +}; + +static struct ctl_table acpi_dir_table[] = +{ + {CTL_ACPI, "acpi", NULL, 0, 0555, acpi_table}, + {0} +}; + +static u32 FASTCALL(acpi_read_pm1_control(struct acpi_facp *)); +static u32 FASTCALL(acpi_read_pm1_status(struct acpi_facp *)); +static void FASTCALL(acpi_write_pm1_control(struct acpi_facp *, u32)); +static void FASTCALL(acpi_write_pm1_status(struct acpi_facp *, u32)); + +/* + * Get the value of the PM1 control register (ACPI_SCI_EN, ...) + */ +static u32 +acpi_read_pm1_control(struct acpi_facp *facp) +{ + u32 value = 0; + if (facp->pm1a_cnt) + value = inw(facp->pm1a_cnt); + if (facp->pm1b_cnt) + value |= inw(facp->pm1b_cnt); + return value; +} + +/* + * Set the value of the PM1 control register (ACPI_BM_RLD, ...) + */ +static void +acpi_write_pm1_control(struct acpi_facp *facp, u32 value) +{ + if (facp->pm1a_cnt) + outw(value, facp->pm1a_cnt); + if (facp->pm1b_cnt) + outw(value, facp->pm1b_cnt); +} + +/* + * Get the value of the fixed event status register + */ +static u32 +acpi_read_pm1_status(struct acpi_facp *facp) +{ + u32 value = 0; + if (facp->pm1a_evt) + value = inw(facp->pm1a_evt); + if (facp->pm1b_evt) + value |= inw(facp->pm1b_evt); + return value; +} + +/* + * Set the value of the fixed event status register (clear events) + */ +static void +acpi_write_pm1_status(struct acpi_facp *facp, u32 value) +{ + if (facp->pm1a_evt) + outw(value, facp->pm1a_evt); + if (facp->pm1b_evt) + outw(value, facp->pm1b_evt); +} + +/* + * Examine/modify value + */ +static int +acpi_do_ulong(ctl_table * ctl, + int write, + struct file *file, + void *buffer, + size_t * len) +{ + char str[2 * sizeof(unsigned long) + 4], *strend; + unsigned long val; + int size; + + if (!write) { + if (file->f_pos) { + *len = 0; + return 0; + } + + val = *(unsigned long *) ctl->data; + size = sprintf(str, "0x%08lx\n", val); + if (*len >= size) { + copy_to_user(buffer, str, size); + *len = size; + } + else + *len = 0; + } + else { + size = sizeof(str) - 1; + if (size > *len) + size = *len; + copy_from_user(str, buffer, size); + str[size] = '\0'; + val = simple_strtoul(str, &strend, 0); + if (strend == str) + return -EINVAL; + *(unsigned long *) ctl->data = val; + } + + file->f_pos += *len; + return 0; +} + +/* + * Handle ACPI event + */ +u32 +acpi_event(void *context) +{ + unsigned long flags; + int event = (int) context; + int mask = 0; + + switch (event) { + case ACPI_EVENT_POWER_BUTTON: + mask = ACPI_PWRBTN; + break; + case ACPI_EVENT_SLEEP_BUTTON: + mask = ACPI_SLPBTN; + break; + } + + if (mask) { + // notify process waiting on /dev/acpi + spin_lock_irqsave(&acpi_event_lock, flags); + acpi_event_status |= mask; + spin_unlock_irqrestore(&acpi_event_lock, flags); + acpi_event_state = acpi_sleep_state; + wake_up_interruptible(&acpi_event_wait); + } + + return AE_OK; +} + +/* + * Wait for next event + */ +int +acpi_do_event(ctl_table * ctl, + int write, + struct file *file, + void *buffer, + size_t * len) +{ + u32 event_status = 0; + acpi_sstate_t event_state = 0; + char str[27]; + int size; + + if (write) + return -EPERM; + if (*len < sizeof(str)) { + *len = 0; + return 0; + } + + for (;;) { + unsigned long flags; + + // we need an atomic exchange here + spin_lock_irqsave(&acpi_event_lock, flags); + event_status = acpi_event_status; + acpi_event_status = 0; + spin_unlock_irqrestore(&acpi_event_lock, flags); + event_state = acpi_event_state; + + if (event_status) + break; + + // wait for an event to arrive + interruptible_sleep_on(&acpi_event_wait); + if (signal_pending(current)) + return -ERESTARTSYS; + } + + size = sprintf(str, + "0x%08x 0x%08x 0x%01x\n", + event_status, + 0, + event_state); + copy_to_user(buffer, str, size); + *len = size; + file->f_pos += size; + + return 0; +} + +/* + * Enter system sleep state + */ +static void +acpi_enter_sx(void *context) +{ + struct acpi_enter_sx_ctx *ctx = (struct acpi_enter_sx_ctx*) context; + struct acpi_facp *facp = acpi_facp; + ACPI_OBJECT_LIST arg_list; + ACPI_OBJECT arg; + u16 value; + + /* + * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. + */ + + // run the _PTS method + memset(&arg_list, 0, sizeof(arg_list)); + arg_list.count = 1; + arg_list.pointer = &arg; + + memset(&arg, 0, sizeof(arg)); + arg.type = ACPI_TYPE_NUMBER; + arg.number.value = ctx->state; + + acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL); + + // clear wake status + acpi_write_pm1_status(facp, ACPI_WAK); + + acpi_sleep_state = ctx->state; + + // set ACPI_SLP_TYPA/b and ACPI_SLP_EN + __cli(); + if (facp->pm1a_cnt) { + value = inw(facp->pm1a_cnt) & ~ACPI_SLP_TYP_MASK; + value |= (ACPI_SLP_TYPA(acpi_slptyp[ctx->state]) + | ACPI_SLP_EN); + outw(value, facp->pm1a_cnt); + } + if (facp->pm1b_cnt) { + value = inw(facp->pm1b_cnt) & ~ACPI_SLP_TYP_MASK; + value |= (ACPI_SLP_TYPB(acpi_slptyp[ctx->state]) + | ACPI_SLP_EN); + outw(value, facp->pm1b_cnt); + } + __sti(); + + if (ctx->state != ACPI_S1) { + printk(KERN_ERR "ACPI: S%d failed\n", ctx->state); + goto out; + } + + // wait until S1 is entered + while (!(acpi_read_pm1_status(facp) & ACPI_WAK)) + safe_halt(); + + // run the _WAK method + memset(&arg_list, 0, sizeof(arg_list)); + arg_list.count = 1; + arg_list.pointer = &arg; + + memset(&arg, 0, sizeof(arg)); + arg.type = ACPI_TYPE_NUMBER; + arg.number.value = ctx->state; + + acpi_evaluate_object(NULL, "\\_WAK", &arg_list, NULL); + + out: + acpi_sleep_state = ACPI_S0; + + if (waitqueue_active(&ctx->wait)) + wake_up_interruptible(&ctx->wait); +} + +/* + * Enter system sleep state and wait for completion + */ +static int +acpi_enter_sx_and_wait(acpi_sstate_t state) +{ + struct acpi_enter_sx_ctx ctx; + + if (!acpi_facp + || acpi_facp->hdr.signature != ACPI_FACP_SIG + || acpi_slptyp[state] == ACPI_INVALID) + return -EINVAL; + + init_waitqueue_head(&ctx.wait); + ctx.state = state; + + if (acpi_os_queue_for_execution(0, acpi_enter_sx, &ctx)) + return -1; + + interruptible_sleep_on(&ctx.wait); + if (signal_pending(current)) + return -ERESTARTSYS; + + return 0; +} + +/* + * Enter system sleep state + */ +static int +acpi_do_sleep(ctl_table * ctl, + int write, + struct file *file, + void *buffer, + size_t * len) +{ + if (!write) { + if (file->f_pos) { + *len = 0; + return 0; + } + } + else { +#ifdef CONFIG_ACPI_S1_SLEEP + int status = acpi_enter_sx_and_wait(ACPI_S1); + if (status) + return status; +#endif + } + file->f_pos += *len; + return 0; +} + +/* + * Clear busmaster activity flag + */ +static inline void +acpi_clear_bm_activity(struct acpi_facp *facp) +{ + acpi_write_pm1_status(facp, ACPI_BM); +} + +/* + * Returns 1 if there has been busmaster activity + */ +static inline int +acpi_bm_activity(struct acpi_facp *facp) +{ + return acpi_read_pm1_status(facp) & ACPI_BM; +} + +/* + * Set system to sleep through busmaster requests + */ +static void +acpi_sleep_on_busmaster(struct acpi_facp *facp) +{ + u32 pm1_cntr = acpi_read_pm1_control(facp); + if (pm1_cntr & ACPI_BM_RLD) { + pm1_cntr &= ~ACPI_BM_RLD; + acpi_write_pm1_control(facp, pm1_cntr); + } +} + +/* + * Set system to wake on busmaster requests + */ +static void +acpi_wake_on_busmaster(struct acpi_facp *facp) +{ + u32 pm1_cntr = acpi_read_pm1_control(facp); + if (!(pm1_cntr & ACPI_BM_RLD)) { + pm1_cntr |= ACPI_BM_RLD; + acpi_write_pm1_control(facp, pm1_cntr); + } + acpi_clear_bm_activity(facp); +} + +/* The ACPI timer is just the low 24 bits */ +#define TIME_BEGIN(tmr) inl(tmr) +#define TIME_END(tmr, begin) ((inl(tmr) - (begin)) & 0x00ffffff) + +/* + * Idle loop (uniprocessor only) + */ +void +acpi_idle(void) +{ + static int sleep_level = 1; + struct acpi_facp *facp = acpi_facp; + + if (!facp + || facp->hdr.signature != ACPI_FACP_SIG + || !facp->pm_tmr + || !acpi_pblk) + goto not_initialized; + + /* + * start from the previous sleep level.. + */ + if (sleep_level == 1) + goto sleep1; + if (sleep_level == 2) + goto sleep2; + sleep3: + sleep_level = 3; + if (!acpi_c3_tested) { + printk(KERN_DEBUG "ACPI C3 works\n"); + acpi_c3_tested = 1; + } + acpi_wake_on_busmaster(facp); + if (facp->pm2_cnt) + goto sleep3_with_arbiter; + + for (;;) { + unsigned long time; + unsigned int pm_tmr = facp->pm_tmr; + + __cli(); + if (current->need_resched) + goto out; + if (acpi_bm_activity(facp)) + goto sleep2; + + time = TIME_BEGIN(pm_tmr); + inb(acpi_pblk + ACPI_P_LVL3); + /* Dummy read, force synchronization with the PMU */ + inl(pm_tmr); + time = TIME_END(pm_tmr, time); + + __sti(); + if (time < acpi_c3_exit_latency) + goto sleep2; + } + + sleep3_with_arbiter: + for (;;) { + unsigned long time; + u8 arbiter; + unsigned int pm2_cntr = facp->pm2_cnt; + unsigned int pm_tmr = facp->pm_tmr; + + __cli(); + if (current->need_resched) + goto out; + if (acpi_bm_activity(facp)) + goto sleep2; + + time = TIME_BEGIN(pm_tmr); + arbiter = inb(pm2_cntr) & ~ACPI_ARB_DIS; + /* Disable arbiter, park on CPU */ + outb(arbiter | ACPI_ARB_DIS, pm2_cntr); + inb(acpi_pblk + ACPI_P_LVL3); + /* Dummy read, force synchronization with the PMU */ + inl(pm_tmr); + time = TIME_END(pm_tmr, time); + /* Enable arbiter again.. */ + outb(arbiter, pm2_cntr); + + __sti(); + if (time < acpi_c3_exit_latency) + goto sleep2; + } + + sleep2: + sleep_level = 2; + if (!acpi_c2_tested) { + printk(KERN_DEBUG "ACPI C2 works\n"); + acpi_c2_tested = 1; + } + acpi_wake_on_busmaster(facp); /* Required to track BM activity.. */ + for (;;) { + unsigned long time; + unsigned int pm_tmr = facp->pm_tmr; + + __cli(); + if (current->need_resched) + goto out; + + time = TIME_BEGIN(pm_tmr); + inb(acpi_pblk + ACPI_P_LVL2); + /* Dummy read, force synchronization with the PMU */ + inl(pm_tmr); + time = TIME_END(pm_tmr, time); + + __sti(); + if (time < acpi_c2_exit_latency) + goto sleep1; + if (acpi_bm_activity(facp)) { + acpi_clear_bm_activity(facp); + continue; + } + if (time > acpi_c3_enter_latency) + goto sleep3; + } + + sleep1: + sleep_level = 1; + acpi_sleep_on_busmaster(facp); + for (;;) { + unsigned long time; + unsigned int pm_tmr = facp->pm_tmr; + + __cli(); + if (current->need_resched) + goto out; + time = TIME_BEGIN(pm_tmr); + safe_halt(); + time = TIME_END(pm_tmr, time); + if (time > acpi_c2_enter_latency) + goto sleep2; + } + + not_initialized: + for (;;) { + __cli(); + if (current->need_resched) + goto out; + safe_halt(); + } + + out: + __sti(); +} + +/* + * Enter soft-off (S5) + */ +static void +acpi_power_off(void) +{ + struct acpi_enter_sx_ctx ctx; + + if (!acpi_facp + || acpi_facp->hdr.signature != ACPI_FACP_SIG + || acpi_slptyp[ACPI_S5] == ACPI_INVALID) + return; + + init_waitqueue_head(&ctx.wait); + ctx.state = ACPI_S5; + acpi_enter_sx(&ctx); +} + +/* + * Get processor information + */ +static ACPI_STATUS +acpi_get_cpu_info(ACPI_HANDLE handle, u32 level, void *ctx, void **value) +{ + ACPI_OBJECT obj; + ACPI_CX_STATE lat[4]; + ACPI_CPU_THROTTLING_STATE throttle[ACPI_MAX_THROTTLE]; + ACPI_BUFFER buf; + int i, count; + + buf.length = sizeof(obj); + buf.pointer = &obj; + if (!ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buf))) + return AE_OK; + + printk(KERN_INFO "ACPI: PBLK %d @ 0x%04x:%d\n", + obj.processor.proc_id, + obj.processor.pblk_address, + obj.processor.pblk_length); + if (acpi_pblk != ACPI_INVALID + || !obj.processor.pblk_address + || obj.processor.pblk_length != 6) + return AE_OK; + + acpi_pblk = obj.processor.pblk_address; + + buf.length = sizeof(lat); + buf.pointer = lat; + if (!ACPI_SUCCESS(acpi_get_processor_cx_info(handle, &buf))) + return AE_OK; + + if (lat[2].latency < MAX_CX_STATE_LATENCY) { + printk(KERN_INFO "ACPI: C2 supported\n"); + acpi_c2_exit_latency = lat[2].latency; + } + if (lat[3].latency < MAX_CX_STATE_LATENCY) { + printk(KERN_INFO "ACPI: C3 supported\n"); + acpi_c3_exit_latency = lat[3].latency; + } + + memset(throttle, 0, sizeof(throttle)); + buf.length = sizeof(throttle); + buf.pointer = throttle; + + if (!ACPI_SUCCESS(acpi_get_processor_throttling_info(handle, &buf))) + return AE_OK; + + for (i = 0, count = 0; i < ACPI_MAX_THROTTLE; i++) { + if (throttle[i].percent_of_clock) + count++; + } + count--; + if (count > 0) + printk(KERN_INFO "ACPI: %d throttling states\n", count); + + return AE_OK; +} + +/* + * Fetch the FACP information + */ +static int +acpi_fetch_facp(void) +{ + ACPI_BUFFER buffer; + + buffer.pointer = acpi_facp; + buffer.length = sizeof(*acpi_facp); + if (!ACPI_SUCCESS(acpi_get_table(ACPI_TABLE_FACP, 1, &buffer))) { + printk(KERN_ERR "ACPI: no FACP\n"); + kfree(acpi_facp); + return -ENODEV; + } + + if (acpi_facp->p_lvl2_lat + && acpi_facp->p_lvl2_lat <= ACPI_MAX_P_LVL2_LAT) { + acpi_c2_exit_latency + = ACPI_uS_TO_TMR_TICKS(acpi_facp->p_lvl2_lat); + acpi_c2_enter_latency + = ACPI_uS_TO_TMR_TICKS(ACPI_TMR_HZ / 1000); + } + if (acpi_facp->p_lvl3_lat + && acpi_facp->p_lvl3_lat <= ACPI_MAX_P_LVL3_LAT) { + acpi_c3_exit_latency + = ACPI_uS_TO_TMR_TICKS(acpi_facp->p_lvl3_lat); + acpi_c3_enter_latency + = ACPI_uS_TO_TMR_TICKS(acpi_facp->p_lvl3_lat * 5); + } + + return 0; +} + +/* + * Execute callbacks (interpret methods) + */ +static void +acpi_intrp_run(void) +{ + for (;;) { + struct acpi_intrp_entry *entry; + unsigned long flags; + + interruptible_sleep_on(&acpi_intrp_wait); + if (signal_pending(current)) + return; + + for (;;) { + entry = NULL; + + spin_lock_irqsave(&acpi_intrp_exec_lock, flags); + if (!list_empty(&acpi_intrp_exec)) { + entry = list_entry(acpi_intrp_exec.next, + struct acpi_intrp_entry, + list); + list_del(&entry->list); + } + spin_unlock_irqrestore(&acpi_intrp_exec_lock, flags); + + if (!entry) + break; + + (*entry->callback)(entry->context); + + kfree(entry); + } + } +} + +/* + * Initialize and run interpreter within a kernel thread + */ +static int +acpi_intrp_thread(void *context) +{ + ACPI_STATUS status; + u8 sx, typa, typb; + + /* + * initialize interpreter + */ + exit_files(current); + daemonize(); + strcpy(current->comm, "acpi"); + + if (!ACPI_SUCCESS(acpi_initialize(NULL))) { + printk(KERN_ERR "ACPI: initialize failed\n"); + return -ENODEV; + } + + if (!ACPI_SUCCESS(acpi_load_firmware_tables())) { + printk(KERN_ERR "ACPI: table load failed\n"); + acpi_terminate(); + return -ENODEV; + } + + if (acpi_fetch_facp()) { + acpi_terminate(); + return -ENODEV; + } + + status = acpi_load_namespace(); + if (!ACPI_SUCCESS(status) && status != AE_CTRL_PENDING) { + printk(KERN_ERR "ACPI: namespace load failed\n"); + acpi_terminate(); + return -ENODEV; + } + + printk(KERN_INFO "ACPI: ACPI support found\n"); + + acpi_walk_namespace(ACPI_TYPE_PROCESSOR, + ACPI_ROOT_OBJECT, + ACPI_INT32_MAX, + acpi_get_cpu_info, + NULL, + NULL); + + for (sx = ACPI_S0; sx <= ACPI_S5; sx++) { + int ca_sx = (sx <= ACPI_S4) ? sx : (sx + 1); + if (ACPI_SUCCESS( + acpi_hw_obtain_sleep_type_register_data(ca_sx, + &typa, + &typb))) + acpi_slptyp[sx] = ACPI_SLP_TYP(typa, typb); + else + acpi_slptyp[sx] = ACPI_INVALID; + } + if (acpi_slptyp[ACPI_S1] != ACPI_INVALID) + printk(KERN_INFO "ACPI: S1 supported\n"); + if (acpi_slptyp[ACPI_S5] != ACPI_INVALID) + printk(KERN_INFO "ACPI: S5 supported\n"); + + if (!ACPI_SUCCESS(acpi_enable())) { + printk(KERN_ERR "ACPI: enable failed\n"); + acpi_terminate(); + return -ENODEV; + } + + if (!ACPI_SUCCESS(acpi_install_fixed_event_handler( + ACPI_EVENT_POWER_BUTTON, + acpi_event, + (void *) ACPI_EVENT_POWER_BUTTON))) { + printk(KERN_ERR "ACPI: power button enable failed\n"); + } + if (!ACPI_SUCCESS(acpi_install_fixed_event_handler( + ACPI_EVENT_SLEEP_BUTTON, + acpi_event, + (void *) ACPI_EVENT_SLEEP_BUTTON))) { + printk(KERN_ERR "ACPI: sleep button enable failed\n"); + } + +#ifdef CONFIG_SMP + if (smp_num_cpus == 1) + pm_idle = acpi_idle; +#else + pm_idle = acpi_idle; +#endif + pm_power_off = acpi_power_off; + + acpi_sysctl = register_sysctl_table(acpi_dir_table, 1); + + /* + * run interpreter + */ + acpi_intrp_run(); + + /* + * terminate interpreter + */ + unregister_sysctl_table(acpi_sysctl); + acpi_terminate(); + + acpi_intrp_pid = -1; + + return 0; +} + +/* + * Start the interpreter + */ +int __init +acpi_init(void) +{ + acpi_facp = kmalloc(sizeof(*acpi_facp), GFP_KERNEL); + if (!acpi_facp) + return -ENOMEM; + memset(acpi_facp, 0, sizeof(*acpi_facp)); + + acpi_intrp_pid = kernel_thread(acpi_intrp_thread, + NULL, + (CLONE_FS | CLONE_FILES + | CLONE_SIGHAND | SIGCHLD)); + return ((acpi_intrp_pid >= 0) ? 0:-ENODEV); +} + +/* + * Terminate the interpreter + */ +void __exit +acpi_exit(void) +{ + int count; + + if (!kill_proc(acpi_intrp_pid, SIGTERM, 1)) { + // wait until interpreter thread terminates (at most 5 seconds) + count = 5 * HZ; + while (acpi_intrp_pid >= 0 && --count) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + } + + // clean up after the interpreter + + if (acpi_irq_handler) { + acpi_os_remove_interrupt_handler(acpi_irq_irq, + acpi_irq_handler); + } + + if (pm_power_off == acpi_power_off) + pm_power_off = NULL; + if (pm_idle == acpi_idle) + pm_idle = NULL; + + kfree(acpi_facp); +} + +module_init(acpi_init); +module_exit(acpi_exit); + +/* + * OS-dependent functions + * + */ + +char * +strupr(char *str) +{ + char *s = str; + while (*s) { + *s = TOUPPER(*s); + s++; + } + return str; +} + +ACPI_STATUS +acpi_os_initialize(void) +{ + return AE_OK; +} + +ACPI_STATUS +acpi_os_terminate(void) +{ + return AE_OK; +} + +s32 +acpi_os_printf(const char *fmt,...) +{ + s32 size; + va_list args; + va_start(args, fmt); + size = acpi_os_vprintf(fmt, args); + va_end(args); + return size; +} + +s32 +acpi_os_vprintf(const char *fmt, va_list args) +{ + static char buffer[512]; + int size = vsprintf(buffer, fmt, args); + printk(KERN_DEBUG "%s", buffer); + return size; +} + +void * +acpi_os_allocate(u32 size) +{ + return kmalloc(size, GFP_KERNEL); +} + +void * +acpi_os_callocate(u32 size) +{ + void *ptr = acpi_os_allocate(size); + if (ptr) + memset(ptr, 0, size); + return ptr; +} + +void +acpi_os_free(void *ptr) +{ + kfree(ptr); +} + +ACPI_STATUS +acpi_os_map_memory(void *phys, u32 size, void **virt) +{ + if ((unsigned long) phys < virt_to_phys(high_memory)) { + *virt = phys_to_virt((unsigned long) phys); + return AE_OK; + } + + *virt = ioremap((unsigned long) phys, size); + if (!*virt) + return AE_ERROR; + + return AE_OK; +} + +void +acpi_os_unmap_memory(void *virt, u32 size) +{ + if (virt >= high_memory) + iounmap(virt); +} + +static void +acpi_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + (*acpi_irq_handler)(acpi_irq_context); +} + +ACPI_STATUS +acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context) +{ + acpi_irq_irq = irq; + acpi_irq_handler = handler; + acpi_irq_context = context; + if (request_irq(irq, + acpi_irq, + SA_INTERRUPT | SA_SHIRQ, + "acpi", + acpi_irq)) { + printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n", irq); + return AE_ERROR; + } + return AE_OK; +} + +ACPI_STATUS +acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler) +{ + if (acpi_irq_handler) { + free_irq(irq, acpi_irq); + acpi_irq_handler = NULL; + } + return AE_OK; +} + +/* + * Running in interpreter thread context, safe to sleep + */ + +void +acpi_os_sleep(u32 sec, u32 ms) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ * sec + (ms * HZ) / 1000); +} + +void +acpi_os_sleep_usec(u32 us) +{ + udelay(us); +} + +u8 +acpi_os_in8(ACPI_IO_ADDRESS port) +{ + return inb(port); +} + +u16 +acpi_os_in16(ACPI_IO_ADDRESS port) +{ + return inw(port); +} + +u32 +acpi_os_in32(ACPI_IO_ADDRESS port) +{ + return inl(port); +} + +void +acpi_os_out8(ACPI_IO_ADDRESS port, u8 val) +{ + outb(val, port); +} + +void +acpi_os_out16(ACPI_IO_ADDRESS port, u16 val) +{ + outw(val, port); +} + +void +acpi_os_out32(ACPI_IO_ADDRESS port, u32 val) +{ + outl(val, port); +} + +ACPI_STATUS +acpi_os_read_pci_cfg_byte( + u32 bus, + u32 func, + u32 addr, + u8 * val) +{ + int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); + if (!val || !dev || pci_read_config_byte(dev, addr, val)) + return AE_ERROR; + return AE_OK; +} + +ACPI_STATUS +acpi_os_read_pci_cfg_word( + u32 bus, + u32 func, + u32 addr, + u16 * val) +{ + int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); + if (!val || !dev || pci_read_config_word(dev, addr, val)) + return AE_ERROR; + return AE_OK; +} + +ACPI_STATUS +acpi_os_read_pci_cfg_dword( + u32 bus, + u32 func, + u32 addr, + u32 * val) +{ + int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); + if (!val || !dev || pci_read_config_dword(dev, addr, val)) + return AE_ERROR; + return AE_OK; +} + +ACPI_STATUS +acpi_os_write_pci_cfg_byte( + u32 bus, + u32 func, + u32 addr, + u8 val) +{ + int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); + if (!dev || pci_write_config_byte(dev, addr, val)) + return AE_ERROR; + return AE_OK; +} + +ACPI_STATUS +acpi_os_write_pci_cfg_word( + u32 bus, + u32 func, + u32 addr, + u16 val) +{ + int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); + if (!dev || pci_write_config_word(dev, addr, val)) + return AE_ERROR; + return AE_OK; +} + +ACPI_STATUS +acpi_os_write_pci_cfg_dword( + u32 bus, + u32 func, + u32 addr, + u32 val) +{ + int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); + if (!dev || pci_write_config_dword(dev, addr, val)) + return AE_ERROR; + return AE_OK; +} + +/* + * Queue for interpreter thread + */ + +ACPI_STATUS +acpi_os_queue_for_execution( + u32 priority, + OSD_EXECUTION_CALLBACK callback, + void *context) +{ + struct acpi_intrp_entry *entry; + unsigned long flags; + + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); + if (!entry) + return AE_ERROR; + + memset(entry, 0, sizeof(entry)); + entry->priority = priority; + entry->callback = callback; + entry->context = context; + INIT_LIST_HEAD(&entry->list); + + if (!waitqueue_active(&acpi_intrp_wait)) { + kfree(entry); + return AE_ERROR; + } + + spin_lock_irqsave(&acpi_intrp_exec_lock, flags); + list_add(&entry->list, &acpi_intrp_exec); + wake_up(&acpi_intrp_wait); + spin_unlock_irqrestore(&acpi_intrp_exec_lock, flags); + + return AE_OK; +} + +/* + * Semaphores are unused, interpreter access is single threaded + */ + +ACPI_STATUS +acpi_os_create_semaphore(u32 max_units, u32 init, ACPI_HANDLE * handle) +{ + *handle = (ACPI_HANDLE) 0; + return AE_OK; +} + +ACPI_STATUS +acpi_os_delete_semaphore(ACPI_HANDLE handle) +{ + return AE_OK; +} + +ACPI_STATUS +acpi_os_wait_semaphore(ACPI_HANDLE handle, u32 units, u32 timeout) +{ + return AE_OK; +} + +ACPI_STATUS +acpi_os_signal_semaphore(ACPI_HANDLE handle, u32 units) +{ + return AE_OK; +} + +ACPI_STATUS +acpi_os_breakpoint(char *msg) +{ + acpi_os_printf("breakpoint: %s", msg); + return AE_OK; +} + +void +acpi_os_dbg_trap(char *msg) +{ + acpi_os_printf("trap: %s", msg); +} + +void +acpi_os_dbg_assert(void *failure, void *file, u32 line, char *msg) +{ + acpi_os_printf("assert: %s", msg); +} + +u32 +acpi_os_get_line(char *buffer) +{ + return 0; +} + +/* + * We just have to assume we're dealing with valid memory + */ + +BOOLEAN +acpi_os_readable(void *ptr, u32 len) +{ + return 1; +} + +BOOLEAN +acpi_os_writable(void *ptr, u32 len) +{ + return 1; +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/parser/psargs.c linux/drivers/acpi/parser/psargs.c --- v2.4.0-test2/linux/drivers/acpi/parser/psargs.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/parser/psargs.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,735 @@ +/****************************************************************************** + * + * Module Name: psargs - Parse AML opcode arguments + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "amlcode.h" +#include "namesp.h" + +#define _COMPONENT PARSER + MODULE_NAME ("psargs"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_package_length + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: Decoded package length. On completion, the AML pointer points + * past the length byte or bytes. + * + * DESCRIPTION: Decode and return a package length field + * + ******************************************************************************/ + +u32 +acpi_ps_get_next_package_length ( + ACPI_PARSE_STATE *parser_state) +{ + s32 encoded_length; + s32 length = 0; + + + encoded_length = (s32) GET8 (parser_state->aml); + parser_state->aml++; + + + switch (encoded_length >> 6) /* bits 6-7 contain encoding scheme */ + { + case 0: /* 1-byte encoding (bits 0-5) */ + + length = (encoded_length & 0x3f); + break; + + + case 1: /* 2-byte encoding (next byte + bits 0-3) */ + + length = (GET8 (parser_state->aml) << 4) | (encoded_length & 0xf); + parser_state->aml++; + break; + + + case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */ + + length = ( (GET8 (parser_state->aml + 1) << 12) + | (GET8 (parser_state->aml) << 4) + | (encoded_length & 0xf)); + parser_state->aml += 2; + break; + + + case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */ + + length = ( (GET8 (parser_state->aml + 2) << 20) + | (GET8 (parser_state->aml + 1) << 12) + | (GET8 (parser_state->aml) << 4) + | (encoded_length & 0xf)); + parser_state->aml += 3; + break; + } + + return (length); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_package_end + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: Pointer to end-of-package +1 + * + * DESCRIPTION: Get next package length and return a pointer past the end of + * the package. Consumes the package length field + * + ******************************************************************************/ + +u8 * +acpi_ps_get_next_package_end ( + ACPI_PARSE_STATE *parser_state) +{ + u8 *start = parser_state->aml; + NATIVE_UINT length; + + + length = (NATIVE_UINT) acpi_ps_get_next_package_length (parser_state); + + return (start + length); /* end of package */ +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_namestring + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: Pointer to the start of the name string (pointer points into + * the AML. + * + * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name + * prefix characters. Set parser state to point past the string. + * (Name is consumed from the AML.) + * + ******************************************************************************/ + +char * +acpi_ps_get_next_namestring ( + ACPI_PARSE_STATE *parser_state) +{ + char *start = (char *) parser_state->aml; + char *end = (char *) parser_state->aml; + s32 length; + + + /* Handle multiple prefix characters */ + + while (acpi_ps_is_prefix_char (GET8 (end))) { + /* include prefix '\\' or '^' */ + + end++; + } + + /* Decode the path */ + + switch (GET8 (end)) + { + case 0: + + /* Null_name */ + + if (end == start) { + start = NULL; + } + end++; + break; + + + case AML_DUAL_NAME_PREFIX: + + /* two name segments */ + + end += 9; + break; + + + case AML_MULTI_NAME_PREFIX_OP: + + /* multiple name segments */ + + length = (s32) GET8 (end + 1) * 4; + end += 2 + length; + break; + + + default: + + /* single name segment */ + /* assert (Acpi_ps_is_lead (GET8 (End))); */ + + end += 4; + break; + } + + parser_state->aml = (u8*) end; + + return (start); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_namepath + * + * PARAMETERS: Parser_state - Current parser state object + * Arg - Where the namepath will be stored + * Arg_count - If the namepath points to a control method + * the method's argument is returned here. + * Method_call - Whether the namepath can be the start + * of a method call + * + * RETURN: None + * + * DESCRIPTION: Get next name (if method call, push appropriate # args). Names + * are looked up in either the parsed or internal namespace to + * determine if the name represents a control method. If a method + * is found, the number of arguments to the method is returned. + * This information is critical for parsing to continue correctly. + * + ******************************************************************************/ + + +#ifdef PARSER_ONLY + +void +acpi_ps_get_next_namepath ( + ACPI_PARSE_STATE *parser_state, + ACPI_GENERIC_OP *arg, + u32 *arg_count, + u8 method_call) +{ + char *path; + ACPI_GENERIC_OP *name; + ACPI_GENERIC_OP *op; + ACPI_GENERIC_OP *count; + + + path = acpi_ps_get_next_namestring (parser_state); + if (!path || !method_call) { + /* Null name case, create a null namepath object */ + + acpi_ps_init_op (arg, AML_NAMEPATH_OP); + arg->value.name = path; + return; + } + + + if (acpi_gbl_parsed_namespace_root) { + /* + * Lookup the name in the parsed namespace + */ + + op = NULL; + if (method_call) { + op = acpi_ps_find (acpi_ps_get_parent_scope (parser_state), + path, AML_METHOD_OP, 0); + } + + if (op) { + if (op->opcode == AML_METHOD_OP) { + /* + * The name refers to a control method, so this namepath is a + * method invocation. We need to 1) Get the number of arguments + * associated with this method, and 2) Change the NAMEPATH + * object into a METHODCALL object. + */ + + count = acpi_ps_get_arg (op, 0); + if (count && count->opcode == AML_BYTE_OP) { + name = acpi_ps_alloc_op (AML_NAMEPATH_OP); + if (name) { + /* Change arg into a METHOD CALL and attach the name */ + + acpi_ps_init_op (arg, AML_METHODCALL_OP); + + name->value.name = path; + + /* Point METHODCALL/NAME to the METHOD NTE */ + + name->acpi_named_object = op; + acpi_ps_append_arg (arg, name); + + *arg_count = count->value.integer & + METHOD_FLAGS_ARG_COUNT; + } + } + + return; + } + + /* + * Else this is normal named object reference. + * Just init the NAMEPATH object with the pathname. + * (See code below) + */ + } + } + + + /* + * Either we didn't find the object in the namespace, or the object is + * something other than a control method. Just initialize the Op with the + * pathname + */ + + acpi_ps_init_op (arg, AML_NAMEPATH_OP); + arg->value.name = path; + + + return; +} + + +#else + + +void +acpi_ps_get_next_namepath ( + ACPI_PARSE_STATE *parser_state, + ACPI_GENERIC_OP *arg, + u32 *arg_count, + u8 method_call) +{ + char *path; + ACPI_GENERIC_OP *name; + ACPI_STATUS status; + ACPI_NAMED_OBJECT *method = NULL; + ACPI_NAMED_OBJECT *entry; + ACPI_GENERIC_STATE scope_info; + + + path = acpi_ps_get_next_namestring (parser_state); + if (!path || !method_call) { + /* Null name case, create a null namepath object */ + + acpi_ps_init_op (arg, AML_NAMEPATH_OP); + arg->value.name = path; + return; + } + + + if (method_call) { + /* + * Lookup the name in the internal namespace + */ + scope_info.scope.name_table = NULL; + entry = parser_state->start_op->acpi_named_object; + if (entry) { + scope_info.scope.name_table = entry->child_table; + } + + /* + * Lookup object. We don't want to add anything new to the namespace + * here, however. So we use MODE_EXECUTE. Allow searching of the + * parent tree, but don't open a new scope -- we just want to lookup the + * object (MUST BE mode EXECUTE to perform upsearch) + */ + + status = acpi_ns_lookup (&scope_info, path, ACPI_TYPE_ANY, IMODE_EXECUTE, + NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, NULL, + &entry); + if (ACPI_SUCCESS (status)) { + if (entry->type == ACPI_TYPE_METHOD) { + method = entry; + name = acpi_ps_alloc_op (AML_NAMEPATH_OP); + if (name) { + /* Change arg into a METHOD CALL and attach name to it */ + + acpi_ps_init_op (arg, AML_METHODCALL_OP); + + name->value.name = path; + + /* Point METHODCALL/NAME to the METHOD NTE */ + + name->acpi_named_object = method; + acpi_ps_append_arg (arg, name); + + *arg_count = ((ACPI_OBJECT_INTERNAL *) method->object)->method.param_count; + } + + return; + } + + /* + * Else this is normal named object reference. + * Just init the NAMEPATH object with the pathname. + * (See code below) + */ + } + } + + /* + * Either we didn't find the object in the namespace, or the object is + * something other than a control method. Just initialize the Op with the + * pathname + */ + + acpi_ps_init_op (arg, AML_NAMEPATH_OP); + arg->value.name = path; + + + return; +} + +#endif + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_simple_arg + * + * PARAMETERS: Parser_state - Current parser state object + * Arg_type - The argument type (AML_*_ARG) + * Arg - Where the argument is returned + * + * RETURN: None + * + * DESCRIPTION: Get the next simple argument (constant, string, or namestring) + * + ******************************************************************************/ + +void +acpi_ps_get_next_simple_arg ( + ACPI_PARSE_STATE *parser_state, + s32 arg_type, + ACPI_GENERIC_OP *arg) +{ + + + switch (arg_type) + { + + case ARGP_BYTEDATA: + + acpi_ps_init_op (arg, AML_BYTE_OP); + arg->value.integer = (u32) GET8 (parser_state->aml); + parser_state->aml++; + break; + + + case ARGP_WORDDATA: + + acpi_ps_init_op (arg, AML_WORD_OP); + + /* Get 2 bytes from the AML stream */ + + MOVE_UNALIGNED16_TO_32 (&arg->value.integer, parser_state->aml); + parser_state->aml += 2; + break; + + + case ARGP_DWORDDATA: + + acpi_ps_init_op (arg, AML_DWORD_OP); + + /* Get 4 bytes from the AML stream */ + + MOVE_UNALIGNED32_TO_32 (&arg->value.integer, parser_state->aml); + parser_state->aml += 4; + break; + + + case ARGP_CHARLIST: + + acpi_ps_init_op (arg, AML_STRING_OP); + arg->value.string = (char*) parser_state->aml; + + while (GET8 (parser_state->aml) != '\0') { + parser_state->aml++; + } + parser_state->aml++; + break; + + + case ARGP_NAME: + case ARGP_NAMESTRING: + + acpi_ps_init_op (arg, AML_NAMEPATH_OP); + arg->value.name = acpi_ps_get_next_namestring (parser_state); + break; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_field + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: A newly allocated FIELD op + * + * DESCRIPTION: Get next field (Named_field, Reserved_field, or Access_field) + * + ******************************************************************************/ + +ACPI_GENERIC_OP * +acpi_ps_get_next_field ( + ACPI_PARSE_STATE *parser_state) +{ + ACPI_PTRDIFF aml_offset = parser_state->aml - + parser_state->aml_start; + ACPI_GENERIC_OP *field; + u16 opcode; + u32 name; + + + /* determine field type */ + + switch (GET8 (parser_state->aml)) + { + + default: + + opcode = AML_NAMEDFIELD_OP; + break; + + + case 0x00: + + opcode = AML_RESERVEDFIELD_OP; + parser_state->aml++; + break; + + + case 0x01: + + opcode = AML_ACCESSFIELD_OP; + parser_state->aml++; + break; + } + + + /* Allocate a new field op */ + + field = acpi_ps_alloc_op (opcode); + if (field) { + field->aml_offset = aml_offset; + + /* Decode the field type */ + + switch (opcode) + { + case AML_NAMEDFIELD_OP: + + /* Get the 4-character name */ + + MOVE_UNALIGNED32_TO_32 (&name, parser_state->aml); + acpi_ps_set_name (field, name); + parser_state->aml += 4; + + /* Get the length which is encoded as a package length */ + + field->value.size = acpi_ps_get_next_package_length (parser_state); + break; + + + case AML_RESERVEDFIELD_OP: + + /* Get the length which is encoded as a package length */ + + field->value.size = acpi_ps_get_next_package_length (parser_state); + break; + + + case AML_ACCESSFIELD_OP: + + /* Get Access_type and Access_atrib and merge into the field Op */ + + field->value.integer = ((GET8 (parser_state->aml) << 8) | + GET8 (parser_state->aml)); + parser_state->aml += 2; + break; + } + } + + return (field); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_arg + * + * PARAMETERS: Parser_state - Current parser state object + * Arg_type - The argument type (AML_*_ARG) + * Arg_count - If the argument points to a control method + * the method's argument is returned here. + * + * RETURN: An op object containing the next argument. + * + * DESCRIPTION: Get next argument (including complex list arguments that require + * pushing the parser stack) + * + ******************************************************************************/ + +ACPI_GENERIC_OP * +acpi_ps_get_next_arg ( + ACPI_PARSE_STATE *parser_state, + s32 arg_type, + u32 *arg_count) +{ + ACPI_GENERIC_OP *arg = NULL; + ACPI_GENERIC_OP *prev = NULL; + ACPI_GENERIC_OP *field; + s32 subop; + + + switch (arg_type) + { + case ARGP_BYTEDATA: + case ARGP_WORDDATA: + case ARGP_DWORDDATA: + case ARGP_CHARLIST: + case ARGP_NAME: + case ARGP_NAMESTRING: + + /* constants, strings, and namestrings are all the same size */ + + arg = acpi_ps_alloc_op (AML_BYTE_OP); + if (arg) { + acpi_ps_get_next_simple_arg (parser_state, arg_type, arg); + } + break; + + + case ARGP_PKGLENGTH: + + /* package length, nothing returned */ + + parser_state->pkg_end = acpi_ps_get_next_package_end (parser_state); + break; + + + case ARGP_FIELDLIST: + + if (parser_state->aml < parser_state->pkg_end) { + /* non-empty list */ + + while (parser_state->aml < parser_state->pkg_end) { + field = acpi_ps_get_next_field (parser_state); + if (!field) { + break; + } + + if (prev) { + prev->next = field; + } + + else { + arg = field; + } + + prev = field; + } + + /* skip to End of byte data */ + + parser_state->aml = parser_state->pkg_end; + } + break; + + + case ARGP_BYTELIST: + + if (parser_state->aml < parser_state->pkg_end) { + /* non-empty list */ + + arg = acpi_ps_alloc_op (AML_BYTELIST_OP); + if (arg) { + /* fill in bytelist data */ + + arg->value.size = (parser_state->pkg_end - parser_state->aml); + acpi_ps_to_bytelist_op (arg)->data = parser_state->aml; + } + + /* skip to End of byte data */ + + parser_state->aml = parser_state->pkg_end; + } + break; + + + case ARGP_TARGET: + case ARGP_SUPERNAME: + { + subop = acpi_ps_peek_opcode (parser_state); + if (subop == 0 || + acpi_ps_is_leading_char (subop) || + acpi_ps_is_prefix_char (subop)) + { + /* Null_name or Name_string */ + + arg = acpi_ps_alloc_op (AML_NAMEPATH_OP); + if (arg) { + acpi_ps_get_next_namepath (parser_state, arg, arg_count, 0); + } + } + + else { + /* single complex argument, nothing returned */ + + *arg_count = 1; + } + } + break; + + + case ARGP_DATAOBJ: + case ARGP_TERMARG: + + /* single complex argument, nothing returned */ + + *arg_count = 1; + break; + + + case ARGP_DATAOBJLIST: + case ARGP_TERMLIST: + case ARGP_OBJLIST: + + if (parser_state->aml < parser_state->pkg_end) { + /* non-empty list of variable arguments, nothing returned */ + + *arg_count = ACPI_VAR_ARGS; + } + break; + } + + return (arg); +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/parser/psopcode.c linux/drivers/acpi/parser/psopcode.c --- v2.4.0-test2/linux/drivers/acpi/parser/psopcode.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/parser/psopcode.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,554 @@ +/****************************************************************************** + * + * Module Name: psopcode - Parser opcode information table + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "amlcode.h" + + +#define _COMPONENT PARSER + MODULE_NAME ("psopcode"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_opcode_info + * + * PARAMETERS: Opcode - The AML opcode + * + * RETURN: A pointer to the info about the opcode. NULL if the opcode was + * not found in the table. + * + * DESCRIPTION: Find AML opcode description based on the opcode + * + ******************************************************************************/ + +ACPI_OP_INFO * +acpi_ps_get_opcode_info ( + u16 opcode) +{ + ACPI_OP_INFO *op; + s32 hash; + + + /* compute hash/index into the Acpi_aml_op_index table */ + + switch (opcode >> 8) + { + case 0: + + /* Simple (8-bit) opcode */ + + hash = opcode; + break; + + + case AML_EXTOP: + + /* Extended (16-bit, prefix+opcode) opcode */ + + hash = (opcode + AML_EXTOP_HASH_OFFSET) & 0xff; + break; + + + case AML_LNOT_OP: + + /* This case is for the bogus opcodes LNOTEQUAL, LLESSEQUAL, LGREATEREQUAL */ + + hash = (opcode + AML_LNOT_HASH_OFFSET) & 0xff; + break; + + + default: + + return NULL; + } + + + /* Get the Op info pointer for this opcode */ + + op = &acpi_gbl_aml_op_info [(s32) acpi_gbl_aml_op_info_index [hash]]; + + + /* If the returned opcode matches, we have a valid opcode */ + + if (op->opcode == opcode) { + return op; + } + + /* Otherwise, the opcode is an ASCII char or other non-opcode value */ + + return NULL; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_opcode_name + * + * PARAMETERS: Opcode - The AML opcode + * + * RETURN: A pointer to the name of the opcode (ASCII String) + * Note: Never returns NULL. + * + * DESCRIPTION: Translate an opcode into a human-readable string + * + ******************************************************************************/ + +char * +acpi_ps_get_opcode_name ( + u16 opcode) +{ + ACPI_OP_INFO *op; + + + op = acpi_ps_get_opcode_info (opcode); + + if (!op) { + return "*ERROR*"; + } + + DEBUG_ONLY_MEMBERS (return op->name); + return "AE_NOT_CONFIGURED"; +} + + +/******************************************************************************* + * + * NAME: Acpi_gbl_Aml_op_info + * + * DESCRIPTION: Opcode table. Each entry contains + * The name is a simple ascii string, the operand specifier is an + * ascii string with one letter per operand. The letter specifies + * the operand type. + * + ******************************************************************************/ + + +/* + * Flags byte: 0-4 (5 bits) = Opcode Type + * 5 (1 bit) = Has arguments flag + * 6-7 (2 bits) = Reserved + */ +#define AML_NO_ARGS 0 +#define AML_HAS_ARGS OP_INFO_HAS_ARGS + +/* + * All AML opcodes and the parse-time arguments for each. Used by the AML parser Each list is compressed + * into a 32-bit number and stored in the master opcode table at the end of this file. + */ + +#define ARGP_ZERO_OP ARG_NONE +#define ARGP_ONE_OP ARG_NONE +#define ARGP_ALIAS_OP ARGP_LIST2 (ARGP_NAMESTRING, ARGP_NAME) +#define ARGP_NAME_OP ARGP_LIST2 (ARGP_NAME, ARGP_DATAOBJ) +#define ARGP_BYTE_OP ARGP_LIST1 (ARGP_BYTEDATA) +#define ARGP_WORD_OP ARGP_LIST1 (ARGP_WORDDATA) +#define ARGP_DWORD_OP ARGP_LIST1 (ARGP_DWORDDATA) +#define ARGP_STRING_OP ARGP_LIST1 (ARGP_CHARLIST) +#define ARGP_SCOPE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_TERMLIST) +#define ARGP_BUFFER_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_BYTELIST) +#define ARGP_PACKAGE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_BYTEDATA, ARGP_DATAOBJLIST) +#define ARGP_METHOD_OP ARGP_LIST4 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_TERMLIST) +#define ARGP_LOCAL0 ARG_NONE +#define ARGP_LOCAL1 ARG_NONE +#define ARGP_LOCAL2 ARG_NONE +#define ARGP_LOCAL3 ARG_NONE +#define ARGP_LOCAL4 ARG_NONE +#define ARGP_LOCAL5 ARG_NONE +#define ARGP_LOCAL6 ARG_NONE +#define ARGP_LOCAL7 ARG_NONE +#define ARGP_ARG0 ARG_NONE +#define ARGP_ARG1 ARG_NONE +#define ARGP_ARG2 ARG_NONE +#define ARGP_ARG3 ARG_NONE +#define ARGP_ARG4 ARG_NONE +#define ARGP_ARG5 ARG_NONE +#define ARGP_ARG6 ARG_NONE +#define ARGP_STORE_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_SUPERNAME) +#define ARGP_REF_OF_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_ADD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_CONCAT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_SUBTRACT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_INCREMENT_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_DECREMENT_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_MULTIPLY_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_DIVIDE_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET, ARGP_TARGET) +#define ARGP_SHIFT_LEFT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_SHIFT_RIGHT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_AND_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_NAND_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_OR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_NOR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_XOR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_NOT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_FIND_SET_LEFT_BIT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_FIND_SET_RIGHT_BIT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_DEREF_OF_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_NOTIFY_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_TERMARG) +#define ARGP_SIZE_OF_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_INDEX_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_MATCH_OP ARGP_LIST6 (ARGP_TERMARG, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_DWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_WORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_BYTE_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_BIT_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_TYPE_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_LAND_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LOR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LNOT_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_LEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LGREATER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LLESS_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_IF_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_TERMLIST) +#define ARGP_ELSE_OP ARGP_LIST2 (ARGP_PKGLENGTH, ARGP_TERMLIST) +#define ARGP_WHILE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_TERMLIST) +#define ARGP_NOOP_CODE ARG_NONE +#define ARGP_RETURN_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_BREAK_OP ARG_NONE +#define ARGP_BREAK_POINT_OP ARG_NONE +#define ARGP_ONES_OP ARG_NONE +#define ARGP_MUTEX_OP ARGP_LIST2 (ARGP_NAME, ARGP_BYTEDATA) +#define ARGP_EVENT_OP ARGP_LIST1 (ARGP_NAME) +#define ARGP_COND_REF_OF_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SUPERNAME) +#define ARGP_CREATE_FIELD_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_LOAD_OP ARGP_LIST2 (ARGP_NAMESTRING, ARGP_SUPERNAME) +#define ARGP_STALL_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_SLEEP_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_ACQUIRE_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_WORDDATA) +#define ARGP_SIGNAL_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_WAIT_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_TERMARG) +#define ARGP_RESET_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_RELEASE_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_FROM_BCDOP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_TO_BCDOP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_UN_LOAD_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_REVISION_OP ARG_NONE +#define ARGP_DEBUG_OP ARG_NONE +#define ARGP_FATAL_OP ARGP_LIST3 (ARGP_BYTEDATA, ARGP_DWORDDATA, ARGP_TERMARG) +#define ARGP_REGION_OP ARGP_LIST4 (ARGP_NAME, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_DEF_FIELD_OP ARGP_LIST4 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_BYTEDATA, ARGP_FIELDLIST) +#define ARGP_DEVICE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_OBJLIST) +#define ARGP_PROCESSOR_OP ARGP_LIST6 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_DWORDDATA, ARGP_BYTEDATA, ARGP_OBJLIST) +#define ARGP_POWER_RES_OP ARGP_LIST5 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_WORDDATA, ARGP_OBJLIST) +#define ARGP_THERMAL_ZONE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_OBJLIST) +#define ARGP_INDEX_FIELD_OP ARGP_LIST5 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_NAMESTRING,ARGP_BYTEDATA, ARGP_FIELDLIST) +#define ARGP_BANK_FIELD_OP ARGP_LIST6 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_NAMESTRING,ARGP_TERMARG, ARGP_BYTEDATA, ARGP_FIELDLIST) +#define ARGP_LNOTEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LLESSEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LGREATEREQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_NAMEPATH_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_METHODCALL_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_BYTELIST_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_RESERVEDFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_NAMEDFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_ACCESSFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_STATICSTRING_OP ARGP_LIST1 (ARGP_NAMESTRING) + + +/* + * All AML opcodes and the runtime arguments for each. Used by the AML interpreter Each list is compressed + * into a 32-bit number and stored in the master opcode table at the end of this file. + * + * (Used by Acpi_aml_prep_operands procedure) + */ + +#define ARGI_ZERO_OP ARG_NONE +#define ARGI_ONE_OP ARG_NONE +#define ARGI_ALIAS_OP ARGI_INVALID_OPCODE +#define ARGI_NAME_OP ARGI_INVALID_OPCODE +#define ARGI_BYTE_OP ARGI_INVALID_OPCODE +#define ARGI_WORD_OP ARGI_INVALID_OPCODE +#define ARGI_DWORD_OP ARGI_INVALID_OPCODE +#define ARGI_STRING_OP ARGI_INVALID_OPCODE +#define ARGI_SCOPE_OP ARGI_INVALID_OPCODE +#define ARGI_BUFFER_OP ARGI_INVALID_OPCODE +#define ARGI_PACKAGE_OP ARGI_INVALID_OPCODE +#define ARGI_METHOD_OP ARGI_INVALID_OPCODE +#define ARGI_LOCAL0 ARG_NONE +#define ARGI_LOCAL1 ARG_NONE +#define ARGI_LOCAL2 ARG_NONE +#define ARGI_LOCAL3 ARG_NONE +#define ARGI_LOCAL4 ARG_NONE +#define ARGI_LOCAL5 ARG_NONE +#define ARGI_LOCAL6 ARG_NONE +#define ARGI_LOCAL7 ARG_NONE +#define ARGI_ARG0 ARG_NONE +#define ARGI_ARG1 ARG_NONE +#define ARGI_ARG2 ARG_NONE +#define ARGI_ARG3 ARG_NONE +#define ARGI_ARG4 ARG_NONE +#define ARGI_ARG5 ARG_NONE +#define ARGI_ARG6 ARG_NONE +#define ARGI_STORE_OP ARGI_LIST2 (ARGI_ANYTYPE, ARGI_TARGETREF) +#define ARGI_REF_OF_OP ARGI_LIST1 (ARGI_REFERENCE) +#define ARGI_ADD_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_CONCAT_OP ARGI_LIST3 (ARGI_STRING, ARGI_STRING, ARGI_TARGETREF) +#define ARGI_SUBTRACT_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_INCREMENT_OP ARGI_LIST1 (ARGI_REFERENCE) +#define ARGI_DECREMENT_OP ARGI_LIST1 (ARGI_REFERENCE) +#define ARGI_MULTIPLY_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_DIVIDE_OP ARGI_LIST4 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF, ARGI_TARGETREF) +#define ARGI_SHIFT_LEFT_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_SHIFT_RIGHT_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_BIT_AND_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_BIT_NAND_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_BIT_OR_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_BIT_NOR_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_BIT_XOR_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_BIT_NOT_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_FIND_SET_LEFT_BIT_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_FIND_SET_RIGHT_BIT_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_DEREF_OF_OP ARGI_LIST1 (ARGI_REFERENCE) +#define ARGI_NOTIFY_OP ARGI_LIST2 (ARGI_REFERENCE, ARGI_NUMBER) +#define ARGI_SIZE_OF_OP ARGI_LIST1 (ARGI_DATAOBJECT) +#define ARGI_INDEX_OP ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_MATCH_OP ARGI_LIST6 (ARGI_PACKAGE, ARGI_NUMBER, ARGI_NUMBER, ARGI_NUMBER, ARGI_NUMBER, ARGI_NUMBER) +#define ARGI_DWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_NUMBER, ARGI_REFERENCE) +#define ARGI_WORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_NUMBER, ARGI_REFERENCE) +#define ARGI_BYTE_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_NUMBER, ARGI_REFERENCE) +#define ARGI_BIT_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_NUMBER, ARGI_REFERENCE) +#define ARGI_TYPE_OP ARGI_LIST1 (ARGI_ANYTYPE) +#define ARGI_LAND_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_NUMBER) +#define ARGI_LOR_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_NUMBER) +#define ARGI_LNOT_OP ARGI_LIST1 (ARGI_NUMBER) +#define ARGI_LEQUAL_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_NUMBER) +#define ARGI_LGREATER_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_NUMBER) +#define ARGI_LLESS_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_NUMBER) +#define ARGI_IF_OP ARGI_INVALID_OPCODE +#define ARGI_ELSE_OP ARGI_INVALID_OPCODE +#define ARGI_WHILE_OP ARGI_INVALID_OPCODE +#define ARGI_NOOP_CODE ARG_NONE +#define ARGI_RETURN_OP ARGI_INVALID_OPCODE +#define ARGI_BREAK_OP ARG_NONE +#define ARGI_BREAK_POINT_OP ARG_NONE +#define ARGI_ONES_OP ARG_NONE +#define ARGI_MUTEX_OP ARGI_INVALID_OPCODE +#define ARGI_EVENT_OP ARGI_INVALID_OPCODE +#define ARGI_COND_REF_OF_OP ARGI_LIST2 (ARGI_REFERENCE, ARGI_TARGETREF) +#define ARGI_CREATE_FIELD_OP ARGI_LIST4 (ARGI_BUFFER, ARGI_NUMBER, ARGI_NUMBER, ARGI_REFERENCE) +#define ARGI_LOAD_OP ARGI_LIST2 (ARGI_REGION, ARGI_TARGETREF) +#define ARGI_STALL_OP ARGI_LIST1 (ARGI_NUMBER) +#define ARGI_SLEEP_OP ARGI_LIST1 (ARGI_NUMBER) +#define ARGI_ACQUIRE_OP ARGI_LIST2 (ARGI_MUTEX, ARGI_NUMBER) +#define ARGI_SIGNAL_OP ARGI_LIST1 (ARGI_EVENT) +#define ARGI_WAIT_OP ARGI_LIST2 (ARGI_EVENT, ARGI_NUMBER) +#define ARGI_RESET_OP ARGI_LIST1 (ARGI_EVENT) +#define ARGI_RELEASE_OP ARGI_LIST1 (ARGI_MUTEX) +#define ARGI_FROM_BCDOP ARGI_LIST2 (ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_TO_BCDOP ARGI_LIST2 (ARGI_NUMBER, ARGI_TARGETREF) +#define ARGI_UN_LOAD_OP ARGI_LIST1 (ARGI_DDBHANDLE) +#define ARGI_REVISION_OP ARG_NONE +#define ARGI_DEBUG_OP ARG_NONE +#define ARGI_FATAL_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_NUMBER) +#define ARGI_REGION_OP ARGI_INVALID_OPCODE +#define ARGI_DEF_FIELD_OP ARGI_INVALID_OPCODE +#define ARGI_DEVICE_OP ARGI_INVALID_OPCODE +#define ARGI_PROCESSOR_OP ARGI_INVALID_OPCODE +#define ARGI_POWER_RES_OP ARGI_INVALID_OPCODE +#define ARGI_THERMAL_ZONE_OP ARGI_INVALID_OPCODE +#define ARGI_INDEX_FIELD_OP ARGI_INVALID_OPCODE +#define ARGI_BANK_FIELD_OP ARGI_INVALID_OPCODE +#define ARGI_LNOTEQUAL_OP ARGI_INVALID_OPCODE +#define ARGI_LLESSEQUAL_OP ARGI_INVALID_OPCODE +#define ARGI_LGREATEREQUAL_OP ARGI_INVALID_OPCODE +#define ARGI_NAMEPATH_OP ARGI_INVALID_OPCODE +#define ARGI_METHODCALL_OP ARGI_INVALID_OPCODE +#define ARGI_BYTELIST_OP ARGI_INVALID_OPCODE +#define ARGI_RESERVEDFIELD_OP ARGI_INVALID_OPCODE +#define ARGI_NAMEDFIELD_OP ARGI_INVALID_OPCODE +#define ARGI_ACCESSFIELD_OP ARGI_INVALID_OPCODE +#define ARGI_STATICSTRING_OP ARGI_INVALID_OPCODE + + +/* + * Master Opcode information table. A summary of everything we know about each opcode, all in one place. + */ + + +ACPI_OP_INFO acpi_gbl_aml_op_info[] = +{ +/* Opcode Opcode Type Has Arguments? Child Name Parser Args Interpreter Args */ + +/* 00 */ OP_INFO_ENTRY (AML_ZERO_OP, OPTYPE_CONSTANT| AML_NO_ARGS| 0, "Zero_op", ARGP_ZERO_OP, ARGI_ZERO_OP), +/* 01 */ OP_INFO_ENTRY (AML_ONE_OP, OPTYPE_CONSTANT| AML_NO_ARGS| 0, "One_op", ARGP_ONE_OP, ARGI_ONE_OP), +/* 02 */ OP_INFO_ENTRY (AML_ALIAS_OP, OPTYPE_NAMED_OBJECT| AML_HAS_ARGS| 0, "Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP), +/* 03 */ OP_INFO_ENTRY (AML_NAME_OP, OPTYPE_NAMED_OBJECT| AML_HAS_ARGS| 0, "Name", ARGP_NAME_OP, ARGI_NAME_OP), +/* 04 */ OP_INFO_ENTRY (AML_BYTE_OP, OPTYPE_LITERAL| AML_NO_ARGS| 0, "Byte_const", ARGP_BYTE_OP, ARGI_BYTE_OP), +/* 05 */ OP_INFO_ENTRY (AML_WORD_OP, OPTYPE_LITERAL| AML_NO_ARGS| 0, "Word_const", ARGP_WORD_OP, ARGI_WORD_OP), +/* 06 */ OP_INFO_ENTRY (AML_DWORD_OP, OPTYPE_LITERAL| AML_NO_ARGS| 0, "Dword_const", ARGP_DWORD_OP, ARGI_DWORD_OP), +/* 07 */ OP_INFO_ENTRY (AML_STRING_OP, OPTYPE_LITERAL| AML_NO_ARGS| 0, "String", ARGP_STRING_OP, ARGI_STRING_OP), +/* 08 */ OP_INFO_ENTRY (AML_SCOPE_OP, OPTYPE_NAMED_OBJECT| AML_HAS_ARGS| 0, "Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP), +/* 09 */ OP_INFO_ENTRY (AML_BUFFER_OP, OPTYPE_DATA_TERM| AML_HAS_ARGS| 0, "Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP), +/* 0A */ OP_INFO_ENTRY (AML_PACKAGE_OP, OPTYPE_DATA_TERM| AML_HAS_ARGS| 0, "Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP), +/* 0B */ OP_INFO_ENTRY (AML_METHOD_OP, OPTYPE_NAMED_OBJECT| AML_HAS_ARGS| 0, "Method", ARGP_METHOD_OP, ARGI_METHOD_OP), +/* 0C */ OP_INFO_ENTRY (AML_LOCAL0, OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS| 0, "Local0", ARGP_LOCAL0, ARGI_LOCAL0), +/* 0D */ OP_INFO_ENTRY (AML_LOCAL1, OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS| 0, "Local1", ARGP_LOCAL1, ARGI_LOCAL1), +/* 0E */ OP_INFO_ENTRY (AML_LOCAL2, OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS| 0, "Local2", ARGP_LOCAL2, ARGI_LOCAL2), +/* 0F */ OP_INFO_ENTRY (AML_LOCAL3, OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS| 0, "Local3", ARGP_LOCAL3, ARGI_LOCAL3), +/* 10 */ OP_INFO_ENTRY (AML_LOCAL4, OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS| 0, "Local4", ARGP_LOCAL4, ARGI_LOCAL4), +/* 11 */ OP_INFO_ENTRY (AML_LOCAL5, OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS| 0, "Local5", ARGP_LOCAL5, ARGI_LOCAL5), +/* 12 */ OP_INFO_ENTRY (AML_LOCAL6, OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS| 0, "Local6", ARGP_LOCAL6, ARGI_LOCAL6), +/* 13 */ OP_INFO_ENTRY (AML_LOCAL7, OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS| 0, "Local7", ARGP_LOCAL7, ARGI_LOCAL7), +/* 14 */ OP_INFO_ENTRY (AML_ARG0, OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS| 0, "Arg0", ARGP_ARG0, ARGI_ARG0), +/* 15 */ OP_INFO_ENTRY (AML_ARG1, OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS| 0, "Arg1", ARGP_ARG1, ARGI_ARG1), +/* 16 */ OP_INFO_ENTRY (AML_ARG2, OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS| 0, "Arg2", ARGP_ARG2, ARGI_ARG2), +/* 17 */ OP_INFO_ENTRY (AML_ARG3, OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS| 0, "Arg3", ARGP_ARG3, ARGI_ARG3), +/* 18 */ OP_INFO_ENTRY (AML_ARG4, OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS| 0, "Arg4", ARGP_ARG4, ARGI_ARG4), +/* 19 */ OP_INFO_ENTRY (AML_ARG5, OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS| 0, "Arg5", ARGP_ARG5, ARGI_ARG5), +/* 1_a */ OP_INFO_ENTRY (AML_ARG6, OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS| 0, "Arg6", ARGP_ARG6, ARGI_ARG6), +/* 1_b */ OP_INFO_ENTRY (AML_STORE_OP, OPTYPE_MONADIC2_r| AML_HAS_ARGS| 0, "Store", ARGP_STORE_OP, ARGI_STORE_OP), +/* 1_c */ OP_INFO_ENTRY (AML_REF_OF_OP, OPTYPE_MONADIC2| AML_HAS_ARGS| 0, "Ref_of", ARGP_REF_OF_OP, ARGI_REF_OF_OP), +/* 1_d */ OP_INFO_ENTRY (AML_ADD_OP, OPTYPE_DYADIC2_r| AML_HAS_ARGS| 0, "Add", ARGP_ADD_OP, ARGI_ADD_OP), +/* 1_e */ OP_INFO_ENTRY (AML_CONCAT_OP, OPTYPE_DYADIC2_r| AML_HAS_ARGS| 0, "Concat", ARGP_CONCAT_OP, ARGI_CONCAT_OP), +/* 1_f */ OP_INFO_ENTRY (AML_SUBTRACT_OP, OPTYPE_DYADIC2_r| AML_HAS_ARGS| 0, "Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP), +/* 20 */ OP_INFO_ENTRY (AML_INCREMENT_OP, OPTYPE_MONADIC2| AML_HAS_ARGS| 0, "Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP), +/* 21 */ OP_INFO_ENTRY (AML_DECREMENT_OP, OPTYPE_MONADIC2| AML_HAS_ARGS| 0, "Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP), +/* 22 */ OP_INFO_ENTRY (AML_MULTIPLY_OP, OPTYPE_DYADIC2_r| AML_HAS_ARGS| 0, "Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP), +/* 23 */ OP_INFO_ENTRY (AML_DIVIDE_OP, OPTYPE_DYADIC2_r| AML_HAS_ARGS| 0, "Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP), +/* 24 */ OP_INFO_ENTRY (AML_SHIFT_LEFT_OP, OPTYPE_DYADIC2_r| AML_HAS_ARGS| 0, "Shift_left", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP), +/* 25 */ OP_INFO_ENTRY (AML_SHIFT_RIGHT_OP, OPTYPE_DYADIC2_r| AML_HAS_ARGS| 0, "Shift_right", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP), +/* 26 */ OP_INFO_ENTRY (AML_BIT_AND_OP, OPTYPE_DYADIC2_r| AML_HAS_ARGS| 0, "And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP), +/* 27 */ OP_INFO_ENTRY (AML_BIT_NAND_OP, OPTYPE_DYADIC2_r| AML_HAS_ARGS| 0, "NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP), +/* 28 */ OP_INFO_ENTRY (AML_BIT_OR_OP, OPTYPE_DYADIC2_r| AML_HAS_ARGS| 0, "Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP), +/* 29 */ OP_INFO_ENTRY (AML_BIT_NOR_OP, OPTYPE_DYADIC2_r| AML_HAS_ARGS| 0, "NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP), +/* 2_a */ OP_INFO_ENTRY (AML_BIT_XOR_OP, OPTYPE_DYADIC2_r| AML_HAS_ARGS| 0, "XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP), +/* 2_b */ OP_INFO_ENTRY (AML_BIT_NOT_OP, OPTYPE_MONADIC2_r| AML_HAS_ARGS| 0, "Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP), +/* 2_c */ OP_INFO_ENTRY (AML_FIND_SET_LEFT_BIT_OP, OPTYPE_MONADIC2_r| AML_HAS_ARGS| 0, "Find_set_left_bit", ARGP_FIND_SET_LEFT_BIT_OP, ARGI_FIND_SET_LEFT_BIT_OP), +/* 2_d */ OP_INFO_ENTRY (AML_FIND_SET_RIGHT_BIT_OP, OPTYPE_MONADIC2_r| AML_HAS_ARGS| 0, "Find_set_right_bit", ARGP_FIND_SET_RIGHT_BIT_OP, ARGI_FIND_SET_RIGHT_BIT_OP), +/* 2_e */ OP_INFO_ENTRY (AML_DEREF_OF_OP, OPTYPE_MONADIC2| AML_HAS_ARGS| 0, "Deref_of", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP), +/* 2_f */ OP_INFO_ENTRY (AML_NOTIFY_OP, OPTYPE_DYADIC1| AML_HAS_ARGS| 0, "Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP), +/* 30 */ OP_INFO_ENTRY (AML_SIZE_OF_OP, OPTYPE_MONADIC2| AML_HAS_ARGS| 0, "Size_of", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP), +/* 31 */ OP_INFO_ENTRY (AML_INDEX_OP, OPTYPE_INDEX| AML_HAS_ARGS| 0, "Index", ARGP_INDEX_OP, ARGI_INDEX_OP), +/* 32 */ OP_INFO_ENTRY (AML_MATCH_OP, OPTYPE_MATCH| AML_HAS_ARGS| 0, "Match", ARGP_MATCH_OP, ARGI_MATCH_OP), +/* 33 */ OP_INFO_ENTRY (AML_DWORD_FIELD_OP, OPTYPE_CREATE_FIELD| AML_HAS_ARGS| 0, "Create_dWord_field", ARGP_DWORD_FIELD_OP, ARGI_DWORD_FIELD_OP), +/* 34 */ OP_INFO_ENTRY (AML_WORD_FIELD_OP, OPTYPE_CREATE_FIELD| AML_HAS_ARGS| 0, "Create_word_field", ARGP_WORD_FIELD_OP, ARGI_WORD_FIELD_OP), +/* 35 */ OP_INFO_ENTRY (AML_BYTE_FIELD_OP, OPTYPE_CREATE_FIELD| AML_HAS_ARGS| 0, "Create_byte_field", ARGP_BYTE_FIELD_OP, ARGI_BYTE_FIELD_OP), +/* 36 */ OP_INFO_ENTRY (AML_BIT_FIELD_OP, OPTYPE_CREATE_FIELD| AML_HAS_ARGS| 0, "Create_bit_field", ARGP_BIT_FIELD_OP, ARGI_BIT_FIELD_OP), +/* 37 */ OP_INFO_ENTRY (AML_TYPE_OP, OPTYPE_MONADIC2| AML_HAS_ARGS| 0, "Object_type", ARGP_TYPE_OP, ARGI_TYPE_OP), +/* 38 */ OP_INFO_ENTRY (AML_LAND_OP, OPTYPE_DYADIC2| AML_HAS_ARGS| 0, "LAnd", ARGP_LAND_OP, ARGI_LAND_OP), +/* 39 */ OP_INFO_ENTRY (AML_LOR_OP, OPTYPE_DYADIC2| AML_HAS_ARGS| 0, "LOr", ARGP_LOR_OP, ARGI_LOR_OP), +/* 3_a */ OP_INFO_ENTRY (AML_LNOT_OP, OPTYPE_MONADIC2| AML_HAS_ARGS| 0, "LNot", ARGP_LNOT_OP, ARGI_LNOT_OP), +/* 3_b */ OP_INFO_ENTRY (AML_LEQUAL_OP, OPTYPE_DYADIC2| AML_HAS_ARGS| 0, "LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP), +/* 3_c */ OP_INFO_ENTRY (AML_LGREATER_OP, OPTYPE_DYADIC2| AML_HAS_ARGS| 0, "LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP), +/* 3_d */ OP_INFO_ENTRY (AML_LLESS_OP, OPTYPE_DYADIC2| AML_HAS_ARGS| 0, "LLess", ARGP_LLESS_OP, ARGI_LLESS_OP), +/* 3_e */ OP_INFO_ENTRY (AML_IF_OP, OPTYPE_CONTROL| AML_HAS_ARGS| 0, "If", ARGP_IF_OP, ARGI_IF_OP), +/* 3_f */ OP_INFO_ENTRY (AML_ELSE_OP, OPTYPE_CONTROL| AML_HAS_ARGS| 0, "Else", ARGP_ELSE_OP, ARGI_ELSE_OP), +/* 40 */ OP_INFO_ENTRY (AML_WHILE_OP, OPTYPE_CONTROL| AML_HAS_ARGS| 0, "While", ARGP_WHILE_OP, ARGI_WHILE_OP), +/* 41 */ OP_INFO_ENTRY (AML_NOOP_CODE, OPTYPE_CONTROL| AML_NO_ARGS| 0, "Noop", ARGP_NOOP_CODE, ARGI_NOOP_CODE), +/* 42 */ OP_INFO_ENTRY (AML_RETURN_OP, OPTYPE_CONTROL| AML_HAS_ARGS| 0, "Return", ARGP_RETURN_OP, ARGI_RETURN_OP), +/* 43 */ OP_INFO_ENTRY (AML_BREAK_OP, OPTYPE_CONTROL| AML_NO_ARGS| 0, "Break", ARGP_BREAK_OP, ARGI_BREAK_OP), +/* 44 */ OP_INFO_ENTRY (AML_BREAK_POINT_OP, OPTYPE_CONTROL| AML_NO_ARGS| 0, "Break_point", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP), +/* 45 */ OP_INFO_ENTRY (AML_ONES_OP, OPTYPE_CONSTANT| AML_NO_ARGS| 0, "Ones_op", ARGP_ONES_OP, ARGI_ONES_OP), + +/* Prefixed opcodes (Two-byte opcodes with a prefix op) */ + +/* 46 */ OP_INFO_ENTRY (AML_MUTEX_OP, OPTYPE_NAMED_OBJECT| AML_HAS_ARGS| 0, "Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP), +/* 47 */ OP_INFO_ENTRY (AML_EVENT_OP, OPTYPE_NAMED_OBJECT| AML_NO_ARGS| 0, "Event", ARGP_EVENT_OP, ARGI_EVENT_OP), +/* 48 */ OP_INFO_ENTRY (AML_COND_REF_OF_OP, OPTYPE_MONADIC2_r| AML_HAS_ARGS| 0, "Cond_ref_of", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP), +/* 49 */ OP_INFO_ENTRY (AML_CREATE_FIELD_OP, OPTYPE_CREATE_FIELD| AML_HAS_ARGS| 0, "Create_field", ARGP_CREATE_FIELD_OP, ARGI_CREATE_FIELD_OP), +/* 4_a */ OP_INFO_ENTRY (AML_LOAD_OP, OPTYPE_RECONFIGURATION| AML_HAS_ARGS| 0, "Load", ARGP_LOAD_OP, ARGI_LOAD_OP), +/* 4_b */ OP_INFO_ENTRY (AML_STALL_OP, OPTYPE_MONADIC1| AML_HAS_ARGS| 0, "Stall", ARGP_STALL_OP, ARGI_STALL_OP), +/* 4_c */ OP_INFO_ENTRY (AML_SLEEP_OP, OPTYPE_MONADIC1| AML_HAS_ARGS| 0, "Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP), +/* 4_d */ OP_INFO_ENTRY (AML_ACQUIRE_OP, OPTYPE_DYADIC2_s| AML_HAS_ARGS| 0, "Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP), +/* 4_e */ OP_INFO_ENTRY (AML_SIGNAL_OP, OPTYPE_MONADIC1| AML_HAS_ARGS| 0, "Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP), +/* 4_f */ OP_INFO_ENTRY (AML_WAIT_OP, OPTYPE_DYADIC2_s| AML_HAS_ARGS| 0, "Wait", ARGP_WAIT_OP, ARGI_WAIT_OP), +/* 50 */ OP_INFO_ENTRY (AML_RESET_OP, OPTYPE_MONADIC1| AML_HAS_ARGS| 0, "Reset", ARGP_RESET_OP, ARGI_RESET_OP), +/* 51 */ OP_INFO_ENTRY (AML_RELEASE_OP, OPTYPE_MONADIC1| AML_HAS_ARGS| 0, "Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP), +/* 52 */ OP_INFO_ENTRY (AML_FROM_BCDOP, OPTYPE_MONADIC2_r| AML_HAS_ARGS| 0, "From_bCD", ARGP_FROM_BCDOP, ARGI_FROM_BCDOP), +/* 53 */ OP_INFO_ENTRY (AML_TO_BCDOP, OPTYPE_MONADIC2_r| AML_HAS_ARGS| 0, "To_bCD", ARGP_TO_BCDOP, ARGI_TO_BCDOP), +/* 54 */ OP_INFO_ENTRY (AML_UN_LOAD_OP, OPTYPE_RECONFIGURATION| AML_HAS_ARGS| 0, "Unload", ARGP_UN_LOAD_OP, ARGI_UN_LOAD_OP), +/* 55 */ OP_INFO_ENTRY (AML_REVISION_OP, OPTYPE_CONSTANT| AML_NO_ARGS| 0, "Revision", ARGP_REVISION_OP, ARGI_REVISION_OP), +/* 56 */ OP_INFO_ENTRY (AML_DEBUG_OP, OPTYPE_CONSTANT| AML_NO_ARGS| 0, "Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP), +/* 57 */ OP_INFO_ENTRY (AML_FATAL_OP, OPTYPE_FATAL| AML_HAS_ARGS| 0, "Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP), +/* 58 */ OP_INFO_ENTRY (AML_REGION_OP, OPTYPE_NAMED_OBJECT| AML_HAS_ARGS| 0, "Op_region", ARGP_REGION_OP, ARGI_REGION_OP), +/* 59 */ OP_INFO_ENTRY (AML_DEF_FIELD_OP, OPTYPE_NAMED_OBJECT| AML_HAS_ARGS| 0, "Field", ARGP_DEF_FIELD_OP, ARGI_DEF_FIELD_OP), +/* 5_a */ OP_INFO_ENTRY (AML_DEVICE_OP, OPTYPE_NAMED_OBJECT| AML_HAS_ARGS| 0, "Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP), +/* 5_b */ OP_INFO_ENTRY (AML_PROCESSOR_OP, OPTYPE_NAMED_OBJECT| AML_HAS_ARGS| 0, "Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP), +/* 5_c */ OP_INFO_ENTRY (AML_POWER_RES_OP, OPTYPE_NAMED_OBJECT| AML_HAS_ARGS| 0, "Power_res", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP), +/* 5_d */ OP_INFO_ENTRY (AML_THERMAL_ZONE_OP, OPTYPE_NAMED_OBJECT| AML_HAS_ARGS| 0, "Thermal_zone", ARGP_THERMAL_ZONE_OP, ARGI_THERMAL_ZONE_OP), +/* 5_e */ OP_INFO_ENTRY (AML_INDEX_FIELD_OP, OPTYPE_NAMED_OBJECT| AML_HAS_ARGS| 0, "Index_field", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP), +/* 5_f */ OP_INFO_ENTRY (AML_BANK_FIELD_OP, OPTYPE_NAMED_OBJECT| AML_HAS_ARGS| 0, "Bank_field", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP), + +/* Internal opcodes that map to invalid AML opcodes */ + +/* 60 */ OP_INFO_ENTRY (AML_LNOTEQUAL_OP, OPTYPE_BOGUS| AML_HAS_ARGS| 0, "LNot_equal", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP), +/* 61 */ OP_INFO_ENTRY (AML_LLESSEQUAL_OP, OPTYPE_BOGUS| AML_HAS_ARGS| 0, "LLess_equal", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP), +/* 62 */ OP_INFO_ENTRY (AML_LGREATEREQUAL_OP, OPTYPE_BOGUS| AML_HAS_ARGS| 0, "LGreater_equal", ARGP_LGREATEREQUAL_OP, ARGI_LGREATEREQUAL_OP), +/* 63 */ OP_INFO_ENTRY (AML_NAMEPATH_OP, OPTYPE_LITERAL| AML_NO_ARGS| 0, "Name_path", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP), +/* 64 */ OP_INFO_ENTRY (AML_METHODCALL_OP, OPTYPE_METHOD_CALL| AML_HAS_ARGS| 0, "Method_call", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP), +/* 65 */ OP_INFO_ENTRY (AML_BYTELIST_OP, OPTYPE_LITERAL| AML_NO_ARGS| 0, "Byte_list", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP), +/* 66 */ OP_INFO_ENTRY (AML_RESERVEDFIELD_OP, OPTYPE_BOGUS| AML_NO_ARGS| 0, "Reserved_field", ARGP_RESERVEDFIELD_OP, ARGI_RESERVEDFIELD_OP), +/* 67 */ OP_INFO_ENTRY (AML_NAMEDFIELD_OP, OPTYPE_BOGUS| AML_NO_ARGS| 0, "Named_field", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP), +/* 68 */ OP_INFO_ENTRY (AML_ACCESSFIELD_OP, OPTYPE_BOGUS| AML_NO_ARGS| 0, "Access_field", ARGP_ACCESSFIELD_OP, ARGI_ACCESSFIELD_OP), +/* 69 */ OP_INFO_ENTRY (AML_STATICSTRING_OP, OPTYPE_BOGUS| AML_NO_ARGS| 0, "Static_string", ARGP_STATICSTRING_OP, ARGI_STATICSTRING_OP), +/* 6_a */ OP_INFO_ENTRY (0, OPTYPE_BOGUS| AML_HAS_ARGS| 0, "UNKNOWN_OP!", ARG_NONE, ARG_NONE), + OP_INFO_ENTRY (0, 0| AML_HAS_ARGS| 0, NULL, ARG_NONE, ARG_NONE) +}; + +#define _UNK 0x6A +#define _UNKNOWN_OPCODE 0x02 /* An example unknown opcode */ + +/* + * This table is directly indexed by the opcodes, and returns an + * index into the table above + */ + +u8 acpi_gbl_aml_op_info_index[256] = +{ +/* 0 1 2 3 4 5 6 7 */ +/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK, +/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, _UNK, _UNK, +/* 0x10 */ 0x08, 0x09, 0x0a, _UNK, 0x0b, _UNK, _UNK, 0x46, +/* 0x18 */ 0x47, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x28 */ 0x48, 0x49, _UNK, _UNK, _UNK, 0x63, _UNK, _UNK, +/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x4a, 0x4b, +/* 0x38 */ 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, +/* 0x40 */ 0x54, _UNK, _UNK, _UNK, _UNK, _UNK, 0x55, 0x56, +/* 0x48 */ 0x57, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, +/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK, +/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, +/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, +/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, _UNK, _UNK, 0x2f, 0x30, +/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, _UNK, +/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x58, 0x59, +/* 0x98 */ 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, _UNK, _UNK, +/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61, +/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK, +/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45, +}; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/parser/psparse.c linux/drivers/acpi/parser/psparse.c --- v2.4.0-test2/linux/drivers/acpi/parser/psparse.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/parser/psparse.c Wed Jul 5 11:23:12 2000 @@ -0,0 +1,726 @@ +/****************************************************************************** + * + * Module Name: psparse - Parser top level AML parse routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* + * Parse the AML and build an operation tree as most interpreters, + * like Perl, do. Parsing is done by hand rather than with a YACC + * generated parser to tightly constrain stack and dynamic memory + * usage. At the same time, parsing is kept flexible and the code + * fairly compact by parsing based on a list of AML opcode + * templates in Acpi_gbl_Aml_op_info[] + */ + +#include "acpi.h" +#include "parser.h" +#include "dispatch.h" +#include "amlcode.h" +#include "namesp.h" +#include "debugger.h" + +#define _COMPONENT PARSER + MODULE_NAME ("psparse"); + + +u32 acpi_gbl_depth = 0; +extern u32 acpi_gbl_scope_depth; + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_delete_completed_op + * + * PARAMETERS: State - Walk state + * Op - Completed op + * + * RETURN: AE_OK + * + * DESCRIPTION: Callback function for Acpi_ps_get_next_walk_op(). Used during + * Acpi_ps_delete_parse tree to delete Op objects when all sub-objects + * have been visited (and deleted.) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ps_delete_completed_op ( + ACPI_WALK_STATE *state, + ACPI_GENERIC_OP *op) +{ + + acpi_ps_free_op (op); + return AE_OK; +} + + +#ifndef PARSER_ONLY +/******************************************************************************* + * + * FUNCTION: Acpi_ps_delete_parse_tree + * + * PARAMETERS: Root - Root of tree (or subtree) to delete + * + * RETURN: None + * + * DESCRIPTION: Delete a portion of or an entire parse tree. + * + ******************************************************************************/ + +void +acpi_ps_delete_parse_tree ( + ACPI_GENERIC_OP *root) +{ + ACPI_GENERIC_OP *op; + ACPI_WALK_STATE walk_state; + + + walk_state.origin = root; + op = root; + + /* TBD: [Restructure] hack for root case */ + + if (op == acpi_gbl_parsed_namespace_root) { + op = acpi_ps_get_child (op); + } + + /* Save root until last, so that we know when the tree has been walked */ + + walk_state.next_op = op; + walk_state.next_op_info = NEXT_OP_DOWNWARD; + + while (walk_state.next_op) { + acpi_ps_get_next_walk_op (&walk_state, walk_state.next_op, + acpi_ps_delete_completed_op); + } +} +#endif + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_peek_opcode + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) + * + ******************************************************************************/ + +u32 +acpi_ps_get_opcode_size ( + u32 opcode) +{ + + /* Extended (2-byte) opcode if > 255 */ + + if (opcode > 0x00FF) { + return 2; + } + + /* Otherwise, just a single byte opcode */ + + return 1; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_peek_opcode + * + * PARAMETERS: Parser_state - A parser state object + * + * RETURN: Status + * + * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) + * + ******************************************************************************/ + +u16 +acpi_ps_peek_opcode ( + ACPI_PARSE_STATE *parser_state) +{ + u8 *aml; + u16 opcode; + + + aml = parser_state->aml; + opcode = (u16) GET8 (aml); + + aml++; + + + /* + * Original code special cased LNOTEQUAL, LLESSEQUAL, LGREATEREQUAL. + * These opcodes are no longer recognized. Instead, they are broken into + * two opcodes. + * + * + * if (Opcode == AML_EXTOP + * || (Opcode == AML_LNOT + * && (GET8 (Acpi_aml) == AML_LEQUAL + * || GET8 (Acpi_aml) == AML_LGREATER + * || GET8 (Acpi_aml) == AML_LLESS))) + * + * extended Opcode, !=, <=, or >= + */ + + if (opcode == AML_EXTOP) { + /* Extended opcode */ + + opcode = (u16) ((opcode << 8) | GET8 (aml)); + aml++; + } + + /* don't convert bare name to a namepath */ + + return opcode; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_create_state + * + * PARAMETERS: Acpi_aml - Acpi_aml code pointer + * Acpi_aml_size - Length of AML code + * + * RETURN: A new parser state object + * + * DESCRIPTION: Create and initialize a new parser state object + * + ******************************************************************************/ + +ACPI_PARSE_STATE * +acpi_ps_create_state ( + u8 *aml, + s32 aml_size) +{ + ACPI_PARSE_STATE *parser_state; + + + parser_state = acpi_cm_callocate (sizeof (ACPI_PARSE_STATE)); + if (!parser_state) { + return (NULL); + } + + parser_state->aml = aml; + parser_state->aml_end = aml + aml_size; + parser_state->pkg_end = parser_state->aml_end; + parser_state->aml_start = aml; + + + return (parser_state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_find_object + * + * PARAMETERS: Opcode - Current opcode + * Parser_state - Current state + * Walk_state - Current state + * *Op - Where found/new op is returned + * + * RETURN: Status + * + * DESCRIPTION: Find a named object. Two versions - one to search the parse + * tree (for parser-only applications such as acpidump), another + * to search the ACPI internal namespace (the parse tree may no + * longer exist) + * + ******************************************************************************/ + +#ifdef PARSER_ONLY + +ACPI_STATUS +acpi_ps_find_object ( + u16 opcode, + ACPI_PARSE_STATE *parser_state, + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP **op) +{ + char *path; + + + /* Find the name in the parse tree */ + + path = acpi_ps_get_next_namestring (parser_state); + + *op = acpi_ps_find (acpi_ps_get_parent_scope (parser_state), + path, opcode, 1); + + if (!(*op)) { + return AE_NOT_FOUND; + } + + return AE_OK; +} +#else + +ACPI_STATUS +acpi_ps_find_object ( + u16 opcode, + ACPI_PARSE_STATE *parser_state, + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP **out_op) +{ + char *path; + ACPI_GENERIC_OP *op; + OBJECT_TYPE_INTERNAL data_type; + ACPI_STATUS status; + ACPI_NAMED_OBJECT *entry = NULL; + + + /* + * The full parse tree has already been deleted -- therefore, we are parsing + * a control method. We can lookup the name in the namespace instead of + * the parse tree! + */ + + + path = acpi_ps_get_next_namestring (parser_state); + + /* Map the raw opcode into an internal object type */ + + data_type = acpi_ds_map_named_opcode_to_data_type (opcode); + + /* + * Enter the object into the namespace + * LOAD_PASS1 means Create if not found + */ + + status = acpi_ns_lookup (walk_state->scope_info, path, data_type, + IMODE_LOAD_PASS1, + NS_NO_UPSEARCH, walk_state, &entry); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Create a new op */ + + op = acpi_ps_alloc_op (opcode); + if (!op) { + return (AE_NO_MEMORY); + } + + /* Initialize */ + + ((ACPI_NAMED_OP *)op)->name = entry->name; + op->acpi_named_object = entry; + + + acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op); + + *out_op = op; + + + return (AE_OK); +} +#endif + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_parse_loop + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: Status + * + * DESCRIPTION: Parse AML (pointed to by the current parser state) and return + * a tree of ops. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ps_parse_loop ( + ACPI_PARSE_STATE *parser_state, + ACPI_WALK_STATE *walk_state, + u32 parse_flags) +{ + ACPI_STATUS status = AE_OK; + ACPI_GENERIC_OP *op = NULL; /* current op */ + ACPI_OP_INFO *op_info; + ACPI_GENERIC_OP *arg = NULL; + ACPI_DEFERRED_OP *deferred_op; + u32 arg_count; /* push for fixed or var args */ + u32 arg_types = 0; + ACPI_PTRDIFF aml_offset; + u16 opcode; + ACPI_GENERIC_OP pre_op; + + +#ifndef PARSER_ONLY + OBJECT_TYPE_INTERNAL data_type; +#endif + + + /* + * Iterative parsing loop, while there is more aml to process: + */ + while (parser_state->aml < parser_state->aml_end) { + if (!op) { + /* Get the next opcode from the AML stream */ + + aml_offset = parser_state->aml - parser_state->aml_start; + opcode = acpi_ps_peek_opcode (parser_state); + op_info = acpi_ps_get_opcode_info (opcode); + + /* + * First cut to determine what we have found: + * 1) A valid AML opcode + * 2) A name string + * 3) An unknown/invalid opcode + */ + + if (op_info) { + /* Found opcode info, this is a normal opcode */ + + parser_state->aml += acpi_ps_get_opcode_size (opcode); + arg_types = op_info->parse_args; + } + + else if (acpi_ps_is_prefix_char (opcode) || + acpi_ps_is_leading_char (opcode)) + { + /* + * Starts with a valid prefix or ASCII char, this is a name + * string. Convert the bare name string to a namepath. + */ + + opcode = AML_NAMEPATH_OP; + arg_types = ARGP_NAMESTRING; + } + + else { + /* The opcode is unrecognized. Just skip unknown opcodes */ + + parser_state->aml += acpi_ps_get_opcode_size (opcode); + continue; + } + + + /* Create Op structure and append to parent's argument list */ + + if (acpi_ps_is_named_op (opcode)) { + pre_op.value.arg = NULL; + pre_op.opcode = opcode; + + while (GET_CURRENT_ARG_TYPE (arg_types) != ARGP_NAME) { + arg = acpi_ps_get_next_arg (parser_state, + GET_CURRENT_ARG_TYPE (arg_types), + &arg_count); + acpi_ps_append_arg (&pre_op, arg); + INCREMENT_ARG_LIST (arg_types); + } + + + /* We know that this arg is a name, move to next arg */ + + INCREMENT_ARG_LIST (arg_types); + + status = acpi_ps_find_object (opcode, parser_state, walk_state, &op); + if (ACPI_FAILURE (status)) { + return (AE_NOT_FOUND); + } + + acpi_ps_append_arg (op, pre_op.value.arg); + acpi_gbl_depth++; + + + if (op->opcode == AML_REGION_OP) { + deferred_op = acpi_ps_to_deferred_op (op); + if (deferred_op) { + /* + * Skip parsing of control method or opregion body, + * because we don't have enough info in the first pass + * to parse them correctly. + * + * Backup to beginning of Op_region declaration (2 for + * Opcode, 4 for name) + * + * Body_length is unknown until we parse the body + */ + + deferred_op->body = parser_state->aml - 6; + deferred_op->body_length = 0; + } + } + } + + else { + /* Not a named opcode, just allocate Op and append to parent */ + + op = acpi_ps_alloc_op (opcode); + if (!op) { + return (AE_NO_MEMORY); + } + + acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op); + } + + op->aml_offset = aml_offset; + + } + + + arg_count = 0; + if (arg_types) /* Are there any arguments that must be processed? */ { + /* get arguments */ + + switch (op->opcode) + { + case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ + case AML_WORD_OP: /* AML_WORDDATA_ARG */ + case AML_DWORD_OP: /* AML_DWORDATA_ARG */ + case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ + + /* fill in constant or string argument directly */ + + acpi_ps_get_next_simple_arg (parser_state, + GET_CURRENT_ARG_TYPE (arg_types), op); + break; + + case AML_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ + + acpi_ps_get_next_namepath (parser_state, op, &arg_count, 1); + arg_types = 0; + break; + + + default: + + /* Op is not a constant or string, append each argument */ + + while (GET_CURRENT_ARG_TYPE (arg_types) && !arg_count) { + aml_offset = parser_state->aml - parser_state->aml_start; + arg = acpi_ps_get_next_arg (parser_state, + GET_CURRENT_ARG_TYPE (arg_types), + &arg_count); + + if (arg) { + arg->aml_offset = aml_offset; + } + + acpi_ps_append_arg (op, arg); + INCREMENT_ARG_LIST (arg_types); + } + + + /* For a method, save the length and address of the body */ + + if (op->opcode == AML_METHOD_OP) { + deferred_op = acpi_ps_to_deferred_op (op); + if (deferred_op) { + /* + * Skip parsing of control method or opregion body, + * because we don't have enough info in the first pass + * to parse them correctly. + */ + + deferred_op->body = parser_state->aml; + deferred_op->body_length = parser_state->pkg_end - + parser_state->aml; + + /* + * Skip body of method. For Op_regions, we must continue + * parsing because the opregion is not a standalone + * package (We don't know where the end is). + */ + parser_state->aml = parser_state->pkg_end; + arg_count = 0; + } + } + + break; + } + } + + if (!arg_count) { + /* completed Op, prepare for next */ + + if (acpi_ps_is_named_op (op->opcode)) { + if (acpi_gbl_depth) { + acpi_gbl_depth--; + } + + if (op->opcode == AML_REGION_OP) { + deferred_op = acpi_ps_to_deferred_op (op); + if (deferred_op) { + /* + * Skip parsing of control method or opregion body, + * because we don't have enough info in the first pass + * to parse them correctly. + * + * Completed parsing an Op_region declaration, we now + * know the length. + */ + + deferred_op->body_length = parser_state->aml - + deferred_op->body; + } + } + + +#ifndef PARSER_ONLY + data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode); + + if (op->opcode == AML_NAME_OP) { + if (op->value.arg) { + data_type = acpi_ds_map_opcode_to_data_type ( + (op->value.arg)->opcode, NULL); + ((ACPI_NAMED_OBJECT*)op->acpi_named_object)->type = + (u8) data_type; + } + } + + /* Pop the scope stack */ + + if (acpi_ns_opens_scope (data_type)) { + + acpi_ds_scope_stack_pop (walk_state); + } +#endif + } + + + parser_state->scope->arg_count--; + + + /* Delete op if asked to */ + +#ifndef PARSER_ONLY + if (parse_flags & PARSE_DELETE_TREE) { + acpi_ps_delete_parse_tree (op); + } +#endif + + + if (acpi_ps_has_completed_scope (parser_state)) { + acpi_ps_pop_scope (parser_state, &op, &arg_types); + } + + else { + op = NULL; + } + } + + else { + /* complex argument, push Op and prepare for argument */ + + acpi_ps_push_scope (parser_state, op, arg_types, arg_count); + op = NULL; + } + + } /* while Parser_state->Aml */ + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_parse_aml + * + * PARAMETERS: Start_scope - The starting point of the parse. Becomes the + * root of the parsed op tree. + * Aml - Pointer to the raw AML code to parse + * Aml_size - Length of the AML to parse + * + * RETURN: Status + * + * DESCRIPTION: Parse raw AML and return a tree of ops + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ps_parse_aml ( + ACPI_GENERIC_OP *start_scope, + u8 *aml, + u32 aml_size, + u32 parse_flags) +{ + ACPI_STATUS status; + ACPI_PARSE_STATE *parser_state; + ACPI_WALK_STATE *walk_state; + ACPI_WALK_LIST walk_list; + ACPI_NAMED_OBJECT *entry = NULL; + + + /* Initialize parser state and scope */ + + parser_state = acpi_ps_create_state (aml, aml_size); + if (!parser_state) { + return (AE_NO_MEMORY); + } + + acpi_ps_init_scope (parser_state, start_scope); + + + /* Initialize a new walk list */ + + walk_list.walk_state = NULL; + + walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, &walk_list); + if (!walk_state) { + status = AE_NO_MEMORY; + goto cleanup; + } + + + /* Setup the current scope */ + + entry = parser_state->start_op->acpi_named_object; + if (entry) { + /* Push start scope on scope stack and make it current */ + + status = acpi_ds_scope_stack_push (entry->child_table, entry->type, + walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + } + + + /* Create the parse tree */ + + status = acpi_ps_parse_loop (parser_state, walk_state, parse_flags); + + +cleanup: + + /* Cleanup */ + + acpi_ds_delete_walk_state (walk_state); + acpi_ps_cleanup_scope (parser_state); + acpi_cm_free (parser_state); + + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/parser/psscope.c linux/drivers/acpi/parser/psscope.c --- v2.4.0-test2/linux/drivers/acpi/parser/psscope.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/parser/psscope.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,271 @@ +/****************************************************************************** + * + * Module Name: psscope - Parser scope stack management routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" + +#define _COMPONENT PARSER + MODULE_NAME ("psscope"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_parent_scope + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: Pointer to an Op object + * + * DESCRIPTION: Get parent of current op being parsed + * + ******************************************************************************/ + +ACPI_GENERIC_OP * +acpi_ps_get_parent_scope ( + ACPI_PARSE_STATE *parser_state) +{ + return parser_state->scope->op; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_has_completed_scope + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: Boolean, TRUE = scope completed. + * + * DESCRIPTION: Is parsing of current argument complete? Determined by + * 1) AML pointer is at or beyond the end of the scope + * 2) The scope argument count has reached zero. + * + ******************************************************************************/ + +u8 +acpi_ps_has_completed_scope ( + ACPI_PARSE_STATE *parser_state) +{ + return (u8) ((parser_state->aml >= parser_state->scope->arg_end || + !parser_state->scope->arg_count)); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_init_scope + * + * PARAMETERS: Parser_state - Current parser state object + * Root - the root object of this new scope + * + * RETURN: Status + * + * DESCRIPTION: Allocate and init a new scope object + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ps_init_scope ( + ACPI_PARSE_STATE *parser_state, + ACPI_GENERIC_OP *root) +{ + ACPI_PARSE_SCOPE *scope; + + + scope = acpi_cm_callocate (sizeof (ACPI_PARSE_SCOPE)); + if (!scope) { + return AE_NO_MEMORY; + } + + scope->op = root; + scope->arg_count = ACPI_VAR_ARGS; + scope->arg_end = parser_state->aml_end; + scope->pkg_end = parser_state->aml_end; + parser_state->scope = scope; + parser_state->start_op = root; + + return AE_OK; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_push_scope + * + * PARAMETERS: Parser_state - Current parser state object + * Op - Current op to be pushed + * Next_arg - Next op argument (to be pushed) + * Arg_count - Fixed or variable number of args + * + * RETURN: Status + * + * DESCRIPTION: Push current op to begin parsing its argument + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ps_push_scope ( + ACPI_PARSE_STATE *parser_state, + ACPI_GENERIC_OP *op, + u32 remaining_args, + u32 arg_count) +{ + ACPI_PARSE_SCOPE *scope = parser_state->scope_avail; + + + if (scope) { + /* grabbed scope from available list */ + + parser_state->scope_avail = scope->parent; + } + + else { + /* allocate scope from the heap */ + + scope = (ACPI_PARSE_SCOPE*) acpi_cm_allocate (sizeof (ACPI_PARSE_SCOPE)); + if (!scope) { + return (AE_NO_MEMORY); + } + } + + /* Always zero out the scope before init */ + + MEMSET (scope, 0, sizeof (*scope)); + + scope->op = op; + scope->arg_list = remaining_args; + scope->arg_count = arg_count; + scope->pkg_end = parser_state->pkg_end; + scope->parent = parser_state->scope; + parser_state->scope = scope; + + if (arg_count == ACPI_VAR_ARGS) { + /* multiple arguments */ + + scope->arg_end = parser_state->pkg_end; + } + + else { + /* single argument */ + + scope->arg_end = ACPI_MAX_AML; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_pop_scope + * + * PARAMETERS: Parser_state - Current parser state object + * Op - Where the popped op is returned + * Next_arg - Where the popped "next argument" is + * returned + * + * RETURN: Status + * + * DESCRIPTION: Return to parsing a previous op + * + ******************************************************************************/ + +void +acpi_ps_pop_scope ( + ACPI_PARSE_STATE *parser_state, + ACPI_GENERIC_OP **op, + u32 *arg_list) +{ + ACPI_PARSE_SCOPE *scope = parser_state->scope; + + + if (scope->parent) { + /* return to parsing previous op */ + + *op = scope->op; + *arg_list = scope->arg_list; + parser_state->pkg_end = scope->pkg_end; + parser_state->scope = scope->parent; + + /* add scope to available list */ + + scope->parent = parser_state->scope_avail; + parser_state->scope_avail = scope; + } + + else { + /* empty parse stack, prepare to fetch next opcode */ + + *op = NULL; + *arg_list = 0; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_cleanup_scope + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: Status + * + * DESCRIPTION: Destroy available list, remaining stack levels, and return + * root scope + * + ******************************************************************************/ + +void +acpi_ps_cleanup_scope ( + ACPI_PARSE_STATE *parser_state) +{ + ACPI_PARSE_SCOPE *scope; + + + if (!parser_state) { + return; + } + + /* destroy available list */ + + while (parser_state->scope_avail) { + scope = parser_state->scope_avail; + parser_state->scope_avail = scope->parent; + acpi_cm_free (scope); + } + + /* destroy scope stack */ + + while (parser_state->scope) { + scope = parser_state->scope; + parser_state->scope = scope->parent; + acpi_cm_free (scope); + } + + return; +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/parser/pstree.c linux/drivers/acpi/parser/pstree.c --- v2.4.0-test2/linux/drivers/acpi/parser/pstree.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/parser/pstree.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,399 @@ +/****************************************************************************** + * + * Module Name: pstree - Parser op tree manipulation/traversal/search + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "amlcode.h" + +#define _COMPONENT PARSER + MODULE_NAME ("pstree"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_arg + * + * PARAMETERS: Op - Get an argument for this op + * Argn - Nth argument to get + * + * RETURN: The argument (as an Op object). NULL if argument does not exist + * + * DESCRIPTION: Get the specified op's argument. + * + ******************************************************************************/ + +ACPI_GENERIC_OP * +acpi_ps_get_arg ( + ACPI_GENERIC_OP *op, + u32 argn) +{ + ACPI_GENERIC_OP *arg = NULL; + ACPI_OP_INFO *op_info; + + + /* Get the info structure for this opcode */ + + op_info = acpi_ps_get_opcode_info (op->opcode); + if (!op_info) { + /* Invalid opcode */ + + return NULL; + } + + /* Check if this opcode requires argument sub-objects */ + + if (!(op_info->flags & OP_INFO_HAS_ARGS)) { + /* Has no linked argument objects */ + + return NULL; + } + + /* Get the requested argument object */ + + arg = op->value.arg; + while (arg && argn) { + argn--; + arg = arg->next; + } + + return arg; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_append_arg + * + * PARAMETERS: Op - Append an argument to this Op. + * Arg - Argument Op to append + * + * RETURN: None. + * + * DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK) + * + ******************************************************************************/ + +void +acpi_ps_append_arg ( + ACPI_GENERIC_OP *op, + ACPI_GENERIC_OP *arg) +{ + ACPI_GENERIC_OP *prev_arg; + ACPI_OP_INFO *op_info; + + + if (!op) { + return; + } + + /* Get the info structure for this opcode */ + + op_info = acpi_ps_get_opcode_info (op->opcode); + if (!op_info) { + /* Invalid opcode */ + + return; + } + + /* Check if this opcode requires argument sub-objects */ + + if (!(op_info->flags & OP_INFO_HAS_ARGS)) { + /* Has no linked argument objects */ + + return; + } + + + /* Append the argument to the linked argument list */ + + if (op->value.arg) { + /* Append to existing argument list */ + + prev_arg = op->value.arg; + while (prev_arg->next) { + prev_arg = prev_arg->next; + } + prev_arg->next = arg; + } + + else { + /* No argument list, this will be the first argument */ + + op->value.arg = arg; + } + + + /* Set the parent in this arg and any args linked after it */ + + while (arg) { + arg->parent = op; + arg = arg->next; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_child + * + * PARAMETERS: Op - Get the child of this Op + * + * RETURN: Child Op, Null if none is found. + * + * DESCRIPTION: Get op's children or NULL if none + * + ******************************************************************************/ + +ACPI_GENERIC_OP * +acpi_ps_get_child ( + ACPI_GENERIC_OP *op) +{ + ACPI_GENERIC_OP *child = NULL; + + + switch (op->opcode) + { + case AML_SCOPE_OP: + case AML_ELSE_OP: + case AML_DEVICE_OP: + case AML_THERMAL_ZONE_OP: + case AML_METHODCALL_OP: + + child = acpi_ps_get_arg (op, 0); + break; + + + case AML_BUFFER_OP: + case AML_PACKAGE_OP: + case AML_METHOD_OP: + case AML_IF_OP: + case AML_WHILE_OP: + case AML_DEF_FIELD_OP: + + child = acpi_ps_get_arg (op, 1); + break; + + + case AML_POWER_RES_OP: + case AML_INDEX_FIELD_OP: + + child = acpi_ps_get_arg (op, 2); + break; + + + case AML_PROCESSOR_OP: + case AML_BANK_FIELD_OP: + + child = acpi_ps_get_arg (op, 3); + break; + + } + + return child; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_depth_next + * + * PARAMETERS: Origin - Root of subtree to search + * Op - Last (previous) Op that was found + * + * RETURN: Next Op found in the search. + * + * DESCRIPTION: Get next op in tree (walking the tree in depth-first order) + * Return NULL when reaching "origin" or when walking up from root + * + ******************************************************************************/ + +ACPI_GENERIC_OP * +acpi_ps_get_depth_next ( + ACPI_GENERIC_OP *origin, + ACPI_GENERIC_OP *op) +{ + ACPI_GENERIC_OP *next = NULL; + ACPI_GENERIC_OP *parent; + ACPI_GENERIC_OP *arg; + + + if (!op) { + return NULL; + } + + /* look for an argument or child */ + + next = acpi_ps_get_arg (op, 0); + if (next) { + return next; + } + + /* look for a sibling */ + + next = op->next; + if (next) { + return next; + } + + /* look for a sibling of parent */ + + parent = op->parent; + + while (parent) { + arg = acpi_ps_get_arg (parent, 0); + while (arg && (arg != origin) && (arg != op)) { + arg = arg->next; + } + + if (arg == origin) { + /* reached parent of origin, end search */ + + return NULL; + } + + if (parent->next) { + /* found sibling of parent */ + return parent->next; + } + + op = parent; + parent = parent->parent; + } + + return next; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_fetch_prefix + * + * PARAMETERS: Scope - Op to fetch prefix for + * Path - A namestring containing the prefix + * io - Direction flag + * + * RETURN: Op referenced by the prefix + * + * DESCRIPTION: Fetch and handle path prefix ('\\' or '^') + * + ******************************************************************************/ + +ACPI_GENERIC_OP * +acpi_ps_fetch_prefix ( + ACPI_GENERIC_OP *scope, + char **path, + u32 io) +{ + u32 prefix = io ? GET8 (*path):**path; + + + switch (prefix) + { + case '\\': + case '/': + + /* go to the root */ + + *path += 1; + while (scope->parent) { + scope = scope->parent; + } + break; + + + case '^': + + /* go up one level */ + + *path += 1; + scope = scope->parent; + break; + } + + if (scope && !scope->parent) { + /* searching from the root, start with its children */ + + scope = acpi_ps_get_child (scope); + } + + return scope; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_fetch_name + * + * PARAMETERS: Path - A string containing the name segment + * io - Direction flag + * + * RETURN: The 4-char ASCII ACPI Name as a u32 + * + * DESCRIPTION: Fetch ACPI name segment (dot-delimited) + * + ******************************************************************************/ + +u32 +acpi_ps_fetch_name ( + char **path, + u32 io) +{ + u32 name = 0; + char *nm; + u32 i; + char ch; + + + if (io) { + /* Get the name from the path pointer */ + + MOVE_UNALIGNED32_TO_32 (&name, *path); + *path += 4; + } + + else { + if (**path == '.') { + *path += 1; + } + + nm = (char*) &name; + for (i = 0; i < 4; i++) { + ch = **path; + if (ch && ch != '.') { + *nm = ch; + *path += 1; + } + + else { + *nm = '_'; + } + nm++; + } + } + + return name; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/parser/psutils.c linux/drivers/acpi/parser/psutils.c --- v2.4.0-test2/linux/drivers/acpi/parser/psutils.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/parser/psutils.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,498 @@ +/****************************************************************************** + * + * Module Name: psutils - Parser miscellaneous utilities (Parser only) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "amlcode.h" + +#define _COMPONENT PARSER + MODULE_NAME ("psutils"); + + +#define PARSEOP_GENERIC 1 +#define PARSEOP_NAMED 2 +#define PARSEOP_DEFERRED 3 +#define PARSEOP_BYTELIST 4 + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_init_op + * + * PARAMETERS: Op - A newly allocated Op object + * Opcode - Opcode to store in the Op + * + * RETURN: Status + * + * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on + * opcode + * + ******************************************************************************/ + +void +acpi_ps_init_op ( + ACPI_GENERIC_OP *op, + u16 opcode) +{ + ACPI_OP_INFO *aml_op; + + + op->data_type = ACPI_DESC_TYPE_PARSER; + op->opcode = opcode; + + + aml_op = acpi_ps_get_opcode_info (opcode); + if (aml_op) { + DEBUG_ONLY_MEMBERS (STRNCPY (op->op_name, aml_op->name, + sizeof (op->op_name))); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_alloc_op + * + * PARAMETERS: Opcode - Opcode that will be stored in the new Op + * + * RETURN: Pointer to the new Op. + * + * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on + * opcode. A cache of opcodes is available for the pure + * GENERIC_OP, since this is by far the most commonly used. + * + ******************************************************************************/ + +ACPI_GENERIC_OP* +acpi_ps_alloc_op ( + u16 opcode) +{ + ACPI_GENERIC_OP *op = NULL; + u32 size; + u8 flags; + + + /* Allocate the minimum required size object */ + + if (acpi_ps_is_deferred_op (opcode)) { + size = sizeof (ACPI_DEFERRED_OP); + flags = PARSEOP_DEFERRED; + } + + else if (acpi_ps_is_named_op (opcode)) { + size = sizeof (ACPI_NAMED_OP); + flags = PARSEOP_NAMED; + } + + else if (acpi_ps_is_bytelist_op (opcode)) { + size = sizeof (ACPI_BYTELIST_OP); + flags = PARSEOP_BYTELIST; + } + + else { + size = sizeof (ACPI_GENERIC_OP); + flags = PARSEOP_GENERIC; + + /* + * The generic op is by far the most common (16 to 1), and therefore + * the op cache is implemented with this type. + * + * Check if there is an Op already available in the cache + */ + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + acpi_gbl_parse_cache_requests++; + if (acpi_gbl_parse_cache) { + /* Extract an op from the front of the cache list */ + + acpi_gbl_parse_cache_depth--; + acpi_gbl_parse_cache_hits++; + + op = acpi_gbl_parse_cache; + acpi_gbl_parse_cache = op->next; + + /* Clear the previously used Op */ + + MEMSET (op, 0, sizeof (ACPI_GENERIC_OP)); + } + acpi_cm_release_mutex (ACPI_MTX_CACHES); + } + + /* Allocate a new Op if necessary */ + + if (!op) { + op = acpi_cm_callocate (size); + } + + /* Initialize the Op */ + if (op) { + acpi_ps_init_op (op, opcode); + op->flags = flags; + } + + return op; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_free_op + * + * PARAMETERS: Op - Op to be freed + * + * RETURN: None. + * + * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list + * or actually free it. + * + ******************************************************************************/ + +void +acpi_ps_free_op ( + ACPI_GENERIC_OP *op) +{ + + + if (op->flags == PARSEOP_GENERIC) { + /* Is the cache full? */ + + if (acpi_gbl_parse_cache_depth < MAX_PARSE_CACHE_DEPTH) { + /* Put a GENERIC_OP back into the cache */ + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + acpi_gbl_parse_cache_depth++; + + op->next = acpi_gbl_parse_cache; + acpi_gbl_parse_cache = op; + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + return; + } + } + + /* + * Not a GENERIC OP, or the cache is full, just free the Op + */ + + acpi_cm_free (op); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_delete_parse_cache + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Free all objects that are on the parse cache list. + * + ******************************************************************************/ + +void +acpi_ps_delete_parse_cache ( + void) +{ + ACPI_GENERIC_OP *next; + + + /* Traverse the global cache list */ + + while (acpi_gbl_parse_cache) { + /* Delete one cached state object */ + + next = acpi_gbl_parse_cache->next; + acpi_cm_free (acpi_gbl_parse_cache); + acpi_gbl_parse_cache = next; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Utility functions + * + * DESCRIPTION: Low level functions + * + * TBD: [Restructure] + * 1) Some of these functions should be macros + * 2) Some can be simplified + * + ******************************************************************************/ + + +/* + * Is "c" a namestring lead character? + */ + + +u8 +acpi_ps_is_leading_char ( + s32 c) +{ + return ((u8) (c == '_' || (c >= 'A' && c <= 'Z'))); +} + + +/* + * Is "c" a namestring prefix character? + */ +u8 +acpi_ps_is_prefix_char ( + s32 c) +{ + return ((u8) (c == '\\' || c == '^')); +} + + +u8 +acpi_ps_is_namespace_object_op ( + u16 opcode) +{ + return ((u8) + (opcode == AML_SCOPE_OP || + opcode == AML_DEVICE_OP || + opcode == AML_THERMAL_ZONE_OP || + opcode == AML_METHOD_OP || + opcode == AML_POWER_RES_OP || + opcode == AML_PROCESSOR_OP || + opcode == AML_DEF_FIELD_OP || + opcode == AML_INDEX_FIELD_OP || + opcode == AML_BANK_FIELD_OP || + opcode == AML_NAMEDFIELD_OP || + opcode == AML_NAME_OP || + opcode == AML_ALIAS_OP || + opcode == AML_MUTEX_OP || + opcode == AML_EVENT_OP || + opcode == AML_REGION_OP || + opcode == AML_CREATE_FIELD_OP || + opcode == AML_BIT_FIELD_OP || + opcode == AML_BYTE_FIELD_OP || + opcode == AML_WORD_FIELD_OP || + opcode == AML_DWORD_FIELD_OP || + opcode == AML_METHODCALL_OP || + opcode == AML_NAMEPATH_OP)); +} + +u8 +acpi_ps_is_namespace_op ( + u16 opcode) +{ + return ((u8) + (opcode == AML_SCOPE_OP || + opcode == AML_DEVICE_OP || + opcode == AML_THERMAL_ZONE_OP || + opcode == AML_METHOD_OP || + opcode == AML_POWER_RES_OP || + opcode == AML_PROCESSOR_OP || + opcode == AML_DEF_FIELD_OP || + opcode == AML_INDEX_FIELD_OP || + opcode == AML_BANK_FIELD_OP || + opcode == AML_NAME_OP || + opcode == AML_ALIAS_OP || + opcode == AML_MUTEX_OP || + opcode == AML_EVENT_OP || + opcode == AML_REGION_OP || + opcode == AML_NAMEDFIELD_OP)); +} + + +/* + * Is opcode for a named object Op? + * (Includes all named object opcodes) + * + * TBD: [Restructure] Need a better way than this brute force approach! + */ +u8 +acpi_ps_is_named_object_op ( + u16 opcode) +{ + return ((u8) + (opcode == AML_SCOPE_OP || + opcode == AML_DEVICE_OP || + opcode == AML_THERMAL_ZONE_OP || + opcode == AML_METHOD_OP || + opcode == AML_POWER_RES_OP || + opcode == AML_PROCESSOR_OP || + opcode == AML_NAMEDFIELD_OP || + opcode == AML_NAME_OP || + opcode == AML_ALIAS_OP || + opcode == AML_MUTEX_OP || + opcode == AML_EVENT_OP || + opcode == AML_REGION_OP || + + + opcode == AML_CREATE_FIELD_OP || + opcode == AML_BIT_FIELD_OP || + opcode == AML_BYTE_FIELD_OP || + opcode == AML_WORD_FIELD_OP || + opcode == AML_DWORD_FIELD_OP || + opcode == AML_METHODCALL_OP || + opcode == AML_NAMEPATH_OP)); +} + + +/* + * Is opcode for a named Op? + */ +u8 +acpi_ps_is_named_op ( + u16 opcode) +{ + return ((u8) + (opcode == AML_SCOPE_OP || + opcode == AML_DEVICE_OP || + opcode == AML_THERMAL_ZONE_OP || + opcode == AML_METHOD_OP || + opcode == AML_POWER_RES_OP || + opcode == AML_PROCESSOR_OP || + opcode == AML_NAME_OP || + opcode == AML_ALIAS_OP || + opcode == AML_MUTEX_OP || + opcode == AML_EVENT_OP || + opcode == AML_REGION_OP || + opcode == AML_NAMEDFIELD_OP)); +} + + +u8 +acpi_ps_is_deferred_op ( + u16 opcode) +{ + return ((u8) + (opcode == AML_METHOD_OP || + opcode == AML_REGION_OP)); +} + + +/* + * Is opcode for a bytelist? + */ +u8 +acpi_ps_is_bytelist_op ( + u16 opcode) +{ + return ((u8) (opcode == AML_BYTELIST_OP)); +} + + +/* + * Is opcode for a Field, Index_field, or Bank_field + */ +u8 +acpi_ps_is_field_op ( + u16 opcode) +{ + return ((u8) + (opcode == AML_CREATE_FIELD_OP + || opcode == AML_DEF_FIELD_OP + || opcode == AML_INDEX_FIELD_OP + || opcode == AML_BANK_FIELD_OP)); +} + + +/* + * Is field creation op + */ +u8 +acpi_ps_is_create_field_op ( + u16 opcode) +{ + return ((u8) + (opcode == AML_CREATE_FIELD_OP || + opcode == AML_BIT_FIELD_OP || + opcode == AML_BYTE_FIELD_OP || + opcode == AML_WORD_FIELD_OP || + opcode == AML_DWORD_FIELD_OP)); +} + + +/* + * Cast an acpi_op to an acpi_deferred_op if possible + */ +ACPI_DEFERRED_OP * +acpi_ps_to_deferred_op ( + ACPI_GENERIC_OP *op) +{ + return (acpi_ps_is_deferred_op (op->opcode) + ? ( (ACPI_DEFERRED_OP *) op) : NULL); +} + + +/* + * Cast an acpi_op to an acpi_named_op if possible + */ +ACPI_NAMED_OP* +acpi_ps_to_named_op ( + ACPI_GENERIC_OP *op) +{ + return (acpi_ps_is_named_op (op->opcode) + ? ( (ACPI_NAMED_OP *) op) : NULL); +} + + +/* + * Cast an acpi_op to an acpi_bytelist_op if possible + */ +ACPI_BYTELIST_OP* +acpi_ps_to_bytelist_op ( + ACPI_GENERIC_OP *op) +{ + return (acpi_ps_is_bytelist_op (op->opcode) + ? ( (ACPI_BYTELIST_OP*) op) : NULL); +} + + +/* + * Get op's name (4-byte name segment) or 0 if unnamed + */ +u32 +acpi_ps_get_name ( + ACPI_GENERIC_OP *op) +{ + ACPI_NAMED_OP *named = acpi_ps_to_named_op (op); + + return (named ? named->name : 0); +} + + +/* + * Set op's name + */ +void +acpi_ps_set_name ( + ACPI_GENERIC_OP *op, + u32 name) +{ + ACPI_NAMED_OP *named = acpi_ps_to_named_op (op); + + if (named) { + named->name = name; + } +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/parser/pswalk.c linux/drivers/acpi/parser/pswalk.c --- v2.4.0-test2/linux/drivers/acpi/parser/pswalk.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/parser/pswalk.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,581 @@ +/****************************************************************************** + * + * Module Name: pswalk - Parser routines to walk parsed op tree(s) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "parser.h" +#include "dispatch.h" +#include "namesp.h" +#include "interp.h" + +#define _COMPONENT PARSER + MODULE_NAME ("pswalk"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_walk_op + * + * PARAMETERS: Walk_state - Current state of the walk + * Op - Current Op to be walked + * Ascending_callback - Procedure called when Op is complete + * Prev_op - Where the previous Op is stored + * Next_op - Where the next Op in the walk is stored + * + * RETURN: Status + * + * DESCRIPTION: Get the next Op in a walk of the parse tree. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ps_get_next_walk_op ( + ACPI_WALK_STATE *walk_state, + ACPI_GENERIC_OP *op, + INTERPRETER_CALLBACK ascending_callback) +{ + ACPI_GENERIC_OP *next; + ACPI_GENERIC_OP *parent; + ACPI_GENERIC_OP *grand_parent; + ACPI_STATUS status; + + + /* Check for a argument only if we are descending in the tree */ + + if (walk_state->next_op_info != NEXT_OP_UPWARD) { + /* Look for an argument or child of the current op */ + + next = acpi_ps_get_arg (op, 0); + if (next) { + /* Still going downward in tree (Op is not completed yet) */ + + walk_state->prev_op = op; + walk_state->next_op = next; + walk_state->next_op_info = NEXT_OP_DOWNWARD; + + return (AE_OK); + } + + + /* + * No more children, this Op is complete. Save Next and Parent + * in case the Op object gets deleted by the callback routine + */ + + next = op->next; + parent = op->parent; + + status = ascending_callback (walk_state, op); + + switch (status) + { + case AE_CTRL_TERMINATE: + + /* + * A control method was terminated via a RETURN statement. + * The walk of this method is complete. + */ + walk_state->prev_op = walk_state->origin; + walk_state->next_op = NULL; + + return (AE_OK); + break; + + + case AE_CTRL_FALSE: + + /* + * Either an IF/WHILE Predicate was false or we encountered a BREAK + * opcode. In both cases, we do not execute the rest of the + * package; We simply close out the parent (finishing the walk of + * this branch of the tree) and continue execution at the parent + * level. + */ + + next = parent->next; + status = AE_OK; + + /* + * If there is a sibling to the parent, we must close out the + * parent now, because we are going to continue to go downward (to + * the sibling) in the parse tree. + */ + if (next) { + status = ascending_callback (walk_state, parent); + + /* The parent sibling will be next */ + + walk_state->prev_op = op; + walk_state->next_op = next; + walk_state->next_op_info = NEXT_OP_DOWNWARD; + + /* Continue downward */ + + return (AE_OK); + } + + /* + * Drop into the loop below because we are moving upwards in + * the tree + */ + + break; + + + default: + /* + * Check for a sibling to the current op. A sibling means + * we are still going "downward" in the tree. + */ + + if (next) { + /* There is a sibling, it will be next */ + + walk_state->prev_op = op; + walk_state->next_op = next; + walk_state->next_op_info = NEXT_OP_DOWNWARD; + + /* Continue downward */ + + return (status); + } + + /* + * No sibling, but check status. + * Abort on error from callback routine + */ + if (status != AE_OK) { + /* Next op will be the parent */ + + walk_state->prev_op = op; + walk_state->next_op = parent; + walk_state->next_op_info = NEXT_OP_UPWARD; + + return (status); + } + + /* + * Drop into the loop below because we are moving upwards in + * the tree + */ + + break; + } + } + + else { + /* + * We are resuming a walk, and we were (are) going upward in the tree. + * So, we want to drop into the parent loop below. + */ + + parent = op; + } + + + /* + * Look for a sibling of the current Op's parent + * Continue moving up the tree until we find a node that has not been + * visited, or we get back to where we started. + */ + while (parent) { + /* We are moving up the tree, therefore this parent Op is complete */ + + grand_parent = parent->parent; + next = parent->next; + + status = ascending_callback (walk_state, parent); + + + switch (status) + { + case AE_CTRL_FALSE: + + /* + * Either an IF/WHILE Predicate was false or we encountered a + * BREAK opcode. In both cases, we do not execute the rest of the + * package; We simply close out the parent (finishing the walk of + * this branch of the tree) and continue execution at the parent + * level. + */ + + parent = grand_parent; + next = grand_parent->next; + grand_parent = grand_parent->parent; + + status = ascending_callback (walk_state, parent); + + /* Now continue to the next node in the tree */ + + break; + + + case AE_CTRL_TRUE: + + /* + * Predicate of a WHILE was true and the loop just completed an + * execution. Go back to the start of the loop and reevaluate the + * predicate. + */ + + op = walk_state->control_state->control.predicate_op; + + walk_state->control_state->common.state = CONTROL_PREDICATE_EXECUTING; + + /* + * Acpi_evaluate the predicate again (next) + * Because we will traverse WHILE tree again + */ + + walk_state->prev_op = op->parent; + walk_state->next_op = op; + walk_state->next_op_info = NEXT_OP_DOWNWARD; + + return (AE_OK); + break; + + + case AE_CTRL_TERMINATE: + + /* + * A control method was terminated via a RETURN statement. + * The walk of this method is complete. + */ + walk_state->prev_op = walk_state->origin; + walk_state->next_op = NULL; + + return (AE_OK); + break; + } + + + /* + * If we are back to the starting point, the walk is complete. + */ + if (parent == walk_state->origin) { + /* Reached the point of origin, the walk is complete */ + + walk_state->prev_op = parent; + walk_state->next_op = NULL; + + return (status); + } + + + /* + * If there is a sibling to this parent (it is not the starting point + * Op), then we will visit it. + */ + if (next) { + /* found sibling of parent */ + + walk_state->prev_op = parent; + walk_state->next_op = next; + walk_state->next_op_info = NEXT_OP_DOWNWARD; + + return (status); + } + + /* + * No sibling, check for an error from closing the parent + * (Also, AE_PENDING if a method call was encountered) + */ + if (status != AE_OK) { + walk_state->prev_op = parent; + walk_state->next_op = grand_parent; + walk_state->next_op_info = NEXT_OP_UPWARD; + + return (status); + } + + /* No siblings, no errors, just move up one more level in the tree */ + + op = parent; + parent = grand_parent; + walk_state->prev_op = op; + } + + + /* Got all the way to the top of the tree, we must be done! */ + /* However, the code should have terminated in the loop above */ + + walk_state->next_op = NULL; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_walk_loop + * + * PARAMETERS: Walk_list - State of the walk + * Start_op - Starting Op of the subtree to be walked + * Descending_callback - Procedure called when a new Op is + * encountered + * Ascending_callback - Procedure called when Op is complete + * + * RETURN: Status + * + * DESCRIPTION: Perform a walk of the parsed AML tree. Begins and terminates at + * the Start_op. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ps_walk_loop ( + ACPI_WALK_LIST *walk_list, + ACPI_GENERIC_OP *start_op, + INTERPRETER_CALLBACK descending_callback, + INTERPRETER_CALLBACK ascending_callback) +{ + ACPI_STATUS status = AE_OK; + ACPI_WALK_STATE *walk_state; + ACPI_GENERIC_OP *op = start_op; + + + walk_state = acpi_ds_get_current_walk_state (walk_list); + + + /* Walk entire subtree, visiting all nodes depth-first */ + + while (op) { + if (walk_state->next_op_info != NEXT_OP_UPWARD) { + status = descending_callback (walk_state, op); + } + + /* + * A TRUE exception means that an ELSE was detected, but the IF + * predicate evaluated TRUE. + */ + if (status == AE_CTRL_TRUE) { + /* + * Ignore the entire ELSE block by moving on to the the next opcode. + * And we do that by simply going up in the tree (either to the next + * sibling or to the parent) from here. + */ + + walk_state->next_op_info = NEXT_OP_UPWARD; + } + + /* Get the next node (op) in the depth-first walk */ + + status = acpi_ps_get_next_walk_op (walk_state, op, ascending_callback); + + /* + * A PENDING exception means that a control method invocation has been + * detected + */ + + if (status == AE_CTRL_PENDING) { + /* Transfer control to the called control method */ + + status = acpi_ds_call_control_method (walk_list, walk_state, op); + + /* + * If the transfer to the new method method call worked, a new walk + * state was created -- get it + */ + + walk_state = acpi_ds_get_current_walk_state (walk_list); + } + + /* Abort the walk on any exception */ + + if (ACPI_FAILURE (status)) { + return (status); + } + + op = walk_state->next_op; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_walk_parsed_aml + * + * PARAMETERS: Start_op - Starting Op of the subtree to be walked + * End_op - Where to terminate the walk + * Descending_callback - Procedure called when a new Op is + * encountered + * Ascending_callback - Procedure called when Op is complete + * + * RETURN: Status + * + * DESCRIPTION: Top level interface to walk the parsed AML tree. Handles + * preemption of executing control methods. + * + * NOTE: The End_op is usually only different from the Start_op if + * we don't want to visit the Start_op during the tree descent. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ps_walk_parsed_aml ( + ACPI_GENERIC_OP *start_op, + ACPI_GENERIC_OP *end_op, + ACPI_OBJECT_INTERNAL *mth_desc, + ACPI_NAME_TABLE *start_scope, + ACPI_OBJECT_INTERNAL **params, + ACPI_OBJECT_INTERNAL **caller_return_desc, + ACPI_OWNER_ID owner_id, + INTERPRETER_CALLBACK descending_callback, + INTERPRETER_CALLBACK ascending_callback) +{ + ACPI_GENERIC_OP *op; + ACPI_WALK_STATE *walk_state; + ACPI_OBJECT_INTERNAL *return_desc; + ACPI_STATUS status; + ACPI_WALK_LIST walk_list; + ACPI_WALK_LIST *prev_walk_list; + + + /* Parameter Validation */ + + if (!start_op || !end_op) { + return AE_BAD_PARAMETER; + } + + /* Initialize a new walk list */ + + walk_list.walk_state = NULL; + + walk_state = acpi_ds_create_walk_state (owner_id, end_op, mth_desc, &walk_list); + if (!walk_state) { + return (AE_NO_MEMORY); + } + + /* TBD: [Restructure] TEMP until we pass Walk_state to the interpreter + */ + prev_walk_list = acpi_gbl_current_walk_list; + acpi_gbl_current_walk_list = &walk_list; + + if (start_scope) { + /* Push start scope on scope stack and make it current */ + + status = acpi_ds_scope_stack_push (start_scope, ACPI_TYPE_METHOD, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + } + + if (mth_desc) { + /* Init arguments if this is a control method */ + /* TBD: [Restructure] add walkstate as a param */ + + acpi_ds_method_data_init_args (params, MTH_NUM_ARGS); + } + + op = start_op; + status = AE_OK; + + + /* + * Execute the walk loop as long as there is a valid Walk State. This + * handles nested control method invocations without recursion. + */ + + while (walk_state) { + if (status == AE_OK) { + status = acpi_ps_walk_loop (&walk_list, op, descending_callback, + ascending_callback); + } + + /* We are done with this walk, move on to the parent if any */ + + BREAKPOINT3; + + walk_state = acpi_ds_pop_walk_state (&walk_list); + + /* Extract return value before we delete Walk_state */ + + return_desc = walk_state->return_desc; + + /* Reset the current scope to the beginning of scope stack */ + + acpi_ds_scope_stack_clear (walk_state); + + /* + * If we just returned from the execution of a control method, + * there's lots of cleanup to do + */ + + if (walk_state->method_desc && + walk_state->method_desc->method.parser_op) + { + acpi_ds_terminate_control_method (walk_state); + } + + /* Delete this walk state and all linked control states */ + + acpi_ds_delete_walk_state (walk_state); + + /* Check if we have restarted a preempted walk */ + + walk_state = acpi_ds_get_current_walk_state (&walk_list); + if (walk_state && + status == AE_OK) + { + /* There is another walk state, restart it */ + + /* + * If the method returned value is not used by the parent, + * The object is deleted + */ + + acpi_ds_restart_control_method (walk_state, return_desc); + + /* Get the next Op to process */ + + op = walk_state->next_op; + } + + /* + * Just completed a 1st-level method, save the final internal return + * value (if any) + */ + + else if (caller_return_desc) { + *caller_return_desc = return_desc; /* NULL if no return value */ + } + + else if (return_desc) { + /* Caller doesn't want it, must delete it */ + + acpi_cm_remove_reference (return_desc); + } + } + + + acpi_gbl_current_walk_list = prev_walk_list; + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/parser/psxface.c linux/drivers/acpi/parser/psxface.c --- v2.4.0-test2/linux/drivers/acpi/parser/psxface.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/parser/psxface.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,132 @@ + +/****************************************************************************** + * + * Module Name: psxface - Parser external interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "parser.h" +#include "dispatch.h" +#include "interp.h" +#include "amlcode.h" +#include "namesp.h" + + +#define _COMPONENT PARSER + MODULE_NAME ("psxface"); + + +char *acpi_gbl_parser_id = "Non-recursive AML Parser"; + + +/***************************************************************************** + * + * FUNCTION: Acpi_psx_execute + * + * PARAMETERS: Obj_desc - A method object containing both the AML + * address and length. + * **Params - List of parameters to pass to method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method + * + ****************************************************************************/ + +ACPI_STATUS +acpi_psx_execute ( + ACPI_NAMED_OBJECT *method_entry, + ACPI_OBJECT_INTERNAL **params, + ACPI_OBJECT_INTERNAL **return_obj_desc) +{ + ACPI_STATUS status; + ACPI_OBJECT_INTERNAL *obj_desc; + u32 i; + + + /* Validate the NTE and get the attached object */ + + if (!method_entry) { + return (AE_NULL_ENTRY); + } + + obj_desc = acpi_ns_get_attached_object (method_entry); + if (!obj_desc) { + return (AE_NULL_OBJECT); + } + + /* Parse method if necessary, wait on concurrency semaphore */ + + status = acpi_ds_begin_method_execution (method_entry, obj_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + + if (params) { + /* + * The caller "owns" the parameters, so give each one an extra + * reference + */ + + for (i = 0; params[i]; i++) { + acpi_cm_add_reference (params[i]); + } + } + + /* + * Method is parsed and ready to execute + * The walk of the parse tree is where we actually execute the method + */ + + status = acpi_ps_walk_parsed_aml (obj_desc->method.parser_op, + obj_desc->method.parser_op, obj_desc, + method_entry->child_table, params, return_obj_desc, + obj_desc->method.owning_id, acpi_ds_exec_begin_op, + acpi_ds_exec_end_op); + + if (params) { + /* Take away the extra reference that we gave the parameters above */ + + for (i = 0; params[i]; i++) { + acpi_cm_update_object_reference (params[i], REF_DECREMENT); + } + } + + + /* + * Normal exit is with Status == AE_RETURN_VALUE when a Return_op has been + * executed, or with Status == AE_PENDING at end of AML block (end of + * Method code) + */ + + if (*return_obj_desc) { + status = AE_CTRL_RETURN_VALUE; + } + + + return (status); +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/resources/rsaddr.c linux/drivers/acpi/resources/rsaddr.c --- v2.4.0-test2/linux/drivers/acpi/resources/rsaddr.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/resources/rsaddr.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,810 @@ +/****************************************************************************** + * + * Module Name: rsaddr - Acpi_rs_address16_resource + * Acpi_rs_address16_stream + * Acpi_rs_address32_resource + * Acpi_rs_address32_stream + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" + +#define _COMPONENT RESOURCE_MANAGER + MODULE_NAME ("rsaddr"); + + +/*************************************************************************** + * FUNCTION: Acpi_rs_address16_resource + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_address16_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u32 index; + u32 struct_size = sizeof(ADDRESS16_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + + temp16 = *(u16 *)buffer; + + *bytes_consumed = temp16 + 3; + + output_struct->id = address16; + + output_struct->length = struct_size; + + /* + * Get the Resource Type (Byte3) + */ + buffer += 2; + temp8 = *buffer; + + /* Values 0-2 are valid */ + if (temp8 > 2) { + return (AE_ERROR); + } + + output_struct->data.address16.resource_type = temp8 & 0x03; + + /* + * Get the General Flags (Byte4) + */ + buffer += 1; + temp8 = *buffer; + + /* + * Producer / Consumer + */ + output_struct->data.address16.producer_consumer = temp8 & 0x01; + + /* + * Decode + */ + output_struct->data.address16.decode = (temp8 >> 1) & 0x01; + + /* + * Min Address Fixed + */ + output_struct->data.address16.min_address_fixed = (temp8 >> 2) & 0x01; + + /* + * Max Address Fixed + */ + output_struct->data.address16.max_address_fixed = (temp8 >> 3) & 0x01; + + /* + * Get the Type Specific Flags (Byte5) + */ + buffer += 1; + temp8 = *buffer; + + if (MEMORY_RANGE == output_struct->data.address16.resource_type) { + output_struct->data.address16.attribute.memory.read_write_attribute = + (u16) (temp8 & 0x01); + output_struct->data.address16.attribute.memory.cache_attribute = + (u16) ((temp8 >> 1) & 0x0F); + } + + else { + if (IO_RANGE == output_struct->data.address16.resource_type) { + output_struct->data.address16.attribute.io.range_attribute = + (u16) (temp8 & 0x03); + } + + else { + /* BUS_NUMBER_RANGE == Address32_data->Resource_type */ + /* Nothing needs to be filled in */ + } + } + + /* + * Get Granularity (Bytes 6-7) + */ + buffer += 1; + MOVE_UNALIGNED16_TO_16 (&output_struct->data.address16.granularity, + buffer); + + /* + * Get Min_address_range (Bytes 8-9) + */ + buffer += 2; + MOVE_UNALIGNED16_TO_16 (&output_struct->data.address16.min_address_range, + buffer); + + /* + * Get Max_address_range (Bytes 10-11) + */ + buffer += 2; + MOVE_UNALIGNED16_TO_16 + (&output_struct->data.address16.max_address_range, + buffer); + + /* + * Get Address_translation_offset (Bytes 12-13) + */ + buffer += 2; + MOVE_UNALIGNED16_TO_16 + (&output_struct->data.address16.address_translation_offset, + buffer); + + /* + * Get Address_length (Bytes 14-15) + */ + buffer += 2; + MOVE_UNALIGNED16_TO_16 + (&output_struct->data.address16.address_length, + buffer); + + /* + * Resource Source Index (if present) + */ + buffer += 2; + + /* + * This will leave us pointing to the Resource Source Index + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * Each Interrupt takes 32-bits + the 5 bytes of the + * stream that are default. + */ + if (*bytes_consumed > 16) { + /* Dereference the Index */ + + temp8 = *buffer; + output_struct->data.address16.resource_source_index = + (u32) temp8; + + /* Point to the String */ + + buffer += 1; + + /* Copy the string into the buffer */ + + index = 0; + + while (0x00 != *buffer) { + output_struct->data.address16.resource_source[index] = + *buffer; + + buffer += 1; + index += 1; + } + + /* + * Add the terminating null + */ + output_struct->data.address16.resource_source[index] = 0x00; + + output_struct->data.address16.resource_source_string_length = + index + 1; + + /* + * In order for the Struct_size to fall on a 32-bit boundry, + * calculate the length of the string and expand the + * Struct_size to the next 32-bit boundry. + */ + temp8 = (u8) (index + 1); + struct_size += ROUND_UP_TO_32_bITS (temp8); + } + else { + output_struct->data.address16.resource_source_index = 0x00; + output_struct->data.address16.resource_source_string_length = 0; + output_struct->data.address16.resource_source[0] = 0x00; + } + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_address16_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_address16_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u8 *length_field; + u8 temp8 = 0; + u8 *temp_pointer = NULL; + u32 actual_bytes; + + + /* + * The descriptor field is static + */ + *buffer = 0x88; + buffer += 1; + + /* + * Save a pointer to the Length field - to be filled in later + */ + length_field = buffer; + buffer += 2; + + /* + * Set the Resource Type (Memory, Io, Bus_number) + */ + temp8 = (u8) (linked_list->data.address16.resource_type & 0x03); + *buffer = temp8; + buffer += 1; + + /* + * Set the general flags + */ + temp8 = (u8) (linked_list->data.address16.producer_consumer & 0x01); + + temp8 |= (linked_list->data.address16.decode & 0x01) << 1; + temp8 |= (linked_list->data.address16.min_address_fixed & 0x01) << 2; + temp8 |= (linked_list->data.address16.max_address_fixed & 0x01) << 3; + + *buffer = temp8; + buffer += 1; + + /* + * Set the type specific flags + */ + temp8 = 0; + + if (MEMORY_RANGE == linked_list->data.address16.resource_type) { + temp8 = (u8) + (linked_list->data.address16.attribute.memory.read_write_attribute & + 0x01); + + temp8 |= + (linked_list->data.address16.attribute.memory.cache_attribute & + 0x0F) << 1; + } + + else if (IO_RANGE == linked_list->data.address16.resource_type) { + temp8 = (u8) + (linked_list->data.address16.attribute.io.range_attribute & + 0x03); + } + + *buffer = temp8; + buffer += 1; + + /* + * Set the address space granularity + */ + MOVE_UNALIGNED16_TO_16 (buffer, + &linked_list->data.address16.granularity); + buffer += 2; + + /* + * Set the address range minimum + */ + MOVE_UNALIGNED16_TO_16 (buffer, + &linked_list->data.address16.min_address_range); + + buffer += 2; + + /* + * Set the address range maximum + */ + MOVE_UNALIGNED16_TO_16 (buffer, + &linked_list->data.address16.max_address_range); + + buffer += 2; + + /* + * Set the address translation offset + */ + MOVE_UNALIGNED16_TO_16 (buffer, + &linked_list->data.address16.address_translation_offset); + + buffer += 2; + + /* + * Set the address length + */ + MOVE_UNALIGNED16_TO_16 (buffer, + &linked_list->data.address16.address_length); + + buffer += 2; + + /* + * Resource Source Index and Resource Source are optional + */ + if (0 != linked_list->data.address16.resource_source_string_length) { + temp8 = (u8) linked_list->data.address16.resource_source_index; + + *buffer = temp8; + buffer += 1; + + temp_pointer = buffer; + + /* + * Copy the string + */ + STRCPY (temp_pointer, linked_list->data.address16.resource_source); + + /* + * Buffer needs to be set to the length of the sting + one for the + * terminating null + */ + buffer += (STRLEN (linked_list->data.address16.resource_source) + 1); + } + + /* + * Return the number of bytes consumed in this operation + */ + actual_bytes = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + *bytes_consumed = actual_bytes; + + /* + * Set the length field to the number of bytes consumed + * minus the header size (3 bytes) + */ + actual_bytes -= 3; + MOVE_UNALIGNED16_TO_16 (length_field, &actual_bytes); + + return (AE_OK); +} + +/*************************************************************************** + * FUNCTION: Acpi_rs_address32_resource + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_address32_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u32 struct_size = sizeof (ADDRESS32_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + u32 index; + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + *bytes_consumed = temp16 + 3; + + output_struct->id = address32; + + /* + * Get the Resource Type (Byte3) + */ + buffer += 2; + temp8 = *buffer; + + /* Values 0-2 are valid */ + if(temp8 > 2) { + return (AE_ERROR); + } + + output_struct->data.address32.resource_type = temp8 & 0x03; + + /* + * Get the General Flags (Byte4) + */ + buffer += 1; + temp8 = *buffer; + + /* + * Producer / Consumer + */ + output_struct->data.address32.producer_consumer = temp8 & 0x01; + + /* + * Decode + */ + output_struct->data.address32.decode = (temp8 >> 1) & 0x01; + + /* + * Min Address Fixed + */ + output_struct->data.address32.min_address_fixed = (temp8 >> 2) & 0x01; + + /* + * Max Address Fixed + */ + output_struct->data.address32.max_address_fixed = (temp8 >> 3) & 0x01; + + /* + * Get the Type Specific Flags (Byte5) + */ + buffer += 1; + temp8 = *buffer; + + if (MEMORY_RANGE == output_struct->data.address32.resource_type) { + output_struct->data.address32.attribute.memory.read_write_attribute = + (u16) (temp8 & 0x01); + + output_struct->data.address32.attribute.memory.cache_attribute = + (u16) ((temp8 >> 1) & 0x0F); + } + + else { + if (IO_RANGE == output_struct->data.address32.resource_type) { + output_struct->data.address32.attribute.io.range_attribute = + (u16) (temp8 & 0x03); + } + + else { + /* BUS_NUMBER_RANGE == Output_struct->Data.Address32.Resource_type */ + /* Nothing needs to be filled in */ + } + } + + /* + * Get Granularity (Bytes 6-9) + */ + buffer += 1; + MOVE_UNALIGNED32_TO_32 (&output_struct->data.address32.granularity, + buffer); + + /* + * Get Min_address_range (Bytes 10-13) + */ + buffer += 4; + MOVE_UNALIGNED32_TO_32 (&output_struct->data.address32.min_address_range, + buffer); + + /* + * Get Max_address_range (Bytes 14-17) + */ + buffer += 4; + MOVE_UNALIGNED32_TO_32 (&output_struct->data.address32.max_address_range, + buffer); + + /* + * Get Address_translation_offset (Bytes 18-21) + */ + buffer += 4; + MOVE_UNALIGNED32_TO_32 + (&output_struct->data.address32.address_translation_offset, + buffer); + + /* + * Get Address_length (Bytes 22-25) + */ + buffer += 4; + MOVE_UNALIGNED32_TO_32 (&output_struct->data.address32.address_length, + buffer); + + /* + * Resource Source Index (if present) + */ + buffer += 4; + + /* + * This will leave us pointing to the Resource Source Index + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * Each Interrupt takes 32-bits + the 5 bytes of the + * stream that are default. + */ + if (*bytes_consumed > 26) { + /* Dereference the Index */ + + temp8 = *buffer; + output_struct->data.address32.resource_source_index = (u32)temp8; + + /* Point to the String */ + + buffer += 1; + + /* Copy the string into the buffer */ + + index = 0; + + while (0x00 != *buffer) { + output_struct->data.address32.resource_source[index] = *buffer; + buffer += 1; + index += 1; + } + + /* + * Add the terminating null + */ + output_struct->data.address32.resource_source[index] = 0x00; + + output_struct->data.address32.resource_source_string_length = index + 1; + + /* + * In order for the Struct_size to fall on a 32-bit boundry, + * calculate the length of the string and expand the + * Struct_size to the next 32-bit boundry. + */ + temp8 = (u8) (index + 1); + struct_size += ROUND_UP_TO_32_bITS (temp8); + } + + else { + output_struct->data.address32.resource_source_index = 0x00; + output_struct->data.address32.resource_source_string_length = 0; + output_struct->data.address32.resource_source[0] = 0x00; + } + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_address32_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_address32_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 *length_field; + u8 temp8 = 0; + u8 *temp_pointer = NULL; + + + /* + * The descriptor field is static + */ + *buffer = 0x87; + + buffer += 1; + + /* + * Set a pointer to the Length field - to be filled in later + */ + + length_field = (u16 *)buffer; + + buffer += 2; + + /* + * Set the Resource Type (Memory, Io, Bus_number) + */ + temp8 = (u8) (linked_list->data.address32.resource_type & 0x03); + + *buffer = temp8; + + buffer += 1; + + /* + * Set the general flags + */ + temp8 = (u8) (linked_list->data.address32.producer_consumer & 0x01); + + temp8 |= (linked_list->data.address32.decode & 0x01) << 1; + + temp8 |= (linked_list->data.address32.min_address_fixed & 0x01) << 2; + + temp8 |= (linked_list->data.address32.max_address_fixed & 0x01) << 3; + + *buffer = temp8; + + buffer += 1; + + /* + * Set the type specific flags + */ + temp8 = 0; + + if(MEMORY_RANGE == linked_list->data.address32.resource_type) { + temp8 = (u8) + (linked_list->data.address32.attribute.memory.read_write_attribute & + 0x01); + + temp8 |= + (linked_list->data.address32.attribute.memory.cache_attribute & + 0x0F) << 1; + } + + else if (IO_RANGE == linked_list->data.address32.resource_type) { + temp8 = (u8) + (linked_list->data.address32.attribute.io.range_attribute & + 0x03); + } + + *buffer = temp8; + buffer += 1; + + /* + * Set the address space granularity + */ + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.address32.granularity); + buffer += 4; + + /* + * Set the address range minimum + */ + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.address32.min_address_range); + + buffer += 4; + + /* + * Set the address range maximum + */ + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.address32.max_address_range); + + buffer += 4; + + /* + * Set the address translation offset + */ + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.address32.address_translation_offset); + + buffer += 4; + + /* + * Set the address length + */ + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.address32.address_length); + + buffer += 4; + + /* + * Resource Source Index and Resource Source are optional + */ + if (0 != linked_list->data.address32.resource_source_string_length) { + temp8 = (u8) linked_list->data.address32.resource_source_index; + + *buffer = temp8; + + buffer += 1; + + temp_pointer = buffer; + + /* + * Copy the string + */ + STRCPY (temp_pointer, linked_list->data.address32.resource_source); + + /* + * Buffer needs to be set to the length of the sting + one for the + * terminating null + */ + buffer += (STRLEN (linked_list->data.address32.resource_source) + 1); + } + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + /* + * Set the length field to the number of bytes consumed + * minus the header size (3 bytes) + */ + *length_field = (u16) (*bytes_consumed - 3); + + return (AE_OK); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/resources/rscalc.c linux/drivers/acpi/resources/rscalc.c --- v2.4.0-test2/linux/drivers/acpi/resources/rscalc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/resources/rscalc.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,754 @@ +/****************************************************************************** + * + * Module Name: rscalc - Acpi_rs_calculate_byte_stream_length + * Acpi_rs_calculate_list_length + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" + +#define _COMPONENT RESOURCE_MANAGER + MODULE_NAME ("rscalc"); + + +/*************************************************************************** + * FUNCTION: Acpi_rs_calculate_byte_stream_length + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Size_needed - u32 pointer of the size buffer needed + * to properly return the parsed data + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Takes the resource byte stream and parses it once, calculating + * the size buffer needed to hold the linked list that conveys + * the resource data. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_calculate_byte_stream_length ( + RESOURCE *linked_list, + u32 *size_needed) +{ + ACPI_STATUS status = AE_OK; + u32 byte_stream_size_needed = 0; + u32 size_of_this_bit; + EXTENDED_IRQ_RESOURCE *ex_irq = NULL; + u8 done = FALSE; + + + while (!done) { + + /* + * Init the variable that will hold the size to add to the + * total. + */ + size_of_this_bit = 0; + + switch (linked_list->id) + { + case irq: + /* + * IRQ Resource + */ + /* + * For an IRQ Resource, Byte 3, although optional, will + * always be created - it holds IRQ information. + */ + size_of_this_bit = 4; + break; + + case dma: + /* + * DMA Resource + */ + /* + * For this resource the size is static + */ + size_of_this_bit = 3; + break; + + case start_dependent_functions: + /* + * Start Dependent Functions Resource + */ + /* + * For a Start_dependent_functions Resource, Byte 1, + * although optional, will always be created. + */ + size_of_this_bit = 2; + break; + + case end_dependent_functions: + /* + * End Dependent Functions Resource + */ + /* + * For this resource the size is static + */ + size_of_this_bit = 1; + break; + + case io: + /* + * IO Port Resource + */ + /* + * For this resource the size is static + */ + size_of_this_bit = 8; + break; + + case fixed_io: + /* + * Fixed IO Port Resource + */ + /* + * For this resource the size is static + */ + size_of_this_bit = 4; + break; + + case vendor_specific: + /* + * Vendor Defined Resource + */ + /* + * For a Vendor Specific resource, if the Length is + * between 1 and 7 it will be created as a Small + * Resource data type, otherwise it is a Large + * Resource data type. + */ + if(linked_list->data.vendor_specific.length > 7) { + size_of_this_bit = 3; + } + else { + size_of_this_bit = 1; + } + size_of_this_bit += + linked_list->data.vendor_specific.length; + break; + + case end_tag: + /* + * End Tag + */ + /* + * For this resource the size is static + */ + size_of_this_bit = 2; + done = TRUE; + break; + + case memory24: + /* + * 24-Bit Memory Resource + */ + /* + * For this resource the size is static + */ + size_of_this_bit = 12; + break; + + case memory32: + /* + * 32-Bit Memory Range Resource + */ + /* + * For this resource the size is static + */ + size_of_this_bit = 20; + break; + + case fixed_memory32: + /* + * 32-Bit Fixed Memory Resource + */ + /* + * For this resource the size is static + */ + size_of_this_bit = 12; + break; + + case address16: + /* + * 16-Bit Address Resource + */ + /* + * The base size of this byte stream is 16. If a + * Resource Source string is not NULL, add 1 for + * the Index + the length of the null terminated + * string Resource Source + 1 for the null. + */ + size_of_this_bit = 16; + + if(NULL != linked_list->data.address16.resource_source) { + size_of_this_bit += (1 + + linked_list->data.address16.resource_source_string_length); + } + break; + + case address32: + /* + * 32-Bit Address Resource + */ + /* + * The base size of this byte stream is 26. If a Resource + * Source string is not NULL, add 1 for the Index + the + * length of the null terminated string Resource Source + + * 1 for the null. + */ + size_of_this_bit = 26; + + if(NULL != linked_list->data.address16.resource_source) { + size_of_this_bit += (1 + + linked_list->data.address16.resource_source_string_length); + } + break; + + case extended_irq: + /* + * Extended IRQ Resource + */ + /* + * The base size of this byte stream is 9. This is for an + * Interrupt table length of 1. For each additional + * interrupt, add 4. + * If a Resource Source string is not NULL, add 1 for the + * Index + the length of the null terminated string + * Resource Source + 1 for the null. + */ + size_of_this_bit = 9; + + size_of_this_bit += + (linked_list->data.extended_irq.number_of_interrupts - + 1) * 4; + + if(NULL != ex_irq->resource_source) { + size_of_this_bit += (1 + + linked_list->data.extended_irq.resource_source_string_length); + } + break; + + default: + /* + * If we get here, everything is out of sync, + * so exit with an error + */ + return (AE_ERROR); + break; + + } /* switch (Linked_list->Id) */ + + /* + * Update the total + */ + byte_stream_size_needed += size_of_this_bit; + + /* + * Point to the next object + */ + linked_list = (RESOURCE *) ((NATIVE_UINT) linked_list + + (NATIVE_UINT) linked_list->length); + } + + /* + * This is the data the caller needs + */ + *size_needed = byte_stream_size_needed; + + return (status); + +} /* Acpi_rs_calculate_byte_stream_length */ + + +/*************************************************************************** + * FUNCTION: Acpi_rs_calculate_list_length + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource byte stream + * Byte_stream_buffer_length - Size of Byte_stream_buffer + * Size_needed - u32 pointer of the size buffer + * needed to properly return the + * parsed data + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Takes the resource byte stream and parses it once, calculating + * the size buffer needed to hold the linked list that conveys + * the resource data. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_calculate_list_length ( + u8 *byte_stream_buffer, + u32 byte_stream_buffer_length, + u32 *size_needed) +{ + u32 buffer_size = 0; + u32 bytes_parsed = 0; + u8 resource_type = 0; + u32 structure_size = 0; + u32 bytes_consumed = 0; + u8 *buffer; + u8 number_of_interrupts = 0; + u8 temp8; + u16 temp16; + u8 index; + u8 number_of_channels = 0; + u8 additional_bytes = 0; + + + while (bytes_parsed < byte_stream_buffer_length) { + /* + * Look at the next byte in the stream + */ + resource_type = *byte_stream_buffer; + + /* + * See if this is a small or large resource + */ + if(resource_type & 0x80) { + /* + * Large Resource Type + */ + switch (resource_type) + { + case MEMORY_RANGE_24: + /* + * 24-Bit Memory Resource + */ + bytes_consumed = 12; + + structure_size = sizeof (MEMORY24_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + break; + + case LARGE_VENDOR_DEFINED: + /* + * Vendor Defined Resource + */ + buffer = byte_stream_buffer; + ++buffer; + + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + bytes_consumed = temp16 + 3; + + /* + * Ensure a 32-bit boundary for the structure + */ + temp16 = (u16) ROUND_UP_TO_32_bITS (temp16); + + structure_size = sizeof (VENDOR_RESOURCE) + + RESOURCE_LENGTH_NO_DATA + + (temp16 * sizeof (u8)); + break; + + case MEMORY_RANGE_32: + /* + * 32-Bit Memory Range Resource + */ + + bytes_consumed = 20; + + structure_size = sizeof (MEMORY32_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + break; + + case FIXED_MEMORY_RANGE_32: + /* + * 32-Bit Fixed Memory Resource + */ + bytes_consumed = 12; + + structure_size = sizeof(FIXED_MEMORY32_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + break; + + case DWORD_ADDRESS_SPACE: + /* + * 32-Bit Address Resource + */ + buffer = byte_stream_buffer; + + ++buffer; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + bytes_consumed = temp16 + 3; + + /* + * Resource Source Index and Resource Source are + * optional elements. Check the length of the + * Bytestream. If it is greater than 23, that + * means that an Index exists and is followed by + * a null termininated string. Therefore, set + * the temp variable to the length minus the minimum + * byte stream length plus the byte for the Index to + * determine the size of the NULL terminiated string. + */ + if (23 < temp16) { + temp8 = (u8) (temp16 - 24); + } + else { + temp8 = 0; + } + + /* + * Ensure a 32-bit boundary for the structure + */ + temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); + + structure_size = sizeof (ADDRESS32_RESOURCE) + + RESOURCE_LENGTH_NO_DATA + + (temp8 * sizeof (u8)); + break; + + case WORD_ADDRESS_SPACE: + /* + * 16-Bit Address Resource + */ + buffer = byte_stream_buffer; + + ++buffer; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + bytes_consumed = temp16 + 3; + + /* + * Resource Source Index and Resource Source are + * optional elements. Check the length of the + * Bytestream. If it is greater than 13, that + * means that an Index exists and is followed by + * a null termininated string. Therefore, set + * the temp variable to the length minus the minimum + * byte stream length plus the byte for the Index to + * determine the size of the NULL terminiated string. + */ + if (13 < temp16) { + temp8 = (u8) (temp16 - 14); + } + else { + temp8 = 0; + } + + /* + * Ensure a 32-bit boundry for the structure + */ + temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); + + structure_size = sizeof (ADDRESS16_RESOURCE) + + RESOURCE_LENGTH_NO_DATA + + (temp8 * sizeof (u8)); + break; + + case EXTENDED_IRQ: + /* + * Extended IRQ + */ + buffer = byte_stream_buffer; + + ++buffer; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + bytes_consumed = temp16 + 3; + + /* + * Point past the length field and the + * Interrupt vector flags to save off the + * Interrupt table length to the Temp8 variable. + */ + buffer += 3; + + temp8 = *buffer; + + /* + * To compensate for multiple interrupt numbers, + * Add 4 bytes for each additional interrupts + * greater than 1 + */ + additional_bytes = (u8) ((temp8 - 1) * 4); + + /* + * Resource Source Index and Resource Source are + * optional elements. Check the length of the + * Bytestream. If it is greater than 9, that + * means that an Index exists and is followed by + * a null termininated string. Therefore, set + * the temp variable to the length minus the minimum + * byte stream length plus the byte for the Index to + * determine the size of the NULL terminiated string. + */ + if (9 + additional_bytes < temp16) { + temp8 = (u8) (temp16 - (9 + additional_bytes)); + } + + else { + temp8 = 0; + } + + /* + * Ensure a 32-bit boundry for the structure + */ + temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); + + structure_size = sizeof (EXTENDED_IRQ_RESOURCE) + + RESOURCE_LENGTH_NO_DATA + + (additional_bytes * sizeof (u8)) + + (temp8 * sizeof (u8)); + + break; + +/* 64-bit not currently supported */ +/* + case 0x8A: + break; +*/ + + default: + /* + * If we get here, everything is out of sync, + * so exit with an error + */ + return (AE_ERROR); + break; + } + } + + else { + /* + * Small Resource Type + * Only bits 7:3 are valid + */ + resource_type >>= 3; + + switch (resource_type) + { + case IRQ_FORMAT: + /* + * IRQ Resource + */ + /* + * Determine if it there are two or three + * trailing bytes + */ + buffer = byte_stream_buffer; + + temp8 = *buffer; + + if(temp8 & 0x01) { + bytes_consumed = 4; + } + + else { + bytes_consumed = 3; + } + + /* + * Point past the descriptor + */ + ++buffer; + + /* + * Look at the number of bits set + */ + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + for (index = 0; index < 16; index++) { + if (temp16 & 0x1) { + ++number_of_interrupts; + } + + temp16 >>= 1; + } + + structure_size = sizeof (IO_RESOURCE) + + RESOURCE_LENGTH_NO_DATA + + (number_of_interrupts * sizeof (u32)); + + break; + + + case DMA_FORMAT: + + /* + * DMA Resource + */ + buffer = byte_stream_buffer; + + bytes_consumed = 3; + + /* + * Point past the descriptor + */ + ++buffer; + + /* + * Look at the number of bits set + */ + temp8 = *buffer; + + for(index = 0; index < 8; index++) { + if(temp8 & 0x1) { + ++number_of_channels; + } + + temp8 >>= 1; + } + + structure_size = sizeof (DMA_RESOURCE) + + RESOURCE_LENGTH_NO_DATA + + (number_of_channels * sizeof (u32)); + + break; + + + case START_DEPENDENT_TAG: + + /* + * Start Dependent Functions Resource + */ + /* + * Determine if it there are two or three trailing bytes + */ + buffer = byte_stream_buffer; + + temp8 = *buffer; + + if(temp8 & 0x01) { + bytes_consumed = 2; + } + else { + bytes_consumed = 1; + } + + + structure_size = + sizeof (START_DEPENDENT_FUNCTIONS_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + break; + + + case END_DEPENDENT_TAG: + + /* + * End Dependent Functions Resource + */ + bytes_consumed = 1; + + structure_size = RESOURCE_LENGTH; + break; + + + case IO_PORT_DESCRIPTOR: + /* + * IO Port Resource + */ + bytes_consumed = 8; + + structure_size = sizeof (IO_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + break; + + + case FIXED_LOCATION_IO_DESCRIPTOR: + + /* + * Fixed IO Port Resource + */ + bytes_consumed = 4; + + structure_size = sizeof (FIXED_IO_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + break; + + + case SMALL_VENDOR_DEFINED: + + /* + * Vendor Specific Resource + */ + buffer = byte_stream_buffer; + + temp8 = *buffer; + temp8 = (u8) (temp8 & 0x7); + bytes_consumed = temp8 + 1; + + /* + * Ensure a 32-bit boundry for the structure + */ + temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); + + structure_size = sizeof (VENDOR_RESOURCE) + + RESOURCE_LENGTH_NO_DATA + + (temp8 * sizeof (u8)); + break; + + + case END_TAG: + + /* + * End Tag + */ + bytes_consumed = 2; + + structure_size = RESOURCE_LENGTH; + break; + + + default: + /* + * If we get here, everything is out of sync, + * so exit with an error + */ + return (AE_ERROR); + break; + + } /* switch */ + + } /* if(Resource_type & 0x80) */ + + /* + * Update the return value and counter + */ + buffer_size += structure_size; + bytes_parsed += bytes_consumed; + + /* + * Set the byte stream to point to the next resource + */ + byte_stream_buffer += bytes_consumed; + + } + + /* + * This is the data the caller needs + */ + *size_needed = buffer_size; + + return (AE_OK); + +} /* Acpi_rs_calculate_list_length */ + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/resources/rscreate.c linux/drivers/acpi/resources/rscreate.c --- v2.4.0-test2/linux/drivers/acpi/resources/rscreate.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/resources/rscreate.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,505 @@ +/****************************************************************************** + * + * Module Name: rscreate - Acpi_rs_create_resource_list + * Acpi_rs_create_pci_routing_table + * Acpi_rs_create_byte_stream + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "resource.h" + +#define _COMPONENT RESOURCE_MANAGER + MODULE_NAME ("rscreate"); + + +/*************************************************************************** + * FUNCTION: Acpi_rs_create_resource_list + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource byte stream + * Output_buffer - Pointer to the user's buffer + * Output_buffer_length - Pointer to the size of Output_buffer + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * If Output_buffer is not large enough, Output_buffer_length + * indicates how large Output_buffer should be, else it + * indicates how may u8 elements of Output_buffer are + * valid. + * + * DESCRIPTION: Takes the byte stream returned from a _CRS, _PRS control method + * execution and parses the stream to create a linked list + * of device resources. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_create_resource_list ( + ACPI_OBJECT_INTERNAL *byte_stream_buffer, + u8 *output_buffer, + u32 *output_buffer_length) +{ + + ACPI_STATUS status = AE_UNKNOWN_STATUS; + u8 *byte_stream_start = NULL; + u32 list_size_needed = 0; + u32 byte_stream_buffer_length = 0; + + + /* + * Validate parameters: + * + * 1. If Byte_stream_buffer is NULL after we know that + * Byte_steam_length is not zero, or + * 2. If Output_buffer is NULL and Output_buffer_length + * is not zero + * + * Return an error + */ + if (!byte_stream_buffer || + (!output_buffer && 0 != *output_buffer_length)) + { + return (AE_BAD_PARAMETER); + } + + byte_stream_buffer_length = byte_stream_buffer->buffer.length; + byte_stream_start = byte_stream_buffer->buffer.pointer; + + /* + * Pass the Byte_stream_buffer into a module that can calculate + * the buffer size needed for the linked list + */ + status = acpi_rs_calculate_list_length (byte_stream_start, + byte_stream_buffer_length, + &list_size_needed); + + /* + * Exit with the error passed back + */ + if (AE_OK != status) { + return (status); + } + + /* + * If the linked list will fit into the available buffer + * call to fill in the list + */ + + if (list_size_needed <= *output_buffer_length) { + /* + * Zero out the return buffer before proceeding + */ + MEMSET (output_buffer, 0x00, *output_buffer_length); + + status = acpi_rs_byte_stream_to_list (byte_stream_start, + byte_stream_buffer_length, + &output_buffer); + + /* + * Exit with the error passed back + */ + if (AE_OK != status) { + return (status); + } + + } + + else { + *output_buffer_length = list_size_needed; + return (AE_BUFFER_OVERFLOW); + } + + *output_buffer_length = list_size_needed; + return (AE_OK); + +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_create_pci_routing_table + * + * PARAMETERS: + * Package_object - Pointer to an ACPI_OBJECT_INTERNAL + * package + * Output_buffer - Pointer to the user's buffer + * Output_buffer_length - Size of Output_buffer + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code. + * If the Output_buffer is too small, the error will be + * AE_BUFFER_OVERFLOW and Output_buffer_length will point + * to the size buffer needed. + * + * DESCRIPTION: Takes the ACPI_OBJECT_INTERNAL package and creates a + * linked list of PCI interrupt descriptions + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_create_pci_routing_table ( + ACPI_OBJECT_INTERNAL *package_object, + u8 *output_buffer, + u32 *output_buffer_length) +{ + u8 *buffer = output_buffer; + ACPI_OBJECT_INTERNAL **top_object_list = NULL; + ACPI_OBJECT_INTERNAL **sub_object_list = NULL; + ACPI_OBJECT_INTERNAL *package_element = NULL; + u32 buffer_size_needed = 0; + u32 number_of_elements = 0; + u32 index = 0; + u8 table_index = 0; + u8 name_found = FALSE; + PCI_ROUTING_TABLE *user_prt = NULL; + + + /* + * Validate parameters: + * + * 1. If Method_return_object is NULL, or + * 2. If Output_buffer is NULL and Output_buffer_length is not zero + * + * Return an error + */ + if (!package_object || + (!output_buffer && 0 != *output_buffer_length)) + { + return (AE_BAD_PARAMETER); + } + + /* + * Calculate the buffer size needed for the routing table. + */ + number_of_elements = package_object->package.count; + + /* + * Properly calculate the size of the return buffer. + * The base size is the number of elements * the sizes of the + * structures. Additional space for the strings is added below. + * The minus one is to subtract the size of the u8 Source[1] + * member because it is added below. + * NOTE: The Number_of_elements is incremented by one to add an end + * table structure that is essentially a structure of zeros. + */ + buffer_size_needed = (number_of_elements + 1) * + (sizeof (PCI_ROUTING_TABLE) - 1); + + /* + * But each PRT_ENTRY structure has a pointer to a string and + * the size of that string must be found. + */ + top_object_list = package_object->package.elements; + + for (index = 0; index < number_of_elements; index++) { + /* + * Dereference the sub-package + */ + package_element = *top_object_list; + + /* + * The Sub_object_list will now point to an array of the + * four IRQ elements: Address, Pin, Source and Source_index + */ + sub_object_list = package_element->package.elements; + + /* + * Scan the Irq_table_elements for the Source Name String + */ + name_found = FALSE; + + for (table_index = 0; table_index < 4 && !name_found; table_index++) { + if (ACPI_TYPE_STRING == (*sub_object_list)->common.type) { + name_found = TRUE; + } + + else { + /* + * Look at the next element + */ + sub_object_list++; + } + } + + /* + * Was a String type found? + */ + if (TRUE == name_found) { + /* + * The length String.Length field includes the + * terminating NULL + */ + buffer_size_needed += ((*sub_object_list)->string.length); + } + + else { + /* + * If no name was found, then this is a NULL, which is + * translated as a u32 zero. + */ + buffer_size_needed += sizeof(u32); + } + + /* + * Point to the next ACPI_OBJECT_INTERNAL + */ + top_object_list++; + } + + /* + * If the data will fit into the available buffer + * call to fill in the list + */ + if (buffer_size_needed <= *output_buffer_length) { + /* + * Zero out the return buffer before proceeding + */ + MEMSET (output_buffer, 0x00, *output_buffer_length); + + /* + * Loop through the ACPI_INTERNAL_OBJECTS - Each object should + * contain a u32 Address, a u8 Pin, a Name and a u8 + * Source_index. + */ + top_object_list = package_object->package.elements; + + number_of_elements = package_object->package.count; + + user_prt = (PCI_ROUTING_TABLE *)buffer; + + for (index = 0; index < number_of_elements; index++) { + /* + * Point User_prt past this current structure + * + * NOTE: On the first iteration, User_prt->Length will + * be zero because we zero'ed out the return buffer + * earlier + */ + buffer += user_prt->length; + + user_prt = (PCI_ROUTING_TABLE *)buffer; + + /* + * Fill in the Length field with the information we + * have at this point. + * The minus one is to subtract the size of the + * u8 Source[1] member because it is added below. + */ + user_prt->length = (sizeof(PCI_ROUTING_TABLE) - 1); + + /* + * Dereference the sub-package + */ + package_element = *top_object_list; + + /* + * The Sub_object_list will now point to an array of + * the four IRQ elements: Address, Pin, Source and + * Source_index + */ + sub_object_list = package_element->package.elements; + + /* + * Dereference the Address + */ + if (ACPI_TYPE_NUMBER == (*sub_object_list)->common.type) { + user_prt->data.address = + (*sub_object_list)->number.value; + } + + else { + return (AE_BAD_DATA); + } + + /* + * Dereference the Pin + */ + sub_object_list++; + + if (ACPI_TYPE_NUMBER == (*sub_object_list)->common.type) { + user_prt->data.pin = + (*sub_object_list)->number.value; + } + + else { + return (AE_BAD_DATA); + } + + /* + * Dereference the Source Name + */ + sub_object_list++; + + if (ACPI_TYPE_STRING == (*sub_object_list)->common.type) { + STRCPY(user_prt->data.source, + (*sub_object_list)->string.pointer); + + /* + * Add to the Length field the length of the string + */ + user_prt->length += (*sub_object_list)->string.length; + } + + else { + /* + * If this is a number, then the Source Name + * is NULL, since the entire buffer was zeroed + * out, we can leave this alone. + */ + if (ACPI_TYPE_NUMBER == (*sub_object_list)->common.type) { + /* + * Add to the Length field the length of + * the u32 NULL + */ + user_prt->length += sizeof(u32); + } + + else { + return (AE_BAD_DATA); + } + } + + /* + * Dereference the Source Index + */ + sub_object_list++; + + if (ACPI_TYPE_NUMBER == (*sub_object_list)->common.type) { + user_prt->data.source_index = + (*sub_object_list)->number.value; + } + + else { + return (AE_BAD_DATA); + } + + /* + * Point to the next ACPI_OBJECT_INTERNAL + */ + top_object_list++; + } + + } + + else { + *output_buffer_length = buffer_size_needed; + + return (AE_BUFFER_OVERFLOW); + } + + /* + * Report the amount of buffer used + */ + *output_buffer_length = buffer_size_needed; + + return (AE_OK); + +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_create_byte_stream + * + * PARAMETERS: + * Linked_list_buffer - Pointer to the resource linked list + * Output_buffer - Pointer to the user's buffer + * Output_buffer_length - Size of Output_buffer + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code. + * If the Output_buffer is too small, the error will be + * AE_BUFFER_OVERFLOW and Output_buffer_length will point + * to the size buffer needed. + * + * DESCRIPTION: Takes the linked list of device resources and + * creates a bytestream to be used as input for the + * _SRS control method. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_create_byte_stream ( + RESOURCE *linked_list_buffer, + u8 *output_buffer, + u32 *output_buffer_length) +{ + ACPI_STATUS status = AE_UNKNOWN_STATUS; + u32 byte_stream_size_needed = 0; + + + /* + * Validate parameters: + * + * 1. If Linked_list_buffer is NULL, or + * 2. If Output_buffer is NULL and Output_buffer_length is not zero + * + * Return an error + */ + if (!linked_list_buffer || + (!output_buffer && 0 != *output_buffer_length)) + { + return (AE_BAD_PARAMETER); + } + + /* + * Pass the Linked_list_buffer into a module that can calculate + * the buffer size needed for the byte stream. + */ + status = acpi_rs_calculate_byte_stream_length (linked_list_buffer, + &byte_stream_size_needed); + + /* + * Exit with the error passed back + */ + if (AE_OK != status) { + return (status); + } + + /* + * If the linked list will fit into the available buffer + * call to fill in the list + */ + + if (byte_stream_size_needed <= *output_buffer_length) { + /* + * Zero out the return buffer before proceeding + */ + MEMSET (output_buffer, 0x00, *output_buffer_length); + + status = acpi_rs_list_to_byte_stream (linked_list_buffer, + byte_stream_size_needed, + &output_buffer); + + /* + * Exit with the error passed back + */ + if (AE_OK != status) { + return (status); + } + + } + else { + *output_buffer_length = byte_stream_size_needed; + return (AE_BUFFER_OVERFLOW); + } + + return (AE_OK); + +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/resources/rsdump.c linux/drivers/acpi/resources/rsdump.c --- v2.4.0-test2/linux/drivers/acpi/resources/rsdump.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/resources/rsdump.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,938 @@ +/****************************************************************************** + * + * Module Name: rsdump - Functions do dump out the resource structures. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" + +#define _COMPONENT RESOURCE_MANAGER + MODULE_NAME ("rsdump"); + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_dump_irq + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_irq ( + RESOURCE_DATA *data) +{ + IRQ_RESOURCE *irq_data = (IRQ_RESOURCE*) data; + u8 index = 0; + + + acpi_os_printf ("\t_iRQ Resource\n"); + + acpi_os_printf ("\t\t%s Triggered\n", + LEVEL_SENSITIVE == irq_data->edge_level ? + "Level" : "Edge"); + + acpi_os_printf ("\t\t_active %s\n", + ACTIVE_LOW == irq_data->active_high_low ? + "Low" : "High"); + + acpi_os_printf ("\t\t%s\n", + SHARED == irq_data->shared_exclusive ? + "Shared" : "Exclusive"); + + acpi_os_printf ("\t\t%d Interrupts ( ", + irq_data->number_of_interrupts); + + for (index = 0; index < irq_data->number_of_interrupts; index++) { + acpi_os_printf ("%d ", irq_data->interrupts[index]); + } + + acpi_os_printf (")\n"); + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_dump_dma + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_dma ( + RESOURCE_DATA *data) +{ + DMA_RESOURCE *dma_data = (DMA_RESOURCE*) data; + u8 index = 0; + + + acpi_os_printf ("\t_dMA Resource\n"); + + switch (dma_data->type) + { + case COMPATIBILITY: + acpi_os_printf ("\t\t_compatibility mode\n"); + break; + + case TYPE_A: + acpi_os_printf ("\t\t_type A\n"); + break; + + case TYPE_B: + acpi_os_printf ("\t\t_type B\n"); + break; + + case TYPE_F: + acpi_os_printf ("\t\t_type F\n"); + break; + + default: + acpi_os_printf ("\t\t_invalid DMA type\n"); + break; + } + + acpi_os_printf ("\t\t%s_bus Master\n", + BUS_MASTER == dma_data->bus_master ? + "" : "Not a "); + + switch (dma_data->transfer) + { + case TRANSFER_8: + acpi_os_printf ("\t\t8-bit only transfer\n"); + break; + + case TRANSFER_8_16: + acpi_os_printf ("\t\t8 and 16-bit transfer\n"); + break; + + case TRANSFER_16: + acpi_os_printf ("\t\t16 bit only transfer\n"); + break; + + default: + acpi_os_printf ("\t\t_invalid transfer preference\n"); + break; + } + + acpi_os_printf ("\t\t_number of Channels: %d ( ", + dma_data->number_of_channels); + + for (index = 0; index < dma_data->number_of_channels; index++) { + acpi_os_printf ("%d ", dma_data->channels[index]); + } + + acpi_os_printf (")\n"); + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_dump_start_dependent_functions + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_start_dependent_functions ( + RESOURCE_DATA *data) +{ + START_DEPENDENT_FUNCTIONS_RESOURCE *sdf_data = + (START_DEPENDENT_FUNCTIONS_RESOURCE*) data; + + + acpi_os_printf ("\t_start Dependent Functions Resource\n"); + + switch (sdf_data->compatibility_priority) + { + case GOOD_CONFIGURATION: + acpi_os_printf ("\t\t_good configuration\n"); + break; + + case ACCEPTABLE_CONFIGURATION: + acpi_os_printf ("\t\t_acceptable configuration\n"); + break; + + case SUB_OPTIMAL_CONFIGURATION: + acpi_os_printf ("\t\t_sub-optimal configuration\n"); + break; + + default: + acpi_os_printf ("\t\t_invalid compatibility priority\n"); + break; + } + + switch(sdf_data->performance_robustness) + { + case GOOD_CONFIGURATION: + acpi_os_printf ("\t\t_good configuration\n"); + break; + + case ACCEPTABLE_CONFIGURATION: + acpi_os_printf ("\t\t_acceptable configuration\n"); + break; + + case SUB_OPTIMAL_CONFIGURATION: + acpi_os_printf ("\t\t_sub-optimal configuration\n"); + break; + + default: + acpi_os_printf ("\t\t_invalid performance " + "robustness preference\n"); + break; + } + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_dump_io + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_io ( + RESOURCE_DATA *data) +{ + IO_RESOURCE *io_data = (IO_RESOURCE*) data; + + + acpi_os_printf ("\t_io Resource\n"); + + acpi_os_printf ("\t\t%d bit decode\n", + DECODE_16 == io_data->io_decode ? 16 : 10); + + acpi_os_printf ("\t\t_range minimum base: 0x%08x\n", + io_data->min_base_address); + + acpi_os_printf ("\t\t_range maximum base: 0x%08x\n", + io_data->max_base_address); + + acpi_os_printf ("\t\t_alignment: 0x%08x\n", + io_data->alignment); + + acpi_os_printf ("\t\t_range Length: 0x%08x\n", + io_data->range_length); + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_dump_fixed_io + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_fixed_io ( + RESOURCE_DATA *data) +{ + FIXED_IO_RESOURCE *fixed_io_data = (FIXED_IO_RESOURCE*) data; + + + acpi_os_printf ("\t_fixed Io Resource\n"); + acpi_os_printf ("\t\t_range base address: 0x%08x", + fixed_io_data->base_address); + + acpi_os_printf ("\t\t_range length: 0x%08x", + fixed_io_data->range_length); + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_dump_vendor_specific + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_vendor_specific ( + RESOURCE_DATA *data) +{ + VENDOR_RESOURCE *vendor_data = (VENDOR_RESOURCE*) data; + u16 index = 0; + + + acpi_os_printf ("\t_vendor Specific Resource\n"); + + acpi_os_printf ("\t\t_length: 0x%08x\n", vendor_data->length); + + for (index = 0; index < vendor_data->length; index++) { + acpi_os_printf ("\t\t_byte %d: 0x%08x\n", + index, vendor_data->reserved[index]); + } + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_dump_memory24 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_memory24 ( + RESOURCE_DATA *data) +{ + MEMORY24_RESOURCE *memory24_data = (MEMORY24_RESOURCE*) data; + + + acpi_os_printf ("\t24-Bit Memory Range Resource\n"); + + acpi_os_printf ("\t\t_read%s\n", + READ_WRITE_MEMORY == + memory24_data->read_write_attribute ? + "/Write" : " only"); + + acpi_os_printf ("\t\t_range minimum base: 0x%08x\n", + memory24_data->min_base_address); + + acpi_os_printf ("\t\t_range maximum base: 0x%08x\n", + memory24_data->max_base_address); + + acpi_os_printf ("\t\t_alignment: 0x%08x\n", + memory24_data->alignment); + + acpi_os_printf ("\t\t_range length: 0x%08x\n", + memory24_data->range_length); + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_dump_memory32 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_memory32 ( + RESOURCE_DATA *data) +{ + MEMORY32_RESOURCE *memory32_data = (MEMORY32_RESOURCE*) data; + + + acpi_os_printf ("\t32-Bit Memory Range Resource\n"); + + acpi_os_printf ("\t\t_read%s\n", + READ_WRITE_MEMORY == + memory32_data->read_write_attribute ? + "/Write" : " only"); + + acpi_os_printf ("\t\t_range minimum base: 0x%08x\n", + memory32_data->min_base_address); + + acpi_os_printf ("\t\t_range maximum base: 0x%08x\n", + memory32_data->max_base_address); + + acpi_os_printf ("\t\t_alignment: 0x%08x\n", + memory32_data->alignment); + + acpi_os_printf ("\t\t_range length: 0x%08x\n", + memory32_data->range_length); + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_dump_fixed_memory32 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_fixed_memory32 ( + RESOURCE_DATA *data) +{ + FIXED_MEMORY32_RESOURCE *fixed_memory32_data = (FIXED_MEMORY32_RESOURCE*) data; + + + acpi_os_printf ("\t32-Bit Fixed Location Memory Range Resource\n"); + + acpi_os_printf ("\t\t_read%s\n", + READ_WRITE_MEMORY == + fixed_memory32_data->read_write_attribute ? + "/Write" : " Only"); + + acpi_os_printf ("\t\t_range base address: 0x%08x\n", + fixed_memory32_data->range_base_address); + + acpi_os_printf ("\t\t_range length: 0x%08x\n", + fixed_memory32_data->range_length); + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_dump_address16 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_address16 ( + RESOURCE_DATA *data) +{ + ADDRESS16_RESOURCE *address16_data = (ADDRESS16_RESOURCE*) data; + + + acpi_os_printf ("\t16-Bit Address Space Resource\n"); + acpi_os_printf ("\t\t_resource Type: "); + + switch (address16_data->resource_type) + { + case MEMORY_RANGE: + + acpi_os_printf ("Memory Range\n"); + + switch (address16_data->attribute.memory.cache_attribute) + { + case NON_CACHEABLE_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Noncacheable memory\n"); + break; + + case CACHABLE_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Cacheable memory\n"); + break; + + case WRITE_COMBINING_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Write-combining memory\n"); + break; + + case PREFETCHABLE_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Prefetchable memory\n"); + break; + + default: + acpi_os_printf ("\t\t_type Specific: " + "Invalid cache attribute\n"); + break; + } + + acpi_os_printf ("\t\t_type Specific: Read%s\n", + READ_WRITE_MEMORY == + address16_data->attribute.memory.read_write_attribute ? + "/Write" : " Only"); + break; + + case IO_RANGE: + + acpi_os_printf ("I/O Range\n"); + + switch (address16_data->attribute.io.range_attribute) + { + case NON_ISA_ONLY_RANGES: + acpi_os_printf ("\t\t_type Specific: " + "Non-ISA Io Addresses\n"); + break; + + case ISA_ONLY_RANGES: + acpi_os_printf ("\t\t_type Specific: " + "ISA Io Addresses\n"); + break; + + case ENTIRE_RANGE: + acpi_os_printf ("\t\t_type Specific: " + "ISA and non-ISA Io Addresses\n"); + break; + + default: + acpi_os_printf ("\t\t_type Specific: " + "Invalid range attribute\n"); + break; + } + break; + + case BUS_NUMBER_RANGE: + + acpi_os_printf ("Bus Number Range\n"); + break; + + default: + + acpi_os_printf ("Invalid resource type. Exiting.\n"); + return; + } + + acpi_os_printf ("\t\t_resource %s\n", + CONSUMER == address16_data->producer_consumer ? + "Consumer" : "Producer"); + + acpi_os_printf ("\t\t%s decode\n", + SUB_DECODE == address16_data->decode ? + "Subtractive" : "Positive"); + + acpi_os_printf ("\t\t_min address is %s fixed\n", + ADDRESS_FIXED == address16_data->min_address_fixed ? + "" : "not"); + + acpi_os_printf ("\t\t_max address is %s fixed\n", + ADDRESS_FIXED == address16_data->max_address_fixed ? + "" : "not"); + + acpi_os_printf ("\t\t_granularity: 0x%08x\n", + address16_data->granularity); + + acpi_os_printf ("\t\t_address range min: 0x%08x\n", + address16_data->min_address_range); + + acpi_os_printf ("\t\t_address range max: 0x%08x\n", + address16_data->max_address_range); + + acpi_os_printf ("\t\t_address translation offset: 0x%08x\n", + address16_data->address_translation_offset); + + acpi_os_printf ("\t\t_address Length: 0x%08x\n", + address16_data->address_length); + + if (0xFF != address16_data->resource_source_index) { + acpi_os_printf ("\t\t_resource Source Index: %d\n", + address16_data->resource_source_index); + acpi_os_printf ("\t\t_resource Source: %s\n", + address16_data->resource_source); + } + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_dump_address32 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_address32 ( + RESOURCE_DATA *data) +{ + ADDRESS32_RESOURCE *address32_data = (ADDRESS32_RESOURCE*) data; + + + acpi_os_printf ("\t32-Bit Address Space Resource\n"); + + switch (address32_data->resource_type) + { + case MEMORY_RANGE: + + acpi_os_printf ("\t\t_resource Type: Memory Range\n"); + + switch (address32_data->attribute.memory.cache_attribute) + { + case NON_CACHEABLE_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Noncacheable memory\n"); + break; + + case CACHABLE_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Cacheable memory\n"); + break; + + case WRITE_COMBINING_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Write-combining memory\n"); + break; + + case PREFETCHABLE_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Prefetchable memory\n"); + break; + + default: + acpi_os_printf ("\t\t_type Specific: " + "Invalid cache attribute\n"); + break; + } + + acpi_os_printf ("\t\t_type Specific: Read%s\n", + READ_WRITE_MEMORY == + address32_data->attribute.memory.read_write_attribute ? + "/Write" : " Only"); + break; + + case IO_RANGE: + + acpi_os_printf ("\t\t_resource Type: Io Range\n"); + + switch (address32_data->attribute.io.range_attribute) + { + case NON_ISA_ONLY_RANGES: + acpi_os_printf ("\t\t_type Specific: " + "Non-ISA Io Addresses\n"); + break; + + case ISA_ONLY_RANGES: + acpi_os_printf ("\t\t_type Specific: " + "ISA Io Addresses\n"); + break; + + case ENTIRE_RANGE: + acpi_os_printf ("\t\t_type Specific: " + "ISA and non-ISA Io Addresses\n"); + break; + + default: + acpi_os_printf ("\t\t_type Specific: " + "Invalid Range attribute"); + break; + } + break; + + case BUS_NUMBER_RANGE: + + acpi_os_printf ("\t\t_resource Type: Bus Number Range\n"); + break; + + default: + + acpi_os_printf ("\t\t_invalid Resource Type..exiting.\n"); + return; + } + + acpi_os_printf ("\t\t_resource %s\n", + CONSUMER == address32_data->producer_consumer ? + "Consumer" : "Producer"); + + acpi_os_printf ("\t\t%s decode\n", + SUB_DECODE == address32_data->decode ? + "Subtractive" : "Positive"); + + acpi_os_printf ("\t\t_min address is %s fixed\n", + ADDRESS_FIXED == address32_data->min_address_fixed ? + "" : "not "); + + acpi_os_printf ("\t\t_max address is %s fixed\n", + ADDRESS_FIXED == address32_data->max_address_fixed ? + "" : "not "); + + acpi_os_printf ("\t\t_granularity: 0x%08x\n", + address32_data->granularity); + + acpi_os_printf ("\t\t_address range min: 0x%08x\n", + address32_data->min_address_range); + + acpi_os_printf ("\t\t_address range max: 0x%08x\n", + address32_data->max_address_range); + + acpi_os_printf ("\t\t_address translation offset: 0x%08x\n", + address32_data->address_translation_offset); + + acpi_os_printf ("\t\t_address Length: 0x%08x\n", + address32_data->address_length); + + if(0xFF != address32_data->resource_source_index) { + acpi_os_printf ("\t\t_resource Source Index: %d\n", + address32_data->resource_source_index); + acpi_os_printf ("\t\t_resource Source: %s\n", + address32_data->resource_source); + } + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_dump_extended_irq + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_extended_irq ( + RESOURCE_DATA *data) +{ + EXTENDED_IRQ_RESOURCE *ext_irq_data = (EXTENDED_IRQ_RESOURCE*) data; + u8 index = 0; + + + acpi_os_printf ("\t_extended IRQ Resource\n"); + + acpi_os_printf ("\t\t_resource %s\n", + CONSUMER == ext_irq_data->producer_consumer ? + "Consumer" : "Producer"); + + acpi_os_printf ("\t\t%s\n", + LEVEL_SENSITIVE == ext_irq_data->edge_level ? + "Level" : "Edge"); + + acpi_os_printf ("\t\t_active %s\n", + ACTIVE_LOW == ext_irq_data->active_high_low ? + "low" : "high"); + + acpi_os_printf ("\t\t%s\n", + SHARED == ext_irq_data->shared_exclusive ? + "Shared" : "Exclusive"); + + acpi_os_printf ("\t\t_interrupts : %d ( ", + ext_irq_data->number_of_interrupts); + + for (index = 0; index < ext_irq_data->number_of_interrupts; index++) { + acpi_os_printf ("%d ", ext_irq_data->interrupts[index]); + } + + acpi_os_printf (")\n"); + + if(0xFF != ext_irq_data->resource_source_index) { + acpi_os_printf ("\t\t_resource Source Index: %d", + ext_irq_data->resource_source_index); + acpi_os_printf ("\t\t_resource Source: %s", + ext_irq_data->resource_source); + } + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_dump_resource_list + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Dispatches the structure to the correct dump routine. + * + ******************************************************************************/ + +void +acpi_rs_dump_resource_list ( + RESOURCE *resource) +{ + s8 count = 0; + u8 done = FALSE; + + + if (acpi_dbg_level & TRACE_RESOURCES && _COMPONENT & acpi_dbg_layer) { + while (!done) { + acpi_os_printf ("\t_resource structure %x.\n", count++); + + switch (resource->id) + { + case irq: + acpi_rs_dump_irq (&resource->data); + break; + + case dma: + acpi_rs_dump_dma (&resource->data); + break; + + case start_dependent_functions: + acpi_rs_dump_start_dependent_functions (&resource->data); + break; + + case end_dependent_functions: + acpi_os_printf ("\t_end_dependent_functions Resource\n"); + /* Acpi_rs_dump_end_dependent_functions (Resource->Data);*/ + break; + + case io: + acpi_rs_dump_io (&resource->data); + break; + + case fixed_io: + acpi_rs_dump_fixed_io (&resource->data); + break; + + case vendor_specific: + acpi_rs_dump_vendor_specific (&resource->data); + break; + + case end_tag: + /*Rs_dump_end_tag (Resource->Data);*/ + acpi_os_printf ("\t_end_tag Resource\n"); + done = TRUE; + break; + + case memory24: + acpi_rs_dump_memory24 (&resource->data); + break; + + case memory32: + acpi_rs_dump_memory32 (&resource->data); + break; + + case fixed_memory32: + acpi_rs_dump_fixed_memory32 (&resource->data); + break; + + case address16: + acpi_rs_dump_address16 (&resource->data); + break; + + case address32: + acpi_rs_dump_address32 (&resource->data); + break; + + case extended_irq: + acpi_rs_dump_extended_irq (&resource->data); + break; + + default: + acpi_os_printf ("Invalid resource type\n"); + break; + + } + + resource = (RESOURCE *) ((NATIVE_UINT) resource + + (NATIVE_UINT) resource->length); + } + } + + return; +} + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_dump_irq_list + * + * PARAMETERS: Data - pointer to the routing table to dump. + * + * RETURN: + * + * DESCRIPTION: Dispatches the structures to the correct dump routine. + * + ******************************************************************************/ + +void +acpi_rs_dump_irq_list ( + u8 *route_table) +{ + u8 *buffer = route_table; + s8 count = 0; + u8 done = FALSE; + PCI_ROUTING_TABLE *prt_element; + + + if (acpi_dbg_level & TRACE_RESOURCES && _COMPONENT & acpi_dbg_layer) { + prt_element = (PCI_ROUTING_TABLE *)buffer; + + while (!done) { + acpi_os_printf ("\t_pCI IRQ Routing Table structure %x.\n", count++); + + acpi_os_printf ("\t\t_address: 0x%x\n", + prt_element->data.address); + + acpi_os_printf ("\t\t_pin: 0x%x\n", prt_element->data.pin); + + acpi_os_printf ("\t\t_source: %s\n", prt_element->data.source); + + acpi_os_printf ("\t\t_source_index: 0x%x\n", + prt_element->data.source_index); + + buffer += prt_element->length; + + prt_element = (PCI_ROUTING_TABLE *)buffer; + + if(0 == prt_element->length) { + done = TRUE; + } + } + } + + return; +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/resources/rsio.c linux/drivers/acpi/resources/rsio.c --- v2.4.0-test2/linux/drivers/acpi/resources/rsio.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/resources/rsio.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,544 @@ +/****************************************************************************** + * + * Module Name: rsio - Acpi_rs_io_resource + * Acpi_rs_fixed_io_resource + * Acpi_rs_io_stream + * Acpi_rs_fixed_io_stream + * Acpi_rs_dma_resource + * Acpi_rs_dma_stream + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" + +#define _COMPONENT RESOURCE_MANAGER + MODULE_NAME ("rsio"); + + +/*************************************************************************** + * FUNCTION: Acpi_rs_io_resource + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_io_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u32 struct_size = sizeof (IO_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * The number of bytes consumed are Constant + */ + *bytes_consumed = 8; + + output_struct->id = io; + + /* + * Check Decode + */ + buffer += 1; + temp8 = *buffer; + + output_struct->data.io.io_decode = temp8 & 0x01; + + /* + * Check Min_base Address + */ + buffer += 1; + temp16 = *(u16 *)buffer; + + output_struct->data.io.min_base_address = temp16; + + /* + * Check Max_base Address + */ + buffer += 2; + temp16 = *(u16 *)buffer; + + output_struct->data.io.max_base_address = temp16; + + /* + * Check Base alignment + */ + buffer += 2; + temp8 = *buffer; + + output_struct->data.io.alignment = temp8; + + /* + * Check Range_length + */ + buffer += 1; + temp8 = *buffer; + + output_struct->data.io.range_length = temp8; + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_fixed_io_resource + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_fixed_io_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u32 struct_size = sizeof (FIXED_IO_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * The number of bytes consumed are Constant + */ + *bytes_consumed = 4; + + output_struct->id = fixed_io; + + /* + * Check Range Base Address + */ + buffer += 1; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + output_struct->data.fixed_io.base_address = temp16; + + /* + * Check Range_length + */ + buffer += 2; + temp8 = *buffer; + + output_struct->data.fixed_io.range_length = temp8; + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_io_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_io_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + /* + * The descriptor field is static + */ + *buffer = 0x47; + + buffer += 1; + + /* + * Io Information Byte + */ + temp8 = (u8) (linked_list->data.io.io_decode & 0x01); + + *buffer = temp8; + + buffer += 1; + + /* + * Set the Range minimum base address + */ + temp16 = (u16) linked_list->data.io.min_base_address; + + *(u16 *)buffer = temp16; + + buffer += 2; + + /* + * Set the Range maximum base address + */ + temp16 = (u16) linked_list->data.io.max_base_address; + + *(u16 *)buffer = temp16; + + buffer += 2; + + /* + * Set the base alignment + */ + temp8 = (u8) linked_list->data.io.alignment; + + *buffer = temp8; + + buffer += 1; + + /* + * Set the range length + */ + temp8 = (u8) linked_list->data.io.range_length; + + *buffer = temp8; + + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_fixed_io_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_fixed_io_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + /* + * The descriptor field is static + */ + *buffer = 0x4B; + + buffer += 1; + + /* + * Set the Range base address + */ + temp16 = (u16) linked_list->data.fixed_io.base_address; + + *(u16 *)buffer = temp16; + + buffer += 2; + + /* + * Set the range length + */ + temp8 = (u8) linked_list->data.fixed_io.range_length; + + *buffer = temp8; + + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_dma_resource + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_dma_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u8 temp8 = 0; + u8 index; + u8 i; + u32 struct_size = sizeof(DMA_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * The number of bytes consumed are Constant + */ + *bytes_consumed = 3; + + output_struct->id = dma; + + /* + * Point to the 8-bits of Byte 1 + */ + buffer += 1; + + temp8 = *buffer; + + /* Decode the IRQ bits */ + + for (i = 0, index = 0; index < 8; index++) { + if ((temp8 >> index) & 0x01) { + output_struct->data.dma.channels[i] = index; + i++; + } + } + output_struct->data.dma.number_of_channels = i; + + + /* + * Calculate the structure size based upon the number of interrupts + */ + struct_size += (output_struct->data.dma.number_of_channels - 1) * 4; + + /* + * Point to Byte 2 + */ + buffer += 1; + + temp8 = *buffer; + + /* + * Check for transfer preference (Bits[1:0]) + */ + output_struct->data.dma.transfer = temp8 & 0x03; + + if (0x03 == output_struct->data.dma.transfer) { + return (AE_BAD_DATA); + } + + /* + * Get bus master preference (Bit[2]) + */ + output_struct->data.dma.bus_master = (temp8 >> 2) & 0x01; + + /* + * Get channel speed support (Bits[6:5]) + */ + output_struct->data.dma.type = (temp8 >> 5) & 0x03; + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_dma_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_dma_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + + + /* + * The descriptor field is static + */ + *buffer = 0x2A; + + buffer += 1; + + temp8 = 0; + + /* + * Loop through all of the Channels and set the mask bits + */ + for (index = 0; + index < linked_list->data.dma.number_of_channels; + index++) + { + temp16 = (u16) linked_list->data.dma.channels[index]; + temp8 |= 0x1 << temp16; + } + + *buffer = temp8; + + buffer += 1; + + /* + * Set the DMA Info + */ + temp8 = (u8) ((linked_list->data.dma.type & 0x03) << 5); + + temp8 |= ((linked_list->data.dma.bus_master & 0x01) << 2); + + temp8 |= (linked_list->data.dma.transfer & 0x03); + + *buffer = temp8; + + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/resources/rsirq.c linux/drivers/acpi/resources/rsirq.c --- v2.4.0-test2/linux/drivers/acpi/resources/rsirq.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/resources/rsirq.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,568 @@ +/****************************************************************************** + * + * Module Name: rsirq - Acpi_rs_irq_resource, + * Acpi_rs_irq_stream + * Acpi_rs_extended_irq_resource + * Acpi_rs_extended_irq_stream + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" + +#define _COMPONENT RESOURCE_MANAGER + MODULE_NAME ("rsirq"); + + +/*************************************************************************** + * FUNCTION: Acpi_rs_irq_resource + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_irq_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + u8 i; + u32 struct_size = sizeof (IRQ_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * The number of bytes consumed are contained in the descriptor + * (Bits:0-1) + */ + temp8 = *buffer; + + *bytes_consumed = (temp8 & 0x03) + 1; + + output_struct->id = irq; + + /* + * Point to the 16-bits of Bytes 1 and 2 + */ + buffer += 1; + temp16 = *(u16 *)buffer; + + output_struct->data.irq.number_of_interrupts = 0; + + /* Decode the IRQ bits */ + for (i = 0, index = 0; index < 16; index++) { + if((temp16 >> index) & 0x01) { + output_struct->data.irq.interrupts[i] = index; + i++; + } + } + output_struct->data.irq.number_of_interrupts = i; + + /* + * Calculate the structure size based upon the number of interrupts + */ + struct_size += (output_struct->data.irq.number_of_interrupts - 1) * 4; + + /* + * Point to Byte 3 if it is used + */ + if (4 == *bytes_consumed) { + buffer += 2; + + temp8 = *buffer; + + /* + * Check for HE, LL or HL + */ + if (temp8 & 0x01) { + output_struct->data.irq.edge_level = EDGE_SENSITIVE; + output_struct->data.irq.active_high_low = ACTIVE_HIGH; + } + + else { + if (temp8 & 0x8) { + output_struct->data.irq.edge_level = LEVEL_SENSITIVE; + output_struct->data.irq.active_high_low = ACTIVE_LOW; + } + + else { + /* + * Only _LL and _HE polarity/trigger interrupts + * are allowed (ACPI spec v1.0b ection 6.4.2.1), + * so an error will occur if we reach this point + */ + return (AE_BAD_DATA); + } + } + + /* + * Check for sharable + */ + output_struct->data.irq.shared_exclusive = (temp8 >> 3) & 0x01; + } + + else { + /* + * Assume Edge Sensitive, Active High, Non-Sharable + * per ACPI Specification + */ + output_struct->data.irq.edge_level = EDGE_SENSITIVE; + output_struct->data.irq.active_high_low = ACTIVE_HIGH; + output_struct->data.irq.shared_exclusive = EXCLUSIVE; + } + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_irq_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_irq_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + u8 IRQinfo_byte_needed; + + + /* + * The descriptor field is set based upon whether a third byte is + * needed to contain the IRQ Information. + */ + if (EDGE_SENSITIVE == linked_list->data.irq.edge_level && + ACTIVE_HIGH == linked_list->data.irq.active_high_low && + EXCLUSIVE == linked_list->data.irq.shared_exclusive) + { + *buffer = 0x22; + IRQinfo_byte_needed = FALSE; + } + else { + *buffer = 0x23; + IRQinfo_byte_needed = TRUE; + } + + buffer += 1; + + temp16 = 0; + + /* + * Loop through all of the interrupts and set the mask bits + */ + for(index = 0; + index < linked_list->data.irq.number_of_interrupts; + index++) + { + temp8 = (u8) linked_list->data.irq.interrupts[index]; + temp16 |= 0x1 << temp8; + } + + *(u16 *)buffer = temp16; + + buffer += 2; + + /* + * Set the IRQ Info byte if needed. + */ + if (IRQinfo_byte_needed) { + temp8 = 0; + + temp8 = (u8) ((linked_list->data.irq.shared_exclusive & + 0x01) << 4); + + if (LEVEL_SENSITIVE == linked_list->data.irq.edge_level && + ACTIVE_LOW == linked_list->data.irq.active_high_low) + { + temp8 |= 0x08; + } + + else { + temp8 |= 0x01; + } + + *buffer = temp8; + + buffer += 1; + } + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_extended_irq_resource + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_extended_irq_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + u32 struct_size = sizeof (EXTENDED_IRQ_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + temp16 = *(u16 *)buffer; + + *bytes_consumed = temp16 + 3; + output_struct->id = extended_irq; + + /* + * Point to the Byte3 + */ + buffer += 2; + temp8 = *buffer; + + output_struct->data.extended_irq.producer_consumer = temp8 & 0x01; + + /* + * Check for HE, LL or HL + */ + if(temp8 & 0x02) { + output_struct->data.extended_irq.edge_level = EDGE_SENSITIVE; + output_struct->data.extended_irq.active_high_low = ACTIVE_HIGH; + } + + else { + if(temp8 & 0x4) { + output_struct->data.extended_irq.edge_level = LEVEL_SENSITIVE; + output_struct->data.extended_irq.active_high_low = ACTIVE_LOW; + } + + else { + /* + * Only _LL and _HE polarity/trigger interrupts + * are allowed (ACPI spec v1.0b ection 6.4.2.1), + * so an error will occur if we reach this point + */ + return (AE_BAD_DATA); + } + } + + /* + * Check for sharable + */ + output_struct->data.extended_irq.shared_exclusive = + (temp8 >> 3) & 0x01; + + /* + * Point to Byte4 (IRQ Table length) + */ + buffer += 1; + temp8 = *buffer; + + output_struct->data.extended_irq.number_of_interrupts = temp8; + + /* + * Add any additional structure size to properly calculate + * the next pointer at the end of this function + */ + struct_size += (temp8 - 1) * 4; + + /* + * Point to Byte5 (First IRQ Number) + */ + buffer += 1; + + /* + * Cycle through every IRQ in the table + */ + for (index = 0; index < temp8; index++) { + output_struct->data.extended_irq.interrupts[index] = + (u32)*buffer; + + /* Point to the next IRQ */ + + buffer += 4; + } + + /* + * This will leave us pointing to the Resource Source Index + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * Each Interrupt takes 32-bits + the 5 bytes of the + * stream that are default. + */ + if (*bytes_consumed > + (u32)(output_struct->data.extended_irq.number_of_interrupts * + 4) + 5) + { + /* Dereference the Index */ + + temp8 = *buffer; + output_struct->data.extended_irq.resource_source_index = + (u32)temp8; + + /* Point to the String */ + + buffer += 1; + + /* Copy the string into the buffer */ + + index = 0; + + while (0x00 != *buffer) { + output_struct->data.extended_irq.resource_source[index] = + *buffer; + + buffer += 1; + index += 1; + } + + /* + * Add the terminating null + */ + output_struct->data.extended_irq.resource_source[index] = 0x00; + output_struct->data.extended_irq.resource_source_string_length = + index + 1; + + /* + * In order for the Struct_size to fall on a 32-bit boundry, + * calculate the length of the string and expand the + * Struct_size to the next 32-bit boundry. + */ + temp8 = (u8) (index + 1); + temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); + } + + else { + output_struct->data.extended_irq.resource_source_index = 0x00; + output_struct->data.extended_irq.resource_source_string_length = 0; + output_struct->data.extended_irq.resource_source[0] = 0x00; + } + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_extended_irq_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_extended_irq_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 *length_field; + u8 temp8 = 0; + u8 index; + u8 *temp_pointer = NULL; + + + /* + * The descriptor field is static + */ + *buffer = 0x89; + buffer += 1; + + /* + * Set a pointer to the Length field - to be filled in later + */ + + length_field = (u16 *)buffer; + buffer += 2; + + /* + * Set the Interrupt vector flags + */ + temp8 = (u8)(linked_list->data.extended_irq.producer_consumer & 0x01); + + temp8 |= ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3); + + if (LEVEL_SENSITIVE == linked_list->data.extended_irq.edge_level && + ACTIVE_LOW == linked_list->data.extended_irq.active_high_low) + { + temp8 |= 0x04; + } + else { + temp8 |= 0x02; + } + + *buffer = temp8; + buffer += 1; + + /* + * Set the Interrupt table length + */ + temp8 = (u8) linked_list->data.extended_irq.number_of_interrupts; + + *buffer = temp8; + + buffer += 1; + + for (index = 0; + index < linked_list->data.extended_irq.number_of_interrupts; + index++) + { + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.extended_irq.interrupts[index]); + buffer += 4; + } + + /* + * Resource Source Index and Resource Source are optional + */ + if (0 != linked_list->data.extended_irq.resource_source_string_length) { + temp8 = (u8) linked_list->data.extended_irq.resource_source_index; + + *buffer = temp8; + buffer += 1; + temp_pointer = buffer; + + /* + * Copy the string + */ + STRCPY (temp_pointer, linked_list->data.extended_irq.resource_source); + + /* + * Buffer needs to be set to the length of the sting + one for the + * terminating null + */ + buffer += (STRLEN (linked_list->data.extended_irq.resource_source) + 1); + } + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + /* + * Set the length field to the number of bytes consumed + * minus the header size (3 bytes) + */ + *length_field = (u16) (*bytes_consumed - 3); + + return (AE_OK); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/resources/rslist.c linux/drivers/acpi/resources/rslist.c --- v2.4.0-test2/linux/drivers/acpi/resources/rslist.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/resources/rslist.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,506 @@ +/****************************************************************************** + * + * Module Name: rslist - Acpi_rs_byte_stream_to_list + * Acpi_list_to_byte_stream + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "resource.h" + +#define _COMPONENT RESOURCE_MANAGER + MODULE_NAME ("rslist"); + + +/*************************************************************************** + * FUNCTION: Acpi_rs_byte_stream_to_list + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource byte stream + * Byte_stream_buffer_length - Length of Byte_stream_buffer + * Output_buffer - Pointer to the buffer that will + * contain the output structures + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Takes the resource byte stream and parses it, creating a + * linked list of resources in the caller's output buffer + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_byte_stream_to_list ( + u8 *byte_stream_buffer, + u32 byte_stream_buffer_length, + u8 **output_buffer) +{ + ACPI_STATUS status = AE_UNKNOWN_STATUS; + u32 bytes_parsed = 0; + u8 resource_type = 0; + u32 bytes_consumed = 0; + u8 **buffer = output_buffer; + u32 structure_size = 0; + u8 end_tag_processed = FALSE; + + + while (bytes_parsed < byte_stream_buffer_length && + FALSE == end_tag_processed) + { + /* + * Look at the next byte in the stream + */ + resource_type = *byte_stream_buffer; + + /* + * See if this is a small or large resource + */ + if(resource_type & 0x80) { + /* + * Large Resource Type + */ + switch (resource_type) + { + case MEMORY_RANGE_24: + /* + * 24-Bit Memory Resource + */ + status = acpi_rs_memory24_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case LARGE_VENDOR_DEFINED: + /* + * Vendor Defined Resource + */ + status = acpi_rs_vendor_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case MEMORY_RANGE_32: + /* + * 32-Bit Memory Range Resource + */ + status = acpi_rs_memory32_range_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case FIXED_MEMORY_RANGE_32: + /* + * 32-Bit Fixed Memory Resource + */ + status = acpi_rs_fixed_memory32_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case DWORD_ADDRESS_SPACE: + /* + * 32-Bit Address Resource + */ + status = acpi_rs_address32_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case WORD_ADDRESS_SPACE: + /* + * 16-Bit Address Resource + */ + status = acpi_rs_address16_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case EXTENDED_IRQ: + /* + * Extended IRQ + */ + status = acpi_rs_extended_irq_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + +/* 64-bit not currently supported */ +/* + case 0x8A: + break; +*/ + + default: + /* + * If we get here, everything is out of sync, + * so exit with an error + */ + return (AE_ERROR); + break; + } + } + + else { + /* + * Small Resource Type + * Only bits 7:3 are valid + */ + resource_type >>= 3; + + switch(resource_type) + { + case IRQ_FORMAT: + /* + * IRQ Resource + */ + status = acpi_rs_irq_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case DMA_FORMAT: + /* + * DMA Resource + */ + status = acpi_rs_dma_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case START_DEPENDENT_TAG: + /* + * Start Dependent Functions Resource + */ + status = acpi_rs_start_dependent_functions_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case END_DEPENDENT_TAG: + /* + * End Dependent Functions Resource + */ + status = acpi_rs_end_dependent_functions_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case IO_PORT_DESCRIPTOR: + /* + * IO Port Resource + */ + status = acpi_rs_io_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case FIXED_LOCATION_IO_DESCRIPTOR: + /* + * Fixed IO Port Resource + */ + status = acpi_rs_fixed_io_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case SMALL_VENDOR_DEFINED: + /* + * Vendor Specific Resource + */ + status = acpi_rs_vendor_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case END_TAG: + /* + * End Tag + */ + status = acpi_rs_end_tag_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + end_tag_processed = TRUE; + + break; + + default: + /* + * If we get here, everything is out of sync, + * so exit with an error + */ + return (AE_ERROR); + break; + + } /* switch */ + } /* if(Resource_type & 0x80) */ + + /* + * Update the return value and counter + */ + bytes_parsed += bytes_consumed; + + /* + * Set the byte stream to point to the next resource + */ + byte_stream_buffer += bytes_consumed; + + /* + * Set the Buffer to the next structure + */ + *buffer += structure_size; + + } /* while (Bytes_parsed < Byte_stream_buffer_length && + FALSE == End_tag_processed) */ + + /* + * Check the reason for exiting the while loop + */ + if (byte_stream_buffer_length != bytes_parsed || TRUE != end_tag_processed) { + return (AE_ERROR); + } + + return (AE_OK); + +} /* Acpi_rs_byte_stream_to_list */ + + +/*************************************************************************** + * FUNCTION: Acpi_rs_list_to_byte_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Byte_steam_size_needed - Calculated size of the byte stream + * needed from calling + * Acpi_rs_calculate_byte_stream_length() + * The size of the Output_buffer is + * guaranteed to be >= + * Byte_stream_size_needed + * Output_buffer - Pointer to the buffer that will + * contain the byte stream + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Takes the resource linked list and parses it, creating a + * byte stream of resources in the caller's output buffer + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_list_to_byte_stream ( + RESOURCE *linked_list, + u32 byte_stream_size_needed, + u8 **output_buffer) +{ + ACPI_STATUS status = AE_UNKNOWN_STATUS; + u8 *buffer = *output_buffer; + u32 bytes_consumed = 0; + u8 done = FALSE; + + + while (!done) { + switch (linked_list->id) + { + case irq: + /* + * IRQ Resource + */ + status = acpi_rs_irq_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case dma: + /* + * DMA Resource + */ + status = acpi_rs_dma_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case start_dependent_functions: + /* + * Start Dependent Functions Resource + */ + status = acpi_rs_start_dependent_functions_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case end_dependent_functions: + /* + * End Dependent Functions Resource + */ + status = acpi_rs_end_dependent_functions_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case io: + /* + * IO Port Resource + */ + status = acpi_rs_io_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case fixed_io: + /* + * Fixed IO Port Resource + */ + status = acpi_rs_fixed_io_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case vendor_specific: + /* + * Vendor Defined Resource + */ + status = acpi_rs_vendor_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case end_tag: + /* + * End Tag + */ + status = acpi_rs_end_tag_stream (linked_list, + &buffer, + &bytes_consumed); + + /* + * An End Tag indicates the end of the Resource Template + */ + done = TRUE; + break; + + case memory24: + /* + * 24-Bit Memory Resource + */ + status = acpi_rs_memory24_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case memory32: + /* + * 32-Bit Memory Range Resource + */ + status = acpi_rs_memory32_range_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case fixed_memory32: + /* + * 32-Bit Fixed Memory Resource + */ + status = acpi_rs_fixed_memory32_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case address16: + /* + * 16-Bit Address Descriptor Resource + */ + status = acpi_rs_address16_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case address32: + /* + * 32-Bit Address Descriptor Resource + */ + status = acpi_rs_address32_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case extended_irq: + /* + * Extended IRQ Resource + */ + status = acpi_rs_extended_irq_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + default: + /* + * If we get here, everything is out of sync, + * so exit with an error + */ + return (AE_BAD_DATA); + break; + + } /* switch (Linked_list->Id) */ + + /* + * Set the Buffer to point to the open byte + */ + buffer += bytes_consumed; + + /* + * Point to the next object + */ + linked_list = (RESOURCE *) ((NATIVE_UINT) linked_list + + (NATIVE_UINT) linked_list->length); + } + + return (AE_OK); + +} /* Acpi_rs_list_to_byte_stream */ + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/resources/rsmemory.c linux/drivers/acpi/resources/rsmemory.c --- v2.4.0-test2/linux/drivers/acpi/resources/rsmemory.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/resources/rsmemory.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,570 @@ +/****************************************************************************** + * + * Module Name: rsmem24 - Acpi_rs_memory24_resource + * Acpi_rs_memory24_stream + * Acpi_rs_memory32_range_resource + * Acpi_rs_fixed_memory32_resource + * Acpi_rs_memory32_range_stream + * Acpi_rs_fixed_memory32_stream + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" + +#define _COMPONENT RESOURCE_MANAGER + MODULE_NAME ("rsmemory"); + + +/*************************************************************************** + * FUNCTION: Acpi_rs_memory24_resource + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_memory24_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u32 struct_size = sizeof (MEMORY24_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + + temp16 = *(u16 *)buffer; + + buffer += 2; + + *bytes_consumed = temp16 + 3; + + output_struct->id = memory24; + + /* + * Check Byte 3 the Read/Write bit + */ + temp8 = *buffer; + + buffer += 1; + + output_struct->data.memory24.read_write_attribute = temp8 & 0x01; + + /* + * Get Min_base_address (Bytes 4-5) + */ + temp16 = *(u16 *)buffer; + + buffer += 2; + + output_struct->data.memory24.min_base_address = temp16; + + /* + * Get Max_base_address (Bytes 6-7) + */ + temp16 = *(u16 *)buffer; + + buffer += 2; + + output_struct->data.memory24.max_base_address = temp16; + + /* + * Get Alignment (Bytes 8-9) + */ + temp16 = *(u16 *)buffer; + + buffer += 2; + + output_struct->data.memory24.alignment = temp16; + + /* + * Get Range_length (Bytes 10-11) + */ + temp16 = *(u16 *)buffer; + + output_struct->data.memory24.range_length = temp16; + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_memory24_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_memory24_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + /* + * The descriptor field is static + */ + *buffer = 0x81; + + buffer += 1; + + /* + * The length field is static + */ + temp16 = 0x09; + + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); + + buffer += 2; + + /* + * Set the Information Byte + */ + temp8 = (u8) (linked_list->data.memory24.read_write_attribute & 0x01); + *buffer = temp8; + buffer += 1; + + /* + * Set the Range minimum base address + */ + MOVE_UNALIGNED16_TO_16 (buffer, &linked_list->data.memory24.min_base_address); + buffer += 2; + + /* + * Set the Range maximum base address + */ + MOVE_UNALIGNED16_TO_16 (buffer, &linked_list->data.memory24.max_base_address); + buffer += 2; + + /* + * Set the base alignment + */ + MOVE_UNALIGNED16_TO_16 (buffer, &linked_list->data.memory24.alignment); + buffer += 2; + + /* + * Set the range length + */ + MOVE_UNALIGNED16_TO_16 (buffer, &linked_list->data.memory24.range_length); + buffer += 2; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_memory32_range_resource + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_memory32_range_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u32 struct_size = sizeof (MEMORY32_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + buffer += 2; + *bytes_consumed = temp16 + 3; + + output_struct->id = memory32; + + /* + * Point to the place in the output buffer where the data portion will + * begin. + * 1. Set the RESOURCE_DATA * Data to point to it's own address, then + * 2. Set the pointer to the next address. + * + * NOTE: Output_struct->Data is cast to u8, otherwise, this addition adds + * 4 * sizeof(RESOURCE_DATA) instead of 4 * sizeof(u8) + */ + + /* + * Check Byte 3 the Read/Write bit + */ + temp8 = *buffer; + buffer += 1; + + output_struct->data.memory32.read_write_attribute = temp8 & 0x01; + + /* + * Get Min_base_address (Bytes 4-7) + */ + MOVE_UNALIGNED32_TO_32 (&output_struct->data.memory32.min_base_address, + buffer); + buffer += 4; + + /* + * Get Max_base_address (Bytes 8-11) + */ + MOVE_UNALIGNED32_TO_32 (&output_struct->data.memory32.max_base_address, + buffer); + buffer += 4; + + /* + * Get Alignment (Bytes 12-15) + */ + MOVE_UNALIGNED32_TO_32 (&output_struct->data.memory32.alignment, buffer); + buffer += 4; + + /* + * Get Range_length (Bytes 16-19) + */ + MOVE_UNALIGNED32_TO_32 (&output_struct->data.memory32.range_length, buffer); + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_fixed_memory32_resource + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_fixed_memory32_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u32 struct_size = sizeof (FIXED_MEMORY32_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + buffer += 2; + *bytes_consumed = temp16 + 3; + + output_struct->id = fixed_memory32; + + /* + * Check Byte 3 the Read/Write bit + */ + temp8 = *buffer; + buffer += 1; + output_struct->data.fixed_memory32.read_write_attribute = temp8 & 0x01; + + /* + * Get Range_base_address (Bytes 4-7) + */ + MOVE_UNALIGNED32_TO_32 (&output_struct->data.fixed_memory32.range_base_address, + buffer); + buffer += 4; + + /* + * Get Range_length (Bytes 8-11) + */ + MOVE_UNALIGNED32_TO_32 (&output_struct->data.fixed_memory32.range_length, + buffer); + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_memory32_range_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_memory32_range_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + /* + * The descriptor field is static + */ + *buffer = 0x85; + buffer += 1; + + /* + * The length field is static + */ + temp16 = 0x11; + + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the Information Byte + */ + temp8 = (u8) (linked_list->data.memory32.read_write_attribute & 0x01); + *buffer = temp8; + buffer += 1; + + /* + * Set the Range minimum base address + */ + MOVE_UNALIGNED32_TO_32 (buffer, &linked_list->data.memory32.min_base_address); + buffer += 4; + + /* + * Set the Range maximum base address + */ + MOVE_UNALIGNED32_TO_32 (buffer, &linked_list->data.memory32.max_base_address); + buffer += 4; + + /* + * Set the base alignment + */ + MOVE_UNALIGNED32_TO_32 (buffer, &linked_list->data.memory32.alignment); + buffer += 4; + + /* + * Set the range length + */ + MOVE_UNALIGNED32_TO_32 (buffer, &linked_list->data.memory32.range_length); + buffer += 4; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_fixed_memory32_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_fixed_memory32_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + /* + * The descriptor field is static + */ + *buffer = 0x86; + buffer += 1; + + /* + * The length field is static + */ + temp16 = 0x09; + + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the Information Byte + */ + temp8 = (u8) (linked_list->data.fixed_memory32.read_write_attribute & 0x01); + *buffer = temp8; + buffer += 1; + + /* + * Set the Range base address + */ + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.fixed_memory32.range_base_address); + buffer += 4; + + /* + * Set the range length + */ + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.fixed_memory32.range_length); + buffer += 4; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/resources/rsmisc.c linux/drivers/acpi/resources/rsmisc.c --- v2.4.0-test2/linux/drivers/acpi/resources/rsmisc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/resources/rsmisc.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,612 @@ +/****************************************************************************** + * + * Module Name: rsmisc - Acpi_rs_end_tag_resource + * Acpi_rs_end_tag_stream + * Acpi_rs_vendor_resource + * Acpi_rs_vendor_stream + * Acpi_rs_start_dependent_functions_resource + * Acpi_rs_end_dependent_functions_resource + * Acpi_rs_start_dependent_functions_stream + * Acpi_rs_end_dependent_functions_stream + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" + +#define _COMPONENT RESOURCE_MANAGER + MODULE_NAME ("rsmisc"); + + +/*************************************************************************** + * FUNCTION: Acpi_rs_end_tag_resource + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_end_tag_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u32 struct_size = RESOURCE_LENGTH; + + + /* + * The number of bytes consumed is static + */ + *bytes_consumed = 2; + + /* + * Fill out the structure + */ + output_struct->id = end_tag; + + /* + * Set the Length parameter + */ + output_struct->length = 0; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_end_tag_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_end_tag_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u8 temp8 = 0; + + + /* + * The descriptor field is static + */ + *buffer = 0x79; + + buffer += 1; + + /* + * Set the Checksum - zero means that the resource data is treated as if + * the checksum operation succeeded (ACPI Spec 1.0b Section 6.4.2.8) + */ + temp8 = 0; + + *buffer = temp8; + + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + +/*************************************************************************** + * FUNCTION: Acpi_rs_vendor_resource + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_vendor_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + u32 struct_size = sizeof (VENDOR_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * Dereference the Descriptor to find if this is a large or small item. + */ + temp8 = *buffer; + + if (temp8 & 0x80) { + /* + * Large Item + */ + /* Point to the length field */ + + buffer += 1; + + /* Dereference */ + + temp16 = *(u16 *)buffer; + + /* Calculate bytes consumed */ + + *bytes_consumed = temp16 + 3; + + /* Point to the first vendor byte */ + + buffer += 2; + } + + else { + /* + * Small Item + */ + + /* Dereference the size */ + + temp16 = (u8)(*buffer & 0x07); + + /* Calculate bytes consumed */ + + *bytes_consumed = temp16 + 1; + + /* Point to the first vendor byte */ + + buffer += 1; + } + + output_struct->id = vendor_specific; + + output_struct->data.vendor_specific.length = temp16; + + for (index = 0; index < temp16; index++) { + output_struct->data.vendor_specific.reserved[index] = *buffer; + buffer += 1; + } + + /* + * In order for the Struct_size to fall on a 32-bit boundry, + * calculate the length of the vendor string and expand the + * Struct_size to the next 32-bit boundry. + */ + struct_size += ROUND_UP_TO_32_bITS (temp16); + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_vendor_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_vendor_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + + + /* + * Dereference the length to find if this is a large or small item. + */ + + if(linked_list->data.vendor_specific.length > 7) { + /* + * Large Item + */ + /* + * Set the descriptor field and length bytes + */ + *buffer = 0x84; + + buffer += 1; + + temp16 = (u16) linked_list->data.vendor_specific.length; + + *(u16 *)buffer = temp16; + + buffer += 2; + } + + else { + /* + * Small Item + */ + + /* + * Set the descriptor field + */ + temp8 = 0x70; + + temp8 |= linked_list->data.vendor_specific.length; + + *buffer = temp8; + + buffer += 1; + } + + /* + * Loop through all of the Vendor Specific fields + */ + for (index = 0; index < linked_list->data.vendor_specific.length; index++) { + temp8 = linked_list->data.vendor_specific.reserved[index]; + *buffer = temp8; + buffer += 1; + } + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + +/*************************************************************************** + * FUNCTION: Acpi_rs_start_dependent_functions_resource + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_start_dependent_functions_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u8 temp8 = 0; + u32 struct_size = + sizeof(START_DEPENDENT_FUNCTIONS_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * The number of bytes consumed are contained in the descriptor (Bits:0-1) + */ + temp8 = *buffer; + + *bytes_consumed = (temp8 & 0x01) + 1; + + output_struct->id = start_dependent_functions; + + /* + * Point to Byte 1 if it is used + */ + if (2 == *bytes_consumed) { + buffer += 1; + temp8 = *buffer; + + /* + * Check Compatibility priority + */ + output_struct->data.start_dependent_functions.compatibility_priority = + temp8 & 0x03; + + if (3 == output_struct->data.start_dependent_functions.compatibility_priority) { + return (AE_ERROR); + } + + /* + * Check Performance/Robustness preference + */ + output_struct->data.start_dependent_functions.performance_robustness = + (temp8 >> 2) & 0x03; + + if (3 == output_struct->data.start_dependent_functions.performance_robustness) { + return (AE_ERROR); + } + } + + else { + output_struct->data.start_dependent_functions.compatibility_priority = + ACCEPTABLE_CONFIGURATION; + + output_struct->data.start_dependent_functions.performance_robustness = + ACCEPTABLE_CONFIGURATION; + } + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_end_dependent_functions_resource + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_end_dependent_functions_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u32 struct_size = RESOURCE_LENGTH; + + + /* + * The number of bytes consumed is static + */ + *bytes_consumed = 1; + + /* + * Fill out the structure + */ + output_struct->id = end_dependent_functions; + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_start_dependent_functions_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ***************************************************************************/ +ACPI_STATUS +acpi_rs_start_dependent_functions_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u8 temp8 = 0; + + + /* + * The descriptor field is set based upon whether a byte is needed + * to contain Priority data. + */ + if (ACCEPTABLE_CONFIGURATION == + linked_list->data.start_dependent_functions.compatibility_priority && + ACCEPTABLE_CONFIGURATION == + linked_list->data.start_dependent_functions.performance_robustness) + { + *buffer = 0x30; + } + else { + *buffer = 0x31; + + buffer += 1; + + /* + * Set the Priority Byte Definition + */ + temp8 = 0; + + temp8 = (u8) + ((linked_list->data.start_dependent_functions.performance_robustness & + 0x03) << 2); + + temp8 |= + (linked_list->data.start_dependent_functions.compatibility_priority & + 0x03); + + *buffer = temp8; + } + + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + + +/*************************************************************************** + * FUNCTION: Acpi_rs_end_dependent_functions_stream + * + * PARAMETERS: + * Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ***************************************************************************/ + +ACPI_STATUS +acpi_rs_end_dependent_functions_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed + ) +{ + u8 *buffer = *output_buffer; + + + /* + * The descriptor field is static + */ + *buffer = 0x38; + + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/resources/rsutils.c linux/drivers/acpi/resources/rsutils.c --- v2.4.0-test2/linux/drivers/acpi/resources/rsutils.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/resources/rsutils.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,430 @@ +/****************************************************************************** + * + * Module Name: rsutils - Utilities for the resource manager + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "namesp.h" +#include "resource.h" + + +#define _COMPONENT RESOURCE_MANAGER + MODULE_NAME ("rsutils"); + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_get_prt_method_data + * + * PARAMETERS: Device_handle - a handle to the containing object + * Ret_buffer - a pointer to a buffer structure for the + * results + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get the _PRT value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_get_prt_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *ret_buffer) +{ + ACPI_OBJECT_INTERNAL *ret_obj; + ACPI_STATUS status; + u32 buffer_space_needed = ret_buffer->length; + + + /* + * Must have a valid handle and buffer, So we have to have a handle + * a return buffer structure and if there is a non-zero buffer length + * we also need a valid pointer in the buffer + */ + if ((!handle) || + (!ret_buffer) || + ((!ret_buffer->pointer) && (ret_buffer->length))) + { + return (AE_BAD_PARAMETER); + } + + /* + * Execute the method, no parameters + */ + status = acpi_ns_evaluate_relative (handle, "_PRT", NULL, &ret_obj); + if (status != AE_OK) { + return (status); + } + + if (!ret_obj) { + /* Return object is required */ + + return (AE_TYPE); + } + + + /* + * The return object will be a package, so check the + * parameters. If the return object is not a package, + * then the underlying AML code is corrupt or improperly + * written. + */ + if (ACPI_TYPE_PACKAGE != ret_obj->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the _CRS method + * execution. + */ + status = acpi_rs_create_pci_routing_table (ret_obj, + ret_buffer->pointer, + &buffer_space_needed); + + /* + * Tell the user how much of the buffer we have used or is needed + * and return the final status. + */ + ret_buffer->length = buffer_space_needed; + + + /* On exit, we must delete the object returned by evaluate_object */ + +cleanup: + + acpi_cm_remove_reference (ret_obj); + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_get_crs_method_data + * + * PARAMETERS: Device_handle - a handle to the containing object + * Ret_buffer - a pointer to a buffer structure for the + * results + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get the _CRS value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_get_crs_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *ret_buffer) +{ + ACPI_OBJECT_INTERNAL *ret_obj; + ACPI_STATUS status; + u32 buffer_space_needed = ret_buffer->length; + + + /* + * Must have a valid handle and buffer, So we have to have a handle + * a return buffer structure and if there is a non-zero buffer length + * we also need a valid pointer in the buffer + */ + if ((!handle) || + (!ret_buffer) || + ((!ret_buffer->pointer) && (ret_buffer->length))) + { + return (AE_BAD_PARAMETER); + } + + /* + * Execute the method, no parameters + */ + status = acpi_ns_evaluate_relative (handle, "_CRS", NULL, &ret_obj); + if (status != AE_OK) { + return (status); + } + + if (!ret_obj) { + /* Return object is required */ + + return (AE_TYPE); + } + + /* + * The return object will be a buffer, but check the + * parameters. If the return object is not a buffer, + * then the underlying AML code is corrupt or improperly + * written. + */ + if (ACPI_TYPE_BUFFER != ret_obj->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the _CRS method + * execution. + */ + status = acpi_rs_create_resource_list (ret_obj, + ret_buffer->pointer, + &buffer_space_needed); + + if (AE_OK == status) { + acpi_rs_dump_resource_list((RESOURCE *)ret_buffer->pointer); + } + + /* + * Tell the user how much of the buffer we have used or is needed + * and return the final status. + */ + ret_buffer->length = buffer_space_needed; + + + /* On exit, we must delete the object returned by evaluate_object */ + +cleanup: + + acpi_cm_remove_reference (ret_obj); + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_get_prs_method_data + * + * PARAMETERS: Device_handle - a handle to the containing object + * Ret_buffer - a pointer to a buffer structure for the + * results + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get the _PRS value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_get_prs_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *ret_buffer) +{ + ACPI_OBJECT_INTERNAL *ret_obj; + ACPI_STATUS status; + u32 buffer_space_needed = ret_buffer->length; + + + /* + * Must have a valid handle and buffer, So we have to have a handle + * a return buffer structure and if there is a non-zero buffer length + * we also need a valid pointer in the buffer + */ + if ((!handle) || + (!ret_buffer) || + ((!ret_buffer->pointer) && (ret_buffer->length))) + { + return (AE_BAD_PARAMETER); + } + + /* + * Execute the method, no parameters + */ + status = acpi_ns_evaluate_relative (handle, "_PRS", NULL, &ret_obj); + if (status != AE_OK) { + return (status); + } + + if (!ret_obj) { + /* Return object is required */ + + return (AE_TYPE); + } + + /* + * The return object will be a buffer, but check the + * parameters. If the return object is not a buffer, + * then the underlying AML code is corrupt or improperly + * written.. + */ + if (ACPI_TYPE_BUFFER != ret_obj->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the _CRS method + * execution. + */ + status = acpi_rs_create_resource_list (ret_obj, + ret_buffer->pointer, + &buffer_space_needed); + + /* + * Tell the user how much of the buffer we have used or is needed + * and return the final status. + */ + ret_buffer->length = buffer_space_needed; + + + /* On exit, we must delete the object returned by evaluate_object */ + +cleanup: + + acpi_cm_remove_reference (ret_obj); + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_rs_set_srs_method_data + * + * PARAMETERS: Device_handle - a handle to the containing object + * *Method_name - Name of method to execute, If NULL, the + * handle is the object to execute + * In_buffer - a pointer to a buffer structure of the + * parameter + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to set the _SRS of an object contained + * in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_set_srs_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *in_buffer) +{ + ACPI_OBJECT_INTERNAL *params[2]; + ACPI_OBJECT_INTERNAL param_obj; + ACPI_STATUS status; + u8 *byte_stream = NULL; + u32 buffer_size_needed = 0; + + /* + * Must have a valid handle and buffer + */ + if ((!handle) || + (!in_buffer) || + (!in_buffer->pointer) || + (!in_buffer->length)) + { + return (AE_BAD_PARAMETER); + } + + /* + * The In_buffer parameter will point to a linked list of + * resource parameters. It needs to be formatted into a + * byte stream to be sent in as an input parameter. + */ + buffer_size_needed = 0; + + /* + * First call is to get the buffer size needed + */ + status = acpi_rs_create_byte_stream (in_buffer->pointer, + byte_stream, + &buffer_size_needed); + + /* + * We expect a return of AE_BUFFER_OVERFLOW + * if not, exit with the error + */ + if (AE_BUFFER_OVERFLOW != status) { + return (status); + } + + /* + * Allocate the buffer needed + */ + byte_stream = acpi_cm_callocate(buffer_size_needed); + + if (NULL == byte_stream) { + return (AE_NO_MEMORY); + } + + /* + * Now call to convert the linked list into a byte stream + */ + status = acpi_rs_create_byte_stream (in_buffer->pointer, + byte_stream, + &buffer_size_needed); + + if(AE_OK != status) { + /* + * Failed the call + */ + acpi_cm_free (byte_stream); + return (status); + } + + /* + * Init the param object + */ + acpi_cm_init_static_object (¶m_obj); + + /* + * Method requires one parameter. Set it up + */ + params [0] = ¶m_obj; + params [1] = NULL; + + /* + * Set up the parameter object + */ + param_obj.common.type = ACPI_TYPE_BUFFER; + param_obj.buffer.length = buffer_size_needed; + param_obj.buffer.pointer = byte_stream; + + /* + * Execute the method, no return value + */ + status = acpi_ns_evaluate_relative (handle, "_SRS", params, NULL); + + /* + * Clean up and return the status from Acpi_ns_evaluate_relative + */ + acpi_cm_free (byte_stream); + return (status); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/resources/rsxface.c linux/drivers/acpi/resources/rsxface.c --- v2.4.0-test2/linux/drivers/acpi/resources/rsxface.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/resources/rsxface.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,177 @@ +/****************************************************************************** + * + * Module Name: rsxface - Public interfaces to the ACPI subsystem + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "interp.h" +#include "namesp.h" +#include "resource.h" + +#define _COMPONENT RESOURCE_MANAGER + MODULE_NAME ("rsxface"); + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_irq_routing_table + * + * PARAMETERS: Device_handle - a handle to the Bus device we are querying + * Out_buffer - a pointer to a buffer to receive the + * current resources for the device + * Buffer_length - the number of bytes available in the buffer + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get the IRQ routing table for a + * specific bus. The caller must first acquire a handle for the + * desired bus. The routine table is placed in the buffer pointed + * to by the Out_buffer variable parameter. + * + * If the function fails an appropriate status will be returned + * and the value of Out_buffer is undefined. + * + * This function attempts to execute the _PRT method contained in + * the object indicated by the passed Device_handle. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_irq_routing_table ( + ACPI_HANDLE device_handle, + ACPI_BUFFER *ret_buffer) +{ + ACPI_STATUS status; + + + status = acpi_rs_get_prt_method_data (device_handle, ret_buffer); + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_current_resources + * + * PARAMETERS: Device_handle - a handle to the device object for the + * device we are querying + * Out_buffer - a pointer to a buffer to receive the + * current resources for the device + * Buffer_length - the number of bytes available in the buffer + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get the current resources for a + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is placed in the buffer + * pointed to by the Out_buffer variable parameter. + * + * If the function fails an appropriate status will be returned + * and the value of Out_buffer is undefined. + * + * This function attempts to execute the _CRS method contained in + * the object indicated by the passed Device_handle. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_current_resources ( + ACPI_HANDLE device_handle, + ACPI_BUFFER *ret_buffer) +{ + ACPI_STATUS status; + + + status = acpi_rs_get_crs_method_data (device_handle, ret_buffer); + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_possible_resources + * + * PARAMETERS: Device_handle - a handle to the device object for the + * device we are querying + * Out_buffer - a pointer to a buffer to receive the + * resources for the device + * Buffer_length - the number of bytes available in the buffer + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get a list of the possible resources + * for a specific device. The caller must first acquire a handle + * for the desired device. The resource data is placed in the + * buffer pointed to by the Out_buffer variable. + * + * If the function fails an appropriate status will be returned + * and the value of Out_buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_possible_resources ( + ACPI_HANDLE device_handle, + ACPI_BUFFER *ret_buffer) +{ + ACPI_STATUS status; + + + status = acpi_rs_get_prs_method_data (device_handle, ret_buffer); + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_set_current_resources + * + * PARAMETERS: Device_handle - a handle to the device object for the + * device we are changing the resources of + * Out_buffer - a pointer to a buffer containing the + * resources to be set for the device + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to set the current resources for a + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is passed to the routine + * the buffer pointed to by the In_buffer variable. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_set_current_resources ( + ACPI_HANDLE device_handle, + ACPI_BUFFER *in_buffer) +{ + ACPI_STATUS status; + + + status = acpi_rs_set_srs_method_data (device_handle, in_buffer); + + return (status); +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/tables/tbget.c linux/drivers/acpi/tables/tbget.c --- v2.4.0-test2/linux/drivers/acpi/tables/tbget.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/tables/tbget.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,324 @@ + +/****************************************************************************** + * + * Module Name: tbget - ACPI Table get* routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "hardware.h" +#include "tables.h" + + +#define _COMPONENT TABLE_MANAGER + MODULE_NAME ("tbget"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_get_table_ptr + * + * PARAMETERS: Table_type - one of the defined table types + * Instance - Which table of this type + * Table_ptr_loc - pointer to location to place the pointer for + * return + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the pointer to an ACPI table. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_get_table_ptr ( + ACPI_TABLE_TYPE table_type, + u32 instance, + ACPI_TABLE_HEADER **table_ptr_loc) +{ + ACPI_TABLE_DESC *table_desc; + u32 i; + + + if (!acpi_gbl_DSDT) { + return (AE_NO_ACPI_TABLES); + } + + if (table_type > ACPI_TABLE_MAX) { + return (AE_BAD_PARAMETER); + } + + + /* + * For all table types (Single/Multiple), the first + * instance is always in the list head. + */ + + if (instance == 1) { + /* + * Just pluck the pointer out of the global table! + * Will be null if no table is present + */ + + *table_ptr_loc = acpi_gbl_acpi_tables[table_type].pointer; + return (AE_OK); + } + + + /* + * Check for instance out of range + */ + if (instance > acpi_gbl_acpi_tables[table_type].count) { + return (AE_NOT_EXIST); + } + + /* Walk the list to get the table */ + + table_desc = acpi_gbl_acpi_tables[table_type].next; + for (i = 1; i < acpi_gbl_acpi_tables[table_type].count; i++) { + table_desc = table_desc->next; + } + + /* We are now pointing to the requested table's descriptor */ + + *table_ptr_loc = table_desc->pointer; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_get_table + * + * PARAMETERS: Physical_address - Physical address of table to retrieve + * *Buffer_ptr - If == NULL, read data from buffer + * rather than searching memory + * *Table_info - Where the table info is returned + * + * RETURN: Status + * + * DESCRIPTION: Maps the physical address of table into a logical address + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_get_table ( + void *physical_address, + char *buffer_ptr, + ACPI_TABLE_DESC *table_info) +{ + ACPI_TABLE_HEADER *table_header = NULL; + ACPI_TABLE_HEADER *full_table = NULL; + u32 size; + u8 allocation; + ACPI_STATUS status = AE_OK; + + + if (!table_info) { + return (AE_BAD_PARAMETER); + } + + + if (buffer_ptr) { + /* + * Getting data from a buffer, not BIOS tables + */ + + table_header = (ACPI_TABLE_HEADER *) buffer_ptr; + status = acpi_tb_validate_table_header (table_header); + if (ACPI_FAILURE (status)) { + /* Table failed verification, map all errors to BAD_DATA */ + + return (AE_BAD_DATA); + } + + /* Allocate buffer for the entire table */ + + full_table = acpi_cm_allocate (table_header->length); + if (!full_table) { + return (AE_NO_MEMORY); + } + + /* Copy the entire table (including header) to the local buffer */ + + size = (ACPI_SIZE) table_header->length; + MEMCPY (full_table, buffer_ptr, size); + + /* Save allocation type */ + + allocation = ACPI_MEM_ALLOCATED; + } + + + /* + * Not reading from a buffer, just map the table's physical memory + * into our address space. + */ + else { + size = SIZE_IN_HEADER; + + status = acpi_tb_map_acpi_table (physical_address, &size, + (void **) &full_table); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Save allocation type */ + + allocation = ACPI_MEM_MAPPED; + } + + + /* Return values */ + + table_info->pointer = full_table; + table_info->length = size; + table_info->allocation = allocation; + table_info->base_pointer = full_table; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_get_all_tables + * + * PARAMETERS: Number_of_tables - Number of tables to get + * Table_ptr - Input buffer pointer, optional + * + * RETURN: Status + * + * DESCRIPTION: Load and validate all tables other than the RSDT. The RSDT must + * already be loaded and validated. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_get_all_tables ( + u32 number_of_tables, + char *table_ptr) +{ + ACPI_STATUS status = AE_OK; + u32 index; + ACPI_TABLE_DESC table_info; + + + /* + * Loop through all table pointers found in RSDT. + * This will NOT include the FACS and DSDT - we must get + * them after the loop + */ + + for (index = 0; index < number_of_tables; index++) { + /* Clear the Table_info each time */ + + MEMSET (&table_info, 0, sizeof (ACPI_TABLE_DESC)); + + /* Get the table via the RSDT */ + + status = acpi_tb_get_table ((void *) acpi_gbl_RSDT->table_offset_entry[index], + table_ptr, &table_info); + + /* Ignore a table that failed verification */ + + if (status == AE_BAD_DATA) { + continue; + } + + /* However, abort on serious errors */ + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Recognize and install the table */ + + status = acpi_tb_install_table (table_ptr, &table_info); + if (ACPI_FAILURE (status)) { + /* + * Unrecognized or unsupported table, delete it and ignore the + * error. Just get as many tables as we can, later we will + * determine if there are enough tables to continue. + */ + + acpi_tb_delete_single_table (&table_info); + } + } + + + /* + * Get the minimum set of ACPI tables, namely: + * + * 1) FACP (via RSDT in loop above) + * 2) FACS + * 3) DSDT + * + */ + + + /* + * Get the FACS (must have the FACP first, from loop above) + * Acpi_tb_get_table_facs will fail if FACP pointer is not valid + */ + + status = acpi_tb_get_table_facs (table_ptr, &table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Install the FACS */ + + status = acpi_tb_install_table (table_ptr, &table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* Get the DSDT (We know that the FACP if valid now) */ + + status = acpi_tb_get_table ((void *) acpi_gbl_FACP->dsdt, table_ptr, &table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Install the DSDT */ + + status = acpi_tb_install_table (table_ptr, &table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Dump the DSDT Header */ + + /* Dump the entire DSDT */ + + /* + * Initialize the capabilities flags. + * Assumes that platform supports ACPI_MODE since we have tables! + */ + + acpi_gbl_system_flags |= acpi_hw_get_mode_capabilities (); + + return (status); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/tables/tbinstal.c linux/drivers/acpi/tables/tbinstal.c --- v2.4.0-test2/linux/drivers/acpi/tables/tbinstal.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/tables/tbinstal.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,533 @@ + +/****************************************************************************** + * + * Module Name: tbinstal - ACPI table installation and removal + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "hardware.h" +#include "tables.h" + + +#define _COMPONENT TABLE_MANAGER + MODULE_NAME ("tbinstal"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_install_table + * + * PARAMETERS: Table_ptr - Input buffer pointer, optional + * Table_info - Return value from Acpi_tb_get_table + * + * RETURN: Status + * + * DESCRIPTION: Load and validate all tables other than the RSDT. The RSDT must + * already be loaded and validated. + * Install the table into the global data structs. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_install_table ( + char *table_ptr, + ACPI_TABLE_DESC *table_info) +{ + ACPI_TABLE_TYPE table_type; + ACPI_TABLE_HEADER *table_header; + ACPI_STATUS status; + + + /* + * Check the table signature and make sure it is recognized + * Also checks the header checksum + */ + + status = acpi_tb_recognize_table (table_ptr, table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Table type is returned by Recognize_table */ + + table_type = table_info->type; + table_header = table_info->pointer; + + /* Lock tables while installing */ + + acpi_cm_acquire_mutex (ACPI_MTX_TABLES); + + /* Install the table into the global data structure */ + + status = acpi_tb_init_table_descriptor (table_info->type, table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + acpi_cm_release_mutex (ACPI_MTX_TABLES); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_recognize_table + * + * PARAMETERS: Table_ptr - Input buffer pointer, optional + * Table_info - Return value from Acpi_tb_get_table + * + * RETURN: Status + * + * DESCRIPTION: Check a table signature for a match against known table types + * + * NOTE: All table pointers are validated as follows: + * 1) Table pointer must point to valid physical memory + * 2) Signature must be 4 ASCII chars, even if we don't recognize the + * name + * 3) Table must be readable for length specified in the header + * 4) Table checksum must be valid (with the exception of the FACS + * which has no checksum for some odd reason) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_recognize_table ( + char *table_ptr, + ACPI_TABLE_DESC *table_info) +{ + ACPI_TABLE_HEADER *table_header; + ACPI_STATUS status; + ACPI_TABLE_TYPE table_type = 0; + u32 i; + + + /* Ensure that we have a valid table pointer */ + + table_header = (ACPI_TABLE_HEADER *) table_info->pointer; + if (!table_header) { + return (AE_BAD_PARAMETER); + } + + /* + * Search for a signature match among the known table types + * Start at index one -> Skip the RSDP + */ + + status = AE_SUPPORT; + for (i = 1; i < NUM_ACPI_TABLES; i++) { + if (!STRNCMP (table_header->signature, + acpi_gbl_acpi_table_data[i].signature, + acpi_gbl_acpi_table_data[i].sig_length)) + { + /* + * Found a signature match, get the pertinent info from the + * Table_data structure + */ + + table_type = i; + status = acpi_gbl_acpi_table_data[i].status; + + break; + } + } + + /* Return the table type and length via the info struct */ + + table_info->type = (u8) table_type; + table_info->length = table_header->length; + + + /* + * Validate checksum for _most_ tables, + * even the ones whose signature we don't recognize + */ + + if (table_type != ACPI_TABLE_FACS) { + /* But don't abort if the checksum is wrong */ + /* TBD: [Future] make this a configuration option? */ + + acpi_tb_verify_table_checksum (table_header); + } + + /* + * An AE_SUPPORT means that the table was not recognized. + * We basically ignore this; just print a debug message + */ + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_init_table_descriptor + * + * PARAMETERS: Table_type - The type of the table + * Table_info - A table info struct + * + * RETURN: None. + * + * DESCRIPTION: Install a table into the global data structs. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_init_table_descriptor ( + ACPI_TABLE_TYPE table_type, + ACPI_TABLE_DESC *table_info) +{ + ACPI_TABLE_DESC *list_head; + ACPI_TABLE_DESC *table_desc; + + + /* + * Install the table into the global data structure + */ + + list_head = &acpi_gbl_acpi_tables[table_type]; + table_desc = list_head; + + + /* + * Two major types of tables: 1) Only one instance is allowed. This + * includes most ACPI tables such as the DSDT. 2) Multiple instances of + * the table are allowed. This includes SSDT and PSDTs. + */ + + if (acpi_gbl_acpi_table_data[table_type].flags == ACPI_TABLE_SINGLE) { + /* + * Only one table allowed, just update the list head + */ + + if (list_head->pointer) { + return (AE_EXIST); + } + + table_desc->count = 1; + } + + + else { + /* + * Multiple tables allowed for this table type, we must link + * the new table in to the list of tables of this type. + */ + + if (list_head->pointer) { + table_desc = acpi_cm_callocate (sizeof (ACPI_TABLE_DESC)); + if (!table_desc) { + return (AE_NO_MEMORY); + } + + list_head->count++; + + /* Update the original previous */ + + list_head->prev->next = table_desc; + + /* Update new entry */ + + table_desc->prev = list_head->prev; + table_desc->next = (ACPI_TABLE_DESC *) list_head; + + /* Update list head */ + + list_head->prev = table_desc; + } + + else { + table_desc->count = 1; + } + } + + + /* Common initialization of the table descriptor */ + + table_desc->pointer = table_info->pointer; + table_desc->base_pointer = table_info->base_pointer; + table_desc->length = table_info->length; + table_desc->allocation = table_info->allocation; + table_desc->aml_pointer = (u8 *) (table_desc->pointer + 1), + table_desc->aml_length = (u32) (table_desc->length - + (u32) sizeof (ACPI_TABLE_HEADER)); + table_desc->table_id = acpi_cm_allocate_owner_id (OWNER_TYPE_TABLE); + table_desc->loaded_into_namespace = FALSE; + + /* + * Set the appropriate global pointer (if there is one) to point to the + * newly installed table + */ + + if (acpi_gbl_acpi_table_data[table_type].global_ptr) { + *(acpi_gbl_acpi_table_data[table_type].global_ptr) = table_info->pointer; + } + + + /* Return Data */ + + table_info->table_id = table_desc->table_id; + table_info->installed_desc = table_desc; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_delete_acpi_tables + * + * PARAMETERS: None. + * + * RETURN: None. + * + * DESCRIPTION: Delete all internal ACPI tables + * + ******************************************************************************/ + +void +acpi_tb_delete_acpi_tables (void) +{ + u32 i; + + + /* + * Free memory allocated for ACPI tables + * Memory can either be mapped or allocated + */ + + for (i = 0; i < ACPI_TABLE_MAX; i++) { + acpi_tb_delete_acpi_table (i); + } + +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_delete_acpi_table + * + * PARAMETERS: Type - The table type to be deleted + * + * RETURN: None. + * + * DESCRIPTION: Delete an internal ACPI table + * Locks the ACPI table mutex + * + ******************************************************************************/ + +void +acpi_tb_delete_acpi_table ( + ACPI_TABLE_TYPE type) +{ + + if (type > ACPI_TABLE_MAX) { + return; + } + + + acpi_cm_acquire_mutex (ACPI_MTX_TABLES); + + /* Free the table */ + + acpi_tb_free_acpi_tables_of_type (&acpi_gbl_acpi_tables[type]); + + + /* Clear the appropriate "typed" global table pointer */ + + switch (type) + { + case ACPI_TABLE_RSDP: + acpi_gbl_RSDP = NULL; + break; + + case ACPI_TABLE_APIC: + acpi_gbl_APIC = NULL; + break; + + case ACPI_TABLE_DSDT: + acpi_gbl_DSDT = NULL; + break; + + case ACPI_TABLE_FACP: + acpi_gbl_FACP = NULL; + break; + + case ACPI_TABLE_FACS: + acpi_gbl_FACS = NULL; + break; + + case ACPI_TABLE_PSDT: + break; + + case ACPI_TABLE_RSDT: + acpi_gbl_RSDT = NULL; + break; + + case ACPI_TABLE_SSDT: + break; + + case ACPI_TABLE_SBST: + acpi_gbl_SBST = NULL; + + default: + break; + } + + acpi_cm_release_mutex (ACPI_MTX_TABLES); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_delete_single_table + * + * PARAMETERS: Table_info - A table info struct + * + * RETURN: None. + * + * DESCRIPTION: Free the memory associated with an internal ACPI table that + * is either installed or has never been installed. + * Table mutex should be locked. + * + ******************************************************************************/ + +ACPI_TABLE_DESC * +acpi_tb_delete_single_table ( + ACPI_TABLE_DESC *table_desc) +{ + ACPI_TABLE_DESC *next_desc; + + + if (!table_desc) { + return (NULL); + } + + + /* Unlink the descriptor */ + + if (table_desc->prev) { + table_desc->prev->next = table_desc->next; + } + + if (table_desc->next) { + table_desc->next->prev = table_desc->prev; + } + + + /* Free the memory allocated for the table itself */ + + if (table_desc->pointer) { + /* Valid table, determine type of memory allocation */ + + switch (table_desc->allocation) + { + + case ACPI_MEM_NOT_ALLOCATED: + + break; + + + case ACPI_MEM_ALLOCATED: + + acpi_cm_free (table_desc->base_pointer); + break; + + + case ACPI_MEM_MAPPED: + + acpi_os_unmap_memory (table_desc->base_pointer, table_desc->length); + break; + } + } + + + /* Free the table descriptor (Don't delete the list head, tho) */ + + + if ((table_desc->prev) == (table_desc->next)) { + + next_desc = NULL; + + /* Clear the list head */ + + table_desc->pointer = NULL; + table_desc->length = 0; + table_desc->count = 0; + + } + + else { + /* Free the table descriptor */ + + next_desc = table_desc->next; + acpi_cm_free (table_desc); + } + + + return (next_desc); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_free_acpi_tables_of_type + * + * PARAMETERS: Table_info - A table info struct + * + * RETURN: None. + * + * DESCRIPTION: Free the memory associated with an internal ACPI table + * Table mutex should be locked. + * + ******************************************************************************/ + +void +acpi_tb_free_acpi_tables_of_type ( + ACPI_TABLE_DESC *list_head) +{ + ACPI_TABLE_DESC *table_desc; + u32 count; + u32 i; + + + /* Get the head of the list */ + + table_desc = list_head; + count = list_head->count; + + /* + * Walk the entire list, deleting both the allocated tables + * and the table descriptors + */ + + for (i = 0; i < count; i++) { + table_desc = acpi_tb_delete_single_table (table_desc); + } + + return; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/tables/tbtable.c linux/drivers/acpi/tables/tbtable.c --- v2.4.0-test2/linux/drivers/acpi/tables/tbtable.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/tables/tbtable.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,388 @@ + +/****************************************************************************** + * + * Module Name: tbtable - ACPI tables: FACP, FACS, and RSDP utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "hardware.h" +#include "tables.h" + + +#define _COMPONENT TABLE_MANAGER + MODULE_NAME ("tbtable"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_get_table_rsdt + * + * PARAMETERS: Number_of_tables - Where the table count is placed + * Table_ptr - Input buffer pointer, optional + * + * RETURN: Status + * + * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_get_table_rsdt ( + u32 *number_of_tables) +{ + ACPI_STATUS status = AE_OK; + ACPI_TABLE_DESC table_info; + + + /* Get the RSDP */ + + status = acpi_tb_find_rsdp (&table_info); + if (ACPI_FAILURE (status)) { + REPORT_WARNING ("RSDP structure not found"); + return (AE_NO_ACPI_TABLES); + } + + /* Save the table pointers and allocation info */ + + status = acpi_tb_init_table_descriptor (ACPI_TABLE_RSDP, &table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + acpi_gbl_RSDP = (ROOT_SYSTEM_DESCRIPTOR_POINTER *) table_info.pointer; + + + /* + * RSDP structure was found; Now get the RSDT + */ + + status = acpi_tb_get_table ((void *) acpi_gbl_RSDP->rsdt_physical_address, NULL, + &table_info); + if (ACPI_FAILURE (status)) { + if (status == AE_BAD_SIGNATURE) { + /* Invalid RSDT signature */ + + REPORT_ERROR ("Invalid signature where RSDP indicates RSDT should be located"); + + } + } + + + /* Always delete the RSDP mapping */ + + acpi_tb_delete_acpi_table (ACPI_TABLE_RSDP); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Save the table pointers and allocation info */ + + status = acpi_tb_init_table_descriptor (ACPI_TABLE_RSDT, &table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + acpi_gbl_RSDT = (ROOT_SYSTEM_DESCRIPTION_TABLE *) table_info.pointer; + + + /* Valid RSDT signature, verify the checksum */ + + status = acpi_tb_verify_table_checksum ((ACPI_TABLE_HEADER *) acpi_gbl_RSDT); + + /* Determine the number of tables pointed to by the RSDT */ + + *number_of_tables = (s32) DIV_4 (acpi_gbl_RSDT->header.length - + sizeof (ACPI_TABLE_HEADER)); + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_scan_memory_for_rsdp + * + * PARAMETERS: Start_address - Starting pointer for search + * Length - Maximum length to search + * + * RETURN: Pointer to the RSDP if found, otherwise NULL. + * + * DESCRIPTION: Search a block of memory for the RSDP signature + * + ******************************************************************************/ + +char * +acpi_tb_scan_memory_for_rsdp ( + char *start_address, + u32 length) +{ + u32 offset; + char *mem_rover; + + + /* Search from given start addr for the requested length */ + + for (offset = 0, mem_rover = start_address; + offset < length; + offset += RSDP_SCAN_STEP, mem_rover += RSDP_SCAN_STEP) + { + + /* The signature and checksum must both be correct */ + + if (STRNCMP (mem_rover, RSDP_SIG, sizeof (RSDP_SIG)-1) == 0 && + acpi_tb_checksum (mem_rover, + sizeof (ROOT_SYSTEM_DESCRIPTOR_POINTER)) == 0) + { + /* If so, we have found the RSDP */ + + return mem_rover; + } + } + + /* Searched entire block, no RSDP was found */ + + return NULL; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_find_rsdp + * + * PARAMETERS: *Buffer_ptr - If == NULL, read data from buffer + * rather than searching memory + * *Table_info - Where the table info is returned + * + * RETURN: Status + * + * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor + * pointer structure. If it is found, set *RSDP to point to it. + * + * NOTE: The RSDP must be either in the first 1_k of the Extended + * BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section + * 5.2.2; assertion #421). + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_find_rsdp ( + ACPI_TABLE_DESC *table_info) +{ + char *table_ptr; + char *mem_rover; + ACPI_STATUS status = AE_OK; + + if (acpi_gbl_acpi_init_data.RSDP_physical_address) { + /* + * RSDP address was supplied as part of the initialization data + */ + + status = acpi_os_map_memory(acpi_gbl_acpi_init_data.RSDP_physical_address, + sizeof (ROOT_SYSTEM_DESCRIPTOR_POINTER), + (void **)&table_ptr); + + if (ACPI_FAILURE (status)) { + return (status); + } + + if (!table_ptr) { + return (AE_NO_MEMORY); + } + + /* + * The signature and checksum must both be correct + */ + + if (STRNCMP (table_ptr, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) { + /* Nope, BAD Signature */ + + return (AE_BAD_SIGNATURE); + } + + /* The signature and checksum must both be correct */ + + if (acpi_tb_checksum (table_ptr, + sizeof (ROOT_SYSTEM_DESCRIPTOR_POINTER)) != 0) + { + /* Nope, BAD Checksum */ + + return (AE_BAD_CHECKSUM); + } + + /* RSDP supplied is OK */ + /* If so, we have found the RSDP */ + + table_info->pointer = (ACPI_TABLE_HEADER *) table_ptr; + table_info->length = sizeof (ROOT_SYSTEM_DESCRIPTOR_POINTER); + table_info->allocation = ACPI_MEM_MAPPED; + table_info->base_pointer = table_ptr; + + return (AE_OK); + } + + /* + * Search memory for RSDP. First map low physical memory. + */ + + status = acpi_os_map_memory (LO_RSDP_WINDOW_BASE, LO_RSDP_WINDOW_SIZE, + (void **)&table_ptr); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * 1) Search EBDA (low memory) paragraphs + */ + + if (NULL != (mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, + LO_RSDP_WINDOW_SIZE))) + { + /* Found it, return pointer and don't delete the mapping */ + + table_info->pointer = (ACPI_TABLE_HEADER *) mem_rover; + table_info->length = LO_RSDP_WINDOW_SIZE; + table_info->allocation = ACPI_MEM_MAPPED; + table_info->base_pointer = table_ptr; + + return (AE_OK); + } + + /* This mapping is no longer needed */ + + acpi_os_unmap_memory (table_ptr, LO_RSDP_WINDOW_SIZE); + + + /* + * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h + */ + + status = acpi_os_map_memory (HI_RSDP_WINDOW_BASE, HI_RSDP_WINDOW_SIZE, + (void **)&table_ptr); + + if (ACPI_FAILURE (status)) { + return (status); + } + + if (NULL != (mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, + HI_RSDP_WINDOW_SIZE))) + { + /* Found it, return pointer and don't delete the mapping */ + + table_info->pointer = (ACPI_TABLE_HEADER *) mem_rover; + table_info->length = HI_RSDP_WINDOW_SIZE; + table_info->allocation = ACPI_MEM_MAPPED; + table_info->base_pointer = table_ptr; + + return (AE_OK); + } + + /* This mapping is no longer needed */ + + acpi_os_unmap_memory (table_ptr, HI_RSDP_WINDOW_SIZE); + + + /* RSDP signature was not found */ + + return (AE_NOT_FOUND); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_get_table_facs + * + * PARAMETERS: *Buffer_ptr - If == NULL, read data from buffer + * rather than searching memory + * *Table_info - Where the table info is returned + * + * RETURN: Status + * + * DESCRIPTION: Returns a pointer to the FACS as defined in FACP. This + * function assumes the global variable FACP has been + * correctly initialized. The value of FACP->Firmware_ctrl + * into a far pointer which is returned. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_get_table_facs ( + char *buffer_ptr, + ACPI_TABLE_DESC *table_info) +{ + void *table_ptr = NULL; + u32 size; + u8 allocation; + ACPI_STATUS status = AE_OK; + + + /* Must have a valid FACP pointer */ + + if (!acpi_gbl_FACP) { + return (AE_NO_ACPI_TABLES); + } + + size = sizeof (FIRMWARE_ACPI_CONTROL_STRUCTURE); + if (buffer_ptr) { + /* + * Getting table from a file -- allocate a buffer and + * read the table. + */ + table_ptr = acpi_cm_allocate (size); + if(!table_ptr) { + return (AE_NO_MEMORY); + } + + MEMCPY (table_ptr, buffer_ptr, size); + + /* Save allocation type */ + + allocation = ACPI_MEM_ALLOCATED; + } + + else { + /* Just map the physical memory to our address space */ + + status = acpi_tb_map_acpi_table ((void *) acpi_gbl_FACP->firmware_ctrl, + &size, &table_ptr); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Save allocation type */ + + allocation = ACPI_MEM_MAPPED; + } + + + /* Return values */ + + table_info->pointer = table_ptr; + table_info->length = size; + table_info->allocation = allocation; + table_info->base_pointer = table_ptr; + + return (status); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/tables/tbutils.c linux/drivers/acpi/tables/tbutils.c --- v2.4.0-test2/linux/drivers/acpi/tables/tbutils.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/tables/tbutils.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,352 @@ + +/****************************************************************************** + * + * Module Name: tbutils - Table manipulation utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "tables.h" +#include "interp.h" + + +#define _COMPONENT TABLE_MANAGER + MODULE_NAME ("tbutils"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_system_table_pointer + * + * PARAMETERS: *Where - Pointer to be examined + * + * RETURN: TRUE if Where is within the AML stream (in one of the ACPI + * system tables such as the DSDT or an SSDT.) + * FALSE otherwise + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_handle_to_object ( + u16 table_id, + ACPI_TABLE_DESC **table_desc) +{ + u32 i; + ACPI_TABLE_DESC *list_head; + + + for (i = 0; i < ACPI_TABLE_MAX; i++) { + list_head = &acpi_gbl_acpi_tables[i]; + do + { + if (list_head->table_id == table_id) { + *table_desc = list_head; + return AE_OK; + } + + list_head = list_head->next; + + } while (list_head != &acpi_gbl_acpi_tables[i]); + } + + + return AE_BAD_PARAMETER; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_system_table_pointer + * + * PARAMETERS: *Where - Pointer to be examined + * + * RETURN: TRUE if Where is within the AML stream (in one of the ACPI + * system tables such as the DSDT or an SSDT.) + * FALSE otherwise + * + ******************************************************************************/ + +u8 +acpi_tb_system_table_pointer ( + void *where) +{ + u32 i; + ACPI_TABLE_DESC *table_desc; + ACPI_TABLE_HEADER *table; + + + /* No function trace, called too often! */ + + + /* Ignore null pointer */ + + if (!where) { + return (FALSE); + } + + + /* Check for a pointer within the DSDT */ + + if (IS_IN_ACPI_TABLE (where, acpi_gbl_DSDT)) { + return (TRUE); + } + + + /* Check each of the loaded SSDTs (if any)*/ + + table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_SSDT]; + + for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count; i++) { + table = table_desc->pointer; + + if (IS_IN_ACPI_TABLE (where, table)) { + return (TRUE); + } + + table_desc = table_desc->next; + } + + + /* Check each of the loaded PSDTs (if any)*/ + + table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_PSDT]; + + for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count; i++) { + table = table_desc->pointer; + + if (IS_IN_ACPI_TABLE (where, table)) { + return (TRUE); + } + + table_desc = table_desc->next; + } + + + /* Pointer does not point into any system table */ + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_validate_table_header + * + * PARAMETERS: Table_header - Logical pointer to the table + * + * RETURN: Status + * + * DESCRIPTION: Check an ACPI table header for validity + * + * NOTE: Table pointers are validated as follows: + * 1) Table pointer must point to valid physical memory + * 2) Signature must be 4 ASCII chars, even if we don't recognize the + * name + * 3) Table must be readable for length specified in the header + * 4) Table checksum must be valid (with the exception of the FACS + * which has no checksum for some odd reason) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_validate_table_header ( + ACPI_TABLE_HEADER *table_header) +{ + ACPI_NAME signature; + + + /* Verify that this is a valid address */ + + if (!acpi_os_readable (table_header, sizeof (ACPI_TABLE_HEADER))) { + return AE_BAD_ADDRESS; + } + + + /* Ensure that the signature is 4 ASCII characters */ + + MOVE_UNALIGNED32_TO_32 (&signature, &table_header->signature); + if (!acpi_cm_valid_acpi_name (signature)) { + REPORT_WARNING ("Invalid table signature found"); + return AE_BAD_SIGNATURE; + } + + + /* Validate the table length */ + + if (table_header->length < sizeof (ACPI_TABLE_HEADER)) { + REPORT_WARNING ("Invalid table header length found"); + return AE_BAD_HEADER; + } + + return AE_OK; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_map_acpi_table + * + * PARAMETERS: Physical_address - Physical address of table to map + * *Size - Size of the table. If zero, the size + * from the table header is used. + * Actual size is returned here. + * **Logical_address - Logical address of mapped table + * + * RETURN: Logical address of the mapped table. + * + * DESCRIPTION: Maps the physical address of table into a logical address + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_map_acpi_table ( + void *physical_address, + u32 *size, + void **logical_address) +{ + ACPI_TABLE_HEADER *table; + u32 table_size = *size; + ACPI_STATUS status = AE_OK; + + + /* If size is zero, look at the table header to get the actual size */ + + if ((*size) == 0) { + /* Get the table header so we can extract the table length */ + + status = acpi_os_map_memory (physical_address, sizeof (ACPI_TABLE_HEADER), + (void **) &table); + if (ACPI_FAILURE (status)) { + return status; + } + + /* Extract the full table length before we delete the mapping */ + + table_size = table->length; + + /* + * Validate the header and delete the mapping. + * We will create a mapping for the full table below. + */ + + status = acpi_tb_validate_table_header (table); + + /* Always unmap the memory for the header */ + + acpi_os_unmap_memory (table, sizeof (ACPI_TABLE_HEADER)); + + /* Exit if header invalid */ + + if (ACPI_FAILURE (status)) { + return status; + } + } + + + /* Map the physical memory for the correct length */ + + status = acpi_os_map_memory (physical_address, table_size, (void **) &table); + if (ACPI_FAILURE (status)) { + return status; + } + + *size = table_size; + *logical_address = table; + + return status; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_verify_table_checksum + * + * PARAMETERS: *Table_header - ACPI table to verify + * + * RETURN: 8 bit checksum of table + * + * DESCRIPTION: Does an 8 bit checksum of table and returns status. A correct + * table should have a checksum of 0. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_verify_table_checksum ( + ACPI_TABLE_HEADER *table_header) +{ + u8 check_sum; + ACPI_STATUS status = AE_OK; + + + /* Compute the checksum on the table */ + + check_sum = acpi_tb_checksum (table_header, table_header->length); + + /* Return the appropriate exception */ + + if (check_sum) { + REPORT_ERROR ("Invalid ACPI table checksum"); + status = AE_BAD_CHECKSUM; + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_checksum + * + * PARAMETERS: Buffer - Buffer to checksum + * Length - Size of the buffer + * + * RETURNS 8 bit checksum of buffer + * + * DESCRIPTION: Computes an 8 bit checksum of the buffer(length) and returns it. + * + ******************************************************************************/ + +u8 +acpi_tb_checksum ( + void *buffer, + u32 length) +{ + u8 *limit; + u8 *rover; + u8 sum = 0; + + + if (buffer && length) { + /* Buffer and Length are valid */ + + limit = (u8 *) buffer + length; + + for (rover = buffer; rover < limit; rover++) { + sum = (u8) (sum + *rover); + } + } + + return sum; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/tables/tbxface.c linux/drivers/acpi/tables/tbxface.c --- v2.4.0-test2/linux/drivers/acpi/tables/tbxface.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/tables/tbxface.c Wed Jul 5 11:23:13 2000 @@ -0,0 +1,352 @@ + +/****************************************************************************** + * + * Module Name: tbxface - Public interfaces to the ACPI subsystem + * ACPI table oriented interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "namesp.h" +#include "interp.h" +#include "tables.h" + + +#define _COMPONENT TABLE_MANAGER + MODULE_NAME ("tbxface"); + + +/******************************************************************************* + * + * FUNCTION: Acpi_load_firmware_tables + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: This function is called to load the ACPI tables from BIOS + * + ******************************************************************************/ + +ACPI_STATUS +acpi_load_firmware_tables (void) +{ + ACPI_STATUS status = AE_OK; + u32 number_of_tables = 0; + + + /* Get the RSDT first */ + + status = acpi_tb_get_table_rsdt (&number_of_tables); + if (status != AE_OK) { + goto error_exit; + } + + + /* Now get the rest of the tables */ + + status = acpi_tb_get_all_tables (number_of_tables, NULL); + if (status != AE_OK) { + goto error_exit; + } + + + return (AE_OK); + + +error_exit: + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_load_table + * + * PARAMETERS: Table_ptr - pointer to a buffer containing the entire + * table to be loaded + * + * RETURN: Status + * + * DESCRIPTION: This function is called to load a table from the caller's + * buffer. The buffer must contain an entire ACPI Table including + * a valid header. The header fields will be verified, and if it + * is determined that the table is invalid, the call will fail. + * + * If the call fails an appropriate status will be returned. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_load_table ( + ACPI_TABLE_HEADER *table_ptr) +{ + ACPI_STATUS status; + ACPI_TABLE_DESC table_info; + + + if (!table_ptr) { + return AE_BAD_PARAMETER; + } + + /* Copy the table to a local buffer */ + + status = acpi_tb_get_table (NULL, ((char *) table_ptr), &table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Install the new table into the local data structures */ + + status = acpi_tb_install_table (NULL, &table_info); + if (ACPI_FAILURE (status)) { + /* TBD: [Errors] must free table allocated by Acpi_tb_get_table */ + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_unload_table + * + * PARAMETERS: Table_type - Type of table to be unloaded + * + * RETURN: Status + * + * DESCRIPTION: This routine is used to force the unload of a table + * + ******************************************************************************/ + +ACPI_STATUS +acpi_unload_table ( + ACPI_TABLE_TYPE table_type) +{ + ACPI_TABLE_DESC *list_head; + + + /* Parameter validation */ + + if (table_type > ACPI_TABLE_MAX) { + return (AE_BAD_PARAMETER); + } + + + /* Find all tables of the requested type */ + + list_head = &acpi_gbl_acpi_tables[table_type]; + do + { + /* Delete the entire namespace under this table NTE */ + + acpi_ns_delete_namespace_by_owner (list_head->table_id); + + /* Delete (or unmap) the actual table */ + + acpi_tb_delete_acpi_table (table_type); + + } while (list_head != &acpi_gbl_acpi_tables[table_type]); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_get_table_header + * + * PARAMETERS: Table_type - one of the defined table types + * Instance - the non zero instance of the table, allows + * support for multiple tables of the same type + * see Acpi_gbl_Acpi_table_flag + * Out_table_header - pointer to the ACPI_TABLE_HEADER if successful + * + * DESCRIPTION: This function is called to get an ACPI table header. The caller + * supplies an pointer to a data area sufficient to contain an ACPI + * ACPI_TABLE_HEADER structure. + * + * The header contains a length field that can be used to determine + * the size of the buffer needed to contain the entire table. This + * function is not valid for the RSD PTR table since it does not + * have a standard header and is fixed length. + * + * If the operation fails for any reason an appropriate status will + * be returned and the contents of Out_table_header are undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_table_header ( + ACPI_TABLE_TYPE table_type, + u32 instance, + ACPI_TABLE_HEADER *out_table_header) +{ + ACPI_TABLE_HEADER *tbl_ptr; + ACPI_STATUS status; + + + status = AE_OK; + + if ((instance == 0) || + (table_type == ACPI_TABLE_RSDP) || + (!out_table_header)) + { + return (AE_BAD_PARAMETER); + } + + /* Check the table type and instance */ + + if ((table_type > ACPI_TABLE_MAX) || + (acpi_gbl_acpi_table_data[table_type].flags == ACPI_TABLE_SINGLE && + instance > 1)) + { + return (AE_BAD_PARAMETER); + } + + + /* Get a pointer to the entire table */ + + status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr); + if (status != AE_OK) { + return (status); + } + + /* + * The function will return a NULL pointer if the table is not loaded + */ + if (tbl_ptr == NULL) { + return (AE_NOT_EXIST); + } + + /* + * Copy the header to the caller's buffer + */ + MEMCPY ((void *) out_table_header, (void *) tbl_ptr, + sizeof (ACPI_TABLE_HEADER)); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_get_table + * + * PARAMETERS: Table_type - one of the defined table types + * Instance - the non zero instance of the table, allows + * support for multiple tables of the same type + * see Acpi_gbl_Acpi_table_flag + * Ret_buffer - pointer to a structure containing a buffer to + * receive the table + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get an ACPI table. The caller + * supplies an Out_buffer large enough to contain the entire ACPI + * table. The caller should call the Acpi_get_table_header function + * first to determine the buffer size needed. Upon completion + * the Out_buffer->Length field will indicate the number of bytes + * copied into the Out_buffer->Buf_ptr buffer. This table will be + * a complete table including the header. + * + * If the operation fails an appropriate status will be returned + * and the contents of Out_buffer are undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_table ( + ACPI_TABLE_TYPE table_type, + u32 instance, + ACPI_BUFFER *ret_buffer) +{ + ACPI_TABLE_HEADER *tbl_ptr; + ACPI_STATUS status; + u32 ret_buf_len; + + + status = AE_OK; + + /* + * Must have a buffer + */ + if ((instance == 0) || + (!ret_buffer) || + (!ret_buffer->pointer) || + (!ret_buffer->length)) + { + return (AE_BAD_PARAMETER); + } + + /* Check the table type and instance */ + + if ((table_type > ACPI_TABLE_MAX) || + (acpi_gbl_acpi_table_data[table_type].flags == ACPI_TABLE_SINGLE && + instance > 1)) + { + return (AE_BAD_PARAMETER); + } + + + /* Get a pointer to the entire table */ + + status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr); + if (status != AE_OK) { + return (status); + } + + /* + * The function will return a NULL pointer if the table is not loaded + */ + if (tbl_ptr == NULL) { + return (AE_NOT_EXIST); + } + + /* + * Got a table ptr, assume it's ok and copy it to the user's buffer + */ + if (table_type == ACPI_TABLE_RSDP) { + /* + * RSD PTR is the only "table" without a header + */ + ret_buf_len = sizeof (ROOT_SYSTEM_DESCRIPTOR_POINTER); + } + else { + ret_buf_len = tbl_ptr->length; + } + + /* + * Verify we have space in the caller's buffer for the table + */ + if (ret_buffer->length < ret_buf_len) { + ret_buffer->length = ret_buf_len; + return (AE_BUFFER_OVERFLOW); + } + + ret_buffer->length = ret_buf_len; + + MEMCPY ((void *) ret_buffer->pointer, (void *) tbl_ptr, ret_buf_len); + + return (AE_OK); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/atm/ambassador.c linux/drivers/atm/ambassador.c --- v2.4.0-test2/linux/drivers/atm/ambassador.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/atm/ambassador.c Thu Jul 6 21:37:24 2000 @@ -373,15 +373,15 @@ static inline void dump_registers (const amb_dev * dev) { #ifdef DEBUG_AMBASSADOR if (debug & DBG_REGS) { - u32 * i; + size_t i; PRINTD (DBG_REGS, "reading PLX control: "); - for (i = (u32 *) 0x00; i < (u32 *) 0x30; ++i) + for (i = 0x00; i < 0x30; i += sizeof(u32)) rd_mem (dev, i); PRINTD (DBG_REGS, "reading mailboxes: "); - for (i = (u32 *) 0x40; i < (u32 *) 0x60; ++i) + for (i = 0x40; i < 0x60; i += sizeof(u32)) rd_mem (dev, i); PRINTD (DBG_REGS, "reading doorb irqev irqen reset:"); - for (i = (u32 *) 0x60; i < (u32 *) 0x70; ++i) + for (i = 0x60; i < 0x70; i += sizeof(u32)) rd_mem (dev, i); } #else diff -u --recursive --new-file v2.4.0-test2/linux/drivers/atm/eni.c linux/drivers/atm/eni.c --- v2.4.0-test2/linux/drivers/atm/eni.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/atm/eni.c Thu Jul 6 21:37:24 2000 @@ -1187,14 +1187,12 @@ if (tx->send) while ((skb = skb_dequeue(&tx->backlog))) { res = do_tx(skb); - if (res == enq_ok) atomic_dec(&tx->backlog_len); - else { - DPRINTK("re-queuing TX PDU\n"); - skb_queue_head(&tx->backlog,skb); + if (res == enq_ok) continue; + DPRINTK("re-queuing TX PDU\n"); + skb_queue_head(&tx->backlog,skb); requeued++; - if (res == enq_jam) return; - else break; - } + if (res == enq_jam) return; + break; } } } @@ -1326,7 +1324,6 @@ tx->send = mem; tx->words = size >> 2; skb_queue_head_init(&tx->backlog); - atomic_set(&tx->backlog_len,0); for (order = 0; size > (1 << (order+10)); order++); eni_out((order << MID_SIZE_SHIFT) | ((tx->send-eni_dev->ram) >> (MID_LOC_SKIP+2)), @@ -2064,6 +2061,8 @@ static int eni_send(struct atm_vcc *vcc,struct sk_buff *skb) { + enum enq_res res; + DPRINTK(">eni_send\n"); if (!ENI_VCC(vcc)->tx) { if (vcc->pop) vcc->pop(vcc,skb); @@ -2085,8 +2084,11 @@ } submitted++; ATM_SKB(skb)->vcc = vcc; + tasklet_disable(&ENI_DEV(vcc->dev)->task); + res = do_tx(skb); + tasklet_enable(&ENI_DEV(vcc->dev)->task); + if (res == enq_ok) return 0; skb_queue_tail(&ENI_VCC(vcc)->tx->backlog,skb); - atomic_inc(&ENI_VCC(vcc)->tx->backlog_len); backlogged++; tasklet_schedule(&ENI_DEV(vcc->dev)->task); return 0; @@ -2186,8 +2188,8 @@ tx == eni_dev->ubr ? " (UBR)" : ""); } if (--left) continue; - return sprintf(page,"%10sbacklog %d bytes\n","", - atomic_read(&tx->backlog_len)); + return sprintf(page,"%10sbacklog %u packets\n","", + skb_queue_len(&tx->backlog)); } for (vcc = dev->vccs; vcc; vcc = vcc->next) { struct eni_vcc *eni_vcc = ENI_VCC(vcc); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/atm/eni.h linux/drivers/atm/eni.h --- v2.4.0-test2/linux/drivers/atm/eni.h Wed Apr 26 16:34:07 2000 +++ linux/drivers/atm/eni.h Thu Jul 6 21:37:24 2000 @@ -47,7 +47,6 @@ int reserved; /* reserved peak cell rate */ int shaping; /* shaped peak cell rate */ struct sk_buff_head backlog; /* queue of waiting TX buffers */ - atomic_t backlog_len; /* length of backlog in bytes */ }; struct eni_vcc { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/atm/fore200e.c linux/drivers/atm/fore200e.c --- v2.4.0-test2/linux/drivers/atm/fore200e.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/atm/fore200e.c Thu Jul 6 21:37:24 2000 @@ -56,9 +56,7 @@ #include #endif -#ifdef MODULE #include -#endif #include "fore200e.h" #include "suni.h" @@ -2601,9 +2599,7 @@ printk(FORE200E "FORE Systems 200E-series driver - version " FORE200E_VERSION "\n"); -#if 0 /* XXX uncomment this to forbid module unloading */ MOD_INC_USE_COUNT; -#endif /* for each configured bus interface */ for (link = 0, bus = fore200e_bus; bus->model_name; bus++) { @@ -2630,10 +2626,8 @@ } } -#if 0 /* XXX uncomment this to forbid module unloading */ if (link <= 0) MOD_DEC_USE_COUNT; -#endif return link; } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/atm/horizon.c linux/drivers/atm/horizon.c --- v2.4.0-test2/linux/drivers/atm/horizon.c Thu May 11 15:30:06 2000 +++ linux/drivers/atm/horizon.c Thu Jul 6 21:37:24 2000 @@ -603,7 +603,8 @@ // note: rounding the rate down means rounding 'p' up - const unsigned long br = test_bit (ultra, &dev->flags) ? BR_ULT : BR_HRZ; + const unsigned long br = test_bit (ultra, (hrz_flags *) &dev->flags) ? + BR_ULT : BR_HRZ; u32 div = CR_MIND; u32 pre; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/atm/idt77105.c linux/drivers/atm/idt77105.c --- v2.4.0-test2/linux/drivers/atm/idt77105.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/atm/idt77105.c Thu Jul 6 21:37:24 2000 @@ -48,10 +48,12 @@ static void idt77105_restart_timer_func(unsigned long); -static struct timer_list stats_timer = { NULL, NULL, 0L, 0L, - &idt77105_stats_timer_func }; -static struct timer_list restart_timer = { NULL, NULL, 0L, 0L, - &idt77105_restart_timer_func }; +static struct timer_list stats_timer = { + function: &idt77105_stats_timer_func +}; +static struct timer_list restart_timer = { + function: &idt77105_restart_timer_func +}; static int start_timer = 1; static struct idt77105_priv *idt77105_all = NULL; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/atm/iphase.c linux/drivers/atm/iphase.c --- v2.4.0-test2/linux/drivers/atm/iphase.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/atm/iphase.c Thu Jul 6 19:27:48 2000 @@ -2303,7 +2303,7 @@ dev->number,error); return -EINVAL; } - IF_INIT(printk(DEV_LABEL "(itf %d): rev.%d,realbase=0x%x,irq=%d\n", + IF_INIT(printk(DEV_LABEL "(itf %d): rev.%d,realbase=0x%lx,irq=%d\n", dev->number, revision, real_base, iadev->irq);) /* find mapping size of board */ @@ -2342,7 +2342,7 @@ dev->number); return error; } - IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=0x%x,irq=%d\n", + IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=0x%lx,irq=%d\n", dev->number, revision, base, iadev->irq);) /* filling the iphase dev structure */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/atm/nicstar.c linux/drivers/atm/nicstar.c --- v2.4.0-test2/linux/drivers/atm/nicstar.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/atm/nicstar.c Thu Jul 6 21:37:24 2000 @@ -21,6 +21,18 @@ ******************************************************************************/ +/**** IMPORTANT INFORMATION *************************************************** + * + * There are currently three types of spinlocks: + * + * 1 - Per card interrupt spinlock (to protect structures and such) + * 2 - Per SCQ scq spinlock + * 3 - Per card resource spinlock (to access registers, etc.) + * + * These must NEVER be grabbed in reverse order. + * + ******************************************************************************/ + /* Header files ***************************************************************/ #include @@ -115,6 +127,85 @@ #define ATM_SKB(s) (&(s)->atm) #endif + /* Spinlock debugging stuff */ +#ifdef NS_DEBUG_SPINLOCKS /* See nicstar.h */ +#define ns_grab_int_lock(card,flags) \ + do { \ + unsigned long nsdsf, nsdsf2; \ + local_irq_save(flags); \ + save_flags(nsdsf); cli();\ + if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \ + (flags)&(1<<9)?"en":"dis"); \ + if (spin_is_locked(&(card)->int_lock) && \ + (card)->cpu_int == smp_processor_id()) { \ + printk("nicstar.c: line %d (cpu %d) int_lock already locked at line %d (cpu %d)\n", \ + __LINE__, smp_processor_id(), (card)->has_int_lock, \ + (card)->cpu_int); \ + printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ + } \ + if (spin_is_locked(&(card)->res_lock) && \ + (card)->cpu_res == smp_processor_id()) { \ + printk("nicstar.c: line %d (cpu %d) res_lock locked at line %d (cpu %d)(trying int)\n", \ + __LINE__, smp_processor_id(), (card)->has_res_lock, \ + (card)->cpu_res); \ + printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ + } \ + spin_lock_irq(&(card)->int_lock); \ + (card)->has_int_lock = __LINE__; \ + (card)->cpu_int = smp_processor_id(); \ + restore_flags(nsdsf); } while (0) +#define ns_grab_res_lock(card,flags) \ + do { \ + unsigned long nsdsf, nsdsf2; \ + local_irq_save(flags); \ + save_flags(nsdsf); cli();\ + if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \ + (flags)&(1<<9)?"en":"dis"); \ + if (spin_is_locked(&(card)->res_lock) && \ + (card)->cpu_res == smp_processor_id()) { \ + printk("nicstar.c: line %d (cpu %d) res_lock already locked at line %d (cpu %d)\n", \ + __LINE__, smp_processor_id(), (card)->has_res_lock, \ + (card)->cpu_res); \ + printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ + } \ + spin_lock_irq(&(card)->res_lock); \ + (card)->has_res_lock = __LINE__; \ + (card)->cpu_res = smp_processor_id(); \ + restore_flags(nsdsf); } while (0) +#define ns_grab_scq_lock(card,scq,flags) \ + do { \ + unsigned long nsdsf, nsdsf2; \ + local_irq_save(flags); \ + save_flags(nsdsf); cli();\ + if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \ + (flags)&(1<<9)?"en":"dis"); \ + if (spin_is_locked(&(scq)->lock) && \ + (scq)->cpu_lock == smp_processor_id()) { \ + printk("nicstar.c: line %d (cpu %d) this scq_lock already locked at line %d (cpu %d)\n", \ + __LINE__, smp_processor_id(), (scq)->has_lock, \ + (scq)->cpu_lock); \ + printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ + } \ + if (spin_is_locked(&(card)->res_lock) && \ + (card)->cpu_res == smp_processor_id()) { \ + printk("nicstar.c: line %d (cpu %d) res_lock locked at line %d (cpu %d)(trying scq)\n", \ + __LINE__, smp_processor_id(), (card)->has_res_lock, \ + (card)->cpu_res); \ + printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ + } \ + spin_lock_irq(&(scq)->lock); \ + (scq)->has_lock = __LINE__; \ + (scq)->cpu_lock = smp_processor_id(); \ + restore_flags(nsdsf); } while (0) +#else /* !NS_DEBUG_SPINLOCKS */ +#define ns_grab_int_lock(card,flags) \ + spin_lock_irqsave(&(card)->int_lock,(flags)) +#define ns_grab_res_lock(card,flags) \ + spin_lock_irqsave(&(card)->res_lock,(flags)) +#define ns_grab_scq_lock(card,scq,flags) \ + spin_lock_irqsave(&(scq)->lock,flags) +#endif /* NS_DEBUG_SPINLOCKS */ + /* Version definition *********************************************************/ /* @@ -406,12 +497,12 @@ sram_address <<= 2; sram_address &= 0x0007FFFC; /* address must be dword aligned */ sram_address |= 0x50000000; /* SRAM read command */ - save_flags(flags); cli(); + ns_grab_res_lock(card, flags); while (CMD_BUSY(card)); writel(sram_address, card->membase + CMD); while (CMD_BUSY(card)); data = readl(card->membase + DR0); - restore_flags(flags); + spin_unlock_irqrestore(&card->res_lock, flags); return data; } @@ -424,7 +515,7 @@ count--; /* count range now is 0..3 instead of 1..4 */ c = count; c <<= 2; /* to use increments of 4 */ - save_flags(flags); cli(); + ns_grab_res_lock(card, flags); while (CMD_BUSY(card)); for (i = 0; i <= c; i += 4) writel(*(value++), card->membase + i); @@ -434,14 +525,14 @@ sram_address &= 0x0007FFFC; sram_address |= (0x40000000 | count); writel(sram_address, card->membase + CMD); - restore_flags(flags); + spin_unlock_irqrestore(&card->res_lock, flags); } static int ns_init_card(int i, struct pci_dev *pcidev) { int j; - struct ns_dev *card; + struct ns_dev *card = NULL; unsigned short pci_command; unsigned char pci_latency; unsigned error; @@ -468,6 +559,8 @@ return error; } cards[i] = card; + spin_lock_init(&card->int_lock); + spin_lock_init(&card->res_lock); card->index = i; card->atmdev = NULL; @@ -853,9 +946,6 @@ card->iovpool.count++; } - - card->in_handler = 0; - card->in_poll = 0; card->intcnt = 0; /* Configure NICStAR */ @@ -1025,6 +1115,7 @@ scq->tbd_count = 0; init_waitqueue_head(&scq->scqfull_waitq); scq->full = 0; + spin_lock_init(&scq->lock); for (i = 0; i < scq->num_entries; i++) scq->skb[i] = NULL; @@ -1161,7 +1252,7 @@ card->lbfqc += 2; } - save_flags(flags); cli(); + ns_grab_res_lock(card, flags); while (CMD_BUSY(card)); writel(addr2, card->membase + DR3); @@ -1170,7 +1261,7 @@ writel(handle1, card->membase + DR0); writel(NS_CMD_WRITE_FREEBUFQ | (u32) type, card->membase + CMD); - restore_flags(flags); + spin_unlock_irqrestore(&card->res_lock, flags); XPRINTK("nicstar%d: Pushing %s buffers at 0x%x and 0x%x.\n", card->index, (type == BUF_SM ? "small" : "large"), addr1, addr2); @@ -1193,6 +1284,7 @@ u32 stat_r; ns_dev *card; struct atm_dev *dev; + unsigned long flags; card = (ns_dev *) dev_id; dev = card->atmdev; @@ -1200,19 +1292,7 @@ PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index); - if (card->in_handler) - { - printk("nicstar%d: Re-entering ns_irq_handler()???\n", card->index); - return; - } - card->in_handler = 1; - if (card->in_poll) - { - card->in_handler = 0; - printk("nicstar%d: Called irq handler while in ns_poll()!?\n", - card->index); - return; - } + ns_grab_int_lock(card, flags); stat_r = readl(card->membase + STAT); @@ -1377,7 +1457,7 @@ process_rsq(card); } - card->in_handler = 0; + spin_unlock_irqrestore(&card->int_lock, flags); PRINTK("nicstar%d: end of interrupt service\n", card->index); } @@ -1595,10 +1675,10 @@ unsigned long flags; addr = NS_RCT + (vcc->vpi << card->vcibits | vcc->vci) * NS_RCT_ENTRY_SIZE; - save_flags(flags); cli(); + ns_grab_res_lock(card, flags); while(CMD_BUSY(card)); writel(NS_CMD_CLOSE_CONNECTION | addr << 2, card->membase + CMD); - restore_flags(flags); + spin_unlock_irqrestore(&card->res_lock, flags); vc->rx = 0; if (vc->rx_iov != NULL) @@ -1617,9 +1697,9 @@ ATM_SKB(iovb)->iovcnt); ATM_SKB(iovb)->iovcnt = 0; ATM_SKB(iovb)->vcc = NULL; - save_flags(flags); cli(); + ns_grab_int_lock(card, flags); recycle_iov_buf(card, iovb); - restore_flags(flags); + spin_unlock_irqrestore(&card->int_lock, flags); vc->rx_iov = NULL; } } @@ -1639,7 +1719,7 @@ for (;;) { - save_flags(flags); cli(); + ns_grab_scq_lock(card, scq, flags); scqep = scq->next; if (scqep == scq->base) scqep = scq->last; @@ -1647,7 +1727,7 @@ scqep--; if (scqep == scq->tail) { - restore_flags(flags); + spin_unlock_irqrestore(&scq->lock, flags); break; } /* If the last entry is not a TSR, place one in the SCQ in order to @@ -1675,8 +1755,8 @@ data = (u32) virt_to_bus(scq->next); ns_write_sram(card, scq->scd, &data, 1); } + spin_unlock_irqrestore(&scq->lock, flags); schedule(); - restore_flags(flags); } /* Free all TST entries */ @@ -1884,19 +1964,22 @@ u32 data; int index; - if (scq->tail == scq->next) + ns_grab_scq_lock(card, scq, flags); + while (scq->tail == scq->next) { if (in_interrupt()) { + spin_unlock_irqrestore(&scq->lock, flags); printk("nicstar%d: Error pushing TBD.\n", card->index); return 1; } - save_flags(flags); cli(); scq->full = 1; + spin_unlock_irqrestore(&scq->lock, flags); interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT); - restore_flags(flags); + ns_grab_scq_lock(card, scq, flags); if (scq->full) { + spin_unlock_irqrestore(&scq->lock, flags); printk("nicstar%d: Timeout pushing TBD.\n", card->index); return 1; } @@ -1926,19 +2009,23 @@ if (vc->tbd_count >= MAX_TBD_PER_VC || scq->tbd_count >= MAX_TBD_PER_SCQ) { - if (scq->tail == scq->next) + int has_run = 0; + + while (scq->tail == scq->next) { if (in_interrupt()) { data = (u32) virt_to_bus(scq->next); ns_write_sram(card, scq->scd, &data, 1); + spin_unlock_irqrestore(&scq->lock, flags); printk("nicstar%d: Error pushing TSR.\n", card->index); return 0; } - save_flags(flags); cli(); scq->full = 1; + if (has_run++) break; + spin_unlock_irqrestore(&scq->lock, flags); interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT); - restore_flags(flags); + ns_grab_scq_lock(card, scq, flags); } if (!scq->full) @@ -1970,10 +2057,11 @@ else PRINTK("nicstar%d: Timeout pushing TSR.\n", card->index); } - data = (u32) virt_to_bus(scq->next); ns_write_sram(card, scq->scd, &data, 1); + spin_unlock_irqrestore(&scq->lock, flags); + return 0; } @@ -2064,6 +2152,7 @@ struct atm_vcc *vcc; struct sk_buff *skb; int i; + unsigned long flags; XPRINTK("nicstar%d: drain_scq() called, scq at 0x%x, pos %d.\n", card->index, (u32) scq, pos); @@ -2073,6 +2162,7 @@ return; } + ns_grab_scq_lock(card, scq, flags); i = (int) (scq->tail - scq->base); if (++i == scq->num_entries) i = 0; @@ -2084,16 +2174,18 @@ if (skb != NULL) { vcc = ATM_SKB(skb)->vcc; - if (vcc->pop != NULL) + if (vcc->pop != NULL) { vcc->pop(vcc, skb); - else - dev_kfree_skb_any(skb); + } else { + dev_kfree_skb_irq(skb); + } scq->skb[i] = NULL; } if (++i == scq->num_entries) i = 0; } scq->tail = scq->base + pos; + spin_unlock_irqrestore(&scq->lock, flags); } @@ -2890,10 +2982,10 @@ { struct sk_buff *hb; - save_flags(flags); cli(); + ns_grab_int_lock(card, flags); hb = skb_dequeue(&card->hbpool.queue); card->hbpool.count--; - restore_flags(flags); + spin_unlock_irqrestore(&card->int_lock, flags); if (hb == NULL) printk("nicstar%d: huge buffer count inconsistent.\n", card->index); @@ -2908,10 +3000,10 @@ hb = alloc_skb(NS_HBUFSIZE, GFP_KERNEL); if (hb == NULL) return -ENOMEM; - save_flags(flags); cli(); + ns_grab_int_lock(card, flags); skb_queue_tail(&card->hbpool.queue, hb); card->hbpool.count++; - restore_flags(flags); + spin_unlock_irqrestore(&card->int_lock, flags); } break; @@ -2920,10 +3012,10 @@ { struct sk_buff *iovb; - save_flags(flags); cli(); + ns_grab_int_lock(card, flags); iovb = skb_dequeue(&card->iovpool.queue); card->iovpool.count--; - restore_flags(flags); + spin_unlock_irqrestore(&card->int_lock, flags); if (iovb == NULL) printk("nicstar%d: iovec buffer count inconsistent.\n", card->index); @@ -2938,10 +3030,10 @@ iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL); if (iovb == NULL) return -ENOMEM; - save_flags(flags); cli(); + ns_grab_int_lock(card, flags); skb_queue_tail(&card->iovpool.queue, iovb); card->iovpool.count++; - restore_flags(flags); + spin_unlock_irqrestore(&card->int_lock, flags); } break; @@ -2986,22 +3078,11 @@ for (i = 0; i < num_cards; i++) { card = cards[i]; - save_flags(flags); cli(); - if (card->in_poll) - { - printk("nicstar: Re-entering ns_poll()???\n"); - restore_flags(flags); - continue; - } - card->in_poll = 1; - if (card->in_handler) - { - card->in_poll = 0; - printk("nicstar%d: ns_poll called while in interrupt handler!?\n", - card->index); - restore_flags(flags); + if (spin_is_locked(&card->int_lock)) { + /* Probably it isn't worth spinning */ continue; } + ns_grab_int_lock(card, flags); stat_w = 0; stat_r = readl(card->membase + STAT); @@ -3014,8 +3095,7 @@ process_rsq(card); writel(stat_w, card->membase + STAT); - card->in_poll = 0; - restore_flags(flags); + spin_unlock_irqrestore(&card->int_lock, flags); } mod_timer(&ns_timer, jiffies + NS_POLL_PERIOD); PRINTK("nicstar: Leaving ns_poll().\n"); @@ -3069,12 +3149,12 @@ unsigned long flags; card = dev->dev_data; - save_flags(flags); cli(); + ns_grab_res_lock(card, flags); while(CMD_BUSY(card)); writel((unsigned long) value, card->membase + DR0); writel(NS_CMD_WRITE_UTILITY | 0x00000200 | (addr & 0x000000FF), card->membase + CMD); - restore_flags(flags); + spin_unlock_irqrestore(&card->res_lock, flags); } @@ -3086,12 +3166,12 @@ unsigned long data; card = dev->dev_data; - save_flags(flags); cli(); + ns_grab_res_lock(card, flags); while(CMD_BUSY(card)); writel(NS_CMD_READ_UTILITY | 0x00000200 | (addr & 0x000000FF), card->membase + CMD); while(CMD_BUSY(card)); data = readl(card->membase + DR0) & 0x000000FF; - restore_flags(flags); + spin_unlock_irqrestore(&card->res_lock, flags); return (unsigned char) data; } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/atm/nicstar.h linux/drivers/atm/nicstar.h --- v2.4.0-test2/linux/drivers/atm/nicstar.h Mon Mar 27 08:08:23 2000 +++ linux/drivers/atm/nicstar.h Thu Jul 6 21:37:24 2000 @@ -28,6 +28,8 @@ /* Options ********************************************************************/ +#undef NS_DEBUG_SPINLOCKS + #define NS_MAX_CARDS 4 /* Maximum number of NICStAR based cards controlled by the device driver. Must be <= 5 */ @@ -705,6 +707,11 @@ int tbd_count; /* Only meaningful on variable rate */ wait_queue_head_t scqfull_waitq; volatile char full; /* SCQ full indicator */ + spinlock_t lock; /* SCQ spinlock */ +#ifdef NS_DEBUG_SPINLOCKS + volatile long has_lock; + volatile int cpu_lock; +#endif /* NS_DEBUG_SPINLOCKS */ } scq_info; @@ -779,8 +786,14 @@ struct sk_buff *rcbuf; /* Current raw cell buffer */ u32 rawch; /* Raw cell queue head */ unsigned intcnt; /* Interrupt counter */ - volatile int in_handler: 1; - volatile int in_poll: 1; + spinlock_t int_lock; /* Interrupt lock */ + spinlock_t res_lock; /* Card resource lock */ +#ifdef NS_DEBUG_SPINLOCKS + volatile long has_int_lock; + volatile int cpu_int; + volatile long has_res_lock; + volatile int cpu_res; +#endif /* NS_DEBUG_SPINLOCKS */ } ns_dev; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/acsi_slm.c linux/drivers/block/acsi_slm.c --- v2.4.0-test2/linux/drivers/block/acsi_slm.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/acsi_slm.c Thu Jun 29 18:25:49 2000 @@ -1007,7 +1007,7 @@ BufferP = SLMBuffer; SLMState = IDLE; - devfs_handle = devfs_mk_dir (NULL, "slm", 3, NULL); + devfs_handle = devfs_mk_dir (NULL, "slm", NULL); devfs_register_series (devfs_handle, "%u", MAX_SLM, DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &slm_fops, NULL); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c --- v2.4.0-test2/linux/drivers/block/ataflop.c Wed Feb 16 17:03:51 2000 +++ linux/drivers/block/ataflop.c Wed Jul 5 11:24:40 2000 @@ -355,7 +355,7 @@ static void fd_select_drive( int drive ); static void fd_deselect( void ); static void fd_motor_off_timer( unsigned long dummy ); -static void check_change( void ); +static void check_change( unsigned long dummy ); static __inline__ void set_head_settle_flag( void ); static __inline__ int get_head_settle_flag( void ); static void floppy_irq (int irq, void *dummy, struct pt_regs *fp); @@ -391,14 +391,16 @@ /************************* End of Prototypes **************************/ static struct timer_list motor_off_timer = - { NULL, NULL, 0, 0, fd_motor_off_timer }; + { function: fd_motor_off_timer }; static struct timer_list readtrack_timer = - { NULL, NULL, 0, 0, fd_readtrack_check }; + { function: fd_readtrack_check }; static struct timer_list timeout_timer = - { NULL, NULL, 0, 0, fd_times_out }; - + { function: fd_times_out }; +static struct timer_list fd_timer = + { function: check_change }; + static inline void start_motor_off_timer(void) { @@ -407,10 +409,9 @@ } static inline void -start_check_change_timer(void) +start_check_change_timer(unsigned long dummy) { - timer_table[FLOPPY_TIMER].expires = jiffies + CHECK_CHANGE_DELAY; - timer_active |= (1 << FLOPPY_TIMER); + mod_timer(&fd_timer, jiffies + CHECK_CHANGE_DELAY); } static inline void @@ -1309,12 +1310,11 @@ stop_timeout(); NeedSeek = 0; - if ((timer_active & (1 << FLOPPY_TIMER)) && - time_before(timer_table[FLOPPY_TIMER].expires, jiffies + 5)) + if (timer_pending(&fd_timer) && time_before(fd_timer.expires, jiffies + 5)) /* If the check for a disk change is done too early after this * last seek command, the WP bit still reads wrong :-(( */ - timer_table[FLOPPY_TIMER].expires = jiffies + 5; + mod_timer(&fd_timer, jiffies + 5); else start_check_change_timer(); start_motor_off_timer(); @@ -1990,10 +1990,6 @@ SelectedDrive = -1; BufferDrive = -1; - /* initialize check_change timer */ - timer_table[FLOPPY_TIMER].fn = check_change; - timer_active &= ~(1 << FLOPPY_TIMER); - DMABuffer = atari_stram_alloc( BUFFER_SIZE+512, NULL, "ataflop" ); if (!DMABuffer) { printk(KERN_ERR "atari_floppy_init: cannot get dma buffer\n"); @@ -2072,8 +2068,7 @@ unregister_blkdev(MAJOR_NR, "fd"); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - timer_active &= ~(1 << FLOPPY_TIMER); - timer_table[FLOPPY_TIMER].fn = 0; + del_timer_sync(&fd_timer); atari_stram_free( DMABuffer ); } #endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c --- v2.4.0-test2/linux/drivers/block/cpqarray.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/cpqarray.c Thu Jul 6 19:25:21 2000 @@ -169,7 +169,7 @@ #else static void ida_procinit(int i) {} static int ida_proc_get_info(char *buffer, char **start, off_t offset, - int length, int *eof, void *data) {} + int length, int *eof, void *data) { return 0;} #endif static void ida_geninit(int ctlr) @@ -331,6 +331,7 @@ iounmap((void*)hba[i]->vaddr); unregister_blkdev(MAJOR_NR+i, hba[i]->devname); del_timer(&hba[i]->timer); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i)); remove_proc_entry(hba[i]->devname, proc_array); kfree(hba[i]->cmd_pool); kfree(hba[i]->cmd_pool_bits); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/elevator.c linux/drivers/block/elevator.c --- v2.4.0-test2/linux/drivers/block/elevator.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/elevator.c Wed Jul 5 13:18:05 2000 @@ -88,25 +88,25 @@ head = head->next; while ((entry = entry->prev) != head && !starving) { - *req = blkdev_entry_to_request(entry); - latency += (*req)->nr_segments; - if (elevator_sequence_before((*req)->elevator_sequence, sequence)) + struct request *__rq = *req = blkdev_entry_to_request(entry); + latency += __rq->nr_segments; + if (elevator_sequence_before(__rq->elevator_sequence, sequence)) starving = 1; if (latency < 0) continue; - if ((*req)->sem) + if (__rq->sem) continue; - if ((*req)->cmd != rw) + if (__rq->cmd != rw) continue; - if ((*req)->nr_sectors + count > *max_sectors) + if (__rq->nr_sectors + count > *max_sectors) continue; - if ((*req)->rq_dev != bh->b_rdev) + if (__rq->rq_dev != bh->b_rdev) continue; - if ((*req)->sector + (*req)->nr_sectors == bh->b_rsector) { - if (latency - (*req)->nr_segments < 0) + if (__rq->sector + __rq->nr_sectors == bh->b_rsector) { + if (latency - __rq->nr_segments < 0) break; action = ELEVATOR_BACK_MERGE; - } else if ((*req)->sector - count == bh->b_rsector) { + } else if (__rq->sector - count == bh->b_rsector) { if (starving) break; action = ELEVATOR_FRONT_MERGE; @@ -138,6 +138,8 @@ struct list_head *entry = real_head; struct request *tmp; + req->elevator_sequence = orig_latency; + if (list_empty(real_head)) { list_add(&req->queue, real_head); return; @@ -159,31 +161,45 @@ int *max_sectors, int *max_segments) { struct list_head *entry, *head = &q->queue_head; - unsigned int count = bh->b_size >> 9; + unsigned int count = bh->b_size >> 9, ret = ELEVATOR_NO_MERGE; entry = head; if (q->head_active && !q->plugged) head = head->next; while ((entry = entry->prev) != head) { - *req = blkdev_entry_to_request(entry); - if (!(*req)->elevator_sequence) + struct request *__rq = *req = blkdev_entry_to_request(entry); + if (!__rq->elevator_sequence) break; - if ((*req)->sem) + if (__rq->sem) continue; - if ((*req)->cmd != rw) + if (__rq->cmd != rw) continue; - if ((*req)->nr_sectors + count > *max_sectors) + if (__rq->nr_sectors + count > *max_sectors) continue; - if ((*req)->rq_dev != bh->b_rdev) + if (__rq->rq_dev != bh->b_rdev) continue; - if ((*req)->sector + (*req)->nr_sectors == bh->b_rsector) - return ELEVATOR_BACK_MERGE; - if ((*req)->sector - count == bh->b_rsector) - return ELEVATOR_FRONT_MERGE; - (*req)->elevator_sequence--; + if (__rq->sector + __rq->nr_sectors == bh->b_rsector) { + ret = ELEVATOR_BACK_MERGE; + break; + } + if (__rq->sector - count == bh->b_rsector) { + ret = ELEVATOR_FRONT_MERGE; + break; + } } - return ELEVATOR_NO_MERGE; + + /* + * second pass scan of requests that got passed over, if any + */ + if (ret != ELEVATOR_NO_MERGE && *req) { + while ((entry = entry->next) != &q->queue_head) { + struct request *tmp = blkdev_entry_to_request(entry); + tmp->elevator_sequence--; + } + } + + return ret; } /* @@ -211,18 +227,18 @@ entry = head; while ((entry = entry->prev) != head) { - *req = blkdev_entry_to_request(entry); - if ((*req)->sem) + struct request *__rq = *req = blkdev_entry_to_request(entry); + if (__rq->sem) continue; - if ((*req)->cmd != rw) + if (__rq->cmd != rw) continue; - if ((*req)->nr_sectors + count > *max_sectors) + if (__rq->nr_sectors + count > *max_sectors) continue; - if ((*req)->rq_dev != bh->b_rdev) + if (__rq->rq_dev != bh->b_rdev) continue; - if ((*req)->sector + (*req)->nr_sectors == bh->b_rsector) + if (__rq->sector + __rq->nr_sectors == bh->b_rsector) return ELEVATOR_BACK_MERGE; - if ((*req)->sector - count == bh->b_rsector) + if (__rq->sector - count == bh->b_rsector) return ELEVATOR_FRONT_MERGE; } return ELEVATOR_NO_MERGE; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.4.0-test2/linux/drivers/block/floppy.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/floppy.c Thu Jul 6 19:42:06 2000 @@ -852,10 +852,10 @@ } /* locks the driver */ -static int lock_fdc(int drive, int interruptible) +static int _lock_fdc(int drive, int interruptible, int line) { if (!usage_count){ - printk(KERN_ERR "Trying to lock fdc while usage count=0\n"); + printk(KERN_ERR "Trying to lock fdc while usage count=0 at line %d\n", line); return -1; } if(floppy_grab_irq_and_dma()==-1) @@ -889,6 +889,8 @@ return 0; } +#define lock_fdc(drive,interruptible) _lock_fdc(drive,interruptible, __LINE__) + #define LOCK_FDC(drive,interruptible) \ if (lock_fdc(drive,interruptible)) return -EINTR; @@ -1872,7 +1874,7 @@ if (timer_pending(&fd_timer)) printk("fd_timer.function=%p\n", fd_timer.function); if (timer_pending(&fd_timeout)){ - printk("timer_table=%p\n",fd_timeout.function); + printk("timer_function=%p\n",fd_timeout.function); printk("expires=%lu\n",fd_timeout.expires-jiffies); printk("now=%lu\n",jiffies); } @@ -2601,6 +2603,11 @@ int aligned_sector_t; int max_sector, max_size, tracksize, ssize; + if(max_buffer_sectors == 0) { + printk("VFS: Block I/O scheduled on unopened device\n"); + return 0; + } + set_fdc(DRIVE(CURRENT->rq_dev)); raw_cmd = &default_raw_cmd; @@ -2955,6 +2962,11 @@ static void do_fd_request(request_queue_t * q) { + if(max_buffer_sectors == 0) { + printk("VFS: do_fd_request called on non-open device\n"); + return; + } + if (usage_count == 0) { printk("warning: usage count=0, CURRENT=%p exiting\n", CURRENT); printk("sect=%ld cmd=%d\n", CURRENT->sector, CURRENT->cmd); @@ -3782,9 +3794,14 @@ return 1; if (UDP->checkfreq < (int)(jiffies - UDRS->last_checked)) { + if(floppy_grab_irq_and_dma()) { + return 1; + } + lock_fdc(drive,0); poll_drive(0,0); process_fd_request(); + floppy_release_irq_and_dma(); } if (UTESTF(FD_DISK_CHANGED) || @@ -3810,6 +3827,10 @@ UTESTF(FD_VERIFY) || test_bit(drive, &fake_change) || NO_GEOM){ + if(usage_count == 0) { + printk("VFS: revalidate called on non-open device.\n"); + return -EFAULT; + } lock_fdc(drive,0); cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY); if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)){ @@ -3831,7 +3852,7 @@ size = 1024; if (!(bh = getblk(dev,0,size))){ process_fd_request(); - return 1; + return -ENXIO; } if (bh && !buffer_uptodate(bh)) ll_rw_block(READ, 1, &bh); @@ -4109,7 +4130,7 @@ raw_cmd = NULL; - devfs_handle = devfs_mk_dir (NULL, "floppy", 0, NULL); + devfs_handle = devfs_mk_dir (NULL, "floppy", NULL); if (devfs_register_blkdev(MAJOR_NR,"fd",&floppy_fops)) { printk("Unable to get major %d for floppy\n",MAJOR_NR); return -EBUSY; @@ -4143,6 +4164,7 @@ if (fdc_state[0].address == -1) { devfs_unregister_blkdev(MAJOR_NR,"fd"); del_timer(&fd_timeout); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); return -ENODEV; } #if N_FDC > 1 diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.4.0-test2/linux/drivers/block/ll_rw_blk.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/ll_rw_blk.c Thu Jul 6 19:25:21 2000 @@ -37,6 +37,8 @@ extern int mac_floppy_init(void); #endif +extern int lvm_init(void); + /* * For the allocated request tables */ @@ -148,34 +150,40 @@ return ret; } -/* - * Hopefully the low level driver has finished any out standing requests - * first... - */ -void blk_cleanup_queue(request_queue_t * q) +static int __block_cleanup_queue(struct list_head *head) { struct list_head *entry; struct request *rq; - int i = QUEUE_NR_REQUESTS; + int i = 0; - if (list_empty(&q->request_freelist)) - return; - - if (q->queue_requests) - BUG(); + if (list_empty(head)) + return 0; - entry = &q->request_freelist; - entry = entry->next; + entry = head->next; do { rq = list_entry(entry, struct request, table); entry = entry->next; list_del(&rq->table); kmem_cache_free(request_cachep, rq); - i--; - } while (!list_empty(&q->request_freelist)); + i++; + } while (!list_empty(head)); - if (i) - printk("blk_cleanup_queue: leaked requests (%d)\n", i); + return i; +} + +/* + * Hopefully the low level driver has finished any out standing requests + * first... + */ +void blk_cleanup_queue(request_queue_t * q) +{ + int count = QUEUE_NR_REQUESTS; + + count -= __block_cleanup_queue(&q->request_freelist[READ]); + count -= __block_cleanup_queue(&q->request_freelist[WRITE]); + + if (count) + printk("blk_cleanup_queue: leaked requests (%d)\n", count); memset(q, 0, sizeof(*q)); } @@ -280,10 +288,9 @@ for (i = 0; i < QUEUE_NR_REQUESTS; i++) { rq = kmem_cache_alloc(request_cachep, SLAB_KERNEL); rq->rq_status = RQ_INACTIVE; - list_add(&rq->table, &q->request_freelist); + list_add(&rq->table, &q->request_freelist[i & 1]); } - q->queue_requests = 0; init_waitqueue_head(&q->wait_for_request); spin_lock_init(&q->request_lock); } @@ -291,7 +298,8 @@ void blk_init_queue(request_queue_t * q, request_fn_proc * rfn) { INIT_LIST_HEAD(&q->queue_head); - INIT_LIST_HEAD(&q->request_freelist); + INIT_LIST_HEAD(&q->request_freelist[READ]); + INIT_LIST_HEAD(&q->request_freelist[WRITE]); elevator_init(&q->elevator, ELEVATOR_LINUS); blk_init_free_list(q); q->request_fn = rfn; @@ -342,25 +350,37 @@ */ static inline struct request *get_request(request_queue_t *q, int rw) { - register struct request *rq = NULL; - - if (!list_empty(&q->request_freelist)) { - elevator_t *e = &q->elevator; + struct list_head *list = &q->request_freelist[rw]; + struct request *rq; - if ((q->queue_requests > QUEUE_WRITES_MAX) && (rw == WRITE)) - return NULL; + /* + * Reads get preferential treatment and are allowed to steal + * from the write free list if necessary. + */ + if (!list_empty(list)) { + rq = blkdev_free_rq(list); + goto got_rq; + } - rq = blkdev_free_rq(&q->request_freelist); - list_del(&rq->table); - rq->rq_status = RQ_ACTIVE; - rq->special = NULL; - rq->q = q; - if (rq->cmd == READ) - rq->elevator_sequence = e->read_latency; - else - rq->elevator_sequence = e->write_latency; - q->queue_requests++; + /* + * if the WRITE list is non-empty, we know that rw is READ + * and that the READ list is empty. allow reads to 'steal' + * from the WRITE list. + */ + if (!list_empty(&q->request_freelist[WRITE])) { + list = &q->request_freelist[WRITE]; + rq = blkdev_free_rq(list); + goto got_rq; } + + return NULL; + +got_rq: + list_del(&rq->table); + rq->free_list = list; + rq->rq_status = RQ_ACTIVE; + rq->special = NULL; + rq->q = q; return rq; } @@ -492,9 +512,9 @@ /* * Request may not have originated from ll_rw_blk */ - if (req->q) { - list_add(&req->table, &req->q->request_freelist); - req->q->queue_requests--; + if (req->free_list) { + list_add(&req->table, req->free_list); + req->free_list = NULL; wake_up(&req->q->wait_for_request); } } @@ -563,7 +583,7 @@ int max_segments = MAX_SEGMENTS; struct request * req = NULL; int rw_ahead, max_sectors, el_ret; - struct list_head *head = &q->queue_head; + struct list_head *head; int latency; elevator_t *elevator = &q->elevator; @@ -608,12 +628,6 @@ goto end_io; /* Hmmph! Nothing to write */ refile_buffer(bh); do_write: - /* - * We don't allow the write-requests to fill up the - * queue completely: we want some room for reads, - * as they take precedence. The last third of the - * requests are only for reads. - */ kstat.pgpgout++; break; default: @@ -652,6 +666,13 @@ spin_lock_irq(&io_request_lock); elevator_default_debug(q, bh->b_rdev); + /* + * skip first entry, for devices with active queue head + */ + head = &q->queue_head; + if (q->head_active && !q->plugged) + head = head->next; + if (list_empty(head)) { q->plug_device_fn(q, bh->b_rdev); /* is atomic */ goto get_rq; @@ -709,12 +730,12 @@ req = __get_request_wait(q, rw); spin_lock_irq(&io_request_lock); + + head = &q->queue_head; + if (q->head_active && !q->plugged) + head = head->next; } - head = &q->queue_head; - if (q->head_active && !q->plugged) - head = head->next; - /* fill up the request-info, and add it to the queue */ req->cmd = rw; req->errors = 0; @@ -842,7 +863,6 @@ sorry: for (i = 0; i < nr; i++) buffer_IO_error(bhs[i]); - return; } void ll_rw_block(int rw, int nr, struct buffer_head * bh[]) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/loop.c linux/drivers/block/loop.c --- v2.4.0-test2/linux/drivers/block/loop.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/loop.c Thu Jun 29 18:25:49 2000 @@ -782,7 +782,7 @@ MAJOR_NR); return -EIO; } - devfs_handle = devfs_mk_dir (NULL, "loop", 0, NULL); + devfs_handle = devfs_mk_dir (NULL, "loop", NULL); devfs_register_series (devfs_handle, "%u", max_loop, DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/lvm-snap.c linux/drivers/block/lvm-snap.c --- v2.4.0-test2/linux/drivers/block/lvm-snap.c Mon Jun 19 16:31:58 2000 +++ linux/drivers/block/lvm-snap.c Sun Jul 9 22:16:55 2000 @@ -29,7 +29,7 @@ #include -static char *lvm_snap_version = "LVM 0.8final (15/02/2000)\n"; +static char *lvm_snap_version __attribute__ ((unused)) = "LVM 0.8final (15/02/2000)\n"; extern const char *const lvm_name; extern int lvm_blocksizes[]; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/lvm.c linux/drivers/block/lvm.c --- v2.4.0-test2/linux/drivers/block/lvm.c Mon Jun 19 16:31:58 2000 +++ linux/drivers/block/lvm.c Fri Jul 7 15:55:52 2000 @@ -165,6 +165,8 @@ #include #endif +#define LOCAL_END_REQUEST + #include #include diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/md.c linux/drivers/block/md.c --- v2.4.0-test2/linux/drivers/block/md.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/md.c Fri Jul 7 15:53:58 2000 @@ -496,7 +496,7 @@ mddev->sb = (mdp_super_t *) __get_free_page (GFP_KERNEL); if (!mddev->sb) return -ENOMEM; - md_clear_page((unsigned long)mddev->sb); + md_clear_page(mddev->sb); return 0; } @@ -510,7 +510,7 @@ printk (OUT_OF_MEM); return -EINVAL; } - md_clear_page((unsigned long)rdev->sb); + md_clear_page(rdev->sb); return 0; } @@ -804,6 +804,7 @@ del_mddev_mapping(mddev, MKDEV(MD_MAJOR, mdidx(mddev))); md_list_del(&mddev->all_mddevs); MD_INIT_LIST_HEAD(&mddev->all_mddevs); + blk_cleanup_queue(&mddev->queue); kfree(mddev); } @@ -3627,7 +3628,7 @@ printk (KERN_ALERT "Unable to get major %d for md\n", MD_MAJOR); return (-1); } - devfs_handle = devfs_mk_dir (NULL, "md", 0, NULL); + devfs_handle = devfs_mk_dir (NULL, "md", NULL); devfs_register_series (devfs_handle, "%u",MAX_MD_DEVS,DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFBLK | S_IRUSR | S_IWUSR, &md_fops, NULL); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/nbd.c linux/drivers/block/nbd.c --- v2.4.0-test2/linux/drivers/block/nbd.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/nbd.c Wed Jul 5 13:15:19 2000 @@ -517,7 +517,7 @@ register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &nbd_fops, nbd_bytesizes[i]>>9); } - devfs_handle = devfs_mk_dir (NULL, "nbd", 0, NULL); + devfs_handle = devfs_mk_dir (NULL, "nbd", NULL); devfs_register_series (devfs_handle, "%u", MAX_NBD, DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFBLK | S_IRUSR | S_IWUSR, @@ -530,6 +530,7 @@ void cleanup_module(void) { devfs_unregister (devfs_handle); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); if (unregister_blkdev(MAJOR_NR, "nbd") != 0) printk("nbd: cleanup_module failed\n"); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/paride/pg.c linux/drivers/block/paride/pg.c --- v2.4.0-test2/linux/drivers/block/paride/pg.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/paride/pg.c Thu Jun 29 18:25:49 2000 @@ -307,7 +307,7 @@ if (PG.present) pi_release(PI); return -1; } - devfs_handle = devfs_mk_dir (NULL, "pg", 2, NULL); + devfs_handle = devfs_mk_dir (NULL, "pg", NULL); devfs_register_series (devfs_handle, "%u", 4, DEVFS_FL_DEFAULT, major, 0, S_IFCHR | S_IRUSR | S_IWUSR, &pg_fops, NULL); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/paride/pt.c linux/drivers/block/paride/pt.c --- v2.4.0-test2/linux/drivers/block/paride/pt.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/paride/pt.c Thu Jun 29 18:25:49 2000 @@ -312,7 +312,7 @@ return -1; } - devfs_handle = devfs_mk_dir (NULL, "pt", 2, NULL); + devfs_handle = devfs_mk_dir (NULL, "pt", NULL); devfs_register_series (devfs_handle, "%u", 4, DEVFS_FL_DEFAULT, major, 0, S_IFCHR | S_IRUSR | S_IWUSR, &pt_fops, NULL); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c --- v2.4.0-test2/linux/drivers/block/ps2esdi.c Thu May 11 15:30:06 2000 +++ linux/drivers/block/ps2esdi.c Thu Jul 6 19:25:21 2000 @@ -121,7 +121,7 @@ static int ps2esdi_drives = 0; static struct hd_struct ps2esdi[MAX_HD << 6]; static u_short io_base; -static struct timer_list esdi_timer = {NULL, NULL, 0, 0L, ps2esdi_reset_timer}; +static struct timer_list esdi_timer = {{NULL, NULL}, 0, 0L, ps2esdi_reset_timer}; static int reset_status; static int ps2esdi_slot = -1; int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */ @@ -232,6 +232,7 @@ free_dma(dma_arb_level); free_irq(PS2ESDI_IRQ, NULL) devfs_unregister_blkdev(MAJOR_NR, "ed"); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/raid0.c linux/drivers/block/raid0.c --- v2.4.0-test2/linux/drivers/block/raid0.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/raid0.c Fri Jul 7 15:53:58 2000 @@ -120,7 +120,7 @@ static int raid0_run (mddev_t *mddev) { - int cur=0, i=0, size, zone0_size, nb_zone; + unsigned long cur=0, i=0, size, zone0_size, nb_zone; raid0_conf_t *conf; MOD_INC_USE_COUNT; @@ -142,11 +142,11 @@ printk("raid0 : conf->smallest->size is %d blocks.\n", conf->smallest->size); nb_zone = md_size[mdidx(mddev)]/conf->smallest->size + (md_size[mdidx(mddev)] % conf->smallest->size ? 1 : 0); - printk("raid0 : nb_zone is %d.\n", nb_zone); + printk("raid0 : nb_zone is %ld.\n", nb_zone); conf->nr_zones = nb_zone; - printk("raid0 : Allocating %d bytes for hash.\n", - sizeof(struct raid0_hash)*nb_zone); + printk("raid0 : Allocating %ld bytes for hash.\n", + nb_zone*sizeof(struct raid0_hash)); conf->hash_table = vmalloc (sizeof (struct raid0_hash)*nb_zone); if (!conf->hash_table) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/raid1.c linux/drivers/block/raid1.c --- v2.4.0-test2/linux/drivers/block/raid1.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/raid1.c Fri Jul 7 15:53:58 2000 @@ -551,7 +551,6 @@ int disks = MD_SB_DISKS; int i, sum_bhs = 0, sectors; struct mirror_info *mirror; - DECLARE_WAITQUEUE(wait, current); if (!buffer_locked(bh)) BUG(); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/raid5.c linux/drivers/block/raid5.c --- v2.4.0-test2/linux/drivers/block/raid5.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/raid5.c Fri Jul 7 15:53:58 2000 @@ -1674,7 +1674,7 @@ tmp->b_data = (char *)page_address(tmp->b_page); if (!tmp->b_data) goto out; - md_clear_page((unsigned long)tmp->b_data); + md_clear_page(tmp->b_data); memset(bh, 0, MD_SB_DISKS * sizeof(struct buffer_head *)); for (i = 0; i < conf->raid_disks; i++) { dev = conf->disks[i].dev; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/rd.c linux/drivers/block/rd.c --- v2.4.0-test2/linux/drivers/block/rd.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/rd.c Wed Jul 5 16:12:12 2000 @@ -408,7 +408,7 @@ rd_blocksizes[i] = rd_blocksize; rd_kbsize[i] = rd_size; } - devfs_handle = devfs_mk_dir (NULL, "rd", 0, NULL); + devfs_handle = devfs_mk_dir (NULL, "rd", NULL); devfs_register_series (devfs_handle, "%u", NUM_RAMDISKS, DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFBLK | S_IRUSR | S_IWUSR, @@ -436,8 +436,8 @@ #ifdef MODULE module_init(rd_init); -#endif module_exit(rd_cleanup); +#endif /* loadable module support */ MODULE_PARM (rd_size, "1i"); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/xd.c linux/drivers/block/xd.c --- v2.4.0-test2/linux/drivers/block/xd.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/xd.c Thu Jun 29 18:25:49 2000 @@ -166,7 +166,7 @@ printk("xd: Unable to get major number %d\n",MAJOR_NR); return -1; } - devfs_handle = devfs_mk_dir (NULL, xd_gendisk.major_name, 0, NULL); + devfs_handle = devfs_mk_dir (NULL, xd_gendisk.major_name, NULL); blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */ xd_gendisk.next = gendisk_head; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/xd.h linux/drivers/block/xd.h --- v2.4.0-test2/linux/drivers/block/xd.h Thu May 11 15:30:06 2000 +++ linux/drivers/block/xd.h Wed Jul 5 11:01:25 2000 @@ -103,9 +103,9 @@ const char *name; } XD_SIGNATURE; -int xd_setup (char *); +static int xd_setup (char *); #ifndef MODULE -int xd_manual_geo_init (char *command); +static int xd_manual_geo_init (char *command); #endif /* MODULE */ static u_char xd_detect (u_char *controller, unsigned int *address); static u_char xd_initdrives (void (*init_drive)(u_char drive)); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/block/z2ram.c linux/drivers/block/z2ram.c --- v2.4.0-test2/linux/drivers/block/z2ram.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/z2ram.c Wed Jul 5 13:15:19 2000 @@ -399,6 +399,8 @@ if ( unregister_blkdev( MAJOR_NR, DEVICE_NAME ) != 0 ) printk( KERN_ERR DEVICE_NAME ": unregister of device failed\n"); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + if ( current_device != -1 ) { i = 0; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/cdrom/aztcd.c linux/drivers/cdrom/aztcd.c --- v2.4.0-test2/linux/drivers/cdrom/aztcd.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/cdrom/aztcd.c Thu Jul 6 19:25:21 2000 @@ -310,7 +310,7 @@ static int AztTimeout, AztTries; static DECLARE_WAIT_QUEUE_HEAD(azt_waitq); -static struct timer_list delay_timer = { NULL, NULL, 0, 0, NULL }; +static struct timer_list delay_timer = { {NULL, NULL}, 0, 0, NULL }; static struct azt_DiskInfo DiskInfo; static struct azt_Toc Toc[MAX_TRACKS]; @@ -1819,12 +1819,13 @@ void __exit aztcd_exit(void) { - devfs_unregister(devfs_find_handle(NULL, "aztcd", 0, 0, 0, DEVFS_SPECIAL_BLK, + devfs_unregister(devfs_find_handle(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0)); if ((devfs_unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) { printk("What's that: can't unregister aztcd\n"); return; } + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); if ((azt_port==0x1f0)||(azt_port==0x170)) { SWITCH_IDE_MASTER; release_region(azt_port,8); /*IDE-interface*/ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c --- v2.4.0-test2/linux/drivers/cdrom/cdrom.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/cdrom/cdrom.c Thu Jun 29 18:25:50 2000 @@ -389,7 +389,7 @@ cdi->options |= (int) CDO_CHECK_TYPE; if (!devfs_handle) - devfs_handle = devfs_mk_dir (NULL, "cdroms", 6, NULL); + devfs_handle = devfs_mk_dir (NULL, "cdroms", NULL); sprintf (vname, "cdrom%u", cdrom_counter++); if (cdi->de) { int pos; @@ -400,9 +400,9 @@ sizeof rname - 3); if (pos >= 0) { strncpy (rname + pos, "../", 3); - devfs_mk_symlink (devfs_handle, vname, 0, + devfs_mk_symlink (devfs_handle, vname, DEVFS_FL_DEFAULT, - rname + pos, 0, &slave, NULL); + rname + pos, &slave, NULL); devfs_auto_unregister (cdi->de, slave); } } @@ -2617,7 +2617,7 @@ #ifdef CONFIG_SYSCTL cdrom_sysctl_register(); #endif - devfs_handle = devfs_mk_dir(NULL, "cdroms", 6, NULL); + devfs_handle = devfs_mk_dir(NULL, "cdroms", NULL); return 0; } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c --- v2.4.0-test2/linux/drivers/cdrom/cdu31a.c Wed Feb 16 17:03:51 2000 +++ linux/drivers/cdrom/cdu31a.c Thu Jul 6 19:25:21 2000 @@ -3245,6 +3245,7 @@ &scd_dops, /* device operations */ NULL, /* link */ NULL, /* handle */ + 0, /* devfs */ 0, /* dev */ 0, /* mask */ 2, /* maximum speed */ @@ -3544,6 +3545,7 @@ } errout0: printk("Unable to register CDU-31a with Uniform cdrom driver\n"); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); if (devfs_unregister_blkdev(MAJOR_NR, "cdu31a")) { printk("Can't unregister block device for cdu31a\n"); @@ -3568,6 +3570,8 @@ printk("Can't unregister cdu31a\n"); return; } + + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); if (cdu31a_irq > 0) free_irq(cdu31a_irq, NULL); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/cdrom/cm206.c linux/drivers/cdrom/cm206.c --- v2.4.0-test2/linux/drivers/cdrom/cm206.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/cdrom/cm206.c Wed Jul 5 13:15:19 2000 @@ -1285,6 +1285,7 @@ printk("Can't unregister major cm206\n"); return; } + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); case 3: free_irq(cm206_irq, NULL); case 2: diff -u --recursive --new-file v2.4.0-test2/linux/drivers/cdrom/gscd.c linux/drivers/cdrom/gscd.c --- v2.4.0-test2/linux/drivers/cdrom/gscd.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/cdrom/gscd.c Wed Jul 5 13:15:19 2000 @@ -95,7 +95,7 @@ /* Schnittstellen zum Kern/FS */ static void do_gscd_request (request_queue_t *); -static void __do_gscd_request (void); +static void __do_gscd_request (unsigned long dummy); static int gscd_ioctl (struct inode *, struct file *, unsigned int, unsigned long); static int gscd_open (struct inode *, struct file *); static int gscd_release (struct inode *, struct file *); @@ -160,6 +160,7 @@ static int AudioEnd_m; static int AudioEnd_f; +static struct timer_list gscd_timer; static struct block_device_operations gscd_fops = { open: gscd_open, @@ -271,23 +272,24 @@ static void do_gscd_request (request_queue_t * q) { - __do_gscd_request(); + __do_gscd_request(0); } -static void __do_gscd_request (void) +static void __do_gscd_request (unsigned long dummy) { unsigned int block,dev; unsigned int nsect; repeat: - if (QUEUE_EMPTY || CURRENT->rq_status == RQ_INACTIVE) return; + if (QUEUE_EMPTY || CURRENT->rq_status == RQ_INACTIVE) + goto out; INIT_REQUEST; dev = MINOR(CURRENT->rq_dev); block = CURRENT->sector; nsect = CURRENT->nr_sectors; if (QUEUE_EMPTY || CURRENT -> sector == -1) - return; + goto out; if (CURRENT -> cmd != READ) { @@ -318,6 +320,8 @@ #endif gscd_read_cmd (); +out: + return; } @@ -992,13 +996,16 @@ void __exit exit_gscd(void) { - devfs_unregister(devfs_find_handle(NULL, "gscd", 0, 0, 0, DEVFS_SPECIAL_BLK, + del_timer_async(&gscd_timer); + + devfs_unregister(devfs_find_handle(NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0)); if ((devfs_unregister_blkdev(MAJOR_NR, "gscd" ) == -EINVAL)) { printk("What's that: can't unregister GoldStar-module\n" ); return; } + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); release_region (gscd_port,4); printk(KERN_INFO "GoldStar-module released.\n" ); } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/cdrom/gscd.h linux/drivers/cdrom/gscd.h --- v2.4.0-test2/linux/drivers/cdrom/gscd.h Tue Dec 2 11:41:44 1997 +++ linux/drivers/cdrom/gscd.h Wed Jul 5 11:24:40 2000 @@ -74,11 +74,10 @@ #define READ_DATA(port, buf, nr) insb(port, buf, nr) #define SET_TIMER(func, jifs) \ - ((timer_table[GSCD_TIMER].expires = jiffies + jifs), \ - (timer_table[GSCD_TIMER].fn = func), \ - (timer_active |= 1<wreg_data, stuffp->irq, stuffp->irq); stuffp->irq = 0; + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); kfree(stuffp); return 0; } @@ -1184,6 +1187,7 @@ kfree(stuffp); if (devfs_unregister_blkdev(MAJOR_NR, "mcdx") != 0) xwarn("cleanup() unregister_blkdev() failed\n"); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); return 2; } printk(msg); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/cdrom/optcd.c linux/drivers/cdrom/optcd.c --- v2.4.0-test2/linux/drivers/cdrom/optcd.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/cdrom/optcd.c Wed Jul 5 13:15:19 2000 @@ -2080,12 +2080,13 @@ void __exit optcd_exit(void) { - devfs_unregister(devfs_find_handle(NULL, "optcd", 0, 0, 0, + devfs_unregister(devfs_find_handle(NULL, "optcd", 0, 0, DEVFS_SPECIAL_BLK, 0)); if (devfs_unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) { printk(KERN_ERR "optcd: what's that: can't unregister\n"); return; } + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); release_region(optcd_port, 4); printk(KERN_INFO "optcd: module released.\n"); } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c --- v2.4.0-test2/linux/drivers/cdrom/sbpcd.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/cdrom/sbpcd.c Wed Jul 5 13:15:19 2000 @@ -5752,7 +5752,7 @@ request_region(CDo_command,4,major_name); - devfs_handle = devfs_mk_dir (NULL, "sbp", 0, NULL); + devfs_handle = devfs_mk_dir (NULL, "sbp", NULL); for (j=0;j=0) kfree(sony_buffer[i]); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); kfree(sony_buffer); kfree(sony_toc); kfree(last_sony_subcode); @@ -1690,7 +1695,7 @@ kfree_s(sony_buffer, 4 * sony_buffer_sectors); kfree_s(last_sony_subcode, sizeof *last_sony_subcode); kfree_s(sony_toc, sizeof *sony_toc); - devfs_unregister(devfs_find_handle(NULL, CDU535_HANDLE, 0, 0, 0, + devfs_unregister(devfs_find_handle(NULL, CDU535_HANDLE, 0, 0, DEVFS_SPECIAL_BLK, 0)); if (devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL) printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n"); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v2.4.0-test2/linux/drivers/char/Makefile Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/Makefile Mon Jun 26 11:57:49 2000 @@ -318,10 +318,7 @@ # set when a framegrabber implements i2c support obj-$(L_I2C) += i2c-old.o -ifeq ($(CONFIG_DZ),y) - L_OBJS += dz.o -endif - +obj-$(CONFIG_DZ) += dz.o obj-$(CONFIG_NWBUTTON) += nwbutton.o obj-$(CONFIG_NWFLASH) += nwflash.o diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/console.c linux/drivers/char/console.c --- v2.4.0-test2/linux/drivers/char/console.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/console.c Thu Jul 6 20:12:54 2000 @@ -66,6 +66,9 @@ * * Resurrected character buffers in videoram plus lots of other trickery * by Martin Mares , July 1998 + * + * Removed old-style timers, introduced console_timer, made timer + * deletion SMP-safe. 17Jun00, Andrew Morton */ #include @@ -139,7 +142,7 @@ static int con_open(struct tty_struct *, struct file *); static void vc_init(unsigned int console, unsigned int rows, unsigned int cols, int do_clear); -static void blank_screen(void); +static void blank_screen(unsigned long dummy); static void gotoxy(int currcons, int new_x, int new_y); static void save_cur(int currcons); static void reset_terminal(int currcons, int do_clear); @@ -147,6 +150,7 @@ static void set_vesa_blanking(unsigned long arg); static void set_cursor(int currcons); static void hide_cursor(int currcons); +static void unblank_screen_t(unsigned long dummy); static int printable = 0; /* Is console ready for printing? */ @@ -196,6 +200,8 @@ */ int (*console_blank_hook)(int) = NULL; +static struct timer_list console_timer; + /* * Low-Level Functions */ @@ -581,10 +587,11 @@ if (redraw) { set_origin(currcons); - set_palette(currcons); - if (sw->con_switch(vc_cons[currcons].d) && vcmode != KD_GRAPHICS) + if (sw->con_switch(vc_cons[currcons].d) && vcmode != KD_GRAPHICS) { /* Update the screen contents */ + set_palette(currcons); do_update_region(currcons, origin, screenbuf_size/2); + } } set_cursor(currcons); if (is_switch) { @@ -2417,19 +2424,16 @@ if (tty_register_driver(&console_driver)) panic("Couldn't register console driver\n"); - timer_table[BLANK_TIMER].fn = blank_screen; - timer_table[BLANK_TIMER].expires = 0; + init_timer(&console_timer); + console_timer.function = blank_screen; if (blankinterval) { - timer_table[BLANK_TIMER].expires = jiffies + blankinterval; - timer_active |= 1<con_save_screen); - for (j=k=0; j<16; j++) { - vc_cons[currcons].d->vc_palette[k++] = default_red[j] ; - vc_cons[currcons].d->vc_palette[k++] = default_grn[j] ; - vc_cons[currcons].d->vc_palette[k++] = default_blu[j] ; - } } currcons = fg_console = 0; master_display_fg = vc_cons[currcons].d; @@ -2589,15 +2588,14 @@ } } -static void vesa_powerdown_screen(void) +static void vesa_powerdown_screen(unsigned long dummy) { - timer_active &= ~(1<con_blank(vc_cons[currcons].d, vesa_blank_mode + 1); } +void do_blank_screen(int entering_gfx) +{ + timer_do_blank_screen(entering_gfx, 0); +} + +static void unblank_screen_t(unsigned long dummy) +{ + unblank_screen(); +} + void unblank_screen(void) { int currcons; @@ -2655,10 +2665,9 @@ printk("unblank_screen: tty %d not allocated ??\n", fg_console+1); return; } - timer_table[BLANK_TIMER].fn = blank_screen; + console_timer.function = blank_screen; if (blankinterval) { - timer_table[BLANK_TIMER].expires = jiffies + blankinterval; - timer_active |= 1<vc_mode == KD_GRAPHICS) return; if (console_blanked) { - timer_table[BLANK_TIMER].fn = unblank_screen; - timer_table[BLANK_TIMER].expires = jiffies; /* Now */ - timer_active |= 1<use_count); DRM_PROC_PRINT_RET(atomic_dec(&q->use_count), "%5d/0x%03x %5d %5d" - " %5d/%c%c/%c%c%c %5d %10d %10d %10d\n", + " %5d/%c%c/%c%c%c %5Zd %10d %10d %10d\n", i, q->flags, atomic_read(&q->use_count), diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/drm/tdfx_drv.c linux/drivers/char/drm/tdfx_drv.c --- v2.4.0-test2/linux/drivers/char/drm/tdfx_drv.c Sun Mar 19 18:35:30 2000 +++ linux/drivers/char/drm/tdfx_drv.c Mon Jul 10 13:11:50 2000 @@ -544,7 +544,7 @@ if (lock.context != tdfx_res_ctx.handle) { current->counter = 5; - current->priority = DEF_PRIORITY/4; + current->nice = 0; } DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); @@ -589,7 +589,7 @@ if (lock.context != tdfx_res_ctx.handle) { current->counter = 5; - current->priority = DEF_PRIORITY; + current->nice = 0; } return 0; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/dz.c linux/drivers/char/dz.c --- v2.4.0-test2/linux/drivers/char/dz.c Thu Mar 2 14:36:22 2000 +++ linux/drivers/char/dz.c Mon Jun 26 18:03:05 2000 @@ -1566,11 +1566,9 @@ NULL }; -long __init dz_serial_console_init(long kmem_start, long kmem_end) +void __init dz_serial_console_init(void) { register_console(&dz_sercons); - - return kmem_start; } #endif /* ifdef CONFIG_SERIAL_CONSOLE */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/epca.c linux/drivers/char/epca.c --- v2.4.0-test2/linux/drivers/char/epca.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/epca.c Wed Jul 5 11:24:41 2000 @@ -127,6 +127,8 @@ -------------------------------------------------------------------------- */ static struct channel *card_ptr[MAXCARDS]; +static struct timer_list epca_timer; + /* ---------------------- Begin function prototypes --------------------- */ /* ---------------------------------------------------------------------- @@ -1564,12 +1566,11 @@ struct channel *ch; unsigned long flags; + del_timer_sync(&epca_timer); save_flags(flags); cli(); - timer_table[DIGI_TIMER].fn = 0; - if ((tty_unregister_driver(&pc_driver)) || (tty_unregister_driver(&pc_callout))) { @@ -1918,12 +1919,12 @@ Start up the poller to check for events on all enabled boards ---------------------------------------------------------------------- */ - timer_table[DIGI_TIMER].fn = (void *)epcapoll; - timer_table[DIGI_TIMER].expires = 0; + init_timer(&epca_timer); + epca_timer.function = epcapoll; + mod_timer(&epca_timer, jiffies + HZ/25); restore_flags(flags); - timer_active |= 1 << DIGI_TIMER; return 0; } /* End pc_init */ @@ -2267,12 +2268,9 @@ } /* End for each card */ - timer_table[DIGI_TIMER].fn = (void *)epcapoll; - timer_table[DIGI_TIMER].expires = jiffies + (HZ / 25); - timer_active |= 1 << DIGI_TIMER; + mod_timer(&epca_timer, jiffies + (HZ / 25)); restore_flags(flags); - } /* End epcapoll */ /* --------------------- Begin doevent ------------------------ */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/ftape/zftape/zftape-init.c linux/drivers/char/ftape/zftape/zftape-init.c --- v2.4.0-test2/linux/drivers/char/ftape/zftape/zftape-init.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/ftape/zftape/zftape-init.c Thu Jun 29 18:25:50 2000 @@ -521,17 +521,17 @@ } for (i = 0; i < 4; i++) { sprintf(devname, "qft%i", i); - devfs_unregister(devfs_find_handle(NULL, devname, 0, QIC117_TAPE_MAJOR, i, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i, DEVFS_SPECIAL_CHR, 0)); sprintf(devname, "nqft%i", i); - devfs_unregister(devfs_find_handle(NULL, devname, 0, QIC117_TAPE_MAJOR, i + 4, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 4, DEVFS_SPECIAL_CHR, 0)); sprintf(devname, "zqft%i", i); - devfs_unregister(devfs_find_handle(NULL, devname, 0, QIC117_TAPE_MAJOR, i + 16, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 16, DEVFS_SPECIAL_CHR, 0)); sprintf(devname, "nzqft%i", i); - devfs_unregister(devfs_find_handle(NULL, devname, 0, QIC117_TAPE_MAJOR, i + 20, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 20, DEVFS_SPECIAL_CHR, 0)); sprintf(devname, "rawqft%i", i); - devfs_unregister(devfs_find_handle(NULL, devname, 0, QIC117_TAPE_MAJOR, i + 32, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 32, DEVFS_SPECIAL_CHR, 0)); sprintf(devname, "nrawqft%i", i); - devfs_unregister(devfs_find_handle(NULL, devname, 0, QIC117_TAPE_MAJOR, i + 36, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 36, DEVFS_SPECIAL_CHR, 0)); } zft_uninit_mem(); /* release remaining memory, if any */ printk(KERN_INFO "zftape successfully unloaded.\n"); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/i810_rng.c linux/drivers/char/i810_rng.c --- v2.4.0-test2/linux/drivers/char/i810_rng.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/i810_rng.c Thu Jun 29 10:14:00 2000 @@ -2,35 +2,35 @@ Hardware driver for Intel i810 Random Number Generator (RNG) Copyright 2000 Jeff Garzik - + Driver Web site: http://gtf.org/garzik/drivers/i810_rng/ - + Based on: Intel 82802AB/82802AC Firmware Hub (FWH) Datasheet May 1999 Order Number: 290658-002 R - + Intel 82802 Firmware Hub: Random Number Generator Programmer's Reference Manual December 1999 Order Number: 298029-001 R - + Intel 82802 Firmware HUB Random Number Generator Driver Copyright (c) 2000 Matt Sottek Special thanks to Matt Sottek. I did the "guts", he did the "brains" and all the testing. (Anybody wanna send me an i810 or i820?) - + ---------------------------------------------------------- - + This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. ---------------------------------------------------------- - + From the firmware hub datasheet: - + The Firmware Hub integrates a Random Number Generator (RNG) using thermal noise generated from inherently random quantum mechanical properties of silicon. When not generating new random @@ -44,7 +44,7 @@ Theory of operation: This driver has TWO modes of operation: - + Mode 1 ------ Character driver. Using the standard open() @@ -52,16 +52,16 @@ the i810 RNG device. This data is NOT CHECKED by any fitness tests, and could potentially be bogus (if the hardware is faulty or has been tampered with). - + /dev/intel_rng is char device major 10, minor 183. - + Mode 2 ------ Injection of entropy into the kernel entropy pool via a timer function. - A timer is run at RNG_TIMER_LEN intervals, reading 8 bits + A timer is run at rng_timer_len intervals, reading 8 bits of data from the RNG. If the RNG has previously passed a FIPS test, then the data will be added to the /dev/random entropy pool. Then, those 8 bits are added to an internal @@ -71,12 +71,12 @@ Thus, the RNG will never be enabled until it passes a FIPS test. And, data will stop flowing into the system entropy pool if the data is determined to be non-random. - + Finally, note that the timer defaults to OFF. This ensures that the system entropy pool will not be polluted with RNG-originated data unless a conscious decision is made by the user. - + HOWEVER NOTE THAT UP TO 2499 BYTES OF DATA CAN BE BOGUS BEFORE THE SYSTEM WILL NOTICE VIA THE FIPS TEST. @@ -84,14 +84,13 @@ Driver notes: - * You may enable and disable the RNG hardware (and this - driver) via sysctl: + * You may enable and disable the RNG timer via sysctl: # disable RNG - echo 0 > /proc/sys/dev/i810_hw_enabled + echo 0 > /proc/sys/dev/i810_rng_timer # enable RNG - echo 1 > /proc/sys/dev/i810_hw_enabled + echo 1 > /proc/sys/dev/i810_rng_timer * The default number of entropy bits added by default is the full 8 bits. If you wish to reduce this value for @@ -103,10 +102,56 @@ * The default number of entropy bits can also be set via a module parameter "rng_entropy" at module load time. + * When the RNG timer is enabled, the driver reads 1 byte + from the hardware RNG every N jiffies. By default, every + half-second. If you would like to change the timer interval, + do so via another sysctl: + + echo 200 > /proc/sys/dev/i810_rng_interval + + NOTE THIS VALUE IS IN JIFFIES, NOT SECONDS OR MILLISECONDS. + Minimum interval is 1 jiffy, maximum interval is 24 hours. + * In order to unload the i810_rng module, you must first disable the hardware via sysctl i810_hw_enabled, as shown above, - and make sure all users of the character device - + and make sure all users of the character device have closed + + * The timer and the character device may be used simultaneously, + if desired. + + * FIXME: Currently only one open() of the character device is allowed. + If another user tries to open() the device, they will get an + -EBUSY error. Instead, this really should either support + multiple simultaneous users of the character device (not hard), + or simply block open() until the current user of the chrdev + calls close(). + + * FIXME: support poll() + + * FIXME: should we be crazy and support mmap()? + + * FIXME: It is possible for the timer function to read, + and shove into the kernel entropy pool, 2499 bytes of data + before the internal FIPS test notices that the data is bad. + The kernel should handle this (I think???), but we should use a + 2500-byte array, and re-run the FIPS test for every byte read. + This will slow things down but guarantee that bad data is + never passed upstream. + + ---------------------------------------------------------- + + Change history: + + 0.6.2: + * Clean up spinlocks. Since we don't have any interrupts + to worry about, but we do have a timer to worry about, + we use spin_lock_bh everywhere except the timer function + itself. + * Fix module load/unload. + * Fix timer function and h/w enable/disable logic + * New timer interval sysctl + * Clean up sysctl names + */ @@ -115,6 +160,7 @@ #include #include #include +#include #include #include #include @@ -127,24 +173,24 @@ /* * core module and version information */ -#define RNG_VERSION "0.6.1" +#define RNG_VERSION "0.6.2" #define RNG_MODULE_NAME "i810_rng" #define RNG_DRIVER_NAME RNG_MODULE_NAME " hardware driver " RNG_VERSION -#define PFX RNG_MODULE_NAME ": " +#define PFX RNG_MODULE_NAME ": " /* * debugging macros */ #undef RNG_DEBUG /* define to 1 to enable copious debugging info */ - + #ifdef RNG_DEBUG /* note: prints function name for you */ #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) #else #define DPRINTK(fmt, args...) #endif - + #define RNG_NDEBUG 0 /* define to 1 to disable lightweight runtime checks */ #if RNG_NDEBUG #define assert(expr) @@ -156,11 +202,11 @@ } #endif - + /* * misc helper macros */ -#define arraysize(x) (sizeof(x)/sizeof(*(x))) +#define arraysize(x) (sizeof(x)/sizeof(*(x))) /* * prototypes @@ -191,7 +237,7 @@ * Frequency that data is added to kernel entropy pool * HZ>>1 == every half-second */ -#define RNG_TIMER_LEN (HZ >> 1) +#define RNG_DEF_TIMER_LEN (HZ >> 1) /* @@ -206,18 +252,22 @@ * various RNG status variables. they are globals * as we only support a single RNG device */ -static int rng_allocated = 0; /* is someone using the RNG region? */ -static int rng_hw_enabled = 0; /* is the RNG h/w, and timer, enabled? */ -static int rng_trusted = 0; /* does FIPS trust out data? */ +static int rng_allocated; /* is someone using the RNG region? */ +static int rng_hw_enabled; /* is the RNG h/w enabled? */ +static int rng_timer_enabled; /* is the RNG timer enabled? */ +static int rng_use_count; /* number of times RNG has been enabled */ +static int rng_trusted; /* does FIPS trust out data? */ static int rng_enabled_sysctl; /* sysctl for enabling/disabling RNG */ -static int rng_entropy = 8; /* number of entropy bits we submit to /dev/random */ -static int rng_entropy_sysctl; /* sysctl for changing entropy bits */ -static int rng_have_mem_region = 0; /* did we grab RNG region via request_mem_region? */ -static int rng_fips_counter = 0; /* size of internal FIPS test data pool */ -static void *rng_mem = NULL; /* token to our ioremap'd RNG register area */ +static int rng_entropy = 8; /* number of entropy bits we submit to /dev/random */ +static int rng_entropy_sysctl; /* sysctl for changing entropy bits */ +static int rng_interval_sysctl; /* sysctl for changing timer interval */ +static int rng_have_mem_region; /* did we grab RNG region via request_mem_region? */ +static int rng_fips_counter; /* size of internal FIPS test data pool */ +static int rng_timer_len = RNG_DEF_TIMER_LEN; /* timer interval, in jiffies */ +static void *rng_mem; /* token to our ioremap'd RNG register area */ static spinlock_t rng_lock = SPIN_LOCK_UNLOCKED; /* hardware lock */ static struct timer_list rng_timer; /* kernel timer for RNG hardware reads and tests */ -static atomic_t rng_open; +static int rng_open; /* boolean, 0 (false) if chrdev is closed, 1 (true) if open */ /* * inlined helper functions for accessing RNG registers @@ -240,7 +290,7 @@ { assert (rng_mem != NULL); assert (rng_hw_enabled == 1); - + return (readb (rng_mem + RNG_STATUS) & RNG_DATA_PRESENT) ? 1 : 0; } @@ -249,22 +299,21 @@ { assert (rng_mem != NULL); assert (rng_hw_enabled == 1); - + return readb (rng_mem + RNG_DATA); } /* - * rng_timer_ticker - executes every RNG_TIMER_LEN jiffies, + * rng_timer_ticker - executes every rng_timer_len jiffies, * adds a single byte to system entropy * and internal FIPS test pools */ static void rng_timer_tick (unsigned long data) { - unsigned long flags; int rng_data; - spin_lock_irqsave (&rng_lock, flags); + spin_lock (&rng_lock); if (rng_data_present ()) { /* gimme some thermal noise, baby */ @@ -285,11 +334,14 @@ rng_run_fips_test (); } - spin_unlock_irqrestore (&rng_lock, flags); + /* run the timer again, if enabled */ + if (rng_timer_enabled) { + rng_timer.expires = jiffies + rng_timer_len; + add_timer (&rng_timer); + } + + spin_unlock (&rng_lock); - /* run the timer again */ - rng_timer.expires = jiffies + RNG_TIMER_LEN; - add_timer (&rng_timer); } @@ -298,43 +350,44 @@ */ static int rng_enable (int enable) { - unsigned long flags; int rc = 0; u8 hw_status; - + DPRINTK ("ENTER\n"); - - spin_lock_irqsave (&rng_lock, flags); + + spin_lock_bh (&rng_lock); hw_status = rng_hwstatus (); - - if (enable && !rng_hw_enabled) { - rng_hwstatus_set (hw_status | RNG_ENABLED); - printk (KERN_INFO PFX "RNG h/w enabled\n"); + if (enable) { rng_hw_enabled = 1; + rng_use_count++; MOD_INC_USE_COUNT; + } else { + rng_use_count--; + if (rng_use_count == 0) + rng_hw_enabled = 0; + MOD_DEC_USE_COUNT; } - - else if (!enable && rng_hw_enabled) { - del_timer (&rng_timer); - rng_hwstatus_set (hw_status & ~RNG_ENABLED); + if (rng_hw_enabled && ((hw_status & RNG_ENABLED) == 0)) { + rng_hwstatus_set (hw_status | RNG_ENABLED); + printk (KERN_INFO PFX "RNG h/w enabled\n"); + } + else if (!rng_hw_enabled && (hw_status & RNG_ENABLED)) { + rng_hwstatus_set (hw_status & ~RNG_ENABLED); printk (KERN_INFO PFX "RNG h/w disabled\n"); - rng_hw_enabled = 0; - MOD_DEC_USE_COUNT; } - - if (enable != (rng_hwstatus () & RNG_ENABLED) ) { - del_timer (&rng_timer); + + spin_unlock_bh (&rng_lock); + + if ((!!enable) != (!!(rng_hwstatus () & RNG_ENABLED))) { printk (KERN_ERR PFX "Unable to %sable the RNG\n", enable ? "en" : "dis"); rc = -EIO; } - spin_unlock_irqrestore (&rng_lock, flags); - DPRINTK ("EXIT, returning %d\n", rc); return rc; } @@ -343,26 +396,42 @@ /* * rng_handle_sysctl_enable - handle a read or write of our enable/disable sysctl */ - + static int rng_handle_sysctl_enable (ctl_table * table, int write, struct file *filp, void *buffer, size_t * lenp) { - unsigned long flags; int enabled_save, rc; DPRINTK ("ENTER\n"); - - spin_lock_irqsave (&rng_lock, flags); - rng_enabled_sysctl = enabled_save = rng_hw_enabled; - spin_unlock_irqrestore (&rng_lock, flags); + + spin_lock_bh (&rng_lock); + + rng_enabled_sysctl = enabled_save = rng_timer_enabled; rc = proc_dointvec (table, write, filp, buffer, lenp); - if (rc) + if (rc) { + spin_unlock_bh (&rng_lock); return rc; - - if (enabled_save != rng_enabled_sysctl) + } + + if (enabled_save != rng_enabled_sysctl) { + rng_timer_enabled = rng_enabled_sysctl; + spin_unlock_bh (&rng_lock); + + /* enable/disable hardware */ rng_enable (rng_enabled_sysctl); + /* enable/disable timer */ + if (rng_enabled_sysctl) { + rng_timer.expires = jiffies + rng_timer_len; + add_timer (&rng_timer); + } else { + del_timer_sync (&rng_timer); + } + } else { + spin_unlock_bh (&rng_lock); + } + DPRINTK ("EXIT, returning 0\n"); return 0; } @@ -371,31 +440,30 @@ /* * rng_handle_sysctl_entropy - handle a read or write of our entropy bits sysctl */ - + static int rng_handle_sysctl_entropy (ctl_table * table, int write, struct file *filp, void *buffer, size_t * lenp) { - unsigned long flags; int entropy_bits_save, rc; DPRINTK ("ENTER\n"); - - spin_lock_irqsave (&rng_lock, flags); + + spin_lock_bh (&rng_lock); rng_entropy_sysctl = entropy_bits_save = rng_entropy; - spin_unlock_irqrestore (&rng_lock, flags); + spin_unlock_bh (&rng_lock); rc = proc_dointvec (table, write, filp, buffer, lenp); if (rc) return rc; - + if (entropy_bits_save == rng_entropy_sysctl) goto out; if ((rng_entropy_sysctl >= 0) && (rng_entropy_sysctl <= 8)) { - spin_lock_irqsave (&rng_lock, flags); + spin_lock_bh (&rng_lock); rng_entropy = rng_entropy_sysctl; - spin_unlock_irqrestore (&rng_lock, flags); + spin_unlock_bh (&rng_lock); printk (KERN_INFO PFX "entropy bits now %d\n", rng_entropy_sysctl); } else { @@ -408,36 +476,89 @@ return 0; } +/* + * rng_handle_sysctl_interval - handle a read or write of our timer interval len sysctl + */ + +static int rng_handle_sysctl_interval (ctl_table * table, int write, struct file *filp, + void *buffer, size_t * lenp) +{ + int timer_len_save, rc; + + DPRINTK ("ENTER\n"); + + spin_lock_bh (&rng_lock); + rng_interval_sysctl = timer_len_save = rng_timer_len; + spin_unlock_bh (&rng_lock); + + rc = proc_dointvec (table, write, filp, buffer, lenp); + if (rc) + return rc; + + if (timer_len_save == rng_interval_sysctl) + goto out; + + if ((rng_interval_sysctl > 0) && + (rng_interval_sysctl < (HZ*86400))) { + spin_lock_bh (&rng_lock); + rng_timer_len = rng_interval_sysctl; + spin_unlock_bh (&rng_lock); + + printk (KERN_INFO PFX "timer interval now %d\n", rng_interval_sysctl); + } else { + printk (KERN_INFO PFX "ignoring invalid timer interval (%d)\n", + rng_interval_sysctl); + } + +out: + DPRINTK ("EXIT, returning 0\n"); + return 0; +} + /* * rng_sysctl - add or remove the rng sysctl */ static void rng_sysctl (int add) { -#define DEV_I810_RNG 1 -#define DEV_I810_RNG_ENTROPY 2 +#define DEV_I810_TIMER 1 +#define DEV_I810_ENTROPY 2 +#define DEV_I810_INTERVAL 3 + /* Definition of the sysctl */ + /* FIXME: use new field:value style of struct initialization */ static ctl_table rng_sysctls[] = { - {DEV_I810_RNG, /* ID */ - RNG_MODULE_NAME "_enabled", /* name in /proc */ + {DEV_I810_TIMER, /* ID */ + RNG_MODULE_NAME "_timer", /* name in /proc */ &rng_enabled_sysctl, sizeof (rng_enabled_sysctl), /* data ptr, data size */ - 0644, /* mode */ - 0, /* child */ + 0644, /* mode */ + 0, /* child */ rng_handle_sysctl_enable, /* proc handler */ - 0, /* strategy */ - 0, /* proc control block */ + 0, /* strategy */ + 0, /* proc control block */ 0, 0} , - {DEV_I810_RNG_ENTROPY, /* ID */ + {DEV_I810_ENTROPY, /* ID */ RNG_MODULE_NAME "_entropy", /* name in /proc */ &rng_entropy_sysctl, sizeof (rng_entropy_sysctl), /* data ptr, data size */ - 0644, /* mode */ - 0, /* child */ + 0644, /* mode */ + 0, /* child */ rng_handle_sysctl_entropy, /* proc handler */ - 0, /* strategy */ - 0, /* proc control block */ + 0, /* strategy */ + 0, /* proc control block */ + 0, 0} + , + {DEV_I810_INTERVAL, /* ID */ + RNG_MODULE_NAME "_interval", /* name in /proc */ + &rng_interval_sysctl, + sizeof (rng_interval_sysctl), /* data ptr, data size */ + 0644, /* mode */ + 0, /* child */ + rng_handle_sysctl_interval, /* proc handler */ + 0, /* strategy */ + 0, /* proc control block */ 0, 0} , {0} @@ -467,35 +588,36 @@ static int rng_dev_open (struct inode *inode, struct file *filp) { int rc = -EINVAL; - unsigned long flags; if ((filp->f_mode & FMODE_READ) == 0) goto err_out; if (filp->f_mode & FMODE_WRITE) goto err_out; - spin_lock_irqsave (&rng_lock, flags); - - if (atomic_read(&rng_open)) { - spin_unlock_irqrestore (&rng_lock, flags); + spin_lock_bh (&rng_lock); + + /* only allow one open of this device, exit with -EBUSY if already open */ + /* FIXME: we should sleep on a semaphore here, unless O_NONBLOCK */ + if (rng_open) { + spin_unlock_bh (&rng_lock); rc = -EBUSY; goto err_out; } - - atomic_set (&rng_open, 1); - spin_unlock_irqrestore (&rng_lock, flags); - + rng_open = 1; + + spin_unlock_bh (&rng_lock); + if (rng_enable(1) != 0) { - spin_lock_irqsave (&rng_lock, flags); - atomic_set (&rng_open, 0); - spin_unlock_irqrestore (&rng_lock, flags); + spin_lock_bh (&rng_lock); + rng_open = 0; + spin_unlock_bh (&rng_lock); rc = -EIO; goto err_out; } - + return 0; - + err_out: return rc; } @@ -503,14 +625,13 @@ static int rng_dev_release (struct inode *inode, struct file *filp) { - unsigned long flags; if (rng_enable(0) != 0) return -EIO; - spin_lock_irqsave (&rng_lock, flags); - atomic_set (&rng_open, 0); - spin_unlock_irqrestore (&rng_lock, flags); + spin_lock_bh (&rng_lock); + rng_open = 0; + spin_unlock_bh (&rng_lock); return 0; } @@ -520,14 +641,13 @@ loff_t *offp) { int have_data, copied = 0; - unsigned long flags; u8 data=0; u8 *page; - + if (size < 1) return 0; - - page = (unsigned char *) get_zeroed_page (GFP_KERNEL); + + page = (unsigned char *) get_free_page (GFP_KERNEL); if (!page) return -ENOMEM; @@ -545,7 +665,7 @@ return tmpsize; } - spin_lock_irqsave (&rng_lock, flags); + spin_lock_bh (&rng_lock); have_data = 0; if (rng_data_present ()) { @@ -553,8 +673,8 @@ have_data = 1; } - spin_unlock_irqrestore (&rng_lock, flags); - + spin_unlock_bh (&rng_lock); + if (have_data) { page[copied] = data; copied++; @@ -567,12 +687,12 @@ if (current->need_resched) schedule (); - + if (signal_pending (current)) { free_page ((long)page); return -ERESTARTSYS; } - + goto read_loop; } @@ -585,7 +705,7 @@ { int rc; u8 hw_status; - + DPRINTK ("ENTER\n"); if (rng_allocated) { @@ -619,7 +739,7 @@ if (rng_entropy < 0 || rng_entropy > RNG_MAX_ENTROPY) rng_entropy = RNG_MAX_ENTROPY; - + /* init core RNG timer, but do not add it */ init_timer (&rng_timer); rng_timer.function = rng_timer_tick; @@ -653,7 +773,7 @@ { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, }, { 0, }, }; -MODULE_DEVICE_TABLE (pci, rng_pci_tbl); +MODULE_DEVICE_TABLE (pci, rng_pci_tbl); static struct pci_driver rng_driver = { name: RNG_MODULE_NAME, @@ -690,31 +810,21 @@ int rc; DPRINTK ("ENTER\n"); - - MOD_INC_USE_COUNT; if (pci_register_driver (&rng_driver) < 1) { DPRINTK ("EXIT, returning -ENODEV\n"); - MOD_DEC_USE_COUNT; return -ENODEV; } - + rc = misc_register (&rng_miscdev); if (rc) { pci_unregister_driver (&rng_driver); DPRINTK ("EXIT, returning %d\n", rc); - MOD_DEC_USE_COUNT; return rc; } printk (KERN_INFO RNG_DRIVER_NAME " loaded\n"); - /* FIXME: verify module unload logic, then remove - * this additional MOD_INC_USE_COUNT */ - MOD_INC_USE_COUNT; - - MOD_DEC_USE_COUNT; /* init complete, unload allowed now */ - DPRINTK ("EXIT, returning 0\n"); return 0; } @@ -725,13 +835,9 @@ */ static void __exit rng_cleanup (void) { - unsigned long flags; - DPRINTK ("ENTER\n"); - spin_lock_irqsave (&rng_lock, flags); - del_timer (&rng_timer); - spin_unlock_irqrestore (&rng_lock, flags); + del_timer_sync (&rng_timer); rng_sysctl (0); pci_unregister_driver (&rng_driver); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/ip2/i2ellis.c linux/drivers/char/ip2/i2ellis.c --- v2.4.0-test2/linux/drivers/char/ip2/i2ellis.c Thu Aug 26 13:05:35 1999 +++ linux/drivers/char/ip2/i2ellis.c Wed Jul 5 11:00:21 2000 @@ -57,7 +57,7 @@ // called. Cleared when ANY board is reset. static struct timer_list * pDelayTimer; // Used by iiDelayTimer static wait_queue_head_t pDelayWait; // Used by iiDelayTimer -static spinlock_t Dl_spinlock; +static rwlock_t Dl_spinlock; //******** //* Code * diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/ip2/i2ellis.h linux/drivers/char/ip2/i2ellis.h --- v2.4.0-test2/linux/drivers/char/ip2/i2ellis.h Wed Apr 26 16:34:07 2000 +++ linux/drivers/char/ip2/i2ellis.h Wed Jul 5 11:00:22 2000 @@ -352,7 +352,7 @@ // Ring-buffers of channel structures whose channels have particular needs. - spinlock_t Fbuf_spinlock; + rwlock_t Fbuf_spinlock; volatile unsigned short i2Fbuf_strip; // Strip index volatile @@ -360,7 +360,7 @@ void *i2Fbuf[CH_QUEUE_SIZE]; // An array of channel pointers // of channels who need to send // flow control packets. - spinlock_t Dbuf_spinlock; + rwlock_t Dbuf_spinlock; volatile unsigned short i2Dbuf_strip; // Strip index volatile @@ -368,7 +368,7 @@ void *i2Dbuf[CH_QUEUE_SIZE]; // An array of channel pointers // of channels who need to send // data or in-line command packets. - spinlock_t Bbuf_spinlock; + rwlock_t Bbuf_spinlock; volatile unsigned short i2Bbuf_strip; // Strip index volatile @@ -397,8 +397,8 @@ unsigned long debugInlineCount; unsigned long debugBypassCount; - spinlock_t read_fifo_spinlock; - spinlock_t write_fifo_spinlock; + rwlock_t read_fifo_spinlock; + rwlock_t write_fifo_spinlock; #ifdef CONFIG_DEVFS_FS /* Device handles into devfs */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/ip2/i2lib.c linux/drivers/char/ip2/i2lib.c --- v2.4.0-test2/linux/drivers/char/ip2/i2lib.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/char/ip2/i2lib.c Wed Jul 5 11:00:22 2000 @@ -529,7 +529,7 @@ unsigned short channel; int cnt; unsigned long flags = 0; - spinlock_t *lock_var_p = NULL; + rwlock_t *lock_var_p = NULL; // Make sure the channel exists, otherwise do nothing if ( !i2Validate ( pCh ) ) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/ip2/i2lib.h linux/drivers/char/ip2/i2lib.h --- v2.4.0-test2/linux/drivers/char/ip2/i2lib.h Wed Apr 26 16:34:07 2000 +++ linux/drivers/char/ip2/i2lib.h Wed Jul 5 11:00:22 2000 @@ -228,10 +228,10 @@ struct tq_struct tqueue_status; struct tq_struct tqueue_hangup; - spinlock_t Ibuf_spinlock; - spinlock_t Obuf_spinlock; - spinlock_t Cbuf_spinlock; - spinlock_t Pbuf_spinlock; + rwlock_t Ibuf_spinlock; + rwlock_t Obuf_spinlock; + rwlock_t Cbuf_spinlock; + rwlock_t Pbuf_spinlock; } i2ChanStr, *i2ChanStrPtr; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/ip2/i2os.h linux/drivers/char/ip2/i2os.h --- v2.4.0-test2/linux/drivers/char/ip2/i2os.h Thu Aug 26 13:05:35 1999 +++ linux/drivers/char/ip2/i2os.h Wed Jul 5 11:00:22 2000 @@ -27,6 +27,7 @@ #include "ip2types.h" #include /* For inb, etc */ +#include //------------------------------------ // Defines for I/O instructions: @@ -61,7 +62,7 @@ //#define SAVE_AND_DISABLE_INTS(a,b) spin_lock_irqsave(a,b) //#define RESTORE_INTS(a,b) spin_unlock_irqrestore(a,b) -#define LOCK_INIT(a) spin_lock_init(a) +#define LOCK_INIT(a) rwlock_init(a) #define SAVE_AND_DISABLE_INTS(a,b) { \ /* printk("get_lock: 0x%x,%4d,%s\n",(int)a,__LINE__,__FILE__);*/ \ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/ip2main.c linux/drivers/char/ip2main.c --- v2.4.0-test2/linux/drivers/char/ip2main.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/ip2main.c Wed Jul 5 11:00:22 2000 @@ -329,7 +329,7 @@ * selected, the board is serviced periodically to see if anything needs doing. */ #define POLL_TIMEOUT (jiffies + 1) -static struct timer_list PollTimer = { NULL, NULL, 0, 0, ip2_poll }; +static struct timer_list PollTimer = { {NULL, NULL}, 0, 0, ip2_poll }; // next, prev, expires,data, func() static char TimerOn = 0; @@ -862,7 +862,7 @@ */ #ifdef CONFIG_DEVFS_FS if (!devfs_handle) - devfs_handle = devfs_mk_dir (NULL, "ip2", 3, NULL); + devfs_handle = devfs_mk_dir (NULL, "ip2", NULL); #endif for( i = 0; i < IP2_MAX_BOARDS; ++i ) { @@ -2568,10 +2568,10 @@ * base. Also line nunber as such is meaningless but we use it for our * array index so it is fixed also. */ - if ( ns.irq != ip2config.irq - || (int) ns.port != ((int) pCh->pMyBord->i2eBase) - || ns.baud_base != pCh->BaudBase - || ns.line != pCh->port_index ) { + if ( (ns.irq != ip2config.irq[pCh->port_index]) + || ((int) ns.port != ((int) (pCh->pMyBord->i2eBase))) + || (ns.baud_base != pCh->BaudBase) + || (ns.line != pCh->port_index) ) { return -EINVAL; } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/istallion.c linux/drivers/char/istallion.c --- v2.4.0-test2/linux/drivers/char/istallion.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/istallion.c Thu Jun 29 18:25:50 2000 @@ -5307,7 +5307,7 @@ if (devfs_register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem)) printk("STALLION: failed to register serial memory device\n"); - devfs_handle = devfs_mk_dir (NULL, "staliomem", 9, NULL); + devfs_handle = devfs_mk_dir (NULL, "staliomem", NULL); devfs_register_series (devfs_handle, "%u", 4, DEVFS_FL_DEFAULT, STL_SIOMEMMAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/lp.c linux/drivers/char/lp.c --- v2.4.0-test2/linux/drivers/char/lp.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/lp.c Thu Jun 29 18:25:50 2000 @@ -771,7 +771,7 @@ return -EIO; } - devfs_handle = devfs_mk_dir (NULL, "printers", 0, NULL); + devfs_handle = devfs_mk_dir (NULL, "printers", NULL); if (parport_register_driver (&lp_driver)) { printk ("lp: unable to register with parport\n"); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/misc.c linux/drivers/char/misc.c --- v2.4.0-test2/linux/drivers/char/misc.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/misc.c Sun Jul 9 22:21:41 2000 @@ -75,6 +75,7 @@ extern int rtc_sun_init(void); /* Combines MK48T02 and MK48T08 */ extern int rtc_DP8570A_init(void); extern int rtc_MK48T08_init(void); +extern int ds1286_init(void); extern int dsp56k_init(void); extern int radio_init(void); extern int pc110pad_init(void); @@ -134,8 +135,11 @@ old_fops = file->f_op; file->f_op = fops_get(c->fops); - if (file->f_op && file->f_op->open) - err=file->f_op->open(inode,file); + if (file->f_op) { + err = 0; + if (file->f_op->open) + err=file->f_op->open(inode,file); + } if (err) { fops_put(file->f_op); file->f_op = fops_get(old_fops); @@ -190,7 +194,7 @@ if (misc->minor < DYNAMIC_MINORS) misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); if (!devfs_handle) - devfs_handle = devfs_mk_dir (NULL, "misc", 4, NULL); + devfs_handle = devfs_mk_dir (NULL, "misc", NULL); misc->devfs_handle = devfs_register (devfs_handle, misc->name, DEVFS_FL_NONE, MISC_MAJOR, misc->minor, diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/msp3400.c linux/drivers/char/msp3400.c --- v2.4.0-test2/linux/drivers/char/msp3400.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/msp3400.c Wed Jul 5 10:56:13 2000 @@ -85,7 +85,9 @@ the autoscan seems work well only with FM... */ static int simple = -1; /* use short programming (>= msp3410 only) */ static int dolby = 0; +#ifdef REGISTER_MIXER static int mixer = -1; +#endif struct msp3400c { int simple; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/n_hdlc.c linux/drivers/char/n_hdlc.c --- v2.4.0-test2/linux/drivers/char/n_hdlc.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/n_hdlc.c Thu Jul 6 19:36:20 2000 @@ -9,7 +9,7 @@ * Al Longyear , Paul Mackerras * * Original release 01/11/99 - * ==FILEDATE 19991217== + * ==FILEDATE 20000706== * * This code is released under the GNU General Public License (GPL) * @@ -78,7 +78,7 @@ */ #define HDLC_MAGIC 0x239e -#define HDLC_VERSION "1.13" +#define HDLC_VERSION "1.16" #include #include @@ -239,6 +239,7 @@ /* Queues for select() functionality */ wait_queue_head_t read_wait; wait_queue_head_t write_wait; + wait_queue_head_t poll_wait; int tbusy; /* reentrancy flag for tx wakeup code */ int woke_up; @@ -317,6 +318,7 @@ /* Ensure that the n_hdlcd process is not hanging on select()/poll() */ wake_up_interruptible (&n_hdlc->read_wait); + wake_up_interruptible (&n_hdlc->poll_wait); wake_up_interruptible (&n_hdlc->write_wait); if (tty != NULL && tty->disc_data == n_hdlc) @@ -463,9 +465,10 @@ register int actual; unsigned long flags; N_HDLC_BUF *tbuf; - + if (debuglevel >= DEBUG_LEVEL_INFO) printk("%s(%d)n_hdlc_send_frames() called\n",__FILE__,__LINE__); + check_again: save_flags(flags); cli (); @@ -475,6 +478,7 @@ return; } n_hdlc->tbusy = 1; + n_hdlc->woke_up = 0; restore_flags(flags); /* get current transmit buffer or get new transmit */ @@ -490,7 +494,6 @@ __FILE__,__LINE__,tbuf,tbuf->count); /* Send the next block of data to device */ - n_hdlc->woke_up = 0; tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); actual = tty->driver.write(tty, 0, tbuf->buf, tbuf->count); @@ -512,6 +515,7 @@ /* wait up sleeping writers */ wake_up_interruptible(&n_hdlc->write_wait); + wake_up_interruptible(&n_hdlc->poll_wait); /* get next pending transmit buffer */ tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list); @@ -521,11 +525,6 @@ __FILE__,__LINE__,tbuf); /* buffer not accepted by driver */ - - /* check if wake up code called since last write call */ - if (n_hdlc->woke_up) - continue; - /* set this buffer as pending buffer */ n_hdlc->tbuf = tbuf; break; @@ -541,6 +540,9 @@ n_hdlc->tbusy = 0; restore_flags(flags); + if (n_hdlc->woke_up) + goto check_again; + if (debuglevel >= DEBUG_LEVEL_INFO) printk("%s(%d)n_hdlc_send_frames() exit\n",__FILE__,__LINE__); @@ -568,11 +570,8 @@ tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); return; } - - if (!n_hdlc->tbuf) - tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); - else - n_hdlc_send_frames (n_hdlc, tty); + + n_hdlc_send_frames (n_hdlc, tty); } /* end of n_hdlc_tty_wakeup() */ @@ -659,11 +658,12 @@ /* wake up any blocked reads and perform async signalling */ wake_up_interruptible (&n_hdlc->read_wait); + wake_up_interruptible (&n_hdlc->poll_wait); if (n_hdlc->tty->fasync != NULL) #if LINUX_VERSION_CODE < VERSION(2,3,0) kill_fasync (n_hdlc->tty->fasync, SIGIO); #else - kill_fasync(&n_hdlc->tty->fasync, SIGIO, POLL_IN); + kill_fasync (&n_hdlc->tty->fasync, SIGIO, POLL_IN); #endif } /* end of n_hdlc_tty_receive() */ @@ -788,34 +788,31 @@ count = maxframe; } + add_wait_queue(&n_hdlc->write_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + /* Allocate transmit buffer */ - tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list); - if (!tbuf) { - /* sleep until transmit buffer available */ - add_wait_queue(&n_hdlc->write_wait, &wait); - while (!tbuf) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - - n_hdlc = tty2n_hdlc (tty); - if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || - tty != n_hdlc->tty) { - printk("n_hdlc_tty_write: %p invalid after wait!\n", n_hdlc); - error = -EIO; - break; - } + /* sleep until transmit buffer available */ + while (!(tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list))) { + schedule(); - if (signal_pending(current)) { - error = -EINTR; - break; - } + n_hdlc = tty2n_hdlc (tty); + if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || + tty != n_hdlc->tty) { + printk("n_hdlc_tty_write: %p invalid after wait!\n", n_hdlc); + error = -EIO; + break; + } - tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list); + if (signal_pending(current)) { + error = -EINTR; + break; } - set_current_state(TASK_RUNNING); - remove_wait_queue(&n_hdlc->write_wait, &wait); } + set_current_state(TASK_RUNNING); + remove_wait_queue(&n_hdlc->write_wait, &wait); + if (!error) { /* Retrieve the user's buffer */ COPY_FROM_USER (error, tbuf->buf, data, count); @@ -978,8 +975,6 @@ * Return Value: * * bit mask containing info on which ops will not block - * - * Note: Called without the kernel lock held. Which is fine. */ static unsigned int n_hdlc_tty_poll (struct tty_struct *tty, struct file *filp, poll_table * wait) @@ -994,11 +989,9 @@ /* queue current process into any wait queue that */ /* may awaken in the future (read and write) */ #if LINUX_VERSION_CODE < VERSION(2,1,89) - poll_wait(&n_hdlc->read_wait, wait); - poll_wait(&n_hdlc->write_wait, wait); + poll_wait(&n_hdlc->poll_wait, wait); #else - poll_wait(filp, &n_hdlc->read_wait, wait); - poll_wait(filp, &n_hdlc->write_wait, wait); + poll_wait(filp, &n_hdlc->poll_wait, wait); #endif /* set bits for operations that wont block */ if(n_hdlc->rx_buf_list.head) @@ -1062,6 +1055,7 @@ n_hdlc->flags = 0; init_waitqueue_head(&n_hdlc->read_wait); + init_waitqueue_head(&n_hdlc->poll_wait); init_waitqueue_head(&n_hdlc->write_wait); return n_hdlc; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c --- v2.4.0-test2/linux/drivers/char/n_tty.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/n_tty.c Thu Jun 29 11:48:35 2000 @@ -18,6 +18,8 @@ * This file may be redistributed under the terms of the GNU Public * License. * + * Reduced memory usage for older ARM systems - Russell King. + * * 2000/01/20 Fixed SMP locking on put_tty_queue using bits of * the patch by Andrew J. Kroll * who actually finally proved there really was a race. @@ -61,6 +63,29 @@ #define TTY_THRESHOLD_THROTTLE 128 /* now based on remaining room */ #define TTY_THRESHOLD_UNTHROTTLE 128 +static inline unsigned char *alloc_buf(void) +{ + unsigned char *p; + int prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; + + if (PAGE_SIZE != N_TTY_BUF_SIZE) { + p = kmalloc(N_TTY_BUF_SIZE, prio); + if (p) + memset(p, 0, N_TTY_BUF_SIZE); + } else + p = (unsigned char *)get_zeroed_page(prio); + + return p; +} + +static inline void free_buf(unsigned char *buf) +{ + if (PAGE_SIZE != N_TTY_BUF_SIZE) + kfree(buf); + else + free_page((unsigned long) buf); +} + static inline void put_tty_queue(unsigned char c, struct tty_struct *tty) { unsigned long flags; @@ -827,7 +852,7 @@ { n_tty_flush_buffer(tty); if (tty->read_buf) { - free_page((unsigned long) tty->read_buf); + free_buf(tty->read_buf); tty->read_buf = 0; } } @@ -838,8 +863,7 @@ return -EINVAL; if (!tty->read_buf) { - tty->read_buf = (unsigned char *) - get_zeroed_page(in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + tty->read_buf = alloc_buf(); if (!tty->read_buf) return -ENOMEM; } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/nvram.c linux/drivers/char/nvram.c --- v2.4.0-test2/linux/drivers/char/nvram.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/nvram.c Sun Jul 9 22:15:26 2000 @@ -25,9 +25,12 @@ * the kernel and is not a module. Since the functions are used by some Atari * drivers, this is the case on the Atari. * + * + * 1.1 Cesar Barros: SMP locking fixes + * added changelog */ -#define NVRAM_VERSION "1.0" +#define NVRAM_VERSION "1.1" #include #include @@ -81,7 +84,7 @@ #endif /* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with - * interrupts disabled. Due to the index-port/data-port design of the RTC, we + * rtc_lock held. Due to the index-port/data-port design of the RTC, we * don't want two different things trying to get to it at once. (e.g. the * periodic 11 min sync from time.c vs. this driver.) */ @@ -96,11 +99,13 @@ #include #include #include +#include #include #include #include +extern spinlock_t rtc_lock; static int nvram_open_cnt = 0; /* #times opened */ static int nvram_open_mode; /* special open modes */ @@ -163,21 +168,20 @@ unsigned long flags; unsigned char c; - save_flags(flags); - cli(); + spin_lock_irqsave (&rtc_lock, flags); c = nvram_read_int( i ); - restore_flags(flags); + spin_unlock_irqrestore (&rtc_lock, flags); return( c ); } +/* This races nicely with trying to read with checksum checking (nvram_read) */ void nvram_write_byte( unsigned char c, int i ) { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave (&rtc_lock, flags); nvram_write_int( c, i ); - restore_flags(flags); + spin_unlock_irqrestore (&rtc_lock, flags); } int nvram_check_checksum( void ) @@ -185,10 +189,9 @@ unsigned long flags; int rv; - save_flags(flags); - cli(); + spin_lock_irqsave (&rtc_lock, flags); rv = nvram_check_checksum_int(); - restore_flags(flags); + spin_unlock_irqrestore (&rtc_lock, flags); return( rv ); } @@ -196,10 +199,9 @@ { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave (&rtc_lock, flags); nvram_set_checksum_int(); - restore_flags(flags); + spin_unlock_irqrestore (&rtc_lock, flags); } #endif /* MACH == ATARI */ @@ -228,63 +230,67 @@ static ssize_t nvram_read(struct file * file, char * buf, size_t count, loff_t *ppos ) { - unsigned long flags; + char contents [NVRAM_BYTES]; unsigned i = *ppos; - char *tmp = buf; - - if (i != *ppos) - return -EINVAL; + char *tmp; - save_flags(flags); - cli(); + spin_lock_irq (&rtc_lock); - if (!nvram_check_checksum_int()) { - restore_flags(flags); - return( -EIO ); - } + if (!nvram_check_checksum_int()) + goto checksum_err; + + for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp) + *tmp = nvram_read_int(i); + + spin_unlock_irq (&rtc_lock); + + copy_to_user_ret (buf, contents, tmp - contents, -EFAULT); - for( ; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp ) - put_user( nvram_read_int(i), tmp ); *ppos = i; - restore_flags(flags); - return( tmp - buf ); + return (tmp - contents); + +checksum_err: + spin_unlock_irq (&rtc_lock); + return -EIO; } static ssize_t nvram_write(struct file * file, const char * buf, size_t count, loff_t *ppos ) { - unsigned long flags; + char contents [NVRAM_BYTES]; unsigned i = *ppos; - const char *tmp = buf; - char c; - - if (i != *ppos) - return -EINVAL; + char * tmp; - save_flags(flags); - cli(); - - if (!nvram_check_checksum_int()) { - restore_flags(flags); - return( -EIO ); - } + /* could comebody please help me indent this better? */ + copy_from_user_ret (contents, buf, (NVRAM_BYTES - i) < count ? + (NVRAM_BYTES - i) : count, + -EFAULT); + + spin_lock_irq (&rtc_lock); + + if (!nvram_check_checksum_int()) + goto checksum_err; + + for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp) + nvram_write_int (*tmp, i); - for( ; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp ) { - get_user( c, tmp ); - nvram_write_int( c, i ); - } nvram_set_checksum_int(); + + spin_unlock_irq (&rtc_lock); + *ppos = i; - restore_flags(flags); - return( tmp - buf ); + return (tmp - contents); + +checksum_err: + spin_unlock_irq (&rtc_lock); + return -EIO; } static int nvram_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg ) { - unsigned long flags; int i; switch( cmd ) { @@ -293,14 +299,13 @@ if (!capable(CAP_SYS_ADMIN)) return( -EACCES ); - save_flags(flags); - cli(); + spin_lock_irq (&rtc_lock); for( i = 0; i < NVRAM_BYTES; ++i ) nvram_write_int( 0, i ); nvram_set_checksum_int(); - restore_flags(flags); + spin_unlock_irq (&rtc_lock); return( 0 ); case NVRAM_SETCKS: /* just set checksum, contents unchanged @@ -309,10 +314,9 @@ if (!capable(CAP_SYS_ADMIN)) return( -EACCES ); - save_flags(flags); - cli(); + spin_lock_irq (&rtc_lock); nvram_set_checksum_int(); - restore_flags(flags); + spin_unlock_irq (&rtc_lock); return( 0 ); default: @@ -355,16 +359,14 @@ static int nvram_read_proc( char *buffer, char **start, off_t offset, int size, int *eof, void *data ) { - unsigned long flags; unsigned char contents[NVRAM_BYTES]; int i, len = 0; off_t begin = 0; - - save_flags(flags); - cli(); + + spin_lock_irq (&rtc_lock); for( i = 0; i < NVRAM_BYTES; ++i ) contents[i] = nvram_read_int( i ); - restore_flags(flags); + spin_unlock_irq (&rtc_lock); *eof = mach_proc_infos( contents, buffer, &len, &begin, offset, size ); @@ -475,15 +477,13 @@ static int pc_proc_infos( unsigned char *nvram, char *buffer, int *len, off_t *begin, off_t offset, int size ) { - unsigned long flags; int checksum; int type; - save_flags(flags); - cli(); + spin_lock_irq (&rtc_lock); checksum = nvram_check_checksum_int(); - restore_flags(flags); - + spin_unlock_irq (&rtc_lock); + PRINT_PROC( "Checksum status: %svalid\n", checksum ? "" : "not " ); PRINT_PROC( "# floppies : %d\n", diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/nwbutton.h linux/drivers/char/nwbutton.h --- v2.4.0-test2/linux/drivers/char/nwbutton.h Sat Feb 26 22:31:44 2000 +++ linux/drivers/char/nwbutton.h Wed Jul 5 13:22:07 2000 @@ -28,8 +28,6 @@ static void button_handler (int irq, void *dev_id, struct pt_regs *regs); static int button_read (struct file *filp, char *buffer, size_t count, loff_t *ppos); -static int button_open (struct inode *inode, struct file *filp); -static int button_release (struct inode *inode, struct file *filp); int button_init (void); int button_add_callback (void (*callback) (void), int count); int button_del_callback (void (*callback) (void)); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c --- v2.4.0-test2/linux/drivers/char/pcxx.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/char/pcxx.c Wed Jul 5 11:24:41 2000 @@ -151,9 +151,11 @@ struct tty_driver pcxe_callout; static int pcxe_refcount; +static struct timer_list pcxx_timer; + DECLARE_TASK_QUEUE(tq_pcxx); -static void pcxxpoll(void); +static void pcxxpoll(unsigned long dummy); static void pcxxdelay(int); static void fepcmd(struct channel *, int, int, int, int, int); static void pcxe_put_char(struct tty_struct *, unsigned char); @@ -216,9 +218,7 @@ save_flags(flags); cli(); - timer_active &= ~(1 << DIGI_TIMER); - timer_table[DIGI_TIMER].fn = NULL; - timer_table[DIGI_TIMER].expires = 0; + del_timer_sync(&pcxx_timer); remove_bh(DIGI_BH); if ((e1 = tty_unregister_driver(&pcxe_driver))) @@ -1199,8 +1199,8 @@ init_bh(DIGI_BH,do_pcxe_bh); - timer_table[DIGI_TIMER].fn = pcxxpoll; - timer_table[DIGI_TIMER].expires = 0; + init_timer(&pcxx_timer); + pcxx_timer.function = pcxxpoll; memset(&pcxe_driver, 0, sizeof(struct tty_driver)); pcxe_driver.magic = TTY_DRIVER_MAGIC; @@ -1620,7 +1620,7 @@ /* * Start up the poller to check for events on all enabled boards */ - timer_active |= 1 << DIGI_TIMER; + mod_timer(&pcxx_timer, HZ/25); if (verbose) printk(KERN_NOTICE "PC/Xx: Driver with %d card(s) ready.\n", enabled_cards); @@ -1629,7 +1629,7 @@ } -static void pcxxpoll(void) +static void pcxxpoll(unsigned long dummy) { unsigned long flags; int crd; @@ -1660,9 +1660,7 @@ memoff(ch); } - timer_table[DIGI_TIMER].fn = pcxxpoll; - timer_table[DIGI_TIMER].expires = jiffies + HZ/25; - timer_active |= 1 << DIGI_TIMER; + mod_timer(&pcxx_timer, jiffies + HZ/25); restore_flags(flags); } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/ppdev.c linux/drivers/char/ppdev.c --- v2.4.0-test2/linux/drivers/char/ppdev.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/ppdev.c Wed Jul 5 11:55:45 2000 @@ -105,8 +105,9 @@ return; } - add->next = pp_port_list; + add->port = port; down (&pp_port_list_lock); + add->next = pp_port_list; pp_port_list = add; up (&pp_port_list_lock); } @@ -662,7 +663,7 @@ PP_MAJOR); return -EIO; } - devfs_handle = devfs_mk_dir (NULL, "parports", 0, NULL); + devfs_handle = devfs_mk_dir (NULL, "parports", NULL); devfs_register_series (devfs_handle, "%u", PARPORT_MAX, DEVFS_FL_DEFAULT, PP_MAJOR, 0, S_IFCHR | S_IRUGO | S_IWUGO, diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/pty.c linux/drivers/char/pty.c --- v2.4.0-test2/linux/drivers/char/pty.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/char/pty.c Thu Jun 29 18:25:50 2000 @@ -429,7 +429,7 @@ /* Unix98 devices */ #ifdef CONFIG_UNIX98_PTYS - devfs_mk_dir (NULL, "pts", 3, NULL); + devfs_mk_dir (NULL, "pts", NULL); printk("pty: %d Unix98 ptys configured\n", UNIX98_NR_MAJORS*NR_PTYS); for ( i = 0 ; i < UNIX98_NR_MAJORS ; i++ ) { int j; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/rocket.c linux/drivers/char/rocket.c --- v2.4.0-test2/linux/drivers/char/rocket.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/rocket.c Wed Jul 5 11:24:41 2000 @@ -138,13 +138,6 @@ #define _INLINE_ inline -/* - * Until we get a formal timer assignment - */ -#ifndef COMTROL_TIMER -#define COMTROL_TIMER 26 -#endif - #ifndef NEW_MODULES /* * NB. we must include the kernel idenfication string in to install the module. @@ -165,6 +158,8 @@ static int rp_num_ports_open = 0; +static struct timer_list rocket_timer; + unsigned long board1 = 0; unsigned long board2 = 0; unsigned long board3 = 0; @@ -504,7 +499,7 @@ /* * The top level polling routine. */ -static void rp_do_poll(void) +static void rp_do_poll(unsigned long dummy) { CONTROLLER_t *ctlp; int ctrl, aiop, ch, line; @@ -556,7 +551,7 @@ * Reset the timer so we get called at the next clock tick. */ if (rp_num_ports_open) { - timer_active |= 1 << COMTROL_TIMER; + mod_timer(&rocket_timer, jiffies + 1); } #ifdef TIME_STAT __asm__(".byte 0x0f,0x31" @@ -1044,7 +1039,7 @@ sSetRTS(cp); } - timer_active |= 1 << COMTROL_TIMER; + mod_timer(&rocket_timer, jiffies + 1); retval = block_til_ready(tty, filp, info); if (retval) { @@ -2145,13 +2140,12 @@ * Set up the timer channel. If it is already in use by * some other driver, give up. */ - if (timer_table[COMTROL_TIMER].fn) { - printk("rocket.o: Timer channel %d already in use!\n", - COMTROL_TIMER); + if (rocket_timer.function) { + printk("rocket.o: Timer already in use!\n"); return -EBUSY; } - timer_table[COMTROL_TIMER].fn = rp_do_poll; - timer_table[COMTROL_TIMER].expires = 0; + init_timer(&rocket_timer); + rocket_timer.function = rp_do_poll; /* * Initialize the array of pointers to our own internal state @@ -2208,7 +2202,7 @@ if (max_board == 0) { printk("No rocketport ports found; unloading driver.\n"); - timer_table[COMTROL_TIMER].fn = 0; + rocket_timer.function = 0; return -ENODEV; } @@ -2300,7 +2294,9 @@ int retval; int i; int released_controller = 0; - + + del_timer_sync(&rocket_timer); + retval = tty_unregister_driver(&callout_driver); if (retval) { printk("Error %d while trying to unregister " @@ -2328,7 +2324,7 @@ } if (tmp_buf) free_page((unsigned long) tmp_buf); - timer_table[COMTROL_TIMER].fn = 0; + rocket_timer.function = 0; } #endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/serial.c linux/drivers/char/serial.c --- v2.4.0-test2/linux/drivers/char/serial.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/serial.c Sun Jul 9 22:21:41 2000 @@ -46,6 +46,9 @@ * 5/00: Support for the RSA-DV II/S card added. * Kiyokazu SUTO * + * 6/00: Remove old-style timer, use timer_list + * Andrew Morton + * * This module exports the following rs232 io functions: * * int rs_init(void); @@ -232,6 +235,8 @@ static struct tty_driver serial_driver, callout_driver; static int serial_refcount; +static struct timer_list serial_timer; + /* serial subtype definitions */ #ifndef SERIAL_TYPE_NORMAL #define SERIAL_TYPE_NORMAL 1 @@ -253,6 +258,8 @@ static int IRQ_timeout[NR_IRQS]; #ifdef CONFIG_SERIAL_CONSOLE static struct console sercons; +#endif +#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE) static unsigned long break_pressed; /* break, really ... */ #endif @@ -304,11 +311,10 @@ #if (defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP)) #define NR_PCI_BOARDS 8 -#ifdef MODULE /* We don't unregister PCI boards right now */ static struct pci_board_inst serial_pci_board[NR_PCI_BOARDS]; static int serial_pci_board_idx = 0; -#endif + #ifndef IS_PCI_REGION_IOPORT #define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \ IORESOURCE_IO) @@ -1023,7 +1029,7 @@ * passable results for a 16550A. (Although at the expense of much * CPU overhead). */ -static void rs_timer(void) +static void rs_timer(unsigned long dummy) { static unsigned long last_strobe = 0; struct async_struct *info; @@ -1057,8 +1063,7 @@ } } last_strobe = jiffies; - timer_table[RS_TIMER].expires = jiffies + RS_STROBE_TIME; - timer_active |= 1 << RS_TIMER; + mod_timer(&serial_timer, jiffies + RS_STROBE_TIME); if (IRQ_ports[0]) { save_flags(flags); cli(); @@ -1069,7 +1074,7 @@ #endif restore_flags(flags); - timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2; + mod_timer(&serial_timer, jiffies + IRQ_timeout[0] - 2); } } @@ -1380,8 +1385,7 @@ /* * Set up serial timers... */ - timer_table[RS_TIMER].expires = jiffies + 2*HZ/100; - timer_active |= 1 << RS_TIMER; + mod_timer(&serial_timer, jiffies + 2*HZ/100); /* * Set up the tty->alt_speed kludge @@ -2046,7 +2050,7 @@ new_port = new_serial.port; if (HIGH_BITS_OFFSET) - new_port += new_serial.port_high << HIGH_BITS_OFFSET; + new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; change_irq = new_serial.irq != state->irq; change_port = (new_port != ((int) state->port)) || @@ -4448,9 +4452,10 @@ { PCI_VENDOR_ID_ROCKWELL, 0x1004, 0x1048, 0x1500, SPCI_FL_BASE1, 1, 115200 }, -#if 0 /* No definition for PCI_DEVICE_ID_NEC_NILE4 */ +#ifdef CONFIG_DDB5074 /* * NEC Vrc-5074 (Nile 4) builtin UART. + * Conditionally compiled in since this is a motherboard device. */ { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4, PCI_ANY_ID, PCI_ANY_ID, @@ -4979,12 +4984,12 @@ /* * The serial driver boot-time initialization code! */ -int __init rs_init(void) +static int __init rs_init(void) { int i; struct serial_state * state; - if (timer_table[RS_TIMER].fn) { + if (serial_timer.function) { printk("RS_TIMER already set, another serial driver " "already loaded?\n"); #ifdef MODULE @@ -4995,8 +5000,9 @@ } init_bh(SERIAL_BH, do_serial_bh); - timer_table[RS_TIMER].fn = rs_timer; - timer_table[RS_TIMER].expires = 0; + init_timer(&serial_timer); + serial_timer.function = rs_timer; + mod_timer(&serial_timer, jiffies + RS_STROBE_TIME); for (i = 0; i < NR_IRQS; i++) { IRQ_ports[i] = 0; @@ -5169,7 +5175,7 @@ port = req->port; if (HIGH_BITS_OFFSET) - port += req->port_high << HIGH_BITS_OFFSET; + port += (unsigned long) req->port_high << HIGH_BITS_OFFSET; save_flags(flags); cli(); for (i = 0; i < NR_PORTS; i++) { @@ -5267,8 +5273,7 @@ restore_flags(flags); } -#ifdef MODULE -void rs_fini(void) +static void __exit rs_fini(void) { unsigned long flags; int e1, e2; @@ -5276,10 +5281,8 @@ struct async_struct *info; /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ + del_timer_sync(&serial_timer); save_flags(flags); cli(); - timer_active &= ~(1 << RS_TIMER); - timer_table[RS_TIMER].fn = NULL; - timer_table[RS_TIMER].expires = 0; remove_bh(SERIAL_BH); if ((e1 = tty_unregister_driver(&serial_driver))) printk("serial: failed to unregister serial driver (%d)\n", @@ -5325,7 +5328,6 @@ free_page(pg); } } -#endif /* MODULE */ module_init(rs_init); module_exit(rs_fini); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/specialix.c linux/drivers/char/specialix.c --- v2.4.0-test2/linux/drivers/char/specialix.c Thu May 11 15:30:07 2000 +++ linux/drivers/char/specialix.c Wed Jul 5 10:56:13 2000 @@ -2338,7 +2338,6 @@ #ifdef CONFIG_PCI if (pci_present()) { struct pci_dev *pdev = NULL; - unsigned int tint; i=0; while (i <= SX_NBOARD) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/stallion.c linux/drivers/char/stallion.c --- v2.4.0-test2/linux/drivers/char/stallion.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/stallion.c Thu Jun 29 18:25:50 2000 @@ -780,7 +780,7 @@ stlpanel_t *panelp; stlport_t *portp; unsigned long flags; - int i, j, k, l; + int i, j, k; #if DEBUG printk("cleanup_module()\n"); @@ -3191,7 +3191,7 @@ */ if (devfs_register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem)) printk("STALLION: failed to register serial board device\n"); - devfs_handle = devfs_mk_dir (NULL, "staliomem", 9, NULL); + devfs_handle = devfs_mk_dir (NULL, "staliomem", NULL); devfs_register_series (devfs_handle, "%u", 4, DEVFS_FL_DEFAULT, STL_SIOMEMMAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/stradis.c linux/drivers/char/stradis.c --- v2.4.0-test2/linux/drivers/char/stradis.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/stradis.c Wed Jul 5 10:56:13 2000 @@ -343,6 +343,7 @@ return result; } +#if 0 /* unused */ /* MUST be a multiple of 8 bytes and 8-byte aligned and < 32768 bytes */ /* data copied into saa->dmadebi buffer, caller must re-enable interrupts */ static void ibm_block_dram_read(struct saa7146 *saa, int address, int bytes) @@ -375,6 +376,7 @@ buf[j] = debiread(saa, debNormal, IBM_MP2_DRAM_DATA, 4); } } +#endif /* unused */ static void do_irq_send_data(struct saa7146 *saa) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/synclink.c linux/drivers/char/synclink.c --- v2.4.0-test2/linux/drivers/char/synclink.c Thu May 11 15:30:07 2000 +++ linux/drivers/char/synclink.c Wed Jul 5 10:56:13 2000 @@ -373,7 +373,7 @@ /* * The size of the serial xmit buffer is 1 page, or 4096 bytes */ -#define SERIAL_XMIT_SIZE 4096 +/* #define SERIAL_XMIT_SIZE 4096 */ /* defined in include/linux/serial.h */ /* @@ -7428,7 +7428,6 @@ } /* End Of mgsl_memory_test() */ -#pragma optimize( "", off ) /* mgsl_load_pci_memory() * * Load a large block of data into the PCI shared memory. @@ -7483,7 +7482,7 @@ for ( Index = 0 ; Index < Intervalcount ; Index++ ) { memcpy(TargetPtr, SourcePtr, PCI_LOAD_INTERVAL); - Dummy = *((unsigned long *)TargetPtr); + Dummy = *((volatile unsigned long *)TargetPtr); TargetPtr += PCI_LOAD_INTERVAL; SourcePtr += PCI_LOAD_INTERVAL; } @@ -7491,7 +7490,6 @@ memcpy( TargetPtr, SourcePtr, count % PCI_LOAD_INTERVAL ); } /* End Of mgsl_load_pci_memory() */ -#pragma optimize( "", on ) void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c --- v2.4.0-test2/linux/drivers/char/tpqic02.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/tpqic02.c Wed Jul 5 11:24:41 2000 @@ -166,6 +166,7 @@ static kdev_t current_tape_dev; static int extra_blocks_left = BLOCKS_BEYOND_EW; +static struct timer_list tp_timer; /* return_*_eof: * NO: not at EOF, @@ -1595,7 +1596,7 @@ * has decided to do a long rewind, just when I didn't expect it. * Just try again. */ -static void qic02_tape_times_out(void) +static void qic02_tape_times_out(unsigned long dummy) { printk("time-out in %s driver\n", TPQIC02_NAME); if ((status_cmd_pending>0) || dma_mode) { @@ -1720,7 +1721,7 @@ wake_up(&qic02_tape_transfer); } else { /* start next transfer, account for track-switching time */ - timer_table[QIC02_TAPE_TIMER].expires = jiffies + 6*HZ; + mod_timer(&tp_timer, jiffies + 6*HZ); dma_transfer(); } } else { @@ -2940,8 +2941,8 @@ init_waitqueue_head(&qic02_tape_transfer); /* prepare timer */ TIMEROFF; - timer_table[QIC02_TAPE_TIMER].expires = 0; - timer_table[QIC02_TAPE_TIMER].fn = qic02_tape_times_out; + init_timer(&tp_timer); + tp_timer.function = qic02_tape_times_out; #ifndef CONFIG_QIC02_DYNCONF if (tape_reset(0)!=TE_OK || tp_sense(TP_WRP|TP_POR|TP_CNI)!=TE_OK) @@ -2984,14 +2985,14 @@ qic02_release_resources(); } devfs_unregister_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME); - devfs_unregister(devfs_find_handle(NULL, "ntpqic11", 0, QIC02_TAPE_MAJOR, 2, DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle(NULL, "tpqic11", 0, QIC02_TAPE_MAJOR, 3, DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle(NULL, "ntpqic24", 0, QIC02_TAPE_MAJOR, 4, DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle(NULL, "tpqic24", 0, QIC02_TAPE_MAJOR, 5, DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle(NULL, "ntpqic120", 0, QIC02_TAPE_MAJOR, 6, DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle(NULL, "tpqic120", 0, QIC02_TAPE_MAJOR, 7, DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle(NULL, "ntpqic150", 0, QIC02_TAPE_MAJOR, 8, DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle(NULL, "tpqic150", 0, QIC02_TAPE_MAJOR, 9, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, "ntpqic11", QIC02_TAPE_MAJOR, 2, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, "tpqic11", QIC02_TAPE_MAJOR, 3, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, "ntpqic24", QIC02_TAPE_MAJOR, 4, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, "tpqic24", QIC02_TAPE_MAJOR, 5, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, "ntpqic120", QIC02_TAPE_MAJOR, 6, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, "tpqic120", QIC02_TAPE_MAJOR, 7, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, "ntpqic150", QIC02_TAPE_MAJOR, 8, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, "tpqic150", QIC02_TAPE_MAJOR, 9, DEVFS_SPECIAL_CHR, 0)); } int init_module(void) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.4.0-test2/linux/drivers/char/tty_io.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/tty_io.c Sun Jul 9 22:30:36 2000 @@ -57,6 +57,9 @@ * * Added support for a Unix98-style ptmx device. * -- C. Scott Ananian , 14-Jan-1998 + * + * Reduced memory usage for older ARM systems + * -- Russell King */ #include @@ -99,6 +102,7 @@ #ifdef CONFIG_VT extern void con_init_devfs (void); #endif +extern int rio_init(void); #define CONSOLE_DEV MKDEV(TTY_MAJOR,0) #define TTY_DEV MKDEV(TTYAUX_MAJOR,0) @@ -111,7 +115,7 @@ #define CHECK_TTY_COUNT 1 struct termios tty_std_termios; /* for the benefit of tty drivers */ -struct tty_driver *tty_drivers = NULL; /* linked list of tty drivers */ +struct tty_driver *tty_drivers; /* linked list of tty drivers */ struct tty_ldisc ldiscs[NR_LDISCS]; /* line disc dispatch table */ #ifdef CONFIG_UNIX98_PTYS @@ -123,7 +127,7 @@ * redirect is the pseudo-tty that console output * is redirected to if asked by TIOCCONS. */ -struct tty_struct * redirect = NULL; +struct tty_struct * redirect; static void initialize_tty_struct(struct tty_struct *tty); @@ -135,32 +139,49 @@ int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); static int tty_fasync(int fd, struct file * filp, int on); -#ifdef CONFIG_SX extern int sx_init (void); -#endif -#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC) extern int vme_scc_init (void); extern long vme_scc_console_init(void); -#endif -#ifdef CONFIG_SERIAL167 extern int serial167_init(void); extern long serial167_console_init(void); -#endif -#if (defined(CONFIG_8xx) || defined(CONFIG_8260)) extern void console_8xx_init(void); extern int rs_8xx_init(void); -#endif /* CONFIG_8xx */ -#ifdef CONFIG_HWC extern void hwc_console_init(void); -#endif -#ifdef CONFIG_3215 extern void con3215_init(void); -#endif /* CONFIG_3215 */ - +extern void rs285_console_init(void); +extern void rs285_init(void); +extern void sa1100_rs_console_init(void); +extern void sa1100_rs_init(void); +extern void sgi_serial_console_init(void); #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif +#ifndef MAX +#define MAX(a,b) ((a) < (b) ? (b) : (a)) +#endif + +static inline struct tty_struct *alloc_tty_struct(void) +{ + struct tty_struct *tty; + + if (PAGE_SIZE > 8192) { + tty = kmalloc(sizeof(struct tty_struct), GFP_KERNEL); + if (tty) + memset(tty, 0, sizeof(struct tty_struct)); + } else + tty = (struct tty_struct *)get_zeroed_page(GFP_KERNEL); + + return tty; +} + +static inline void free_tty_struct(struct tty_struct *tty) +{ + if (PAGE_SIZE > 8192) + kfree(tty); + else + free_page((unsigned long) tty); +} /* * This routine returns the name of tty. @@ -692,7 +713,7 @@ unlock_kernel(); } else { for (;;) { - unsigned long size = PAGE_SIZE*2; + unsigned long size = MAX(PAGE_SIZE*2,16384); if (size > count) size = count; lock_kernel(); @@ -823,7 +844,7 @@ tp = o_tp = NULL; ltp = o_ltp = NULL; - tty = (struct tty_struct*) get_zeroed_page(GFP_KERNEL); + tty = alloc_tty_struct(); if(!tty) goto fail_no_mem; initialize_tty_struct(tty); @@ -849,7 +870,7 @@ } if (driver->type == TTY_DRIVER_TYPE_PTY) { - o_tty = (struct tty_struct *) get_zeroed_page(GFP_KERNEL); + o_tty = alloc_tty_struct(); if (!o_tty) goto free_mem_out; initialize_tty_struct(o_tty); @@ -969,12 +990,12 @@ if (o_tp) kfree_s(o_tp, sizeof(struct termios)); if (o_tty) - free_page((unsigned long) o_tty); + free_tty_struct(o_tty); if (ltp) kfree_s(ltp, sizeof(struct termios)); if (tp) kfree_s(tp, sizeof(struct termios)); - free_page((unsigned long) tty); + free_tty_struct(tty); fail_no_mem: retval = -ENOMEM; @@ -1005,7 +1026,7 @@ } o_tty->magic = 0; (*o_tty->driver.refcount)--; - free_page((unsigned long) o_tty); + free_tty_struct(o_tty); } tty->driver.table[idx] = NULL; @@ -1016,7 +1037,7 @@ } tty->magic = 0; (*tty->driver.refcount)--; - free_page((unsigned long) tty); + free_tty_struct(tty); } /* @@ -1397,9 +1418,9 @@ static int nr_warns = 0; if (nr_warns < 5) { printk(KERN_WARNING "tty_io.c: " - "process %d (%s) used obsolete /dev/%s - " + "process %d (%s) used obsolete /dev/%s - " "update software to use /dev/ttyS%d\n", - current->pid, current->comm, + current->pid, current->comm, tty_name(tty, buf), TTY_NUMBER(tty)); nr_warns++; } @@ -2009,7 +2030,7 @@ tty.driver = *driver; tty.device = MKDEV(driver->major, minor); - handle = devfs_find_handle (NULL, tty_name (&tty, buf), 0, + handle = devfs_find_handle (NULL, tty_name (&tty, buf), driver->major, minor, DEVFS_SPECIAL_CHR, 0); devfs_unregister (handle); @@ -2148,9 +2169,12 @@ #ifdef CONFIG_SERIAL_CONSOLE #if (defined(CONFIG_8xx) || defined(CONFIG_8260)) console_8xx_init(); -#elif defined(CONFIG_SERIAL) +#elif defined(CONFIG_SERIAL) serial_console_init(); #endif /* CONFIG_8xx */ +#ifdef CONFIG_SGI_SERIAL + sgi_serial_console_init(); +#endif #if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC) vme_scc_console_init(); #endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c --- v2.4.0-test2/linux/drivers/char/vc_screen.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/vc_screen.c Thu Jun 29 18:25:50 2000 @@ -469,9 +469,9 @@ sprintf (name, "a%u", index + 1); if (unregister) { - devfs_unregister ( devfs_find_handle (devfs_handle, name + 1, 0, 0, 0, + devfs_unregister ( devfs_find_handle (devfs_handle, name + 1, 0, 0, DEVFS_SPECIAL_CHR, 0) ); - devfs_unregister ( devfs_find_handle (devfs_handle, name, 0, 0, 0, + devfs_unregister ( devfs_find_handle (devfs_handle, name, 0, 0, DEVFS_SPECIAL_CHR, 0) ); } else @@ -495,7 +495,7 @@ if (error) printk("unable to get major %d for vcs device", VCS_MAJOR); - devfs_handle = devfs_mk_dir (NULL, "vcc", 3, NULL); + devfs_handle = devfs_mk_dir (NULL, "vcc", NULL); devfs_register (devfs_handle, "0", DEVFS_FL_DEFAULT, VCS_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/videodev.c linux/drivers/char/videodev.c --- v2.4.0-test2/linux/drivers/char/videodev.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/videodev.c Thu Jun 29 18:16:49 2000 @@ -330,6 +330,8 @@ video_dev_proc_entry->owner = THIS_MODULE; } +#ifdef MODULE +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) static void videodev_proc_destroy(void) { if (video_dev_proc_entry != NULL) @@ -338,6 +340,8 @@ if (video_proc_entry != NULL) remove_proc_entry("video", &proc_root); } +#endif +#endif static void videodev_proc_create_dev (struct video_device *vfd, char *name) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/char/zr36120.c linux/drivers/char/zr36120.c --- v2.4.0-test2/linux/drivers/char/zr36120.c Thu May 11 15:30:07 2000 +++ linux/drivers/char/zr36120.c Wed Jul 5 10:56:13 2000 @@ -153,6 +153,7 @@ static void zoran_set_geo(struct zoran* ztv, struct vidinfo* i); +#if 0 /* unused */ static void zoran_dump(struct zoran *ztv) { @@ -169,6 +170,7 @@ p += sprintf(p, "%08x ",zrread(i)); } } +#endif /* unused */ static void reap_states(struct zoran* ztv) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/i2c/i2c-core.c linux/drivers/i2c/i2c-core.c --- v2.4.0-test2/linux/drivers/i2c/i2c-core.c Sun Mar 19 18:35:30 2000 +++ linux/drivers/i2c/i2c-core.c Sun Jul 9 22:15:47 2000 @@ -168,6 +168,7 @@ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,48)) proc_entry->proc_fops = &i2cproc_operations; + proc_entry->owner = THIS_MODULE; #else proc_entry->ops = &i2cproc_inode_operations; #endif @@ -1114,26 +1115,26 @@ extern int i2c_dev_init(void); #endif #ifdef CONFIG_I2C_ALGOBIT - extern int algo_bit_init(void); + extern int i2c_algo_bit_init(void); #endif #ifdef CONFIG_I2C_BITLP - extern int bitlp_init(void); + extern int i2c_bitlp_init(void); #endif #ifdef CONFIG_I2C_BITELV - extern int bitelv_init(void); + extern int i2c_bitelv_init(void); #endif #ifdef CONFIG_I2C_BITVELLE - extern int bitvelle_init(void); + extern int i2c_bitvelle_init(void); #endif #ifdef CONFIG_I2C_BITVIA - extern int bitvia_init(void); + extern int i2c_bitvia_init(void); #endif #ifdef CONFIG_I2C_ALGOPCF - extern int algo_pcf_init(void); + extern int i2c_algo_pcf_init(void); #endif #ifdef CONFIG_I2C_PCFISA - extern int pcfisa_init(void); + extern int i2c_pcfisa_init(void); #endif /* This is needed for automatic patch generation: sensors code starts here */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c --- v2.4.0-test2/linux/drivers/i2o/i2o_block.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/i2o/i2o_block.c Thu Jul 6 19:24:51 2000 @@ -83,10 +83,10 @@ /* * Events that this OSM is interested in */ -#define I2OB_EVENT_MASK I2O_EVT_IND_BSA_VOLUME_LOAD | \ - I2O_EVT_IND_BSA_VOLUME_UNLOAD | \ - I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ | \ - I2O_EVT_IND_BSA_CAPACITY_CHANGE +#define I2OB_EVENT_MASK (I2O_EVT_IND_BSA_VOLUME_LOAD | \ + I2O_EVT_IND_BSA_VOLUME_UNLOAD | \ + I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ | \ + I2O_EVT_IND_BSA_CAPACITY_CHANGE) /* @@ -147,7 +147,7 @@ struct i2ob_request *next; struct request *req; int num; -} __cacheline_aligned; +}; /* * Per IOP requst queue information @@ -1664,6 +1664,7 @@ if(i2o_install_handler(&i2o_block_handler)<0) { unregister_blkdev(MAJOR_NR, "i2o_block"); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); printk(KERN_ERR "i2o_block: unable to register OSM.\n"); return -EINVAL; } @@ -1729,6 +1730,11 @@ */ if (unregister_blkdev(MAJOR_NR, "i2o_block") != 0) printk("i2o_block: cleanup_module failed\n"); + + /* + * free request queue + */ + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); if(evt_running) { i = kill_proc(evt_pid, SIGTERM, 1); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ide/hd.c linux/drivers/ide/hd.c --- v2.4.0-test2/linux/drivers/ide/hd.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/ide/hd.c Wed Jul 5 11:24:41 2000 @@ -105,6 +105,24 @@ static int hd_blocksizes[MAX_HD<<6]; static int hd_hardsectsizes[MAX_HD<<6]; +static struct timer_list device_timer; + +#define SET_TIMER \ + do { \ + mod_timer(&device_timer, jiffies + TIMEOUT_VALUE); \ + } while (0) + +#define CLEAR_TIMER del_timer(&device_timer); + +#undef SET_INTR + +#define SET_INTR(x) \ +if ((DEVICE_INTR = (x)) != NULL) \ + SET_TIMER; \ +else \ + CLEAR_TIMER; + + #if (HD_DELAY > 0) unsigned long last_req; @@ -471,7 +489,7 @@ * This is another of the error-routines I don't know what to do with. The * best idea seems to just set reset, and start all over again. */ -static void hd_times_out(void) +static void hd_times_out(unsigned long dummy) { unsigned int dev; @@ -527,7 +545,7 @@ if (DEVICE_INTR) return; repeat: - timer_active &= ~(1<capacity = 0x1fffff; + HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS] = (toc->capacity * SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9); + drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME; + /* Remember that we've read this stuff. */ CDROM_STATE_FLAGS (drive)->toc_valid = 1; @@ -2066,11 +2069,11 @@ struct request_sense sense; int ret; - toc = info->toc; - if (!CDROM_STATE_FLAGS(drive)->toc_valid || toc == NULL) + if (!CDROM_STATE_FLAGS(drive)->toc_valid || info->toc == NULL) if ((ret = cdrom_read_toc(drive, &sense))) return ret; + toc = info->toc; ms_info->addr.lba = toc->last_session_lba; ms_info->xa_flag = toc->xa_flag; @@ -2614,11 +2617,10 @@ /* options */ char *ignore = NULL; -#ifdef MODULE MODULE_PARM(ignore, "s"); MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); -void __exit ide_cdrom_exit(void) +static void __exit ide_cdrom_exit(void) { ide_drive_t *drive; int failed = 0; @@ -2630,7 +2632,6 @@ } ide_unregister_module (&ide_cdrom_module); } -#endif /* MODULE */ int ide_cdrom_init(void) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ide/ide-cs.c linux/drivers/ide/ide-cs.c --- v2.4.0-test2/linux/drivers/ide/ide-cs.c Thu May 11 15:30:07 2000 +++ linux/drivers/ide/ide-cs.c Thu Jul 6 19:25:21 2000 @@ -233,7 +233,7 @@ config_info_t conf; cistpl_cftable_entry_t *cfg = &parse.cftable_entry; cistpl_cftable_entry_t dflt = { 0 }; - int i, pass, last_ret, last_fn, hd, io_base, ctl_base; + int i, pass, last_ret, last_fn, hd=-1, io_base, ctl_base; DEBUG(0, "ide_config(0x%p)\n", link); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ide/ide-probe.c linux/drivers/ide/ide-probe.c --- v2.4.0-test2/linux/drivers/ide/ide-probe.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/ide/ide-probe.c Wed Jul 5 13:15:19 2000 @@ -580,6 +580,17 @@ #endif /* MAX_HWIFS > 1 */ /* + * init request queue + */ +static void ide_init_queue(ide_drive_t *drive) +{ + request_queue_t *q = &drive->queue; + + q->queuedata = HWGROUP(drive); + blk_init_queue(q, do_ide_request); +} + +/* * This routine sets up the irq for an ide interface, and creates a new * hwgroup for the irq/hwif if none was previously assigned. * @@ -677,6 +688,7 @@ hwgroup->drive = drive; drive->next = hwgroup->drive->next; hwgroup->drive->next = drive; + ide_init_queue(drive); } if (!hwgroup->hwif) { hwgroup->hwif = HWIF(hwgroup->drive); @@ -780,16 +792,13 @@ (hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index, hwif->channel, unit, hwif->drives[unit].lun); hwif->drives[unit].de = - devfs_mk_dir (ide_devfs_handle, name, 0, NULL); + devfs_mk_dir (ide_devfs_handle, name, NULL); } } } static int hwif_init (ide_hwif_t *hwif) { - request_queue_t *q; - unsigned int unit; - if (!hwif->present) return 0; if (!hwif->irq) { @@ -839,12 +848,6 @@ blk_dev[hwif->major].queue = ide_get_queue; read_ahead[hwif->major] = 8; /* (4kB) */ hwif->present = 1; /* success */ - - for (unit = 0; unit < MAX_DRIVES; ++unit) { - q = &hwif->drives[unit].queue; - q->queuedata = hwif->hwgroup; - blk_init_queue(q, do_ide_request); - } #if (DEBUG_SPINLOCK > 0) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ide/ide.c linux/drivers/ide/ide.c --- v2.4.0-test2/linux/drivers/ide/ide.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/ide/ide.c Sun Jul 9 10:04:35 2000 @@ -2023,6 +2023,7 @@ drive->id = NULL; } drive->present = 0; + blk_cleanup_queue(&drive->queue); } if (d->present) hwgroup->drive = d; @@ -2048,7 +2049,6 @@ kfree(blksize_size[hwif->major]); kfree(max_sectors[hwif->major]); kfree(max_readahead[hwif->major]); - blk_cleanup_queue(BLK_DEFAULT_QUEUE(hwif->major)); blk_dev[hwif->major].data = NULL; blk_dev[hwif->major].queue = NULL; blksize_size[hwif->major] = NULL; @@ -2858,6 +2858,18 @@ const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1); const char max_hwif = '0' + (MAX_HWIFS - 1); + + if (strncmp(s,"hd",2) == 0 && s[2] == '=') /* hd= is for hd.c */ + return 0; /* driver and not us */ + + if (strncmp(s,"ide",3) && + strncmp(s,"idebus",6) && +#ifdef CONFIG_BLK_DEV_VIA82CXXX + strncmp(s,"splitfifo",9) && +#endif /* CONFIG_BLK_DEV_VIA82CXXX */ + strncmp(s,"hd",2)) /* hdx= & hdxlun= */ + return 0; + printk("ide_setup: %s", s); init_ide_data (); @@ -2867,7 +2879,7 @@ printk(" : Enabled support for IDE doublers\n"); ide_doubler = 1; - return 0; + return 1; } #endif /* CONFIG_BLK_DEV_IDEDOUBLER */ @@ -2875,7 +2887,7 @@ if (!strcmp(s, "ide=reverse")) { ide_scan_direction = 1; printk(" : Enabled support for IDE inverse scan order.\n"); - return 0; + return 1; } #endif /* CONFIG_BLK_DEV_IDEPCI */ @@ -3188,17 +3200,17 @@ case 0: goto bad_option; default: printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n"); - return 0; + return 1; } } bad_option: printk(" -- BAD OPTION\n"); - return 0; + return 1; bad_hwif: printk("-- NOT SUPPORTED ON ide%d", hw); done: printk("\n"); - return 0; + return 1; } /* @@ -3594,7 +3606,7 @@ if (!banner_printed) { printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n"); - ide_devfs_handle = devfs_mk_dir (NULL, "ide", 3, NULL); + ide_devfs_handle = devfs_mk_dir (NULL, "ide", NULL); system_bus_speed = ide_system_bus_speed(); banner_printed = 1; } @@ -3614,6 +3626,10 @@ return 0; } +#ifdef MODULE +char *options = NULL; +MODULE_PARM(options,"s"); + static void __init parse_options (char *line) { char *next = line; @@ -3623,21 +3639,11 @@ while ((line = next) != NULL) { if ((next = strchr(line,' ')) != NULL) *next++ = 0; - if (!strncmp(line,"ide",3) || - !strncmp(line,"idebus",6) || -#ifdef CONFIG_BLK_DEV_VIA82CXXX - !strncmp(line,"splitfifo",9) || -#endif /* CONFIG_BLK_DEV_VIA82CXXX */ - !strncmp(line,"hdxlun",6) || - (!strncmp(line,"hd",2) && line[2] != '=')) - (void) ide_setup(line); + if (!ide_setup(line)) + printk ("Unknown option '%s'\n", line); } } -#ifdef MODULE -char *options = NULL; -MODULE_PARM(options,"s"); - int init_module (void) { parse_options(options); @@ -3664,12 +3670,6 @@ #else /* !MODULE */ -static int parse_ide_setup (char *line) -{ - parse_options(line); - /* We MUST return 0 as otherwise no subsequent __setup option works... */ - return 0; -} -__setup("", parse_ide_setup); +__setup("", ide_setup); #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ide/piix.c linux/drivers/ide/piix.c --- v2.4.0-test2/linux/drivers/ide/piix.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/ide/piix.c Fri Jul 7 15:55:24 2000 @@ -191,6 +191,7 @@ extern char *ide_xfer_verbose (byte xfer_rate); +#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING) /* * */ @@ -221,6 +222,7 @@ return 0; } } +#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_PIIX_TUNING) */ /* * Based on settings done by AMI BIOS diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/Config.in linux/drivers/ieee1394/Config.in --- v2.4.0-test2/linux/drivers/ieee1394/Config.in Mon Mar 27 08:08:24 2000 +++ linux/drivers/ieee1394/Config.in Wed Jul 5 13:03:56 2000 @@ -4,18 +4,20 @@ mainmenu_option next_comment comment 'IEEE 1394 (FireWire) support' - tristate 'IEEE 1394 (FireWire) support (EXPERIMENTAL)' CONFIG_IEEE1394 $CONFIG_PCI + dep_tristate 'IEEE 1394 (FireWire) support (EXPERIMENTAL)' CONFIG_IEEE1394 $CONFIG_PCI if [ "$CONFIG_IEEE1394" != "n" ]; then dep_tristate 'Texas Instruments PCILynx support' CONFIG_IEEE1394_PCILYNX $CONFIG_IEEE1394 if [ "$CONFIG_IEEE1394_PCILYNX" != "n" ]; then bool ' Use PCILynx local RAM' CONFIG_IEEE1394_PCILYNX_LOCALRAM + bool ' Support for non-IEEE1394 local ports' CONFIG_IEEE1394_PCILYNX_PORTS fi dep_tristate 'Adaptec AIC-5800 (AHA-89xx) support' CONFIG_IEEE1394_AIC5800 $CONFIG_IEEE1394 dep_tristate 'OHCI (Open Host Controller Interface) support' CONFIG_IEEE1394_OHCI1394 $CONFIG_IEEE1394 + dep_tristate 'Video1394 support' CONFIG_IEEE1394_VIDEO1394 $CONFIG_IEEE1394_OHCI1394 dep_tristate 'Raw IEEE1394 I/O support' CONFIG_IEEE1394_RAWIO $CONFIG_IEEE1394 diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/Makefile linux/drivers/ieee1394/Makefile --- v2.4.0-test2/linux/drivers/ieee1394/Makefile Fri Jun 23 21:55:09 2000 +++ linux/drivers/ieee1394/Makefile Wed Jul 5 13:03:56 2000 @@ -53,13 +53,20 @@ endif ifeq ($(CONFIG_IEEE1394_OHCI1394),y) -L_OBJS += ohci1394.o +LX_OBJS += ohci1394.o else ifeq ($(CONFIG_IEEE1394_OHCI1394),m) - M_OBJS += ohci1394.o + MX_OBJS += ohci1394.o endif endif +ifeq ($(CONFIG_IEEE1394_VIDEO1394),y) +L_OBJS += video1394.o +else + ifeq ($(CONFIG_IEEE1394_VIDEO1394),m) + M_OBJS += video1394.o + endif +endif ifeq ($(CONFIG_IEEE1394_RAWIO),y) L_OBJS += raw1394.o diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/aic5800.c linux/drivers/ieee1394/aic5800.c --- v2.4.0-test2/linux/drivers/ieee1394/aic5800.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/ieee1394/aic5800.c Wed Jul 5 13:03:56 2000 @@ -646,7 +646,7 @@ phyid = phyid & 0x3F; handle_selfid(aic, host, phyid, isroot, rcv_bytes); } else { - hpsb_packet_received(host, aic->rcv_page, rcv_bytes); + hpsb_packet_received(host, aic->rcv_page, rcv_bytes, 0); }; } else { PRINT(KERN_ERR, aic->id, diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/csr.c linux/drivers/ieee1394/csr.c --- v2.4.0-test2/linux/drivers/ieee1394/csr.c Mon Mar 27 08:08:24 2000 +++ linux/drivers/ieee1394/csr.c Wed Jul 5 13:03:56 2000 @@ -4,6 +4,9 @@ * CSR implementation, iso/bus manager implementation. * * Copyright (C) 1999 Andreas E. Bombe + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. */ #include diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/guid.c linux/drivers/ieee1394/guid.c --- v2.4.0-test2/linux/drivers/ieee1394/guid.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/ieee1394/guid.c Wed Jul 5 13:03:56 2000 @@ -4,6 +4,9 @@ * GUID collection and management * * Copyright (C) 2000 Andreas E. Bombe + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. */ #include diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/highlevel.c linux/drivers/ieee1394/highlevel.c --- v2.4.0-test2/linux/drivers/ieee1394/highlevel.c Mon Mar 27 08:08:24 2000 +++ linux/drivers/ieee1394/highlevel.c Wed Jul 5 13:03:56 2000 @@ -2,6 +2,9 @@ * IEEE 1394 for Linux * * Copyright (C) 1999 Andreas E. Bombe + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. */ #include diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/hosts.c linux/drivers/ieee1394/hosts.c --- v2.4.0-test2/linux/drivers/ieee1394/hosts.c Sun Feb 20 21:12:39 2000 +++ linux/drivers/ieee1394/hosts.c Wed Jul 5 13:03:56 2000 @@ -5,6 +5,9 @@ * * Copyright (C) 1999 Andreas E. Bombe * Copyright (C) 1999 Emanuel Pirker + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. */ #include diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/ieee1394_core.c linux/drivers/ieee1394/ieee1394_core.c --- v2.4.0-test2/linux/drivers/ieee1394/ieee1394_core.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/ieee1394/ieee1394_core.c Wed Jul 5 13:03:56 2000 @@ -5,6 +5,9 @@ * highlevel or lowlevel code * * Copyright (C) 1999, 2000 Andreas E. Bombe + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. */ #include @@ -534,7 +537,7 @@ if (packet == NULL) break void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data, - size_t size) + size_t size, int write_acked) { struct hpsb_packet *packet; int length, rcode, extcode; @@ -548,7 +551,8 @@ addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; rcode = highlevel_write(host, source, data+3, addr, 4); - if (((data[0] >> 16) & NODE_MASK) != NODE_MASK) { + if (!write_acked + && ((data[0] >> 16) & NODE_MASK) != NODE_MASK) { /* not a broadcast write, reply */ PREP_REPLY_PACKET(0); fill_async_write_resp(packet, rcode); @@ -561,7 +565,8 @@ rcode = highlevel_write(host, source, data+4, addr, data[3]>>16); - if (((data[0] >> 16) & NODE_MASK) != NODE_MASK) { + if (!write_acked + && ((data[0] >> 16) & NODE_MASK) != NODE_MASK) { /* not a broadcast write, reply */ PREP_REPLY_PACKET(0); fill_async_write_resp(packet, rcode); @@ -644,7 +649,8 @@ #undef PREP_REPLY_PACKET -void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size) +void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, + int write_acked) { int tcode; @@ -672,7 +678,7 @@ case TCODE_READQ: case TCODE_READB: case TCODE_LOCK_REQUEST: - handle_incoming_packet(host, tcode, data, size); + handle_incoming_packet(host, tcode, data, size, write_acked); break; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/ieee1394_core.h linux/drivers/ieee1394/ieee1394_core.h --- v2.4.0-test2/linux/drivers/ieee1394/ieee1394_core.h Mon Mar 27 08:08:24 2000 +++ linux/drivers/ieee1394/ieee1394_core.h Wed Jul 5 13:03:56 2000 @@ -52,8 +52,7 @@ * overwritten to allow in-place byte swapping. Neither of these is * CRCed (the sizes also don't include CRC), but contain space for at * least one additional quadlet to allow in-place CRCing. The memory is - * also guaranteed to have physical mapping (virt_to_bus() is meaningful - * on these pointers). + * also guaranteed to be DMA mappable. */ quadlet_t *header; quadlet_t *data; @@ -145,7 +144,12 @@ * immediately), with the header (i.e. the first four quadlets) in machine byte * order and the data block in big endian. *data can be safely overwritten * after this call. + * + * If the packet is a write request, write_acked is to be set to true if it was + * ack_complete'd already, false otherwise. This arg is ignored for any other + * packet type. */ -void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size); +void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, + int write_acked); #endif /* _IEEE1394_CORE_H */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/ieee1394_syms.c linux/drivers/ieee1394/ieee1394_syms.c --- v2.4.0-test2/linux/drivers/ieee1394/ieee1394_syms.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/ieee1394/ieee1394_syms.c Wed Jul 5 13:03:56 2000 @@ -4,6 +4,9 @@ * Exported symbols for module usage. * * Copyright (C) 1999 Andreas E. Bombe + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. */ #include diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/ieee1394_transactions.c linux/drivers/ieee1394/ieee1394_transactions.c --- v2.4.0-test2/linux/drivers/ieee1394/ieee1394_transactions.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/ieee1394/ieee1394_transactions.c Wed Jul 5 13:03:56 2000 @@ -4,6 +4,9 @@ * Transaction support. * * Copyright (C) 1999 Andreas E. Bombe + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. */ #include @@ -152,38 +155,58 @@ * Return value: The allocated transaction label or -1 if there was no free * tlabel and @wait is false. */ +static int __get_tlabel(struct hpsb_host *host, nodeid_t nodeid) +{ + int tlabel; + + if (host->tlabel_count) { + host->tlabel_count--; + + if (host->tlabel_pool[0] != ~0) { + tlabel = ffz(host->tlabel_pool[0]); + host->tlabel_pool[0] |= 1 << tlabel; + } else { + tlabel = ffz(host->tlabel_pool[1]); + host->tlabel_pool[1] |= 1 << tlabel; + tlabel += 32; + } + return tlabel; + } + return -1; +} + int get_tlabel(struct hpsb_host *host, nodeid_t nodeid, int wait) { unsigned long flags; int tlabel; + wait_queue_t wq; - while (1) { - spin_lock_irqsave(&host->tlabel_lock, flags); + spin_lock_irqsave(&host->tlabel_lock, flags); - if (host->tlabel_count) { - host->tlabel_count--; + tlabel = __get_tlabel(host, nodeid); + if (tlabel != -1 || !wait) { + spin_unlock_irqrestore(&host->tlabel_lock, flags); + return tlabel; + } + + init_waitqueue_entry(&wq, current); + add_wait_queue(&host->tlabel_wait, &wq); + + for (;;) { + set_current_state(TASK_UNINTERRUPTIBLE); + tlabel = __get_tlabel(host, nodeid); + if (tlabel != -1) break; + + spin_unlock_irqrestore(&host->tlabel_lock, flags); + schedule(); + spin_lock_irqsave(&host->tlabel_lock, flags); + } + + spin_unlock_irqrestore(&host->tlabel_lock, flags); + set_current_state(TASK_RUNNING); + remove_wait_queue(&host->tlabel_wait, &wq); - if (host->tlabel_pool[0] != ~0) { - tlabel = ffz(host->tlabel_pool[0]); - host->tlabel_pool[0] |= 1 << tlabel; - } else { - tlabel = ffz(host->tlabel_pool[1]); - host->tlabel_pool[1] |= 1 << tlabel; - tlabel += 32; - } - - spin_unlock_irqrestore(&host->tlabel_lock, flags); - return tlabel; - } - - spin_unlock_irqrestore(&host->tlabel_lock, flags); - - if (wait) { - sleep_on(&host->tlabel_wait); - } else { - return -1; - } - } + return tlabel; } /** diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/ieee1394_types.h linux/drivers/ieee1394/ieee1394_types.h --- v2.4.0-test2/linux/drivers/ieee1394/ieee1394_types.h Fri Jun 23 21:55:09 2000 +++ linux/drivers/ieee1394/ieee1394_types.h Wed Jul 5 13:03:56 2000 @@ -11,15 +11,23 @@ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) +#include #define DECLARE_WAITQUEUE(name, task) struct wait_queue name = { task, NULL } typedef struct wait_queue *wait_queue_head_t; +typedef struct wait_queue wait_queue_t; inline static void init_waitqueue_head(wait_queue_head_t *wh) { *wh = NULL; } +inline static void init_waitqueue_entry(wait_queue_t *wq, struct task_struct *p) +{ + wq->task = p; + wq->next = NULL; +} + static __inline__ void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); @@ -30,6 +38,22 @@ #define set_current_state(state_value) \ do { current->state = (state_value); } while (0) + +#include +/* Pure 2^n version of get_order */ +extern __inline__ int get_order(unsigned long size) +{ + int order; + size = (size-1) >> (PAGE_SHIFT-1); + order = -1; + do { + size >>= 1; + order++; + } while (size); + return order; +} + + #include inline static int pci_enable_device(struct pci_dev *dev) { @@ -39,8 +63,134 @@ return 0; } +#define PCI_DMA_BIDIRECTIONAL 0 +#define PCI_DMA_TODEVICE 1 +#define PCI_DMA_FROMDEVICE 2 +#define PCI_DMA_NONE 3 +#define PCI_ROM_RESOURCE 6 +#define pci_resource_start(dev, bar) ((bar) == PCI_ROM_RESOURCE \ + ? (dev)->rom_address \ + : (dev)->base_address[(bar)]) +#define BUG() *(int *)0 = 0 + +#include +typedef u32 dma_addr_t; + +extern inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) +{ + return 1; +} + +extern inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t *dma_handle) +{ + void *ret; + ret = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)); + if (ret) { + memset(ret, 0, size); + *dma_handle = virt_to_bus(ret); + } + return ret; +} + +extern inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + free_pages((unsigned long)vaddr, get_order(size)); +} + +extern inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, + size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); + return virt_to_bus(ptr); +} + +extern inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, + size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); +} + +struct scatterlist {}; +extern inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nents, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); + return nents; +} + +extern inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nents, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); +} + +extern inline void pci_dma_sync_single(struct pci_dev *hwdev, + dma_addr_t dma_handle, + size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); +} + +extern inline void pci_dma_sync_sg(struct pci_dev *hwdev, + struct scatterlist *sg, + int nelems, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); +} + + +#ifndef _LINUX_DEVFS_FS_KERNEL_H +typedef struct devfs_entry * devfs_handle_t; +#define DEVFS_FL_NONE 0 + +static inline devfs_handle_t devfs_register (devfs_handle_t dir, + const char *name, + unsigned int flags, + unsigned int major, + unsigned int minor, + umode_t mode, + void *ops, void *info) +{ + return NULL; +} +static inline void devfs_unregister (devfs_handle_t de) +{ + return; +} +static inline int devfs_register_chrdev (unsigned int major, const char *name, + struct file_operations *fops) +{ + return register_chrdev (major, name, fops); +} +static inline int devfs_unregister_chrdev (unsigned int major,const char *name) +{ + return unregister_chrdev (major, name); +} +#endif /* _LINUX_DEVFS_FS_KERNEL_H */ + + +#define V22_COMPAT_MOD_INC_USE_COUNT MOD_INC_USE_COUNT +#define V22_COMPAT_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT +#define OWNER_THIS_MODULE + +#else /* Linux version < 2.3 */ + +#define V22_COMPAT_MOD_INC_USE_COUNT do {} while (0) +#define V22_COMPAT_MOD_DEC_USE_COUNT do {} while (0) +#define OWNER_THIS_MODULE owner: THIS_MODULE, + #endif /* Linux version < 2.3 */ + + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) #include #else @@ -55,9 +205,9 @@ #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif -typedef __u32 quadlet_t; -typedef __u64 octlet_t; -typedef __u16 nodeid_t; +typedef u32 quadlet_t; +typedef u64 octlet_t; +typedef u16 nodeid_t; #define BUS_MASK 0xffc0 #define NODE_MASK 0x003f diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/ohci1394.c linux/drivers/ieee1394/ohci1394.c --- v2.4.0-test2/linux/drivers/ieee1394/ohci1394.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/ieee1394/ohci1394.c Wed Jul 5 13:03:56 2000 @@ -25,10 +25,10 @@ * . Async Request Receive * . Async Response Transmit * . Iso Receive + * . DMA mmap for iso receive * * Things not implemented: * . Iso Transmit - * . DMA to user's space in iso receive mode * . DMA error recovery * * Things to be fixed: @@ -38,7 +38,6 @@ * . Self-id are sometimes not received properly * if card is initialized with no other nodes * on the bus - * . SONY CXD3222 chip is not working properly * . Apple PowerBook detected but not working yet */ @@ -56,7 +55,7 @@ * Albrecht Dress * . Apple PowerBook detection * Daniel Kobras - * . Reset the board properly before leaving + * . Reset the board properly before leaving + misc cleanups */ #include @@ -130,6 +129,8 @@ { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_UPD72870 }, { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_UPD72871 }, { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_FW }, + { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_ALI_OHCI1394_M5251 }, + { PCI_VENDOR_ID_LUCENT, PCI_DEVICE_ID_LUCENT_FW323 }, { -1, -1 } }; @@ -142,617 +143,6 @@ static void dma_trm_bh(void *data); static void dma_rcv_bh(void *data); static void dma_trm_reset(struct dma_trm_ctx *d); -static void stop_context(struct ti_ohci *ohci, int reg, char *msg); - -#ifdef _VIDEO_1394_H - -/* Taken from bttv.c */ -/*******************************/ -/* Memory management functions */ -/*******************************/ - -#define MDEBUG(x) do { } while(0) /* Debug memory management */ - -/* [DaveM] I've recoded most of this so that: - * 1) It's easier to tell what is happening - * 2) It's more portable, especially for translating things - * out of vmalloc mapped areas in the kernel. - * 3) Less unnecessary translations happen. - * - * The code used to assume that the kernel vmalloc mappings - * existed in the page tables of every process, this is simply - * not guarenteed. We now use pgd_offset_k which is the - * defined way to get at the kernel page tables. - */ - -/* Given PGD from the address space's page table, return the kernel - * virtual mapping of the physical memory mapped at ADR. - */ -static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) -{ - unsigned long ret = 0UL; - pmd_t *pmd; - pte_t *ptep, pte; - - if (!pgd_none(*pgd)) { - pmd = pmd_offset(pgd, adr); - if (!pmd_none(*pmd)) { - ptep = pte_offset(pmd, adr); - pte = *ptep; - if(pte_present(pte)) - ret = (pte_page(pte)|(adr&(PAGE_SIZE-1))); - } - } - MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); - return ret; -} - -static inline unsigned long uvirt_to_bus(unsigned long adr) -{ - unsigned long kva, ret; - - kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr); - ret = virt_to_bus((void *)kva); - MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret)); - return ret; -} - -static inline unsigned long kvirt_to_bus(unsigned long adr) -{ - unsigned long va, kva, ret; - - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); - ret = virt_to_bus((void *)kva); - MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret)); - return ret; -} - -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the - * area and marking the pages as reserved. - */ -static inline unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long va, kva, ret; - - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); - ret = __pa(kva); - MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret)); - return ret; -} - -static void * rvmalloc(unsigned long size) -{ - void * mem; - unsigned long adr, page; - - mem=vmalloc(size); - if (mem) - { - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr=(unsigned long) mem; - while (size > 0) - { - page = kvirt_to_pa(adr); - mem_map_reserve(MAP_NR(__va(page))); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } - } - return mem; -} - -static void rvfree(void * mem, unsigned long size) -{ - unsigned long adr, page; - - if (mem) - { - adr=(unsigned long) mem; - while (size > 0) - { - page = kvirt_to_pa(adr); - mem_map_unreserve(MAP_NR(__va(page))); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } - vfree(mem); - } -} - -static int free_dma_fbuf_ctx(struct dma_fbuf_ctx **d) -{ - int i; - struct ti_ohci *ohci; - - if ((*d)==NULL) return -1; - - ohci = (struct ti_ohci *)(*d)->ohci; - - DBGMSG(ohci->id, "Freeing dma_fbuf_ctx %d", (*d)->ctx); - - stop_context(ohci, (*d)->ctrlClear, NULL); - - if ((*d)->buf) rvfree((void *)(*d)->buf, - (*d)->num_desc * (*d)->buf_size); - - if ((*d)->prg) { - for (i=0;i<(*d)->num_desc;i++) - if ((*d)->prg[i]) kfree((*d)->prg[i]); - kfree((*d)->prg); - } - - if ((*d)->buffer_status) - kfree((*d)->buffer_status); - - kfree(*d); - *d = NULL; - - return 0; -} - -static struct dma_fbuf_ctx * -alloc_dma_fbuf_ctx(struct ti_ohci *ohci, int ctx, int num_desc, - int buf_size, int channel) -{ - struct dma_fbuf_ctx *d=NULL; - int i; - - d = (struct dma_fbuf_ctx *)kmalloc(sizeof(struct dma_fbuf_ctx), - GFP_KERNEL); - - if (d==NULL) { - PRINT(KERN_ERR, ohci->id, "failed to allocate dma_fbuf_ctx"); - return NULL; - } - - d->ohci = (void *)ohci; - d->ctx = ctx; - d->channel = channel; - d->num_desc = num_desc; - d->frame_size = buf_size; - if (buf_size%PAGE_SIZE) - d->buf_size = buf_size + PAGE_SIZE - (buf_size%PAGE_SIZE); - else - d->buf_size = buf_size; - d->ctrlSet = OHCI1394_IrRcvContextControlSet+32*d->ctx; - d->ctrlClear = OHCI1394_IrRcvContextControlClear+32*d->ctx; - d->cmdPtr = OHCI1394_IrRcvCommandPtr+32*d->ctx; - d->ctxMatch = OHCI1394_IrRcvContextMatch+32*d->ctx; - d->nb_cmd = d->buf_size / PAGE_SIZE + 1; - d->last_buffer = 0; - d->buf = NULL; - d->prg = NULL; - init_waitqueue_head(&d->waitq); - - d->buf = rvmalloc(d->num_desc * d->buf_size); - - if (d->buf == NULL) { - PRINT(KERN_ERR, ohci->id, "failed to allocate dma fbuffer"); - free_dma_fbuf_ctx(&d); - return NULL; - } - memset(d->buf, 0, d->num_desc * d->buf_size); - - d->prg = kmalloc(d->num_desc * sizeof(struct dma_cmd *), - GFP_KERNEL); - - if (d->prg == NULL) { - PRINT(KERN_ERR, ohci->id, "failed to allocate dma fbuf prg"); - free_dma_fbuf_ctx(&d); - return NULL; - } - memset(d->prg, 0, d->num_desc * sizeof(struct dma_cmd *)); - - for (i=0;inum_desc;i++) { - d->prg[i] = kmalloc(d->nb_cmd * sizeof(struct dma_cmd), - GFP_KERNEL); - if (d->prg[i] == NULL) { - PRINT(KERN_ERR, ohci->id, - "failed to allocate dma fbuf prg"); - free_dma_fbuf_ctx(&d); - return NULL; - } - } - - d->buffer_status = kmalloc(d->num_desc * sizeof(unsigned int), - GFP_KERNEL); - - if (d->buffer_status == NULL) { - PRINT(KERN_ERR, ohci->id, "failed to allocate dma fbuf prg"); - free_dma_fbuf_ctx(&d); - return NULL; - } - memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int)); - - PRINT(KERN_INFO, ohci->id, "Iso DMA to User's Space: %d buffers " - "of size %d allocated for a frame size %d, each with %d prgs", - d->num_desc, d->buf_size, d->frame_size, d->nb_cmd); - - return d; -} - -static void initialize_dma_fbuf_prg(struct dma_cmd *prg, int n, - int frame_size, unsigned long buf) -{ - int i; - int leftsize = (frame_size%PAGE_SIZE) ? - frame_size%PAGE_SIZE : PAGE_SIZE; - - /* the first descriptor will sync and read only 4 bytes */ - prg[0].control = (0x280F << 16) | 4; - prg[0].address = kvirt_to_bus(buf); - prg[0].branchAddress = (virt_to_bus(&(prg[1].control)) - & 0xfffffff0) | 0x1; - prg[0].status = 0; - - /* the second descriptor will read PAGE_SIZE-4 bytes */ - prg[1].control = (0x280C << 16) | (PAGE_SIZE-4); - prg[1].address = kvirt_to_bus(buf+4); - prg[1].branchAddress = (virt_to_bus(&(prg[2].control)) - & 0xfffffff0) | 0x1; - prg[1].status = 0; - - for (i=2;iohci; - int i; - - stop_context(ohci, d->ctrlClear, NULL); - - for (i=0;inum_desc;i++) { - initialize_dma_fbuf_prg(d->prg[i], d->nb_cmd, d->frame_size, - (unsigned long)d->buf+i*d->buf_size); - } - - /* Set bufferFill, no header */ - reg_write(ohci, d->ctrlSet, 0x80000000); - - /* Set the context match register to match on all tags, - sync for sync tag, and listen to d->channel */ - reg_write(ohci, d->ctxMatch, 0xf0000000|((tag&0xf)<<8)|d->channel); - - /* Set up isoRecvIntMask to generate interrupts */ - reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1<ctx); -} - -/* find which context is listening to this channel */ -int fbuf_ctx_listening(struct ti_ohci *ohci, int channel) -{ - int i; - for (i=0;inb_iso_ctx-1;i++) - if (ohci->fbuf_context[i]) { - if (ohci->fbuf_context[i]->channel==channel) - return i; - } - - PRINT(KERN_ERR, ohci->id, - "no iso context is listening to channel %d", - channel); - return -1; -} - -static int ohci_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct ti_ohci *ohci=&cards[MINOR(inode->i_rdev)]; - - switch(cmd) - { - case VIDEO1394_LISTEN_CHANNEL: - { - struct video1394_mmap v; - int i; - - if(copy_from_user(&v, (void *)arg, sizeof(v))) - return -EFAULT; - if (v.channel<0 || v.channel>(ISO_CHANNELS-1)) { - PRINT(KERN_ERR, ohci->id, - "iso channel %d out of bound", v.channel); - return -EFAULT; - } - if (test_and_set_bit(v.channel, &ohci->IR_channel_usage)) { - PRINT(KERN_ERR, ohci->id, - "channel %d is already taken", v.channel); - return -EFAULT; - } - - /* find a free iso context */ - for (i=0;inb_iso_ctx-1;i++) - if (ohci->fbuf_context[i]==NULL) break; - - if (i==(ohci->nb_iso_ctx-1)) { - PRINT(KERN_ERR, ohci->id, "no iso context available"); - return -EFAULT; - } - - if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) { - PRINT(KERN_ERR, ohci->id, - "%d buffers of size %d bytes is too big", - v.nb_buffers, v.buf_size); - return -EFAULT; - } - - ohci->fbuf_context[i] = - alloc_dma_fbuf_ctx(ohci, i+1, v.nb_buffers, - v.buf_size, v.channel); - - if (ohci->fbuf_context[i] == NULL) { - PRINT(KERN_ERR, ohci->id, - "Couldn't allocate fbuf context"); - return -EFAULT; - } - initialize_dma_fbuf_ctx(ohci->fbuf_context[i], v.sync_tag); - - ohci->current_fbuf_ctx = ohci->fbuf_context[i]; - - v.buf_size = ohci->fbuf_context[i]->buf_size; - - PRINT(KERN_INFO, ohci->id, - "iso context %d listen on channel %d", i+1, - v.channel); - - if(copy_to_user((void *)arg, &v, sizeof(v))) - return -EFAULT; - - return 0; - } - case VIDEO1394_UNLISTEN_CHANNEL: - { - int channel; - int i; - - if(copy_from_user(&channel, (void *)arg, sizeof(int))) - return -EFAULT; - - if (!test_and_clear_bit(channel, &ohci->IR_channel_usage)) { - PRINT(KERN_ERR, ohci->id, - "channel %d is not being used", channel); - return -EFAULT; - } - - i = fbuf_ctx_listening(ohci, channel); - if (i<0) return -EFAULT; - - free_dma_fbuf_ctx(&ohci->fbuf_context[i]); - - PRINT(KERN_INFO, ohci->id, - "iso context %d stop listening on channel %d", - i+1, channel); - - return 0; - } - case VIDEO1394_QUEUE_BUFFER: - { - struct video1394_wait v; - struct dma_fbuf_ctx *d; - int i; - - if(copy_from_user(&v, (void *)arg, sizeof(v))) - return -EFAULT; - - i = fbuf_ctx_listening(ohci, v.channel); - if (i<0) return -EFAULT; - d = ohci->fbuf_context[i]; - - if ((v.buffer<0) || (v.buffer>d->num_desc)) { - PRINT(KERN_ERR, ohci->id, - "buffer %d out of range",v.buffer); - return -EFAULT; - } - - if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) { - PRINT(KERN_ERR, ohci->id, - "buffer %d is already used",v.buffer); - return -EFAULT; - } - - d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED; - - d->prg[d->last_buffer][d->nb_cmd-1].branchAddress = - (virt_to_bus(&(d->prg[v.buffer][0].control)) - & 0xfffffff0) | 0x1; - - d->last_buffer = v.buffer; - - if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) - { - DBGMSG(ohci->id, "Starting iso DMA ctx=%d",d->ctx); - - /* Tell the controller where the first program is */ - reg_write(ohci, d->cmdPtr, - virt_to_bus(&(d->prg[v.buffer][0])) | 0x1 ); - - /* Run IR context */ - reg_write(ohci, d->ctrlSet, 0x8000); - } - else { - /* Wake up dma context if necessary */ - if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { - PRINT(KERN_INFO, ohci->id, - "Waking up iso dma ctx=%d", d->ctx); - reg_write(ohci, d->ctrlSet, 0x1000); - } - } - return 0; - - } - case VIDEO1394_WAIT_BUFFER: - { - struct video1394_wait v; - struct dma_fbuf_ctx *d; - int i; - - if(copy_from_user(&v, (void *)arg, sizeof(v))) - return -EFAULT; - - i = fbuf_ctx_listening(ohci, v.channel); - if (i<0) return -EFAULT; - d = ohci->fbuf_context[i]; - - if ((v.buffer<0) || (v.buffer>d->num_desc)) { - PRINT(KERN_ERR, ohci->id, - "buffer %d out of range",v.buffer); - return -EFAULT; - } - - switch(d->buffer_status[v.buffer]) { - case VIDEO1394_BUFFER_READY: - d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; - return 0; - case VIDEO1394_BUFFER_QUEUED: - while(d->buffer_status[v.buffer]!= - VIDEO1394_BUFFER_READY) { - interruptible_sleep_on(&d->waitq); - if(signal_pending(current)) return -EINTR; - } - d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; - return 0; - default: - PRINT(KERN_ERR, ohci->id, - "buffer %d is not queued",v.buffer); - return -EFAULT; - } - } - default: - return -EINVAL; - } -} - -/* - * This maps the vmalloced and reserved fbuffer to user space. - * - * FIXME: - * - PAGE_READONLY should suffice!? - * - remap_page_range is kind of inefficient for page by page remapping. - * But e.g. pte_alloc() does not work in modules ... :-( - */ - -static int do_fbuf_mmap(struct ti_ohci *ohci, struct dma_fbuf_ctx *d, - const char *adr, unsigned long size) -{ - unsigned long start=(unsigned long) adr; - unsigned long page,pos; - - if (size>d->num_desc * d->buf_size) { - PRINT(KERN_ERR, ohci->id, - "fbuf context %d buf size is different from mmap size", - d->ctx); - return -EINVAL; - } - if (!d->buf) { - PRINT(KERN_ERR, ohci->id, - "fbuf context %d is not allocated", d->ctx); - return -EINVAL; - } - - pos=(unsigned long) d->buf; - while (size > 0) { - page = kvirt_to_pa(pos); - if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - start+=PAGE_SIZE; - pos+=PAGE_SIZE; - size-=PAGE_SIZE; - } - return 0; -} - -int ohci_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct ti_ohci *ohci=&cards[MINOR(file->f_dentry->d_inode->i_rdev)]; - PRINT(KERN_INFO, ohci->id, "mmap"); - if (ohci->current_fbuf_ctx == NULL) { - PRINT(KERN_ERR, ohci->id, "current fbuf context not set"); - return -EINVAL; - } - - return do_fbuf_mmap(ohci, ohci->current_fbuf_ctx, - (char *)vma->vm_start, - (unsigned long)(vma->vm_end-vma->vm_start)); - return 0; -} - -static int ohci_open(struct inode *inode, struct file *file) -{ - struct ti_ohci *ohci=&cards[MINOR(inode->i_rdev)]; - PRINT(KERN_INFO, ohci->id, "open"); - return 0; -} - -static int ohci_release(struct inode *inode, struct file *file) -{ - struct ti_ohci *ohci=&cards[MINOR(inode->i_rdev)]; - int i; - - PRINT(KERN_INFO, ohci->id, "release"); - for (i=0;inb_iso_ctx-1;i++) - if (ohci->fbuf_context[i]) { - if (!test_and_clear_bit(ohci->fbuf_context[i]->channel, - &ohci->IR_channel_usage)) { - PRINT(KERN_ERR, ohci->id, - "channel %d is not being used", - ohci->fbuf_context[i]->channel); - } - PRINT(KERN_INFO, ohci->id, - "iso context %d stop listening on channel %d", - i+1, ohci->fbuf_context[i]->channel); - free_dma_fbuf_ctx(&ohci->fbuf_context[i]); - } - return 0; -} - -static struct file_operations ohci_fops= -{ - owner: THIS_MODULE, - ioctl: ohci_ioctl, - mmap: ohci_mmap, - open: ohci_open, - release: ohci_release -}; - -int wakeup_dma_fbuf_ctx(struct ti_ohci *ohci, struct dma_fbuf_ctx *d) -{ - int i; - - if (d==NULL) { - PRINT(KERN_ERR, ohci->id, "Iso receive event received but " - "context not allocated"); - return -EFAULT; - } - - for (i=0;inum_desc;i++) { - if (d->prg[i][d->nb_cmd-1].status) { - d->prg[i][d->nb_cmd-1].status=0; - d->buffer_status[i] = VIDEO1394_BUFFER_READY; - } - } - if (waitqueue_active(&d->waitq)) wake_up_interruptible(&d->waitq); - return 0; -} - -#endif - - /*********************************** * IEEE-1394 functionality section * @@ -827,14 +217,14 @@ inline static int handle_selfid(struct ti_ohci *ohci, struct hpsb_host *host, int phyid, int isroot) { - quadlet_t *q = ohci->self_id_buffer; + quadlet_t *q = ohci->selfid_buf_cpu; quadlet_t self_id_count=reg_read(ohci, OHCI1394_SelfIDCount); size_t size; quadlet_t lsid; /* Self-id handling seems much easier than for the aic5800 chip. All the self-id packets, including this device own self-id, - should be correctly arranged in the self_id_buffer at this + should be correctly arranged in the selfid buffer at this stage */ /* Check status of self-id reception */ @@ -952,55 +342,36 @@ return 0; } -static void stop_context(struct ti_ohci *ohci, int reg, char *msg) -{ - int i=0; - - /* stop the channel program if it's still running */ - reg_write(ohci, reg, 0x8000); - - /* Wait until it effectively stops */ - while (reg_read(ohci, reg) & 0x400) { - i++; - if (i>5000) { - PRINT(KERN_ERR, ohci->id, - "runaway loop while stopping context..."); - break; - } - } - if (msg) PRINT(KERN_ERR, ohci->id, "%s\n dma prg stopped\n", msg); -} - /* Generate the dma receive prgs and start the context */ static void initialize_dma_rcv_ctx(struct dma_rcv_ctx *d) { struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); int i; - stop_context(ohci, d->ctrlClear, NULL); + ohci1394_stop_context(ohci, d->ctrlClear, NULL); for (i=0; inum_desc; i++) { /* end of descriptor list? */ if ((i+1) < d->num_desc) { - d->prg[i]->control = (0x283C << 16) | d->buf_size; - d->prg[i]->branchAddress = - (virt_to_bus(d->prg[i+1]) & 0xfffffff0) | 0x1; + d->prg_cpu[i]->control = (0x283C << 16) | d->buf_size; + d->prg_cpu[i]->branchAddress = + (d->prg_bus[i+1] & 0xfffffff0) | 0x1; } else { - d->prg[i]->control = (0x283C << 16) | d->buf_size; - d->prg[i]->branchAddress = - (virt_to_bus(d->prg[0]) & 0xfffffff0); + d->prg_cpu[i]->control = (0x283C << 16) | d->buf_size; + d->prg_cpu[i]->branchAddress = + d->prg_bus[0] & 0xfffffff0; } - d->prg[i]->address = virt_to_bus(d->buf[i]); - d->prg[i]->status = d->buf_size; + d->prg_cpu[i]->address = d->buf_bus[i]; + d->prg_cpu[i]->status = d->buf_size; } d->buf_ind = 0; d->buf_offset = 0; /* Tell the controller where the first AR program is */ - reg_write(ohci, d->cmdPtr, virt_to_bus(d->prg[0]) | 0x1); + reg_write(ohci, d->cmdPtr, d->prg_bus[0] | 0x1); /* Run AR context */ reg_write(ohci, d->ctrlSet, 0x00008000); @@ -1014,26 +385,30 @@ struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); /* Stop the context */ - stop_context(ohci, d->ctrlClear, NULL); + ohci1394_stop_context(ohci, d->ctrlClear, NULL); d->prg_ind = 0; d->sent_ind = 0; d->free_prgs = d->num_desc; d->branchAddrPtr = NULL; - d->first = NULL; - d->last = NULL; + d->fifo_first = NULL; + d->fifo_last = NULL; + d->pending_first = NULL; + d->pending_last = NULL; PRINT(KERN_INFO, ohci->id, "AT dma ctx=%d initialized", d->ctx); } /* Count the number of available iso contexts */ -static int get_nb_iso_ctx(struct ti_ohci *ohci) +static int get_nb_iso_ctx(struct ti_ohci *ohci, int reg) { int i,ctx=0; u32 tmp; - reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 0xffffffff); - tmp = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet); + reg_write(ohci, reg, 0xffffffff); + tmp = reg_read(ohci, reg); + + DBGMSG(ohci->id,"Iso contexts reg: %08x implemented: %08x", reg, tmp); /* Count the number of contexts */ for(i=0; i<32; i++) { @@ -1062,7 +437,7 @@ if ((retval=ohci_soft_reset(ohci))<0) return retval; /* - *Delay aftger soft reset to make sure everything has settled + * Delay after soft reset to make sure everything has settled * down (sanity) */ mdelay(100); @@ -1089,31 +464,33 @@ reg_write(ohci, OHCI1394_LinkControlSet, 0x00300000); /* Clear interrupt registers */ - reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); + reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); /* Set up self-id dma buffer */ - reg_write(ohci, OHCI1394_SelfIDBuffer, - virt_to_bus(ohci->self_id_buffer)); + reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus); /* enable self-id dma */ reg_write(ohci, OHCI1394_LinkControlSet, 0x00000200); /* Set the configuration ROM mapping register */ - reg_write(ohci, OHCI1394_ConfigROMmap, - virt_to_bus(ohci->csr_config_rom)); - - /* Write the config ROM header */ - reg_write(ohci, OHCI1394_ConfigROMhdr, - cpu_to_be32(ohci->csr_config_rom[0])); + reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus); /* Set bus options */ reg_write(ohci, OHCI1394_BusOptions, - cpu_to_be32(ohci->csr_config_rom[2])); - + cpu_to_be32(ohci->csr_config_rom_cpu[2])); + +#if 0 /* Write the GUID into the csr config rom */ - ohci->csr_config_rom[3] = be32_to_cpu(reg_read(ohci, OHCI1394_GUIDHi)); - ohci->csr_config_rom[4] = be32_to_cpu(reg_read(ohci, OHCI1394_GUIDLo)); + ohci->csr_config_rom_cpu[3] = + be32_to_cpu(reg_read(ohci, OHCI1394_GUIDHi)); + ohci->csr_config_rom_cpu[4] = + be32_to_cpu(reg_read(ohci, OHCI1394_GUIDLo)); +#endif + + /* Write the config ROM header */ + reg_write(ohci, OHCI1394_ConfigROMhdr, + cpu_to_be32(ohci->csr_config_rom_cpu[0])); ohci->max_packet_size = 1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1); @@ -1124,39 +501,56 @@ reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400); /* Initialize IR dma */ - ohci->nb_iso_ctx = get_nb_iso_ctx(ohci); - PRINT(KERN_INFO, ohci->id, "%d iso contexts available", - ohci->nb_iso_ctx); - for (i=0;inb_iso_ctx;i++) { - reg_write(ohci, OHCI1394_IrRcvContextControlClear+32*i, + ohci->nb_iso_rcv_ctx = + get_nb_iso_ctx(ohci, OHCI1394_IsoRecvIntMaskSet); + PRINT(KERN_INFO, ohci->id, "%d iso receive contexts available", + ohci->nb_iso_rcv_ctx); + for (i=0;inb_iso_rcv_ctx;i++) { + reg_write(ohci, OHCI1394_IsoRcvContextControlClear+32*i, 0xffffffff); - reg_write(ohci, OHCI1394_IrRcvContextMatch+32*i, 0); - reg_write(ohci, OHCI1394_IrRcvCommandPtr+32*i, 0); + reg_write(ohci, OHCI1394_IsoRcvContextMatch+32*i, 0); + reg_write(ohci, OHCI1394_IsoRcvCommandPtr+32*i, 0); } -#ifdef _VIDEO_1394_H - ohci->fbuf_context = (struct dma_fbuf_ctx **) - kmalloc((ohci->nb_iso_ctx-1)*sizeof(struct dma_fbuf_ctx *), - GFP_KERNEL); - if (ohci->fbuf_context) - memset(ohci->fbuf_context, 0, - (ohci->nb_iso_ctx-1)*sizeof(struct dma_fbuf_ctx *)); - else { - PRINT(KERN_ERR, ohci->id, "Cannot allocate fbuf_context"); - return -1; - } -#endif + /* Set bufferFill, isochHeader, multichannel for IR context */ - reg_write(ohci, OHCI1394_IrRcvContextControlSet, 0xd0000000); + reg_write(ohci, OHCI1394_IsoRcvContextControlSet, 0xd0000000); /* Set the context match register to match on all tags */ - reg_write(ohci, OHCI1394_IrRcvContextMatch, 0xf0000000); + reg_write(ohci, OHCI1394_IsoRcvContextMatch, 0xf0000000); + + /* Clear the interrupt mask */ + reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); + reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); + + /* Initialize IT dma */ + ohci->nb_iso_xmit_ctx = + get_nb_iso_ctx(ohci, OHCI1394_IsoXmitIntMaskSet); + PRINT(KERN_INFO, ohci->id, "%d iso transmit contexts available", + ohci->nb_iso_xmit_ctx); + for (i=0;inb_iso_xmit_ctx;i++) { + reg_write(ohci, OHCI1394_IsoXmitContextControlClear+32*i, + 0xffffffff); + reg_write(ohci, OHCI1394_IsoXmitCommandPtr+32*i, 0); + } + + /* Clear the interrupt mask */ + reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff); + reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff); + + /* Clear the multi channel mask high and low registers */ + reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff); + reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff); + + /* Initialize AR dma */ + initialize_dma_rcv_ctx(ohci->ar_req_context); + initialize_dma_rcv_ctx(ohci->ar_resp_context); - /* Clear the multi channel mask high and low registers */ - reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff); - reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff); + /* Initialize AT dma */ + initialize_dma_trm_ctx(ohci->at_req_context); + initialize_dma_trm_ctx(ohci->at_resp_context); - /* Clear the interrupt mask */ - reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); + /* Initialize IR dma */ + initialize_dma_rcv_ctx(ohci->ir_context); /* Set up isoRecvIntMask to generate interrupts for context 0 (thanks to Michael Greger for seeing that I forgot this) */ @@ -1193,23 +587,13 @@ OHCI1394_ARRQ | OHCI1394_respTxComplete | OHCI1394_reqTxComplete | - OHCI1394_isochRx + OHCI1394_isochRx | + OHCI1394_isochTx ); /* Enable link */ reg_write(ohci, OHCI1394_HCControlSet, 0x00020000); - /* Initialize AR dma */ - initialize_dma_rcv_ctx(ohci->ar_req_context); - initialize_dma_rcv_ctx(ohci->ar_resp_context); - - /* Initialize AT dma */ - initialize_dma_trm_ctx(ohci->at_req_context); - initialize_dma_trm_ctx(ohci->at_resp_context); - - /* Initialize IR dma */ - initialize_dma_rcv_ctx(ohci->ir_context); - return 1; } @@ -1223,74 +607,132 @@ } } -/* Insert a packet in the AT DMA fifo and generate the DMA prg */ +/* + * Insert a packet in the AT DMA fifo and generate the DMA prg + * FIXME: rewrite the program in order to accept packets crossing + * page boundaries. + * check also that a single dma descriptor doesn't cross a + * page boundary. + */ static void insert_packet(struct ti_ohci *ohci, struct dma_trm_ctx *d, struct hpsb_packet *packet) { u32 cycleTimer; int idx = d->prg_ind; - d->prg[idx].begin.address = 0; - d->prg[idx].begin.branchAddress = 0; + d->prg_cpu[idx]->begin.address = 0; + d->prg_cpu[idx]->begin.branchAddress = 0; if (d->ctx==1) { /* * For response packets, we need to put a timeout value in * the 16 lower bits of the status... let's try 1 sec timeout */ cycleTimer = reg_read(ohci, OHCI1394_IsochronousCycleTimer); - d->prg[idx].begin.status = + d->prg_cpu[idx]->begin.status = (((((cycleTimer>>25)&0x7)+1)&0x7)<<13) | ((cycleTimer&0x01fff000)>>12); DBGMSG(ohci->id, "cycleTimer: %08x timeStamp: %08x", - cycleTimer, d->prg[idx].begin.status); + cycleTimer, d->prg_cpu[idx]->begin.status); } else - d->prg[idx].begin.status = 0; + d->prg_cpu[idx]->begin.status = 0; - d->prg[idx].data[0] = packet->speed_code<<16 | + d->prg_cpu[idx]->data[0] = packet->speed_code<<16 | (packet->header[0] & 0xFFFF); - d->prg[idx].data[1] = (packet->header[1] & 0xFFFF) | + d->prg_cpu[idx]->data[1] = (packet->header[1] & 0xFFFF) | (packet->header[0] & 0xFFFF0000); - d->prg[idx].data[2] = packet->header[2]; - d->prg[idx].data[3] = packet->header[3]; + d->prg_cpu[idx]->data[2] = packet->header[2]; + d->prg_cpu[idx]->data[3] = packet->header[3]; if (packet->data_size) { /* block transmit */ - d->prg[idx].begin.control = OUTPUT_MORE_IMMEDIATE | 0x10; - d->prg[idx].end.control = OUTPUT_LAST | packet->data_size; - d->prg[idx].end.address = virt_to_bus(packet->data); - d->prg[idx].end.branchAddress = 0; - d->prg[idx].end.status = 0x4000; + d->prg_cpu[idx]->begin.control = OUTPUT_MORE_IMMEDIATE | 0x10; + d->prg_cpu[idx]->end.control = OUTPUT_LAST | packet->data_size; + /* + * FIXME: check that the packet data buffer + * do not cross a page boundary + */ + d->prg_cpu[idx]->end.address = + pci_map_single(ohci->dev, packet->data, + packet->data_size, PCI_DMA_TODEVICE); + d->prg_cpu[idx]->end.branchAddress = 0; + d->prg_cpu[idx]->end.status = 0; if (d->branchAddrPtr) - *(d->branchAddrPtr) = virt_to_bus(d->prg+idx) | 0x3; - d->branchAddrPtr = &(d->prg[idx].end.branchAddress); + *(d->branchAddrPtr) = d->prg_bus[idx] | 0x3; + d->branchAddrPtr = &(d->prg_cpu[idx]->end.branchAddress); } else { /* quadlet transmit */ - d->prg[idx].begin.control = + d->prg_cpu[idx]->begin.control = OUTPUT_LAST_IMMEDIATE | packet->header_size; if (d->branchAddrPtr) - *(d->branchAddrPtr) = virt_to_bus(d->prg+idx) | 0x2; - d->branchAddrPtr = &(d->prg[idx].begin.branchAddress); + *(d->branchAddrPtr) = d->prg_bus[idx] | 0x2; + d->branchAddrPtr = &(d->prg_cpu[idx]->begin.branchAddress); } d->free_prgs--; /* queue the packet in the appropriate context queue */ - if (d->last) { - d->last->xnext = packet; - d->last = packet; + if (d->fifo_last) { + d->fifo_last->xnext = packet; + d->fifo_last = packet; + } + else { + d->fifo_first = packet; + d->fifo_last = packet; + } + d->prg_ind = (d->prg_ind+1)%d->num_desc; +} + +/* + * This function fills the AT FIFO with the (eventual) pending packets + * and runs or wake up the AT DMA prg if necessary. + * The function MUST be called with the d->lock held. + */ +static int dma_trm_flush(struct ti_ohci *ohci, struct dma_trm_ctx *d) +{ + int idx,z; + + if (d->pending_first == NULL || d->free_prgs == 0) + return 0; + + idx = d->prg_ind; + z = (d->pending_first->data_size) ? 3 : 2; + + /* insert the packets into the at dma fifo */ + while (d->free_prgs>0 && d->pending_first) { + insert_packet(ohci, d, d->pending_first); + d->pending_first = d->pending_first->xnext; + } + if (d->pending_first == NULL) + d->pending_last = NULL; + else + PRINT(KERN_INFO, ohci->id, + "AT DMA FIFO ctx=%d full... waiting",d->ctx); + + /* Is the context running ? (should be unless it is + the first packet to be sent in this context) */ + if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) { + DBGMSG(ohci->id,"Starting AT DMA ctx=%d",d->ctx); + reg_write(ohci, d->cmdPtr, d->prg_bus[idx]|z); + run_context(ohci, d->ctrlSet, NULL); } else { - d->first = packet; - d->last = packet; + DBGMSG(ohci->id,"Waking AT DMA ctx=%d",d->ctx); + /* wake up the dma context if necessary */ + if (!(reg_read(ohci, d->ctrlSet) & 0x400)) + reg_write(ohci, d->ctrlSet, 0x1000); } + return 1; } +/* + * Transmission of an async packet + */ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet) { struct ti_ohci *ohci = host->hostdata; struct dma_trm_ctx *d; unsigned char tcode; - int timeout=50; + unsigned long flags; if (packet->data_size >= ohci->max_packet_size) { PRINT(KERN_ERR, ohci->id, @@ -1305,48 +747,21 @@ if (tcode & 0x02) d = ohci->at_resp_context; else d = ohci->at_req_context; - spin_lock(&d->lock); - - if (d->free_prgs<1) { - PRINT(KERN_INFO, ohci->id, - "AT DMA ctx=%d Running out of prgs... waiting",d->ctx); - } - while (d->free_prgs<1) { - spin_unlock(&d->lock); - interruptible_sleep_on(&d->waitq); - if(signal_pending(current)) return -EINTR; - if (timeout--<0) { - stop_context(ohci, d->ctrlClear, - "AT DMA runaway loop... bailing out"); - return 0; - } - spin_lock(&d->lock); - } - - insert_packet(ohci, d, packet); - - /* Is the context running ? (should be unless it is - the first packet to be sent in this context) */ - if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) { - DBGMSG(ohci->id,"Starting AT DMA ctx=%d",d->ctx); - if (packet->data_size) - reg_write(ohci, d->cmdPtr, - virt_to_bus(&(d->prg[d->prg_ind])) | 0x3); - else - reg_write(ohci, d->cmdPtr, - virt_to_bus(&(d->prg[d->prg_ind])) | 0x2); + spin_lock_irqsave(&d->lock,flags); - run_context(ohci, d->ctrlSet, NULL); + /* queue the packet for later insertion into to dma fifo */ + if (d->pending_last) { + d->pending_last->xnext = packet; + d->pending_last = packet; } else { - DBGMSG(ohci->id,"Waking AT DMA ctx=%d",d->ctx); - /* wake up the dma context if necessary */ - if (!(reg_read(ohci, d->ctrlSet) & 0x400)) - reg_write(ohci, d->ctrlSet, 0x1000); + d->pending_first = packet; + d->pending_last = packet; } + + dma_trm_flush(ohci, d); - d->prg_ind = (d->prg_ind+1)%d->num_desc; - spin_unlock(&d->lock); + spin_unlock_irqrestore(&d->lock,flags); return 1; } @@ -1359,7 +774,10 @@ switch (cmd) { case RESET_BUS: - host->attempt_root=1; + /* + * FIXME: this flag might be necessary in some case + */ + /* host->attempt_root = 1; */ PRINT(KERN_INFO, ohci->id, "resetting bus on request%s", (host->attempt_root ? " and attempting to become root" : "")); @@ -1415,14 +833,9 @@ spin_lock_irqsave(&ohci->IR_channel_lock, flags); -#if 0 - PRINT(KERN_INFO, ohci->id, "!!! try listen on channel %d !!!", - arg); -#endif - if (!test_and_set_bit(arg, &ohci->IR_channel_usage)) { - PRINT(KERN_INFO, ohci->id, - "listening enabled on channel %d", arg); + DBGMSG(ohci->id, + "listening enabled on channel %d", arg); if (arg > 31) { u32 setMask= 0x00000001; @@ -1447,8 +860,8 @@ spin_lock_irqsave(&ohci->IR_channel_lock, flags); if (test_and_clear_bit(arg, &ohci->IR_channel_usage)) { - PRINT(KERN_INFO, ohci->id, - "listening disabled on iso channel %d", arg); + DBGMSG(ohci->id, + "listening disabled on iso channel %d", arg); if (arg > 31) { u32 clearMask= 0x00000001; @@ -1490,29 +903,42 @@ static void dma_trm_reset(struct dma_trm_ctx *d) { struct ti_ohci *ohci; + unsigned long flags; if (d==NULL) { PRINT_G(KERN_ERR, "dma_trm_reset called with NULL arg"); return; } ohci = (struct ti_ohci *)(d->ohci); - stop_context(ohci, d->ctrlClear, NULL); + ohci1394_stop_context(ohci, d->ctrlClear, NULL); - spin_lock(&d->lock); + spin_lock_irqsave(&d->lock,flags); + + /* is there still any packet pending in the fifo ? */ + while(d->fifo_first) { + PRINT(KERN_INFO, ohci->id, + "AT dma reset ctx=%d, aborting transmission", + d->ctx); + hpsb_packet_sent(ohci->host, d->fifo_first, ACKX_ABORTED); + d->fifo_first = d->fifo_first->xnext; + } + d->fifo_first = d->fifo_last = NULL; /* is there still any packet pending ? */ - while(d->first) { + while(d->pending_first) { PRINT(KERN_INFO, ohci->id, "AT dma reset ctx=%d, aborting transmission", d->ctx); - hpsb_packet_sent(ohci->host, d->first, ACKX_ABORTED); - d->first = d->first->xnext; + hpsb_packet_sent(ohci->host, d->pending_first, + ACKX_ABORTED); + d->pending_first = d->pending_first->xnext; } - d->first = d->last = NULL; + d->pending_first = d->pending_last = NULL; + d->branchAddrPtr=NULL; d->sent_ind = d->prg_ind; d->free_prgs = d->num_desc; - spin_unlock(&d->lock); + spin_unlock_irqrestore(&d->lock,flags); } static void ohci_irq_handler(int irq, void *dev_id, @@ -1528,10 +954,10 @@ /* read the interrupt event register */ event=reg_read(ohci, OHCI1394_IntEventClear); - DBGMSG(ohci->id, "IntEvent: %08x",event); - if (!event) return; + DBGMSG(ohci->id, "IntEvent: %08x",event); + /* clear the interrupt event register */ reg_write(ohci, OHCI1394_IntEventClear, event); @@ -1560,7 +986,7 @@ DBGMSG(ohci->id, "Got reqTxComplete interrupt " "status=0x%08X", reg_read(ohci, d->ctrlSet)); if (reg_read(ohci, d->ctrlSet) & 0x800) - stop_context(ohci, d->ctrlClear, + ohci1394_stop_context(ohci, d->ctrlClear, "reqTxComplete"); else dma_trm_bh((void *)d); @@ -1570,7 +996,7 @@ DBGMSG(ohci->id, "Got respTxComplete interrupt " "status=0x%08X", reg_read(ohci, d->ctrlSet)); if (reg_read(ohci, d->ctrlSet) & 0x800) - stop_context(ohci, d->ctrlClear, + ohci1394_stop_context(ohci, d->ctrlClear, "respTxComplete"); else dma_trm_bh((void *)d); @@ -1580,9 +1006,9 @@ DBGMSG(ohci->id, "Got RQPkt interrupt status=0x%08X", reg_read(ohci, d->ctrlSet)); if (reg_read(ohci, d->ctrlSet) & 0x800) - stop_context(ohci, d->ctrlClear, "RQPkt"); + ohci1394_stop_context(ohci, d->ctrlClear, "RQPkt"); else { -#if 1 +#if IEEE1394_USE_BOTTOM_HALVES queue_task(&d->task, &tq_immediate); mark_bh(IMMEDIATE_BH); #else @@ -1595,9 +1021,9 @@ DBGMSG(ohci->id, "Got RSPkt interrupt status=0x%08X", reg_read(ohci, d->ctrlSet)); if (reg_read(ohci, d->ctrlSet) & 0x800) - stop_context(ohci, d->ctrlClear, "RSPkt"); + ohci1394_stop_context(ohci, d->ctrlClear, "RSPkt"); else { -#if 1 +#if IEEE1394_USE_BOTTOM_HALVES queue_task(&d->task, &tq_immediate); mark_bh(IMMEDIATE_BH); #else @@ -1608,9 +1034,6 @@ if (event & OHCI1394_isochRx) { quadlet_t isoRecvIntEvent; struct dma_rcv_ctx *d = ohci->ir_context; -#ifdef _VIDEO_1394_H - int i; -#endif isoRecvIntEvent = reg_read(ohci, OHCI1394_IsoRecvIntEventSet); reg_write(ohci, OHCI1394_IsoRecvIntEventClear, @@ -1620,10 +1043,10 @@ reg_read(ohci, d->ctrlSet), isoRecvIntEvent); if (isoRecvIntEvent & 0x1) { if (reg_read(ohci, d->ctrlSet) & 0x800) - stop_context(ohci, d->ctrlClear, + ohci1394_stop_context(ohci, d->ctrlClear, "isochRx"); else { -#if 1 +#if IEEE1394_USE_BOTTOM_HALVES queue_task(&d->task, &tq_immediate); mark_bh(IMMEDIATE_BH); #else @@ -1631,12 +1054,21 @@ #endif } } -#ifdef _VIDEO_1394_H - for (i=0;inb_iso_ctx-1;i++) - if (isoRecvIntEvent & (1<<(i+1))) - wakeup_dma_fbuf_ctx( - ohci,ohci->fbuf_context[i]); -#endif + if (ohci->video_tmpl) + ohci->video_tmpl->irq_handler(ohci->id, + isoRecvIntEvent, + 0); + } + if (event & OHCI1394_isochTx) { + quadlet_t isoXmitIntEvent; + isoXmitIntEvent = + reg_read(ohci, OHCI1394_IsoXmitIntEventSet); + reg_write(ohci, OHCI1394_IsoXmitIntEventClear, + isoXmitIntEvent); + DBGMSG(ohci->id, "Got isochTx interrupt"); + if (ohci->video_tmpl) + ohci->video_tmpl->irq_handler(ohci->id, 0, + isoXmitIntEvent); } if (event & OHCI1394_selfIDComplete) { if (host->in_bus_reset) { @@ -1703,10 +1135,10 @@ struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); DBGMSG(ohci->id, "Inserting dma buf ctx=%d idx=%d", d->ctx, idx); - d->prg[idx]->status = d->buf_size; - d->prg[idx]->branchAddress &= 0xfffffff0; + d->prg_cpu[idx]->status = d->buf_size; + d->prg_cpu[idx]->branchAddress &= 0xfffffff0; idx = (idx + d->num_desc - 1 ) % d->num_desc; - d->prg[idx]->branchAddress |= 0x1; + d->prg_cpu[idx]->branchAddress |= 0x1; /* wake up the dma context if necessary */ if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { @@ -1724,7 +1156,7 @@ /* Where is the data length ? */ if (offset+12>=d->buf_size) - length = (d->buf[(idx+1)%d->num_desc] + length = (d->buf_cpu[(idx+1)%d->num_desc] [3-(d->buf_size-offset)/4]>>16); else length = (buf_ptr[3]>>16); @@ -1769,7 +1201,7 @@ struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); unsigned int split_left, idx, offset, rescount; unsigned char tcode; - int length, bytes_left; + int length, bytes_left, ack; quadlet_t *buf_ptr; char *split_ptr; char msg[256]; @@ -1778,9 +1210,9 @@ idx = d->buf_ind; offset = d->buf_offset; - buf_ptr = d->buf[idx] + offset/4; + buf_ptr = d->buf_cpu[idx] + offset/4; - rescount = d->prg[idx]->status&0xffff; + rescount = d->prg_cpu[idx]->status&0xffff; bytes_left = d->buf_size - rescount - offset; while (bytes_left>0) { @@ -1790,21 +1222,22 @@ if (length<4) { /* something is wrong */ sprintf(msg,"unexpected tcode 0x%X in AR ctx=%d", tcode, d->ctx); - stop_context(ohci, d->ctrlClear, msg); + ohci1394_stop_context(ohci, d->ctrlClear, msg); spin_unlock(&d->lock); return; } if ((offset+length)>d->buf_size) { /* Split packet */ if (length>d->split_buf_size) { - stop_context(ohci, d->ctrlClear, + ohci1394_stop_context(ohci, d->ctrlClear, "split packet size exceeded"); d->buf_ind = idx; d->buf_offset = offset; spin_unlock(&d->lock); return; } - if (d->prg[(idx+1)%d->num_desc]->status==d->buf_size) { + if (d->prg_cpu[(idx+1)%d->num_desc]->status + ==d->buf_size) { /* other part of packet not written yet */ /* this should never happen I think */ /* anyway we'll get it on the next call */ @@ -1822,7 +1255,7 @@ split_ptr += d->buf_size-offset; insert_dma_buffer(d, idx); idx = (idx+1) % d->num_desc; - buf_ptr = d->buf[idx]; + buf_ptr = d->buf_cpu[idx]; offset=0; while (split_left >= d->buf_size) { memcpy(split_ptr,buf_ptr,d->buf_size); @@ -1830,7 +1263,7 @@ split_left -= d->buf_size; insert_dma_buffer(d, idx); idx = (idx+1) % d->num_desc; - buf_ptr = d->buf[idx]; + buf_ptr = d->buf_cpu[idx]; } if (split_left>0) { memcpy(split_ptr, buf_ptr, split_left); @@ -1838,17 +1271,6 @@ buf_ptr += offset/4; } - /* - * Tip by James Goodwin - * We need to handle write requests that are received - * to our middle address space (posted writes). - * In this case, the hardware generates an - * ack_complete... but, if we pass the packet up to - * the subsystem, it will try and send a response - * (which it shouldn't), because it assumes we - * returned ack_pending. - */ - /* * We get one phy packet for each bus reset. * we know that from now on the bus topology may @@ -1862,22 +1284,12 @@ (d->spb[length/4-1]>>16)&0x1f, (d->spb[length/4-1]>>21)&0x3, tcode, length, d->spb[3], d->ctx); + + ack = (((d->spb[length/4-1]>>16)&0x1f) + == 0x11) ? 1 : 0; - /* - * Tip by James Goodwin - * Handle case of posted writes. If we receive - * an ack_complete, we should not send a - * response. Fake out upper layers by turning - * the packet into a broadcast packet... we - * should really modify the core stack to - * accept an ack received argument and figure - * out whether to reply. - */ - if (((d->spb[length/4-1]>>16)&0x1f) == 0x11) { - d->spb[0] |= (ALL_NODES<<16); - } hpsb_packet_received(ohci->host, d->spb, - length); + length, ack); } else PRINT(KERN_INFO, ohci->id, @@ -1899,21 +1311,11 @@ (buf_ptr[length/4-1]>>21)&0x3, tcode, length, buf_ptr[3], d->ctx); - /* - * Tip by James Goodwin - * Handle case of posted writes. If we receive - * an ack_complete, we should not send a - * response. Fake out upper layers by turning - * the packet into a broadcast packet... we - * should really modify the core stack to - * accept an ack received argument and figure - * out whether to reply. - */ - if (((d->spb[length/4-1]>>16)&0x1f) == 0x11) { - buf_ptr[0] |= (ALL_NODES<<16); - } + ack = (((buf_ptr[length/4-1]>>16)&0x1f) + == 0x11) ? 1 : 0; + hpsb_packet_received(ohci->host, buf_ptr, - length); + length, ack); } else PRINT(KERN_INFO, ohci->id, @@ -1924,11 +1326,11 @@ if (offset==d->buf_size) { insert_dma_buffer(d, idx); idx = (idx+1) % d->num_desc; - buf_ptr = d->buf[idx]; + buf_ptr = d->buf_cpu[idx]; offset=0; } } - rescount = d->prg[idx]->status & 0xffff; + rescount = d->prg_cpu[idx]->status & 0xffff; bytes_left = d->buf_size - rescount - offset; } @@ -1945,32 +1347,51 @@ struct dma_trm_ctx *d = (struct dma_trm_ctx*)data; struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); struct hpsb_packet *packet; + unsigned long flags; u32 ack; - spin_lock(&d->lock); + spin_lock_irqsave(&d->lock, flags); - if (d->first==NULL) { - stop_context(ohci, d->ctrlClear, + if (d->fifo_first==NULL) { +#if 0 + ohci1394_stop_context(ohci, d->ctrlClear, "Packet sent ack received but queue is empty"); - spin_unlock(&d->lock); +#endif + spin_unlock_irqrestore(&d->lock, flags); return; } - packet = d->first; - d->first = d->first->xnext; - if (d->first==NULL) d->last=NULL; - if (packet->data_size) - ack = d->prg[d->sent_ind].end.status>>16; - else - ack = d->prg[d->sent_ind].begin.status>>16; - d->sent_ind = (d->sent_ind+1)%d->num_desc; - d->free_prgs++; - spin_unlock(&d->lock); - if (waitqueue_active(&d->waitq)) wake_up_interruptible(&d->waitq); + while (d->fifo_first) { + packet = d->fifo_first; + if (packet->data_size) + ack = d->prg_cpu[d->sent_ind]->end.status>>16; + else + ack = d->prg_cpu[d->sent_ind]->begin.status>>16; + + if (ack==0) + /* this packet hasn't been sent yet*/ + break; + + DBGMSG(ohci->id, + "Packet sent to node %d ack=0x%X spd=%d ctx=%d", + (packet->header[0]>>16)&0x3f, ack&0x1f, (ack>>5)&0x3, + d->ctx); + hpsb_packet_sent(ohci->host, packet, ack&0xf); + + if (packet->data_size) + pci_unmap_single(ohci->dev, + d->prg_cpu[d->sent_ind]->end.address, + packet->data_size, PCI_DMA_TODEVICE); + + d->sent_ind = (d->sent_ind+1)%d->num_desc; + d->free_prgs++; + d->fifo_first = d->fifo_first->xnext; + } + if (d->fifo_first==NULL) d->fifo_last=NULL; + + dma_trm_flush(ohci, d); - DBGMSG(ohci->id, "Packet sent to node %d ack=0x%X spd=%d ctx=%d", - (packet->header[0]>>16)&0x3f, ack&0x1f, (ack>>5)&0x3, d->ctx); - hpsb_packet_sent(ohci->host, packet, ack&0xf); + spin_unlock_irqrestore(&d->lock, flags); } static int free_dma_rcv_ctx(struct dma_rcv_ctx **d) @@ -1984,17 +1405,25 @@ DBGMSG(ohci->id, "Freeing dma_rcv_ctx %d",(*d)->ctx); - stop_context(ohci, (*d)->ctrlClear, NULL); + ohci1394_stop_context(ohci, (*d)->ctrlClear, NULL); - if ((*d)->buf) { - for (i=0; i<(*d)->num_desc; i++) - if ((*d)->buf[i]) kfree((*d)->buf[i]); - kfree((*d)->buf); - } - if ((*d)->prg) { + if ((*d)->buf_cpu) { for (i=0; i<(*d)->num_desc; i++) - if ((*d)->prg[i]) kfree((*d)->prg[i]); - kfree((*d)->prg); + if ((*d)->buf_cpu[i] && (*d)->buf_bus[i]) + pci_free_consistent( + ohci->dev, (*d)->buf_size, + (*d)->buf_cpu[i], (*d)->buf_bus[i]); + kfree((*d)->buf_cpu); + kfree((*d)->buf_bus); + } + if ((*d)->prg_cpu) { + for (i=0; i<(*d)->num_desc; i++) + if ((*d)->prg_cpu[i] && (*d)->prg_bus[i]) + pci_free_consistent( + ohci->dev, sizeof(struct dma_cmd), + (*d)->prg_cpu[i], (*d)->prg_bus[i]); + kfree((*d)->prg_cpu); + kfree((*d)->prg_bus); } if ((*d)->spb) kfree((*d)->spb); @@ -2030,27 +1459,34 @@ d->ctrlClear = ctrlClear; d->cmdPtr = cmdPtr; - d->buf = NULL; - d->prg = NULL; + d->buf_cpu = NULL; + d->buf_bus = NULL; + d->prg_cpu = NULL; + d->prg_bus = NULL; d->spb = NULL; - d->buf = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_KERNEL); + d->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_KERNEL); + d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); - if (d->buf == NULL) { + if (d->buf_cpu == NULL || d->buf_bus == NULL) { PRINT(KERN_ERR, ohci->id, "failed to allocate dma buffer"); free_dma_rcv_ctx(&d); return NULL; } - memset(d->buf, 0, d->num_desc * sizeof(quadlet_t*)); + memset(d->buf_cpu, 0, d->num_desc * sizeof(quadlet_t*)); + memset(d->buf_bus, 0, d->num_desc * sizeof(dma_addr_t)); - d->prg = kmalloc(d->num_desc * sizeof(struct dma_cmd*), GFP_KERNEL); + d->prg_cpu = kmalloc(d->num_desc * sizeof(struct dma_cmd*), + GFP_KERNEL); + d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); - if (d->prg == NULL) { + if (d->prg_cpu == NULL || d->prg_bus == NULL) { PRINT(KERN_ERR, ohci->id, "failed to allocate dma prg"); free_dma_rcv_ctx(&d); return NULL; } - memset(d->prg, 0, d->num_desc * sizeof(struct dma_cmd*)); + memset(d->prg_cpu, 0, d->num_desc * sizeof(struct dma_cmd*)); + memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t)); d->spb = kmalloc(d->split_buf_size, GFP_KERNEL); @@ -2061,10 +1497,12 @@ } for (i=0; inum_desc; i++) { - d->buf[i] = kmalloc(d->buf_size, GFP_KERNEL); + d->buf_cpu[i] = pci_alloc_consistent(ohci->dev, + d->buf_size, + d->buf_bus+i); - if (d->buf[i] != NULL) { - memset(d->buf[i], 0, d->buf_size); + if (d->buf_cpu[i] != NULL) { + memset(d->buf_cpu[i], 0, d->buf_size); } else { PRINT(KERN_ERR, ohci->id, "failed to allocate dma buffer"); @@ -2072,10 +1510,13 @@ return NULL; } - d->prg[i]= kmalloc(sizeof(struct dma_cmd), GFP_KERNEL); + + d->prg_cpu[i] = pci_alloc_consistent(ohci->dev, + sizeof(struct dma_cmd), + d->prg_bus+i); - if (d->prg[i] != NULL) { - memset(d->prg[i], 0, sizeof(struct dma_cmd)); + if (d->prg_cpu[i] != NULL) { + memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd)); } else { PRINT(KERN_ERR, ohci->id, "failed to allocate dma prg"); @@ -2098,6 +1539,7 @@ static int free_dma_trm_ctx(struct dma_trm_ctx **d) { struct ti_ohci *ohci; + int i; if (*d==NULL) return -1; @@ -2105,9 +1547,18 @@ DBGMSG(ohci->id, "Freeing dma_trm_ctx %d",(*d)->ctx); - stop_context(ohci, (*d)->ctrlClear, NULL); + ohci1394_stop_context(ohci, (*d)->ctrlClear, NULL); + + if ((*d)->prg_cpu) { + for (i=0; i<(*d)->num_desc; i++) + if ((*d)->prg_cpu[i] && (*d)->prg_bus[i]) + pci_free_consistent( + ohci->dev, sizeof(struct at_dma_prg), + (*d)->prg_cpu[i], (*d)->prg_bus[i]); + kfree((*d)->prg_cpu); + kfree((*d)->prg_bus); + } - if ((*d)->prg) kfree((*d)->prg); kfree(*d); *d = NULL; return 0; @@ -2118,6 +1569,7 @@ int ctrlSet, int ctrlClear, int cmdPtr) { struct dma_trm_ctx *d=NULL; + int i; d = (struct dma_trm_ctx *)kmalloc(sizeof(struct dma_trm_ctx), GFP_KERNEL); @@ -2133,16 +1585,35 @@ d->ctrlSet = ctrlSet; d->ctrlClear = ctrlClear; d->cmdPtr = cmdPtr; - d->prg = NULL; + d->prg_cpu = NULL; + d->prg_bus = NULL; - d->prg = kmalloc(d->num_desc * sizeof(struct at_dma_prg), GFP_KERNEL); + d->prg_cpu = kmalloc(d->num_desc * sizeof(struct at_dma_prg*), + GFP_KERNEL); + d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); - if (d->prg == NULL) { + if (d->prg_cpu == NULL || d->prg_bus == NULL) { PRINT(KERN_ERR, ohci->id, "failed to allocate at dma prg"); free_dma_trm_ctx(&d); return NULL; } - memset(d->prg, 0, d->num_desc * sizeof(struct at_dma_prg)); + memset(d->prg_cpu, 0, d->num_desc * sizeof(struct at_dma_prg*)); + memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t)); + + for (i=0; inum_desc; i++) { + d->prg_cpu[i] = pci_alloc_consistent(ohci->dev, + sizeof(struct at_dma_prg), + d->prg_bus+i); + + if (d->prg_cpu[i] != NULL) { + memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg)); + } else { + PRINT(KERN_ERR, ohci->id, + "failed to allocate at dma prg"); + free_dma_trm_ctx(&d); + return NULL; + } + } spin_lock_init(&d->lock); @@ -2150,15 +1621,42 @@ d->task.routine = dma_trm_bh; d->task.data = (void*)d; - init_waitqueue_head(&d->waitq); - return d; } +static u32 ohci_crc16(unsigned *data, int length) +{ + int check=0, i; + int shift, sum, next=0; + + for (i = length; i; i--) { + for (next = check, shift = 28; shift >= 0; shift -= 4 ) { + sum = ((next >> 12) ^ (*data >> shift)) & 0xf; + next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum); + } + check = next & 0xffff; + data++; + } + + return check; +} + +static void ohci_init_config_rom(struct ti_ohci *ohci) +{ + int i; + + ohci_csr_rom[3] = reg_read(ohci, OHCI1394_GUIDHi); + ohci_csr_rom[4] = reg_read(ohci, OHCI1394_GUIDLo); + + ohci_csr_rom[0] = 0x04040000 | ohci_crc16(ohci_csr_rom+1, 4); + + for (i=0;icsr_config_rom_cpu[i] = cpu_to_be32(ohci_csr_rom[i]); +} + static int add_card(struct pci_dev *dev) { struct ti_ohci *ohci; /* shortcut to currently handled device */ - int i; if (num_of_cards == MAX_OHCI1394_CARDS) { PRINT_G(KERN_WARNING, "cannot handle more than %d cards. " @@ -2182,21 +1680,29 @@ ohci->state = 0; /* csr_config rom allocation */ - ohci->csr_config_rom = kmalloc(1024, GFP_KERNEL); - if (ohci->csr_config_rom == NULL) { + ohci->csr_config_rom_cpu = + pci_alloc_consistent(ohci->dev, sizeof(ohci_csr_rom), + &ohci->csr_config_rom_bus); + if (ohci->csr_config_rom_cpu == NULL) { FAIL("failed to allocate buffer config rom"); } - for (i=0;icsr_config_rom[i] = cpu_to_be32(ohci_csr_rom[i]); DBGMSG(ohci->id, "The 1st byte at offset 0x404 is: 0x%02x", - *((char *)ohci->csr_config_rom+4)); + *((char *)ohci->csr_config_rom_cpu+4)); - /* self-id dma buffer allocation */ - ohci->self_id_buffer = kmalloc(2048, GFP_KERNEL); - if (ohci->self_id_buffer == NULL) { + /* + * self-id dma buffer allocation + * FIXME: some early chips may need 8KB alignment for the + * selfid buffer + */ + ohci->selfid_buf_cpu = + pci_alloc_consistent(ohci->dev, 2048, &ohci->selfid_buf_bus); + if (ohci->selfid_buf_cpu == NULL) { FAIL("failed to allocate DMA buffer for self-id packets"); } + if ((unsigned long)ohci->selfid_buf_cpu & 0xfff) + PRINT(KERN_INFO, ohci->id, "Selfid buffer %p not aligned on " + "8Kb boundary", ohci->selfid_buf_cpu); ohci->ar_req_context = alloc_dma_rcv_ctx(ohci, 0, AR_REQ_NUM_DESC, @@ -2241,9 +1747,9 @@ ohci->ir_context = alloc_dma_rcv_ctx(ohci, 2, IR_NUM_DESC, IR_BUF_SIZE, IR_SPLIT_BUF_SIZE, - OHCI1394_IrRcvContextControlSet, - OHCI1394_IrRcvContextControlClear, - OHCI1394_IrRcvCommandPtr); + OHCI1394_IsoRcvContextControlSet, + OHCI1394_IsoRcvContextControlClear, + OHCI1394_IsoRcvCommandPtr); if (ohci->ir_context == NULL) { FAIL("failed to allocate IR context"); @@ -2274,6 +1780,8 @@ FAIL("failed to allocate shared interrupt %d", dev->irq); } + ohci_init_config_rom(ohci); + return 0; #undef FAIL } @@ -2297,12 +1805,9 @@ //unsigned char phyreg; //int i, nports; int i; + struct dma_rcv_ctx *d=NULL; struct dma_trm_ctx *dt=NULL; -#ifdef _VIDEO_1394_H - int j; - struct dma_fbuf_ctx *f=ohci->fbuf_context[0]; -#endif p += sprintf(p,"IEEE-1394 OHCI Driver status report:\n"); p += sprintf(p," bus number: 0x%x Node ID: 0x%x\n", @@ -2332,26 +1837,6 @@ p += sprintf(p,"\n---Iso Receive DMA---\n"); -#ifdef _VIDEO_1394_H - -#if 0 - if (f!=NULL) { - for (i=0; inum_desc; i++) { - for (j=0;jnb_cmd;j++) { - p += sprintf(p, - "prg[%d][%d]: %p %08x %08x %08x %08x\n", - i,j,virt_to_bus(&(f->prg[i][j])), - f->prg[i][j].control, - f->prg[i][j].address, - f->prg[i][j].branchAddress, - f->prg[i][j].status); - } - } - } -#endif - -#else - d = ohci->ir_context; #if 0 for (i=0; inum_desc; i++) { @@ -2389,7 +1874,7 @@ dt->prg_ind, dt->sent_ind, dt->free_prgs, dt->branchAddrPtr); p += sprintf(p, "AT req queue: first: %p last: %p\n", - dt->first, dt->last); + dt->fifo_first, dt->fifo_last); dt = ohci->at_resp_context; #if 0 for (i=0; inum_desc; i++) { @@ -2437,15 +1922,14 @@ dt->prg_ind, dt->sent_ind, dt->free_prgs, dt->branchAddrPtr); p += sprintf(p, "AT resp queue: first: %p last: %p\n", - dt->first, dt->last); -#endif + dt->fifo_first, dt->fifo_last); /* ----- Register Dump ----- */ p += sprintf(p,"\n### HC Register dump ###\n"); SR("Version : %08x GUID_ROM : %08x ATRetries : %08x\n", OHCI1394_Version, OHCI1394_GUID_ROM, OHCI1394_ATRetries); - SR("CSRReadData : %08x CSRCompData : %08x CSRControl : %08x\n", - OHCI1394_CSRReadData, OHCI1394_CSRCompareData, OHCI1394_CSRControl); + SR("CSRData : %08x CSRCompData : %08x CSRControl : %08x\n", + OHCI1394_CSRData, OHCI1394_CSRCompareData, OHCI1394_CSRControl); SR("ConfigROMhdr: %08x BusID : %08x BusOptions : %08x\n", OHCI1394_ConfigROMhdr, OHCI1394_BusID, OHCI1394_BusOptions); SR("GUIDHi : %08x GUIDLo : %08x ConfigROMmap: %08x\n", @@ -2481,14 +1965,21 @@ SR("AsRsRvCtxCtl: %08x AsRsRvCmdPtr: %08x IntEvent : %08x\n", OHCI1394_AsRspRcvContextControlSet, OHCI1394_AsRspRcvCommandPtr, OHCI1394_IntEventSet); - for (i=0;i<4;i++) { + for (i=0;inb_iso_rcv_ctx;i++) { p += sprintf(p,"IsoRCtxCtl%02d: %08x IsoRCmdPtr%02d: %08x" " IsoRCxtMch%02d: %08x\n", i, reg_read(ohci, - OHCI1394_IrRcvContextControlSet+32*i), - i,reg_read(ohci, OHCI1394_IrRcvCommandPtr+32*i), + OHCI1394_IsoRcvContextControlSet+32*i), + i,reg_read(ohci, OHCI1394_IsoRcvCommandPtr+32*i), i,reg_read(ohci, - OHCI1394_IrRcvContextMatch+32*i)); + OHCI1394_IsoRcvContextMatch+32*i)); + } + for (i=0;inb_iso_xmit_ctx;i++) { + p += sprintf(p,"IsoTCtxCtl%02d: %08x IsoTCmdPtr%02d: %08x\n", + i, + reg_read(ohci, + OHCI1394_IsoXmitContextControlSet+32*i), + i,reg_read(ohci,OHCI1394_IsoXmitCommandPtr+32*i)); } #if 0 @@ -2554,9 +2045,11 @@ static void remove_card(struct ti_ohci *ohci) { -#ifdef _VIDEO_1394_H - int i; -#endif + /* + * Reset the board properly before leaving + * Daniel Kobras + */ + ohci_soft_reset(ohci); /* Free AR dma */ free_dma_rcv_ctx(&ohci->ar_req_context); @@ -2569,28 +2062,18 @@ /* Free IR dma */ free_dma_rcv_ctx(&ohci->ir_context); -#ifdef _VIDEO_1394_H - /* Free the frame buffer context */ - if (ohci->fbuf_context) - for (i=0;inb_iso_ctx-1;i++) { - free_dma_fbuf_ctx(&ohci->fbuf_context[i]); - } -#endif - - /* - * Reset the board properly before leaving - * Daniel Kobras - */ - ohci_soft_reset(ohci); - /* Free self-id buffer */ - if (ohci->self_id_buffer) - kfree(ohci->self_id_buffer); + if (ohci->selfid_buf_cpu) + pci_free_consistent(ohci->dev, 2048, + ohci->selfid_buf_cpu, + ohci->selfid_buf_bus); /* Free config rom */ - if (ohci->csr_config_rom) - kfree(ohci->csr_config_rom); - + if (ohci->csr_config_rom_cpu) + pci_free_consistent(ohci->dev, sizeof(ohci_csr_rom), + ohci->csr_config_rom_cpu, + ohci->csr_config_rom_bus); + /* Free the IRQ */ free_irq(ohci->dev->irq, ohci); @@ -2646,9 +2129,9 @@ struct ti_ohci *ohci=host->hostdata; DBGMSG(ohci->id, "request csr_rom address: %08X", - (u32)ohci->csr_config_rom); + (u32)ohci->csr_config_rom_cpu); - *ptr = ohci->csr_config_rom; + *ptr = ohci->csr_config_rom_cpu; return sizeof(ohci_csr_rom); } @@ -2675,6 +2158,118 @@ return &tmpl; } +void ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg) +{ + int i=0; + + /* stop the channel program if it's still running */ + reg_write(ohci, reg, 0x8000); + + /* Wait until it effectively stops */ + while (reg_read(ohci, reg) & 0x400) { + i++; + if (i>5000) { + PRINT(KERN_ERR, ohci->id, + "runaway loop while stopping context..."); + break; + } + } + if (msg) PRINT(KERN_ERR, ohci->id, "%s\n dma prg stopped\n", msg); +} + +struct ti_ohci *ohci1394_get_struct(int card_num) +{ + if (card_num>=0 && card_numvideo_tmpl) + return -ENFILE; + ohci->video_tmpl = tmpl; + MOD_INC_USE_COUNT; + return 0; +} + +void ohci1394_unregister_video(struct ti_ohci *ohci, + struct video_template *tmpl) +{ + if (ohci->video_tmpl != tmpl) { + PRINT(KERN_ERR, ohci->id, + "Trying to unregister wrong video device"); + } + else { + ohci->video_tmpl = NULL; + MOD_DEC_USE_COUNT; + } +} + +#if 0 +int ohci_compare_swap(struct ti_ohci *ohci, quadlet_t *data, + quadlet_t compare, int sel) +{ + int timeout = 255; + reg_write(ohci, OHCI1394_CSRData, *data); + reg_write(ohci, OHCI1394_CSRCompareData, compare); + reg_write(ohci, OHCI1394_CSRControl, sel); + while(!(reg_read(ohci, OHCI1394_CSRControl)&0x80000000)) { + if (timeout--) { + PRINT(KERN_INFO, ohci->id, "request_channel timeout"); + return -1; + } + } + *data = reg_read(ohci, OHCI1394_CSRData); + return 0; +} + +int ohci1394_request_channel(struct ti_ohci *ohci, int channel) +{ + int csrSel; + quadlet_t chan, data1=0, data2=0; + int timeout = 32; + + if (channel<32) { + chan = 1<id, "request_channel timeout"); + return -1; + } + while (timeout--) { + if (data1 & chan) { + PRINT(KERN_INFO, ohci->id, + "request channel %d failed", channel); + return -1; + } + data2 = data1; + data1 |= chan; + if (ohci_compare_swap(ohci, &data1, data2, csrSel)<0) { + PRINT(KERN_INFO, ohci->id, "request_channel timeout"); + return -1; + } + if (data1==data2) { + PRINT(KERN_INFO, ohci->id, + "request channel %d succeded", channel); + return 0; + } + } + PRINT(KERN_INFO, ohci->id, "request channel %d failed", channel); + return -1; +} +#endif + +EXPORT_SYMBOL(ohci1394_stop_context); +EXPORT_SYMBOL(ohci1394_get_struct); +EXPORT_SYMBOL(ohci1394_register_video); +EXPORT_SYMBOL(ohci1394_unregister_video); #ifdef MODULE @@ -2695,10 +2290,6 @@ #endif #endif -#ifdef _VIDEO_1394_H - unregister_chrdev(OHCI1394_MAJOR, "ohci1394"); -#endif - PRINT_G(KERN_INFO, "removed " OHCI1394_DRIVER_NAME " module\n"); } @@ -2709,17 +2300,8 @@ if (hpsb_register_lowlevel(get_ohci_template())) { PRINT_G(KERN_ERR, "registering failed\n"); return -ENXIO; - } else { -#ifdef _VIDEO_1394_H - if (register_chrdev(OHCI1394_MAJOR, "ohci1394", &ohci_fops)) - { - printk("ohci1394: unable to get major %d\n", - OHCI1394_MAJOR); - return -EIO; - } -#endif - return 0; - } + } + return 0; } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/ohci1394.h linux/drivers/ieee1394/ohci1394.h --- v2.4.0-test2/linux/drivers/ieee1394/ohci1394.h Fri Jun 23 21:55:09 2000 +++ linux/drivers/ieee1394/ohci1394.h Wed Jul 5 13:03:56 2000 @@ -22,8 +22,8 @@ #define _OHCI1394_H #include "ieee1394_types.h" -/* include this for the video frame grabber */ -/* #include "video1394.h" */ + +#define IEEE1394_USE_BOTTOM_HALVES 0 #define OHCI1394_DRIVER_NAME "ohci1394" @@ -71,6 +71,18 @@ #define PCI_DEVICE_ID_APPLE_UNI_N_FW 0x0018 #endif +#ifndef PCI_DEVICE_ID_ALI_OHCI1394_M5251 +#define PCI_DEVICE_ID_ALI_OHCI1394_M5251 0x5251 +#endif + +#ifndef PCI_VENDOR_ID_LUCENT +#define PCI_VENDOR_ID_LUCENT 0x11c1 +#endif + +#ifndef PCI_DEVICE_ID_LUCENT_FW323 +#define PCI_DEVICE_ID_LUCENT_FW323 0x5811 +#endif + #define MAX_OHCI1394_CARDS 4 #define OHCI1394_MAX_AT_REQ_RETRIES 0x2 @@ -87,8 +99,8 @@ #define AR_RESP_SPLIT_BUF_SIZE 4096 /* split packet buffer */ #define IR_NUM_DESC 16 /* number of IR descriptors */ -#define IR_BUF_SIZE 6480 /* 6480 bytes/buffer */ -#define IR_SPLIT_BUF_SIZE 8192 /* split packet buffer */ +#define IR_BUF_SIZE 4096 /* 6480 bytes/buffer */ +#define IR_SPLIT_BUF_SIZE 4096 /* split packet buffer */ #define AT_REQ_NUM_DESC 32 /* number of AT req descriptors */ #define AT_RESP_NUM_DESC 32 /* number of AT resp descriptors */ @@ -113,8 +125,15 @@ unsigned int num_desc; unsigned int buf_size; unsigned int split_buf_size; - struct dma_cmd **prg; - quadlet_t **buf; + + /* dma block descriptors */ + struct dma_cmd **prg_cpu; + dma_addr_t *prg_bus; + + /* dma buffers */ + quadlet_t **buf_cpu; + dma_addr_t *buf_bus; + unsigned int buf_ind; unsigned int buf_offset; quadlet_t *spb; @@ -130,45 +149,37 @@ void *ohci; int ctx; unsigned int num_desc; - struct at_dma_prg *prg; + + /* dma block descriptors */ + struct at_dma_prg **prg_cpu; + dma_addr_t *prg_bus; + unsigned int prg_ind; unsigned int sent_ind; int free_prgs; quadlet_t *branchAddrPtr; - struct hpsb_packet *first; - struct hpsb_packet *last; + + /* list of packets inserted in the AT FIFO */ + struct hpsb_packet *fifo_first; + struct hpsb_packet *fifo_last; + + /* list of pending packets to be inserted in the AT FIFO */ + struct hpsb_packet *pending_first; + struct hpsb_packet *pending_last; + spinlock_t lock; struct tq_struct task; int ctrlClear; int ctrlSet; int cmdPtr; - wait_queue_head_t waitq; }; -#ifdef _VIDEO_1394_H - -#define OHCI1394_MAJOR 172 -#define ISO_CHANNELS 64 - -struct dma_fbuf_ctx { - void *ohci; - int ctx; - int channel; - int last_buffer; - unsigned int num_desc; - unsigned int buf_size; - unsigned int frame_size; - unsigned int nb_cmd; - unsigned char *buf; - struct dma_cmd **prg; - unsigned int *buffer_status; - int ctrlClear; - int ctrlSet; - int cmdPtr; - int ctxMatch; - wait_queue_head_t waitq; +/* video device template */ +struct video_template { + void (*irq_handler) (int card, quadlet_t isoRecvEvent, + quadlet_t isoXmitEvent); }; -#endif + struct ti_ohci { int id; /* sequential card number */ @@ -180,8 +191,13 @@ /* remapped memory spaces */ void *registers; - quadlet_t *self_id_buffer; /* dma buffer for self-id packets */ - quadlet_t *csr_config_rom; /* buffer for csr config rom */ + /* dma buffer for self-id packets */ + quadlet_t *selfid_buf_cpu; + dma_addr_t selfid_buf_bus; + + /* buffer for csr config rom */ + quadlet_t *csr_config_rom_cpu; + dma_addr_t csr_config_rom_bus; unsigned int max_packet_size; @@ -197,13 +213,10 @@ struct dma_rcv_ctx *ir_context; u64 IR_channel_usage; spinlock_t IR_channel_lock; - int nb_iso_ctx; + int nb_iso_rcv_ctx; -#ifdef _VIDEO_1394_H - /* frame buffer context */ - struct dma_fbuf_ctx **fbuf_context; - struct dma_fbuf_ctx *current_fbuf_ctx; -#endif + /* iso transmit */ + int nb_iso_xmit_ctx; /* IEEE-1394 part follows */ struct hpsb_host *host; @@ -214,8 +227,23 @@ int self_id_errors; int NumBusResets; + + /* video device */ + struct video_template *video_tmpl; }; +inline static int cross_bound(unsigned long addr, unsigned int size) +{ + int cross=0; + if (size>PAGE_SIZE) { + cross = size/PAGE_SIZE; + size -= cross*PAGE_SIZE; + } + if ((PAGE_SIZE-addr%PAGE_SIZE)lock); /* FIXME - use ffz() to make this readable */ - for (i = 0; i < LOCALRAM_SIZE; i++) { + for (i = 0; i < (LOCALRAM_SIZE / 1024); i++) { m = lynx->pcl_bmap[i]; for (j = 0; j < 8; j++) { if (m & 1<async_queue; + struct hpsb_packet *packet = lynx->async.queue; + + lynx->async.header_dma = pci_map_single(lynx->dev, packet->header, + packet->header_size, + PCI_DMA_TODEVICE); + if (packet->data_size) { + lynx->async.data_dma = pci_map_single(lynx->dev, packet->data, + packet->data_size, + PCI_DMA_TODEVICE); + } else { + lynx->async.data_dma = 0; + } pcl.next = PCL_NEXT_INVALID; pcl.async_error_next = PCL_NEXT_INVALID; @@ -400,16 +411,16 @@ pcl.buffer[0].control = PCL_CMD_XMT | packet->speed_code << 14 | packet->header_size | PCL_BIGENDIAN; #endif - pcl.buffer[0].pointer = virt_to_bus(packet->header); + pcl.buffer[0].pointer = lynx->async.header_dma; pcl.buffer[1].control = PCL_LAST_BUFF | packet->data_size; - pcl.buffer[1].pointer = virt_to_bus(packet->data); + pcl.buffer[1].pointer = lynx->async.data_dma; if (!packet->data_be) { pcl.buffer[1].control |= PCL_BIGENDIAN; } - put_pcl(lynx, lynx->async_pcl, &pcl); - run_pcl(lynx, lynx->async_pcl_start, 3); + put_pcl(lynx, lynx->async.pcl, &pcl); + run_pcl(lynx, lynx->async.pcl_start, 3); } @@ -440,8 +451,8 @@ int i; u32 *pcli; - lynx->async_queue = NULL; - spin_lock_init(&lynx->async_queue_lock); + lynx->async.queue = NULL; + spin_lock_init(&lynx->async.queue_lock); spin_lock_init(&lynx->phy_reg_lock); pcl.next = pcl_bus(lynx, lynx->rcv_pcl); @@ -456,13 +467,13 @@ pcl.buffer[0].control = PCL_CMD_RCV | PCL_BIGENDIAN | 16; pcl.buffer[1].control = PCL_LAST_BUFF | 4080; #endif - pcl.buffer[0].pointer = virt_to_bus(lynx->rcv_page); - pcl.buffer[1].pointer = virt_to_bus(lynx->rcv_page) + 16; + pcl.buffer[0].pointer = lynx->rcv_page_dma; + pcl.buffer[1].pointer = lynx->rcv_page_dma + 16; put_pcl(lynx, lynx->rcv_pcl, &pcl); - pcl.next = pcl_bus(lynx, lynx->async_pcl); - pcl.async_error_next = pcl_bus(lynx, lynx->async_pcl); - put_pcl(lynx, lynx->async_pcl_start, &pcl); + pcl.next = pcl_bus(lynx, lynx->async.pcl); + pcl.async_error_next = pcl_bus(lynx, lynx->async.pcl); + put_pcl(lynx, lynx->async.pcl_start, &pcl); pcl.next = PCL_NEXT_INVALID; pcl.async_error_next = PCL_NEXT_INVALID; @@ -476,7 +487,7 @@ int page = i / ISORCV_PER_PAGE; int sec = i % ISORCV_PER_PAGE; - pcl.buffer[0].pointer = virt_to_bus(lynx->iso_rcv.page[page]) + pcl.buffer[0].pointer = lynx->iso_rcv.page_dma[page] + sec * MAX_ISORCV_SIZE; pcl.buffer[1].pointer = pcl.buffer[0].pointer + 4; put_pcl(lynx, lynx->iso_rcv.pcl[i], &pcl); @@ -542,7 +553,9 @@ lynx = host->hostdata; remove_card(lynx); } else { +#ifdef CONFIG_IEEE1394_PCILYNX_PORTS unregister_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME); +#endif } } @@ -568,13 +581,13 @@ cpu_to_be32s(&packet->header[3]); } - spin_lock_irqsave(&lynx->async_queue_lock, flags); + spin_lock_irqsave(&lynx->async.queue_lock, flags); - if (lynx->async_queue == NULL) { - lynx->async_queue = packet; + if (lynx->async.queue == NULL) { + lynx->async.queue = packet; send_next_async(lynx); } else { - p = lynx->async_queue; + p = lynx->async.queue; while (p->xnext != NULL) { p = p->xnext; } @@ -582,7 +595,7 @@ p->xnext = packet; } - spin_unlock_irqrestore(&lynx->async_queue_lock, flags); + spin_unlock_irqrestore(&lynx->async.queue_lock, flags); return 1; } @@ -637,13 +650,13 @@ break; case CANCEL_REQUESTS: - spin_lock_irqsave(&lynx->async_queue_lock, flags); + spin_lock_irqsave(&lynx->async.queue_lock, flags); reg_write(lynx, DMA3_CHAN_CTRL, 0); - packet = lynx->async_queue; - lynx->async_queue = NULL; + packet = lynx->async.queue; + lynx->async.queue = NULL; - spin_unlock_irqrestore(&lynx->async_queue_lock, flags); + spin_unlock_irqrestore(&lynx->async.queue_lock, flags); while (packet != NULL) { lastpacket = packet; @@ -696,7 +709,7 @@ * IEEE-1394 functionality section END * ***************************************/ - +#ifdef CONFIG_IEEE1394_PCILYNX_PORTS /* VFS functions for local bus / aux device access. Access to those * is implemented as a character device instead of block devices * because buffers are not wanted for this. Therefore llseek (from @@ -710,7 +723,7 @@ static struct file_operations aux_ops = { - owner: THIS_MODULE, + OWNER_THIS_MODULE /* FIXME: should have custom llseek with bounds checking */ read: mem_read, write: mem_write, @@ -735,18 +748,23 @@ enum { rom, aux, ram } type; struct memdata *md; + V22_COMPAT_MOD_INC_USE_COUNT; + if (cid < PCILYNX_MINOR_AUX_START) { /* just for completeness */ + V22_COMPAT_MOD_DEC_USE_COUNT; return -ENXIO; } else if (cid < PCILYNX_MINOR_ROM_START) { cid -= PCILYNX_MINOR_AUX_START; if (cid >= num_of_cards || !cards[cid].aux_port) { + V22_COMPAT_MOD_DEC_USE_COUNT; return -ENXIO; } type = aux; } else if (cid < PCILYNX_MINOR_RAM_START) { cid -= PCILYNX_MINOR_ROM_START; if (cid >= num_of_cards || !cards[cid].local_rom) { + V22_COMPAT_MOD_DEC_USE_COUNT; return -ENXIO; } type = rom; @@ -755,6 +773,7 @@ * It is currently used inside the driver! */ cid -= PCILYNX_MINOR_RAM_START; if (cid >= num_of_cards || !cards[cid].local_ram) { + V22_COMPAT_MOD_DEC_USE_COUNT; return -ENXIO; } type = ram; @@ -762,6 +781,7 @@ md = (struct memdata *)vmalloc(sizeof(struct memdata)); if (md == NULL) { + V22_COMPAT_MOD_DEC_USE_COUNT; return -ENOMEM; } @@ -793,6 +813,7 @@ vfree(md); + V22_COMPAT_MOD_DEC_USE_COUNT; return 0; } @@ -801,16 +822,15 @@ struct memdata *md = (struct memdata *)file->private_data; int cid = md->cid; unsigned int mask; - int intr_seen; /* reading and writing is always allowed */ mask = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM; if (md->type == aux) { poll_wait(file, &cards[cid].aux_intr_wait, pt); - intr_seen = atomic_read(&cards[cid].aux_intr_seen); - if (atomic_read(&md->aux_intr_last_seen) != intr_seen) { + if (atomic_read(&md->aux_intr_last_seen) + != atomic_read(&cards[cid].aux_intr_seen)) { mask |= POLLPRI; atomic_inc(&md->aux_intr_last_seen); } @@ -956,7 +976,7 @@ } while (bcount >= 4) { - retval = mem_dmaread(md, virt_to_phys(md->lynx->mem_dma_buffer) + retval = mem_dmaread(md, md->lynx->mem_dma_buffer_dma + count - bcount, bcount, off); if (retval < 0) return retval; @@ -1008,7 +1028,7 @@ file->f_pos += count; return count; } - +#endif /* CONFIG_IEEE1394_PCILYNX_PORTS */ /******************************************************** @@ -1028,6 +1048,7 @@ reg_write(lynx, LINK_INT_STATUS, linkint); //printk("-%d- one interrupt: 0x%08x / 0x%08x\n", lynx->id, intmask, linkint); +#ifdef CONFIG_IEEE1394_PCILYNX_PORTS if (intmask & PCI_INT_AUX_INT) { atomic_inc(&lynx->aux_intr_seen); wake_up_interruptible(&lynx->aux_intr_wait); @@ -1036,6 +1057,7 @@ if (intmask & PCI_INT_DMA0_HLT) { wake_up_interruptible(&lynx->mem_dma_intr_wait); } +#endif if (intmask & PCI_INT_1394) { @@ -1108,17 +1130,24 @@ u32 ack; struct hpsb_packet *packet; - spin_lock(&lynx->async_queue_lock); + spin_lock(&lynx->async.queue_lock); ack = reg_read(lynx, DMA3_CHAN_STAT); - packet = lynx->async_queue; - lynx->async_queue = packet->xnext; + packet = lynx->async.queue; + lynx->async.queue = packet->xnext; + + pci_unmap_single(lynx->dev, lynx->async.header_dma, + packet->header_size, PCI_DMA_TODEVICE); + if (packet->data_size) { + pci_unmap_single(lynx->dev, lynx->async.data_dma, + packet->data_size, PCI_DMA_TODEVICE); + } - if (lynx->async_queue != NULL) { + if (lynx->async.queue != NULL) { send_next_async(lynx); } - spin_unlock(&lynx->async_queue_lock); + spin_unlock(&lynx->async.queue_lock); if (ack & DMA_CHAN_STAT_SPECIALACK) { ack = (ack >> 15) & 0xf; @@ -1150,7 +1179,7 @@ || (*q_data >> 4 & 0xf) == TCODE_WRITEQ) { cpu_to_be32s(q_data + 3); } - hpsb_packet_received(host, q_data, stat & 0x1fff); + hpsb_packet_received(host, q_data, stat & 0x1fff, 0); } run_pcl(lynx, lynx->rcv_pcl_start, 1); @@ -1184,7 +1213,8 @@ "iso receive error on %d to 0x%p", idx, data); } else { hpsb_packet_received(lynx->host, data, - lynx->iso_rcv.stat[idx] & 0x1fff); + lynx->iso_rcv.stat[idx] & 0x1fff, + 0); } spin_lock_irqsave(&lynx->iso_rcv.lock, flags); @@ -1210,12 +1240,11 @@ } while (0) struct ti_lynx *lynx; /* shortcut to currently handled device */ - unsigned long page; unsigned int i; if (num_of_cards == MAX_PCILYNX_CARDS) { PRINT_G(KERN_WARNING, "cannot handle more than %d cards. " - "Adjust MAX_PCILYNX_CARDS in ti_pcilynx.h.", + "Adjust MAX_PCILYNX_CARDS in pcilynx.h.", MAX_PCILYNX_CARDS); return 1; } @@ -1225,6 +1254,10 @@ lynx->id = num_of_cards-1; lynx->dev = dev; + if (!pci_dma_supported(dev, 0xffffffff)) { + FAIL("DMA address limits not supported for PCILynx hardware %d", + lynx->id); + } if (pci_enable_device(dev)) { FAIL("failed to enable PCILynx hardware %d", lynx->id); } @@ -1239,61 +1272,50 @@ } #ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM - lynx->pcl_mem = kmalloc(8 * sizeof(lynx->pcl_bmap) - * sizeof(struct ti_pcl), GFP_KERNEL); + lynx->pcl_mem = pci_alloc_consistent(dev, LOCALRAM_SIZE, + &lynx->pcl_mem_dma); if (lynx->pcl_mem != NULL) { lynx->state = have_pcl_mem; PRINT(KERN_INFO, lynx->id, - "allocated PCL memory %d Bytes @ 0x%p", - 8 * sizeof(lynx->pcl_bmap) * sizeof(struct ti_pcl), + "allocated PCL memory %d Bytes @ 0x%p", LOCALRAM_SIZE, lynx->pcl_mem); } else { FAIL("failed to allocate PCL memory area"); } #endif - lynx->mem_dma_buffer = kmalloc(65536, GFP_KERNEL); - if (lynx->mem_dma_buffer != NULL) { - lynx->state = have_aux_buf; - } else { +#ifdef CONFIG_IEEE1394_PCILYNX_PORTS + lynx->mem_dma_buffer = pci_alloc_consistent(dev, 65536, + &lynx->mem_dma_buffer_dma); + if (lynx->mem_dma_buffer == NULL) { FAIL("failed to allocate DMA buffer for aux"); } + lynx->state = have_aux_buf; +#endif - page = get_free_page(GFP_KERNEL); - if (page != 0) { - lynx->rcv_page = (void *)page; - lynx->state = have_1394_buffers; - } else { + lynx->rcv_page = pci_alloc_consistent(dev, PAGE_SIZE, + &lynx->rcv_page_dma); + if (lynx->rcv_page == NULL) { FAIL("failed to allocate receive buffer"); } + lynx->state = have_1394_buffers; for (i = 0; i < ISORCV_PAGES; i++) { - page = get_free_page(GFP_KERNEL); - if (page != 0) { - lynx->iso_rcv.page[i] = (void *)page; - } else { + lynx->iso_rcv.page[i] = + pci_alloc_consistent(dev, PAGE_SIZE, + &lynx->iso_rcv.page_dma[i]); + if (lynx->iso_rcv.page[i] == NULL) { FAIL("failed to allocate iso receive buffers"); } } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) - lynx->registers = ioremap_nocache(dev->base_address[0], - PCILYNX_MAX_REGISTER); - lynx->local_ram = ioremap(dev->base_address[1], PCILYNX_MAX_MEMORY); - lynx->aux_port = ioremap(dev->base_address[2], PCILYNX_MAX_MEMORY); -#else lynx->registers = ioremap_nocache(pci_resource_start(dev,0), PCILYNX_MAX_REGISTER); lynx->local_ram = ioremap(pci_resource_start(dev,1), PCILYNX_MAX_MEMORY); - lynx->aux_port = ioremap(pci_resource_start(dev,2), PCILYNX_MAX_MEMORY); -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,15) - lynx->local_rom = ioremap(dev->rom_address, PCILYNX_MAX_MEMORY); -#else + lynx->aux_port = ioremap(pci_resource_start(dev,2), PCILYNX_MAX_MEMORY); lynx->local_rom = ioremap(pci_resource_start(dev,PCI_ROM_RESOURCE), PCILYNX_MAX_MEMORY); -#endif lynx->state = have_iomappings; if (lynx->registers == NULL) { @@ -1309,15 +1331,17 @@ /* alloc_pcl return values are not checked, it is expected that the * provided PCL space is sufficient for the initial allocations */ +#ifdef CONFIG_IEEE1394_PCILYNX_PORTS if (lynx->aux_port != NULL) { lynx->dmem_pcl = alloc_pcl(lynx); aux_setup_pcls(lynx); sema_init(&lynx->mem_dma_mutex, 1); } +#endif lynx->rcv_pcl = alloc_pcl(lynx); lynx->rcv_pcl_start = alloc_pcl(lynx); - lynx->async_pcl = alloc_pcl(lynx); - lynx->async_pcl_start = alloc_pcl(lynx); + lynx->async.pcl = alloc_pcl(lynx); + lynx->async.pcl_start = alloc_pcl(lynx); for (i = 0; i < NUM_ISORCV_PCL; i++) { lynx->iso_rcv.pcl[i] = alloc_pcl(lynx); @@ -1330,8 +1354,10 @@ reg_write(lynx, PCI_INT_ENABLE, PCI_INT_AUX_INT | PCI_INT_DMA_ALL); +#ifdef CONFIG_IEEE1394_PCILYNX_PORTS init_waitqueue_head(&lynx->mem_dma_intr_wait); init_waitqueue_head(&lynx->aux_intr_wait); +#endif lynx->iso_rcv.tq.routine = (void (*)(void*))iso_rcv_bh; lynx->iso_rcv.tq.data = lynx; @@ -1372,15 +1398,22 @@ case have_1394_buffers: for (i = 0; i < ISORCV_PAGES; i++) { if (lynx->iso_rcv.page[i]) { - free_page((unsigned long)lynx->iso_rcv.page[i]); + pci_free_consistent(lynx->dev, PAGE_SIZE, + lynx->iso_rcv.page[i], + lynx->iso_rcv.page_dma[i]); } } - free_page((unsigned long)lynx->rcv_page); + pci_free_consistent(lynx->dev, PAGE_SIZE, lynx->rcv_page, + lynx->rcv_page_dma); case have_aux_buf: - kfree(lynx->mem_dma_buffer); +#ifdef CONFIG_IEEE1394_PCILYNX_PORTS + pci_free_consistent(lynx->dev, 65536, lynx->mem_dma_buffer, + lynx->mem_dma_buffer_dma); +#endif case have_pcl_mem: #ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM - kfree(lynx->pcl_mem); + pci_free_consistent(lynx->dev, LOCALRAM_SIZE, lynx->pcl_mem, + lynx->pcl_mem_dma); #endif case have_intr: free_irq(lynx->dev->irq, lynx); @@ -1416,11 +1449,13 @@ return -ENXIO; } +#ifdef CONFIG_IEEE1394_PCILYNX_PORTS if (register_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME, &aux_ops)) { PRINT_G(KERN_ERR, "allocation of char major number %d failed", PCILYNX_MAJOR); return -EBUSY; } +#endif return 0; } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/pcilynx.h linux/drivers/ieee1394/pcilynx.h --- v2.4.0-test2/linux/drivers/ieee1394/pcilynx.h Fri Jun 23 21:55:09 2000 +++ linux/drivers/ieee1394/pcilynx.h Wed Jul 5 13:03:56 2000 @@ -12,7 +12,7 @@ #define PCI_DEVICE_ID_TI_PCILYNX 0x8000 #define MAX_PCILYNX_CARDS 4 -#define LOCALRAM_SIZE 64 +#define LOCALRAM_SIZE 4096 #define NUM_ISORCV_PCL 4 #define MAX_ISORCV_SIZE 2048 @@ -50,23 +50,27 @@ void *aux_port; +#ifdef CONFIG_IEEE1394_PCILYNX_PORTS atomic_t aux_intr_seen; wait_queue_head_t aux_intr_wait; void *mem_dma_buffer; + dma_addr_t mem_dma_buffer_dma; struct semaphore mem_dma_mutex; wait_queue_head_t mem_dma_intr_wait; +#endif /* - * use local RAM of LOCALRAM_SIZE (in kB) for PCLs, which allows for + * use local RAM of LOCALRAM_SIZE bytes for PCLs, which allows for * LOCALRAM_SIZE * 8 PCLs (each sized 128 bytes); * the following is an allocation bitmap */ - u8 pcl_bmap[LOCALRAM_SIZE]; + u8 pcl_bmap[LOCALRAM_SIZE / 1024]; -#ifndef CONFIG_IEEE1394_LYNXRAM +#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM /* point to PCLs memory area if needed */ void *pcl_mem; + dma_addr_t pcl_mem_dma; #endif /* PCLs for local mem / aux transfers */ @@ -81,16 +85,21 @@ pcl_t rcv_pcl_start, rcv_pcl; void *rcv_page; + dma_addr_t rcv_page_dma; int rcv_active; - pcl_t async_pcl_start, async_pcl; - struct hpsb_packet *async_queue; - spinlock_t async_queue_lock; + struct { + pcl_t pcl_start, pcl; + struct hpsb_packet *queue; + spinlock_t queue_lock; + dma_addr_t header_dma, data_dma; + } async; struct { pcl_t pcl[NUM_ISORCV_PCL]; u32 stat[NUM_ISORCV_PCL]; void *page[ISORCV_PAGES]; + dma_addr_t page_dma[ISORCV_PAGES]; pcl_t pcl_start; int chan_count; int next, last, used, running; @@ -381,11 +390,7 @@ inline static u32 pcl_bus(const struct ti_lynx *lynx, pcl_t pclid) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) - return lynx->dev->base_address[1] + pclid * sizeof(struct ti_pcl); -#else - return lynx->dev->resource[1].start + pclid * sizeof(struct ti_pcl); -#endif + return pci_resource_start(lynx->dev, 1) + pclid * sizeof(struct ti_pcl); } #else /* CONFIG_IEEE1394_PCILYNX_LOCALRAM */ @@ -407,7 +412,7 @@ inline static u32 pcl_bus(const struct ti_lynx *lynx, pcl_t pclid) { - return virt_to_bus(lynx->pcl_mem) + pclid * sizeof(struct ti_pcl); + return lynx->pcl_mem_dma + pclid * sizeof(struct ti_pcl); } #endif /* CONFIG_IEEE1394_PCILYNX_LOCALRAM */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/raw1394.c linux/drivers/ieee1394/raw1394.c --- v2.4.0-test2/linux/drivers/ieee1394/raw1394.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/ieee1394/raw1394.c Wed Jul 5 13:03:56 2000 @@ -4,6 +4,9 @@ * Raw interface to the bus * * Copyright (C) 1999, 2000 Andreas E. Bombe + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. */ #include @@ -13,8 +16,13 @@ #include #include #include +#include #include +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) +#include +#endif + #include "ieee1394.h" #include "ieee1394_types.h" #include "ieee1394_core.h" @@ -24,6 +32,8 @@ #include "raw1394.h" +static devfs_handle_t devfs_handle = NULL; + LIST_HEAD(host_info_list); static int host_count = 0; spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED; @@ -257,7 +267,7 @@ req->req.type = RAW1394_REQ_ISO_RECEIVE; req->req.generation = get_hpsb_generation(); req->req.misc = 0; - req->req.recvb = fi->iso_buffer; + req->req.recvb = (u64)fi->iso_buffer; req->req.length = MIN(length, fi->iso_buffer_length); list_add_tail(&req->list, &reqs); @@ -326,7 +336,7 @@ req->req.type = RAW1394_REQ_FCP_REQUEST; req->req.generation = get_hpsb_generation(); req->req.misc = nodeid | (direction << 16); - req->req.recvb = (quadlet_t *)fi->fcp_buffer; + req->req.recvb = (u64)fi->fcp_buffer; req->req.length = length; list_add_tail(&req->list, &reqs); @@ -343,7 +353,7 @@ } -static int dev_read(struct file *file, char *buffer, size_t count, +static ssize_t dev_read(struct file *file, char *buffer, size_t count, loff_t *offset_is_ignored) { struct file_info *fi = (struct file_info *)file->private_data; @@ -376,7 +386,8 @@ req = list_entry(lh, struct pending_request, list); if (req->req.length) { - if (copy_to_user(req->req.recvb, req->data, req->req.length)) { + if (copy_to_user((void *)req->req.recvb, req->data, + req->req.length)) { req->req.error = RAW1394_ERROR_MEMFAULT; } } @@ -507,7 +518,7 @@ } else { fi->listen_channels |= 1ULL << channel; hpsb_listen_channel(hl_handle, fi->host, channel); - fi->iso_buffer = req->req.recvb; + fi->iso_buffer = (void *)req->req.recvb; fi->iso_buffer_length = req->req.length; } } else { @@ -563,7 +574,7 @@ break; case RAW1394_REQ_ASYNC_WRITE: - if (copy_from_user(req->data, req->req.sendb, + if (copy_from_user(req->data, (void *)req->req.sendb, req->req.length)) { req->req.error = RAW1394_ERROR_MEMFAULT; break; @@ -588,7 +599,7 @@ } } - if (copy_from_user(req->data, req->req.sendb, + if (copy_from_user(req->data, (void *)req->req.sendb, req->req.length)) { req->req.error = RAW1394_ERROR_MEMFAULT; break; @@ -646,7 +657,7 @@ if (req->req.length == 4) { quadlet_t x; - if (copy_from_user(&x, req->req.sendb, 4)) { + if (copy_from_user(&x, (void *)req->req.sendb, 4)) { req->req.error = RAW1394_ERROR_MEMFAULT; } @@ -658,7 +669,7 @@ req->req.length); if (!packet) return -ENOMEM; - if (copy_from_user(packet->data, req->req.sendb, + if (copy_from_user(packet->data, (void *)req->req.sendb, req->req.length)) { req->req.error = RAW1394_ERROR_MEMFAULT; } @@ -684,7 +695,7 @@ req->req.misc); if (!packet) return -ENOMEM; - if (copy_from_user(packet->data, req->req.sendb, + if (copy_from_user(packet->data, (void *)req->req.sendb, req->req.length)) { req->req.error = RAW1394_ERROR_MEMFAULT; break; @@ -761,12 +772,12 @@ } -static int dev_write(struct file *file, const char *buffer, size_t count, +static ssize_t dev_write(struct file *file, const char *buffer, size_t count, loff_t *offset_is_ignored) { struct file_info *fi = (struct file_info *)file->private_data; struct pending_request *req; - int retval = 0; + ssize_t retval = 0; if (count != sizeof(struct raw1394_request)) { return -EINVAL; @@ -828,8 +839,11 @@ return -ENXIO; } + V22_COMPAT_MOD_INC_USE_COUNT; + fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL); if (fi == NULL) { + V22_COMPAT_MOD_DEC_USE_COUNT; return -ENOMEM; } @@ -898,6 +912,7 @@ kfree(fi); + V22_COMPAT_MOD_DEC_USE_COUNT; return 0; } @@ -910,7 +925,7 @@ }; static struct file_operations file_ops = { - owner: THIS_MODULE, + OWNER_THIS_MODULE read: dev_read, write: dev_write, poll: dev_poll, @@ -926,18 +941,24 @@ return -ENOMEM; } - if (register_chrdev(RAW1394_DEVICE_MAJOR, RAW1394_DEVICE_NAME, - &file_ops)) { - HPSB_ERR("raw1394 failed to allocate device major"); + devfs_handle = devfs_register(NULL, RAW1394_DEVICE_NAME, DEVFS_FL_NONE, + RAW1394_DEVICE_MAJOR, 0, + S_IFCHR | S_IRUSR | S_IWUSR, &file_ops, + NULL); + + if (devfs_register_chrdev(RAW1394_DEVICE_MAJOR, RAW1394_DEVICE_NAME, + &file_ops)) { + HPSB_ERR("raw1394 failed to register /dev/raw1394 device"); return -EBUSY; } - + printk(KERN_INFO "raw1394: /dev/%s device initialized\n", RAW1394_DEVICE_NAME); return 0; } void cleanup_raw1394(void) { - unregister_chrdev(RAW1394_DEVICE_MAJOR, RAW1394_DEVICE_NAME); + devfs_unregister_chrdev(RAW1394_DEVICE_MAJOR, RAW1394_DEVICE_NAME); + devfs_unregister(devfs_handle); hpsb_unregister_highlevel(hl_handle); } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/raw1394.h linux/drivers/ieee1394/raw1394.h --- v2.4.0-test2/linux/drivers/ieee1394/raw1394.h Mon Mar 27 08:08:24 2000 +++ linux/drivers/ieee1394/raw1394.h Wed Jul 5 13:03:56 2000 @@ -1,11 +1,10 @@ - #ifndef IEEE1394_RAW1394_H #define IEEE1394_RAW1394_H #define RAW1394_DEVICE_MAJOR 171 #define RAW1394_DEVICE_NAME "raw1394" -#define RAW1394_KERNELAPI_VERSION 2 +#define RAW1394_KERNELAPI_VERSION 3 /* state: opened */ #define RAW1394_REQ_INITIALIZE 1 @@ -45,24 +44,27 @@ #define RAW1394_ERROR_TIMEOUT (-1102) +#include + struct raw1394_request { - int type; - int error; - int misc; - - unsigned int generation; - octlet_t address; - - unsigned long tag; - - size_t length; - quadlet_t *sendb; - quadlet_t *recvb; + __u32 type; + __s32 error; + __u32 misc; + + __u32 generation; + __u32 length; + + __u64 address; + + __u64 tag; + + __u64 sendb; + __u64 recvb; }; struct raw1394_khost_list { - int nodes; - char name[32]; + __u32 nodes; + __u8 name[32]; }; #ifdef __KERNEL__ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/video1394.c linux/drivers/ieee1394/video1394.c --- v2.4.0-test2/linux/drivers/ieee1394/video1394.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/ieee1394/video1394.c Wed Jul 5 13:03:56 2000 @@ -0,0 +1,1266 @@ +/* + * video1394.c - video driver for OHCI 1394 boards + * Copyright (C)1999,2000 Sebastien Rougeaux + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ieee1394.h" +#include "ieee1394_types.h" +#include "hosts.h" +#include "ieee1394_core.h" +#include "video1394.h" + +#include "ohci1394.h" + +#define VIDEO1394_MAJOR 172 +#define ISO_CHANNELS 64 +#define ISO_RECEIVE 0 +#define ISO_TRANSMIT 1 + +struct it_dma_prg { + struct dma_cmd begin; + quadlet_t data[4]; + struct dma_cmd end; + quadlet_t pad[4]; /* FIXME: quick hack for memory alignment */ +}; + +struct dma_iso_ctx { + struct ti_ohci *ohci; + int ctx; + int channel; + int last_buffer; + unsigned int num_desc; + unsigned int buf_size; + unsigned int frame_size; + unsigned int packet_size; + unsigned int left_size; + unsigned int nb_cmd; + unsigned char *buf; + struct dma_cmd **ir_prg; + struct it_dma_prg **it_prg; + unsigned int *buffer_status; + int ctrlClear; + int ctrlSet; + int cmdPtr; + int ctxMatch; + wait_queue_head_t waitq; +}; + +struct video_card { + struct ti_ohci *ohci; + + struct dma_iso_ctx **ir_context; + struct dma_iso_ctx **it_context; + struct dma_iso_ctx *current_ctx; +}; + +#ifdef CONFIG_IEEE1394_VERBOSEDEBUG +#define VIDEO1394_DEBUG +#endif + +#ifdef DBGMSG +#undef DBGMSG +#endif + +#ifdef VIDEO1394_DEBUG +#define DBGMSG(card, fmt, args...) \ +printk(KERN_INFO "video1394_%d: " fmt "\n" , card , ## args) +#else +#define DBGMSG(card, fmt, args...) +#endif + +/* print general (card independent) information */ +#define PRINT_G(level, fmt, args...) \ +printk(level "video1394: " fmt "\n" , ## args) + +/* print card specific information */ +#define PRINT(level, card, fmt, args...) \ +printk(level "video1394_%d: " fmt "\n" , card , ## args) + +void irq_handler(int card, quadlet_t isoRecvIntEvent, + quadlet_t isoXmitIntEvent); + +static struct video_card video_cards[MAX_OHCI1394_CARDS]; +static int num_of_video_cards = 0; +static struct video_template video_tmpl = { irq_handler }; + +/* Taken from bttv.c */ +/*******************************/ +/* Memory management functions */ +/*******************************/ + +#define MDEBUG(x) do { } while(0) /* Debug memory management */ + +/* [DaveM] I've recoded most of this so that: + * 1) It's easier to tell what is happening + * 2) It's more portable, especially for translating things + * out of vmalloc mapped areas in the kernel. + * 3) Less unnecessary translations happen. + * + * The code used to assume that the kernel vmalloc mappings + * existed in the page tables of every process, this is simply + * not guarenteed. We now use pgd_offset_k which is the + * defined way to get at the kernel page tables. + */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) +#define page_address(x) (x) +#endif + +/* Given PGD from the address space's page table, return the kernel + * virtual mapping of the physical memory mapped at ADR. + */ +static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) +{ + unsigned long ret = 0UL; + pmd_t *pmd; + pte_t *ptep, pte; + + if (!pgd_none(*pgd)) { + pmd = pmd_offset(pgd, adr); + if (!pmd_none(*pmd)) { + ptep = pte_offset(pmd, adr); + pte = *ptep; + if(pte_present(pte)) + ret = (page_address(pte_page(pte))| + (adr&(PAGE_SIZE-1))); + } + } + MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); + return ret; +} + +static inline unsigned long uvirt_to_bus(unsigned long adr) +{ + unsigned long kva, ret; + + kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr); + ret = virt_to_bus((void *)kva); + MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret)); + return ret; +} + +static inline unsigned long kvirt_to_bus(unsigned long adr) +{ + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = uvirt_to_kva(pgd_offset_k(va), va); + ret = virt_to_bus((void *)kva); + MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret)); + return ret; +} + +/* Here we want the physical address of the memory. + * This is used when initializing the contents of the + * area and marking the pages as reserved. + */ +static inline unsigned long kvirt_to_pa(unsigned long adr) +{ + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = uvirt_to_kva(pgd_offset_k(va), va); + ret = __pa(kva); + MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret)); + return ret; +} + +static void * rvmalloc(unsigned long size) +{ + void * mem; + unsigned long adr, page; + + mem=vmalloc(size); + if (mem) + { + memset(mem, 0, size); /* Clear the ram out, + no junk to the user */ + adr=(unsigned long) mem; + while (size > 0) + { + page = kvirt_to_pa(adr); + mem_map_reserve(MAP_NR(__va(page))); + adr+=PAGE_SIZE; + size-=PAGE_SIZE; + } + } + return mem; +} + +static void rvfree(void * mem, unsigned long size) +{ + unsigned long adr, page; + + if (mem) + { + adr=(unsigned long) mem; + while (size > 0) + { + page = kvirt_to_pa(adr); + mem_map_unreserve(MAP_NR(__va(page))); + adr+=PAGE_SIZE; + size-=PAGE_SIZE; + } + vfree(mem); + } +} + +static int free_dma_iso_ctx(struct dma_iso_ctx **d) +{ + int i; + struct ti_ohci *ohci; + + if ((*d)==NULL) return -1; + + ohci = (struct ti_ohci *)(*d)->ohci; + + DBGMSG(ohci->id, "Freeing dma_iso_ctx %d", (*d)->ctx); + + ohci1394_stop_context(ohci, (*d)->ctrlClear, NULL); + + if ((*d)->buf) rvfree((void *)(*d)->buf, + (*d)->num_desc * (*d)->buf_size); + + if ((*d)->ir_prg) { + for (i=0;i<(*d)->num_desc;i++) + if ((*d)->ir_prg[i]) kfree((*d)->ir_prg[i]); + kfree((*d)->ir_prg); + } + + if ((*d)->it_prg) { + for (i=0;i<(*d)->num_desc;i++) + if ((*d)->it_prg[i]) kfree((*d)->it_prg[i]); + kfree((*d)->it_prg); + } + + if ((*d)->buffer_status) + kfree((*d)->buffer_status); + + kfree(*d); + *d = NULL; + + return 0; +} + +static struct dma_iso_ctx * +alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int ctx, int num_desc, + int buf_size, int channel, unsigned int packet_size) +{ + struct dma_iso_ctx *d=NULL; + int i; + + d = (struct dma_iso_ctx *)kmalloc(sizeof(struct dma_iso_ctx), + GFP_KERNEL); + memset(d, 0, sizeof(struct dma_iso_ctx)); + + if (d==NULL) { + PRINT(KERN_ERR, ohci->id, "failed to allocate dma_iso_ctx"); + return NULL; + } + + d->ohci = (void *)ohci; + d->ctx = ctx; + d->channel = channel; + d->num_desc = num_desc; + d->frame_size = buf_size; + if (buf_size%PAGE_SIZE) + d->buf_size = buf_size + PAGE_SIZE - (buf_size%PAGE_SIZE); + else + d->buf_size = buf_size; + d->last_buffer = -1; + d->buf = NULL; + d->ir_prg = NULL; + init_waitqueue_head(&d->waitq); + + d->buf = rvmalloc(d->num_desc * d->buf_size); + + if (d->buf == NULL) { + PRINT(KERN_ERR, ohci->id, "failed to allocate dma buffer"); + free_dma_iso_ctx(&d); + return NULL; + } + memset(d->buf, 0, d->num_desc * d->buf_size); + + if (type == ISO_RECEIVE) { + d->ctrlSet = OHCI1394_IsoRcvContextControlSet+32*d->ctx; + d->ctrlClear = OHCI1394_IsoRcvContextControlClear+32*d->ctx; + d->cmdPtr = OHCI1394_IsoRcvCommandPtr+32*d->ctx; + d->ctxMatch = OHCI1394_IsoRcvContextMatch+32*d->ctx; + + d->ir_prg = kmalloc(d->num_desc * sizeof(struct dma_cmd *), + GFP_KERNEL); + + if (d->ir_prg == NULL) { + PRINT(KERN_ERR, ohci->id, + "failed to allocate dma ir prg"); + free_dma_iso_ctx(&d); + return NULL; + } + memset(d->ir_prg, 0, d->num_desc * sizeof(struct dma_cmd *)); + + d->nb_cmd = d->buf_size / PAGE_SIZE + 1; + d->left_size = (d->frame_size % PAGE_SIZE) ? + d->frame_size % PAGE_SIZE : PAGE_SIZE; + + for (i=0;inum_desc;i++) { + d->ir_prg[i] = kmalloc(d->nb_cmd * + sizeof(struct dma_cmd), + GFP_KERNEL); + if (d->ir_prg[i] == NULL) { + PRINT(KERN_ERR, ohci->id, + "failed to allocate dma ir prg"); + free_dma_iso_ctx(&d); + return NULL; + } + } + } + else { /* ISO_TRANSMIT */ + d->ctrlSet = OHCI1394_IsoXmitContextControlSet+16*d->ctx; + d->ctrlClear = OHCI1394_IsoXmitContextControlClear+16*d->ctx; + d->cmdPtr = OHCI1394_IsoXmitCommandPtr+16*d->ctx; + + d->it_prg = kmalloc(d->num_desc * sizeof(struct it_dma_prg *), + GFP_KERNEL); + + if (d->it_prg == NULL) { + PRINT(KERN_ERR, ohci->id, + "failed to allocate dma it prg"); + free_dma_iso_ctx(&d); + return NULL; + } + memset(d->it_prg, 0, d->num_desc*sizeof(struct it_dma_prg *)); + + d->packet_size = packet_size; + + if (PAGE_SIZE % packet_size || packet_size>2048) { + PRINT(KERN_ERR, ohci->id, + "Packet size %d not yet supported\n", + packet_size); + free_dma_iso_ctx(&d); + return NULL; + } + + d->nb_cmd = d->frame_size / d->packet_size; + if (d->frame_size % d->packet_size) { + d->nb_cmd++; + d->left_size = d->frame_size % d->packet_size; + } + else + d->left_size = d->packet_size; + + for (i=0;inum_desc;i++) { + d->it_prg[i] = kmalloc(d->nb_cmd * + sizeof(struct it_dma_prg), + GFP_KERNEL); + if (d->it_prg[i] == NULL) { + PRINT(KERN_ERR, ohci->id, + "failed to allocate dma it prg"); + free_dma_iso_ctx(&d); + return NULL; + } + } + } + + d->buffer_status = kmalloc(d->num_desc * sizeof(unsigned int), + GFP_KERNEL); + + if (d->buffer_status == NULL) { + PRINT(KERN_ERR, ohci->id, "failed to allocate dma ir prg"); + free_dma_iso_ctx(&d); + return NULL; + } + memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int)); + + PRINT(KERN_INFO, ohci->id, "Iso %s DMA: %d buffers " + "of size %d allocated for a frame size %d, each with %d prgs", + (type==ISO_RECEIVE) ? "receive" : "transmit", + d->num_desc, d->buf_size, d->frame_size, d->nb_cmd); + + return d; +} + +static void reset_ir_status(struct dma_iso_ctx *d, int n) +{ + int i; + d->ir_prg[n][0].status = 4; + d->ir_prg[n][1].status = PAGE_SIZE-4; + for (i=2;inb_cmd-1;i++) + d->ir_prg[n][i].status = PAGE_SIZE; + d->ir_prg[n][i].status = d->left_size; +} + +static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n) +{ + struct dma_cmd *ir_prg = d->ir_prg[n]; + unsigned long buf = (unsigned long)d->buf+n*d->buf_size; + int i; + + /* the first descriptor will sync and read only 4 bytes */ + ir_prg[0].control = (0x280F << 16) | 4; + ir_prg[0].address = kvirt_to_bus(buf); + ir_prg[0].branchAddress = (virt_to_bus(&(ir_prg[1].control)) + & 0xfffffff0) | 0x1; + + /* the second descriptor will read PAGE_SIZE-4 bytes */ + ir_prg[1].control = (0x280C << 16) | (PAGE_SIZE-4); + ir_prg[1].address = kvirt_to_bus(buf+4); + ir_prg[1].branchAddress = (virt_to_bus(&(ir_prg[2].control)) + & 0xfffffff0) | 0x1; + + for (i=2;inb_cmd-1;i++) { + ir_prg[i].control = (0x280C << 16) | PAGE_SIZE; + ir_prg[i].address = kvirt_to_bus(buf+(i-1)*PAGE_SIZE); + + ir_prg[i].branchAddress = + (virt_to_bus(&(ir_prg[i+1].control)) + & 0xfffffff0) | 0x1; + } + + /* the last descriptor will generate an interrupt */ + ir_prg[i].control = (0x283C << 16) | d->left_size; + ir_prg[i].address = kvirt_to_bus(buf+(i-1)*PAGE_SIZE); +} + +static void initialize_dma_ir_ctx(struct dma_iso_ctx *d, int tag) +{ + struct ti_ohci *ohci = (struct ti_ohci *)d->ohci; + int i; + + ohci1394_stop_context(ohci, d->ctrlClear, NULL); + + for (i=0;inum_desc;i++) { + initialize_dma_ir_prg(d, i); + reset_ir_status(d, i); + } + + /* Set bufferFill, no header */ + reg_write(ohci, d->ctrlSet, 0x80000000); + + /* Set the context match register to match on all tags, + sync for sync tag, and listen to d->channel */ + reg_write(ohci, d->ctxMatch, 0xf0000000|((tag&0xf)<<8)|d->channel); + + /* Set up isoRecvIntMask to generate interrupts */ + reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1<ctx); +} + +/* find which context is listening to this channel */ +int ir_ctx_listening(struct video_card *video, int channel) +{ + int i; + struct ti_ohci *ohci = video->ohci; + + for (i=0;inb_iso_rcv_ctx-1;i++) + if (video->ir_context[i]) { + if (video->ir_context[i]->channel==channel) + return i; + } + + PRINT(KERN_ERR, ohci->id, + "no iso context is listening to channel %d", + channel); + return -1; +} + +int it_ctx_talking(struct video_card *video, int channel) +{ + int i; + struct ti_ohci *ohci = video->ohci; + + for (i=0;inb_iso_xmit_ctx;i++) + if (video->it_context[i]) { + if (video->it_context[i]->channel==channel) + return i; + } + + PRINT(KERN_ERR, ohci->id, + "no iso context is talking to channel %d", + channel); + return -1; +} + +int wakeup_dma_ir_ctx(struct ti_ohci *ohci, struct dma_iso_ctx *d) +{ + int i; + + if (d==NULL) { + PRINT(KERN_ERR, ohci->id, "Iso receive event received but " + "context not allocated"); + return -EFAULT; + } + + for (i=0;inum_desc;i++) { + if (d->ir_prg[i][d->nb_cmd-1].status & 0xFFFF0000) { + reset_ir_status(d, i); + d->buffer_status[i] = VIDEO1394_BUFFER_READY; + } + } + if (waitqueue_active(&d->waitq)) wake_up_interruptible(&d->waitq); + return 0; +} + +int wakeup_dma_it_ctx(struct ti_ohci *ohci, struct dma_iso_ctx *d) +{ + int i; + + if (d==NULL) { + PRINT(KERN_ERR, ohci->id, "Iso transmit event received but " + "context not allocated"); + return -EFAULT; + } + + for (i=0;inum_desc;i++) { + if (d->it_prg[i][d->nb_cmd-1].end.status & 0xFFFF0000) { + d->it_prg[i][d->nb_cmd-1].end.status = 0; + d->buffer_status[i] = VIDEO1394_BUFFER_READY; + } + } + if (waitqueue_active(&d->waitq)) wake_up_interruptible(&d->waitq); + return 0; +} + +static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag) +{ + struct it_dma_prg *it_prg = d->it_prg[n]; + unsigned long buf = (unsigned long)d->buf+n*d->buf_size; + int i; + + for (i=0;inb_cmd;i++) { + + it_prg[i].begin.control = OUTPUT_MORE_IMMEDIATE | 8 ; + it_prg[i].begin.address = 0; + + it_prg[i].begin.status = 0; + + /* FIXME: what is the tag value + speed selection */ + it_prg[i].data[0] = + (DMA_SPEED_400<<16) | (d->channel<<8) | 0xa0; + if (i==0) it_prg[i].data[0] |= sync_tag; + it_prg[i].data[1] = d->packet_size << 16; + it_prg[i].data[2] = 0; + it_prg[i].data[3] = 0; + + it_prg[i].end.control = 0x100c0000; + it_prg[i].end.address = + kvirt_to_bus(buf+i*d->packet_size); + + if (inb_cmd-1) { + it_prg[i].end.control |= d->packet_size; + it_prg[i].begin.branchAddress = + (virt_to_bus(&(it_prg[i+1].begin.control)) + & 0xfffffff0) | 0x3; + it_prg[i].end.branchAddress = + (virt_to_bus(&(it_prg[i+1].begin.control)) + & 0xfffffff0) | 0x3; + } + else { + /* the last prg generates an interrupt */ + it_prg[i].end.control |= 0x08300000 | d->left_size; + /* the last prg doesn't branch */ + it_prg[i].begin.branchAddress = 0; + it_prg[i].end.branchAddress = 0; + } + it_prg[i].end.status = 0; + +#if 0 + printk("%d:%d: %08x-%08x ctrl %08x brch %08x d0 %08x d1 %08x\n",n,i, + virt_to_bus(&(it_prg[i].begin.control)), + virt_to_bus(&(it_prg[i].end.control)), + it_prg[i].end.control, + it_prg[i].end.branchAddress, + it_prg[i].data[0], it_prg[i].data[1]); +#endif + } +} + +static void initialize_dma_it_ctx(struct dma_iso_ctx *d, int sync_tag) +{ + struct ti_ohci *ohci = (struct ti_ohci *)d->ohci; + int i; + + ohci1394_stop_context(ohci, d->ctrlClear, NULL); + + for (i=0;inum_desc;i++) + initialize_dma_it_prg(d, i, sync_tag); + + /* Set up isoRecvIntMask to generate interrupts */ + reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1<ctx); +} + +static int do_iso_mmap(struct ti_ohci *ohci, struct dma_iso_ctx *d, + const char *adr, unsigned long size) +{ + unsigned long start=(unsigned long) adr; + unsigned long page,pos; + + if (size>d->num_desc * d->buf_size) { + PRINT(KERN_ERR, ohci->id, + "iso context %d buf size is different from mmap size", + d->ctx); + return -EINVAL; + } + if (!d->buf) { + PRINT(KERN_ERR, ohci->id, + "iso context %d is not allocated", d->ctx); + return -EINVAL; + } + + pos=(unsigned long) d->buf; + while (size > 0) { + page = kvirt_to_pa(pos); + if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) + return -EAGAIN; + start+=PAGE_SIZE; + pos+=PAGE_SIZE; + size-=PAGE_SIZE; + } + return 0; +} + +static int video1394_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct video_card *video = &video_cards[MINOR(inode->i_rdev)]; + struct ti_ohci *ohci= video->ohci; + + switch(cmd) + { + case VIDEO1394_LISTEN_CHANNEL: + case VIDEO1394_TALK_CHANNEL: + { + struct video1394_mmap v; + int i; + + if(copy_from_user(&v, (void *)arg, sizeof(v))) + return -EFAULT; + if (v.channel<0 || v.channel>(ISO_CHANNELS-1)) { + PRINT(KERN_ERR, ohci->id, + "iso channel %d out of bound", v.channel); + return -EFAULT; + } + if (test_and_set_bit(v.channel, &ohci->IR_channel_usage)) { + PRINT(KERN_ERR, ohci->id, + "channel %d is already taken", v.channel); + return -EFAULT; + } + + if (v.buf_size<=0) { + PRINT(KERN_ERR, ohci->id, + "Invalid %d length buffer requested",v.buf_size); + return -EFAULT; + } + + if (v.nb_buffers<=0) { + PRINT(KERN_ERR, ohci->id, + "Invalid %d buffers requested",v.nb_buffers); + return -EFAULT; + } + + if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) { + PRINT(KERN_ERR, ohci->id, + "%d buffers of size %d bytes is too big", + v.nb_buffers, v.buf_size); + return -EFAULT; + } + + if (cmd == VIDEO1394_LISTEN_CHANNEL) { + /* find a free iso receive context */ + for (i=0;inb_iso_rcv_ctx-1;i++) + if (video->ir_context[i]==NULL) break; + + if (i==(ohci->nb_iso_rcv_ctx-1)) { + PRINT(KERN_ERR, ohci->id, + "no iso context available"); + return -EFAULT; + } + + video->ir_context[i] = + alloc_dma_iso_ctx(ohci, ISO_RECEIVE, i+1, + v.nb_buffers, v.buf_size, + v.channel, 0); + + if (video->ir_context[i] == NULL) { + PRINT(KERN_ERR, ohci->id, + "Couldn't allocate ir context"); + return -EFAULT; + } + initialize_dma_ir_ctx(video->ir_context[i], + v.sync_tag); + + video->current_ctx = video->ir_context[i]; + + v.buf_size = video->ir_context[i]->buf_size; + + PRINT(KERN_INFO, ohci->id, + "iso context %d listen on channel %d", i+1, + v.channel); + } + else { + /* find a free iso transmit context */ + for (i=0;inb_iso_xmit_ctx;i++) + if (video->it_context[i]==NULL) break; + + if (i==ohci->nb_iso_xmit_ctx) { + PRINT(KERN_ERR, ohci->id, + "no iso context available"); + return -EFAULT; + } + + video->it_context[i] = + alloc_dma_iso_ctx(ohci, ISO_TRANSMIT, i, + v.nb_buffers, v.buf_size, + v.channel, v.packet_size); + + if (video->it_context[i] == NULL) { + PRINT(KERN_ERR, ohci->id, + "Couldn't allocate it context"); + return -EFAULT; + } + initialize_dma_it_ctx(video->it_context[i], + v.sync_tag); + + video->current_ctx = video->it_context[i]; + + v.buf_size = video->it_context[i]->buf_size; + + PRINT(KERN_INFO, ohci->id, + "iso context %d talk on channel %d", i, + v.channel); + } + + if(copy_to_user((void *)arg, &v, sizeof(v))) + return -EFAULT; + + return 0; + } + case VIDEO1394_UNLISTEN_CHANNEL: + case VIDEO1394_UNTALK_CHANNEL: + { + int channel; + int i; + + if(copy_from_user(&channel, (void *)arg, sizeof(int))) + return -EFAULT; + + if (!test_and_clear_bit(channel, &ohci->IR_channel_usage)) { + PRINT(KERN_ERR, ohci->id, + "channel %d is not being used", channel); + return -EFAULT; + } + + if (cmd == VIDEO1394_UNLISTEN_CHANNEL) { + i = ir_ctx_listening(video, channel); + if (i<0) return -EFAULT; + + free_dma_iso_ctx(&video->ir_context[i]); + + PRINT(KERN_INFO, ohci->id, + "iso context %d stop listening on channel %d", + i+1, channel); + } + else { + i = it_ctx_talking(video, channel); + if (i<0) return -EFAULT; + + free_dma_iso_ctx(&video->it_context[i]); + + PRINT(KERN_INFO, ohci->id, + "iso context %d stop talking on channel %d", + i, channel); + } + + return 0; + } + case VIDEO1394_LISTEN_QUEUE_BUFFER: + { + struct video1394_wait v; + struct dma_iso_ctx *d; + int i; + + if(copy_from_user(&v, (void *)arg, sizeof(v))) + return -EFAULT; + + i = ir_ctx_listening(video, v.channel); + if (i<0) return -EFAULT; + d = video->ir_context[i]; + + if ((v.buffer<0) || (v.buffer>d->num_desc)) { + PRINT(KERN_ERR, ohci->id, + "buffer %d out of range",v.buffer); + return -EFAULT; + } + + if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) { + PRINT(KERN_ERR, ohci->id, + "buffer %d is already used",v.buffer); + return -EFAULT; + } + + d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED; + + if (d->last_buffer>=0) + d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = + (virt_to_bus(&(d->ir_prg[v.buffer][0].control)) + & 0xfffffff0) | 0x1; + + d->last_buffer = v.buffer; + + d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = 0; + + if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) + { + DBGMSG(ohci->id, "Starting iso DMA ctx=%d",d->ctx); + + /* Tell the controller where the first program is */ + reg_write(ohci, d->cmdPtr, + virt_to_bus(&(d->ir_prg[v.buffer][0]))|0x1); + + /* Run IR context */ + reg_write(ohci, d->ctrlSet, 0x8000); + } + else { + /* Wake up dma context if necessary */ + if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { + PRINT(KERN_INFO, ohci->id, + "Waking up iso dma ctx=%d", d->ctx); + reg_write(ohci, d->ctrlSet, 0x1000); + } + } + return 0; + + } + case VIDEO1394_LISTEN_WAIT_BUFFER: + { + struct video1394_wait v; + struct dma_iso_ctx *d; + int i; + + if(copy_from_user(&v, (void *)arg, sizeof(v))) + return -EFAULT; + + i = ir_ctx_listening(video, v.channel); + if (i<0) return -EFAULT; + d = video->ir_context[i]; + + if ((v.buffer<0) || (v.buffer>d->num_desc)) { + PRINT(KERN_ERR, ohci->id, + "buffer %d out of range",v.buffer); + return -EFAULT; + } + + switch(d->buffer_status[v.buffer]) { + case VIDEO1394_BUFFER_READY: + d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; + return 0; + case VIDEO1394_BUFFER_QUEUED: +#if 1 + while(d->buffer_status[v.buffer]!= + VIDEO1394_BUFFER_READY) { + interruptible_sleep_on(&d->waitq); + if(signal_pending(current)) return -EINTR; + } +#else + if (wait_event_interruptible(d->waitq, + d->buffer_status[v.buffer] + == VIDEO1394_BUFFER_READY) + == -ERESTARTSYS) + return -EINTR; +#endif + d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; + return 0; + default: + PRINT(KERN_ERR, ohci->id, + "buffer %d is not queued",v.buffer); + return -EFAULT; + } + } + case VIDEO1394_TALK_QUEUE_BUFFER: + { + struct video1394_wait v; + struct dma_iso_ctx *d; + int i; + + if(copy_from_user(&v, (void *)arg, sizeof(v))) + return -EFAULT; + + i = it_ctx_talking(video, v.channel); + if (i<0) return -EFAULT; + d = video->it_context[i]; + + if ((v.buffer<0) || (v.buffer>d->num_desc)) { + PRINT(KERN_ERR, ohci->id, + "buffer %d out of range",v.buffer); + return -EFAULT; + } + + if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) { + PRINT(KERN_ERR, ohci->id, + "buffer %d is already used",v.buffer); + return -EFAULT; + } + + d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED; + + if (d->last_buffer>=0) { + d->it_prg[d->last_buffer] + [d->nb_cmd-1].end.branchAddress = + (virt_to_bus(&(d->it_prg[v.buffer][0].begin.control)) + & 0xfffffff0) | 0x3; + + d->it_prg[d->last_buffer] + [d->nb_cmd-1].begin.branchAddress = + (virt_to_bus(&(d->it_prg[v.buffer][0].begin.control)) + & 0xfffffff0) | 0x3; + } + d->last_buffer = v.buffer; + + d->it_prg[d->last_buffer][d->nb_cmd-1].end.branchAddress = 0; + + if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) + { + DBGMSG(ohci->id, "Starting iso transmit DMA ctx=%d", + d->ctx); + + /* Tell the controller where the first program is */ + reg_write(ohci, d->cmdPtr, + virt_to_bus(&(d->it_prg[v.buffer][0]))|0x3); + + /* Run IT context */ + reg_write(ohci, d->ctrlSet, 0x8000); + } + else { + /* Wake up dma context if necessary */ + if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { + PRINT(KERN_INFO, ohci->id, + "Waking up iso transmit dma ctx=%d", + d->ctx); + reg_write(ohci, d->ctrlSet, 0x1000); + } + } + return 0; + + } + case VIDEO1394_TALK_WAIT_BUFFER: + { + struct video1394_wait v; + struct dma_iso_ctx *d; + int i; + + if(copy_from_user(&v, (void *)arg, sizeof(v))) + return -EFAULT; + + i = it_ctx_talking(video, v.channel); + if (i<0) return -EFAULT; + d = video->it_context[i]; + + if ((v.buffer<0) || (v.buffer>d->num_desc)) { + PRINT(KERN_ERR, ohci->id, + "buffer %d out of range",v.buffer); + return -EFAULT; + } + + switch(d->buffer_status[v.buffer]) { + case VIDEO1394_BUFFER_READY: + d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; + return 0; + case VIDEO1394_BUFFER_QUEUED: +#if 1 + while(d->buffer_status[v.buffer]!= + VIDEO1394_BUFFER_READY) { + interruptible_sleep_on(&d->waitq); + if(signal_pending(current)) return -EINTR; + } +#else + if (wait_event_interruptible(d->waitq, + d->buffer_status[v.buffer] + == VIDEO1394_BUFFER_READY) + == -ERESTARTSYS) + return -EINTR; +#endif + d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; + return 0; + default: + PRINT(KERN_ERR, ohci->id, + "buffer %d is not queued",v.buffer); + return -EFAULT; + } + } + default: + return -EINVAL; + } +} + +/* + * This maps the vmalloced and reserved buffer to user space. + * + * FIXME: + * - PAGE_READONLY should suffice!? + * - remap_page_range is kind of inefficient for page by page remapping. + * But e.g. pte_alloc() does not work in modules ... :-( + */ + +int video1394_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct video_card *video = + &video_cards[MINOR(file->f_dentry->d_inode->i_rdev)]; + struct ti_ohci *ohci= video->ohci; + + PRINT(KERN_INFO, ohci->id, "mmap"); + if (video->current_ctx == NULL) { + PRINT(KERN_ERR, ohci->id, "current iso context not set"); + return -EINVAL; + } + + return do_iso_mmap(ohci, video->current_ctx, + (char *)vma->vm_start, + (unsigned long)(vma->vm_end-vma->vm_start)); + return 0; +} + +static int video1394_open(struct inode *inode, struct file *file) +{ + int i = MINOR(inode->i_rdev); + + if (i<0 || i>=num_of_video_cards) { + PRINT(KERN_ERR, i, "ohci card %d not found", i); + return -EIO; + } + + V22_COMPAT_MOD_INC_USE_COUNT; + + PRINT(KERN_INFO, i, "open"); + + return 0; +} + +static int video1394_release(struct inode *inode, struct file *file) +{ + struct video_card *video = &video_cards[MINOR(inode->i_rdev)]; + struct ti_ohci *ohci= video->ohci; + int i; + + for (i=0;inb_iso_rcv_ctx-1;i++) + if (video->ir_context[i]) { + if (!test_and_clear_bit( + video->ir_context[i]->channel, + &ohci->IR_channel_usage)) { + PRINT(KERN_ERR, ohci->id, + "channel %d is not being used", + video->ir_context[i]->channel); + } + PRINT(KERN_INFO, ohci->id, + "iso receive context %d stop listening " + "on channel %d", i+1, + video->ir_context[i]->channel); + free_dma_iso_ctx(&video->ir_context[i]); + } + + for (i=0;inb_iso_xmit_ctx;i++) + if (video->it_context[i]) { + if (!test_and_clear_bit( + video->it_context[i]->channel, + &ohci->IR_channel_usage)) { + PRINT(KERN_ERR, ohci->id, + "channel %d is not being used", + video->it_context[i]->channel); + } + PRINT(KERN_INFO, ohci->id, + "iso transmit context %d stop talking " + "on channel %d", i+1, + video->it_context[i]->channel); + free_dma_iso_ctx(&video->it_context[i]); + } + + + V22_COMPAT_MOD_DEC_USE_COUNT; + + PRINT(KERN_INFO, ohci->id, "release"); + return 0; +} + +void irq_handler(int card, quadlet_t isoRecvIntEvent, + quadlet_t isoXmitIntEvent) +{ + int i; + struct video_card *video = &video_cards[card]; + + DBGMSG(card, "Iso event Recv: %08x Xmit: %08x", + isoRecvIntEvent, isoXmitIntEvent); + + for (i=0;iohci->nb_iso_rcv_ctx-1;i++) + if (isoRecvIntEvent & (1<<(i+1))) + wakeup_dma_ir_ctx(video->ohci, + video->ir_context[i]); + + for (i=0;iohci->nb_iso_xmit_ctx;i++) + if (isoXmitIntEvent & (1<ohci, + video->it_context[i]); +} + +static struct file_operations video1394_fops= +{ + OWNER_THIS_MODULE + ioctl: video1394_ioctl, + mmap: video1394_mmap, + open: video1394_open, + release: video1394_release +}; + +static int video1394_init(int i, struct ti_ohci *ohci) +{ + struct video_card *video = &video_cards[i]; + + if (ohci1394_register_video(ohci, &video_tmpl)<0) { + PRINT(KERN_ERR, i, "register_video failed"); + return -1; + } + + video->ohci = ohci; + + /* Iso receive dma contexts */ + video->ir_context = (struct dma_iso_ctx **) + kmalloc((ohci->nb_iso_rcv_ctx-1)* + sizeof(struct dma_iso_ctx *), GFP_KERNEL); + if (video->ir_context) + memset(video->ir_context, 0, + (ohci->nb_iso_rcv_ctx-1)*sizeof(struct dma_iso_ctx *)); + else { + PRINT(KERN_ERR, ohci->id, "Cannot allocate ir_context"); + return -1; + } + + /* Iso transmit dma contexts */ + video->it_context = (struct dma_iso_ctx **) + kmalloc(ohci->nb_iso_xmit_ctx * + sizeof(struct dma_iso_ctx *), GFP_KERNEL); + if (video->it_context) + memset(video->it_context, 0, + ohci->nb_iso_xmit_ctx * sizeof(struct dma_iso_ctx *)); + else { + PRINT(KERN_ERR, ohci->id, "Cannot allocate it_context"); + return -1; + } + + return 0; +} + +static void remove_card(struct video_card *video) +{ + int i; + + ohci1394_unregister_video(video->ohci, &video_tmpl); + + /* Free the iso receive contexts */ + if (video->ir_context) { + for (i=0;iohci->nb_iso_rcv_ctx-1;i++) { + free_dma_iso_ctx(&video->ir_context[i]); + } + kfree(video->ir_context); + } + + /* Free the iso transmit contexts */ + if (video->it_context) { + for (i=0;iohci->nb_iso_xmit_ctx;i++) { + free_dma_iso_ctx(&video->it_context[i]); + } + kfree(video->it_context); + } +} + +#ifdef MODULE + +/* EXPORT_NO_SYMBOLS; */ + +MODULE_AUTHOR("Sebastien Rougeaux "); +MODULE_DESCRIPTION("driver for digital video on OHCI board"); +MODULE_SUPPORTED_DEVICE("video1394"); + +void cleanup_module(void) +{ + int i; + unregister_chrdev(VIDEO1394_MAJOR, VIDEO1394_DRIVER_NAME); + + for (i=0; i #include #include +#include #include "capilli.h" #include "avmcard.h" #include "capicmd.h" #include "capiutil.h" -static char *revision = "$Revision: 1.13 $"; +static char *revision = "$Revision: 1.14 $"; /* ------------------------------------------------------------- */ @@ -420,7 +424,7 @@ b1_put_slice(port, skb->data, len); } restore_flags(flags); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } /* ------------------------------------------------------------- */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/isdn/avmb1/b1dma.c linux/drivers/isdn/avmb1/b1dma.c --- v2.4.0-test2/linux/drivers/isdn/avmb1/b1dma.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/isdn/avmb1/b1dma.c Thu Jun 29 11:37:15 2000 @@ -1,11 +1,14 @@ /* - * $Id: b1dma.c,v 1.4 2000/04/03 16:38:05 calle Exp $ + * $Id: b1dma.c,v 1.5 2000/06/19 16:51:53 keil Exp $ * * Common module for AVM B1 cards that support dma with AMCC * * (c) Copyright 2000 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1dma.c,v $ + * Revision 1.5 2000/06/19 16:51:53 keil + * don't free skb in irq context + * * Revision 1.4 2000/04/03 16:38:05 calle * made suppress_pollack static. * @@ -32,12 +35,13 @@ #include #include #include +#include #include "capilli.h" #include "avmcard.h" #include "capicmd.h" #include "capiutil.h" -static char *revision = "$Revision: 1.4 $"; +static char *revision = "$Revision: 1.5 $"; /* ------------------------------------------------------------- */ @@ -430,7 +434,7 @@ b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr); restore_flags(flags); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } /* ------------------------------------------------------------- */ @@ -615,11 +619,6 @@ if ((status & TX_TC_INT) != 0) { card->csr &= ~EN_TX_TC_INT; b1dma_dispatch_tx(card); - } else if (card->csr & EN_TX_TC_INT) { - if (b1dmainmeml(card->mbase+AMCC_TXLEN) == 0) { - card->csr &= ~EN_TX_TC_INT; - b1dma_dispatch_tx(card); - } } b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr); } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/isdn/avmb1/b1pci.c linux/drivers/isdn/avmb1/b1pci.c --- v2.4.0-test2/linux/drivers/isdn/avmb1/b1pci.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/avmb1/b1pci.c Thu Jun 29 11:37:15 2000 @@ -1,11 +1,24 @@ /* - * $Id: b1pci.c,v 1.21 2000/04/03 13:29:24 calle Exp $ + * $Id: b1pci.c,v 1.25 2000/05/29 12:29:18 keil Exp $ * * Module for AVM B1 PCI-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1pci.c,v $ + * Revision 1.25 2000/05/29 12:29:18 keil + * make pci_enable_dev compatible to 2.2 kernel versions + * + * Revision 1.24 2000/05/19 15:43:22 calle + * added calls to pci_device_start(). + * + * Revision 1.23 2000/05/06 00:52:36 kai + * merged changes from kernel tree + * fixed timer and net_device->name breakage + * + * Revision 1.22 2000/04/21 13:01:33 calle + * Revision in b1pciv4 driver was missing. + * * Revision 1.21 2000/04/03 13:29:24 calle * make Tim Waugh happy (module unload races in 2.3.99-pre3). * no real problem there, but now it is much cleaner ... @@ -74,12 +87,13 @@ #include #include #include +#include #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.21 $"; +static char *revision = "$Revision: 1.25 $"; /* ------------------------------------------------------------- */ @@ -466,16 +480,26 @@ struct capicardparams param; int retval; - if (pci_enable_device(dev)) - return 0; /* return failure */ - - if (pci_resource_flags(dev, 2) & IORESOURCE_IO) { /* B1 PCI V4 */ + if (pci_resource_start(dev, 2)) { /* B1 PCI V4 */ #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 driver = &b1pciv4_driver; #endif - param.membase = pci_resource_start (dev, 0); - param.port = pci_resource_start (dev, 2); + param.membase = pci_resource_start(dev, 0); + param.port = pci_resource_start(dev, 2); param.irq = dev->irq; + + retval = pci_enable_device (dev); + if (retval != 0) { + printk(KERN_ERR + "%s: failed to enable AVM-B1 V4 at i/o %#x, irq %d, mem %#x err=%d\n", + driver->name, param.port, param.irq, param.membase, retval); +#ifdef MODULE + cleanup_module(); +#endif + MOD_DEC_USE_COUNT; + return -EIO; + } + printk(KERN_INFO "%s: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n", driver->name, param.port, param.irq, param.membase); @@ -491,8 +515,20 @@ } } else { param.membase = 0; - param.port = pci_resource_start (dev, 1); + param.port = pci_resource_start(dev, 1); param.irq = dev->irq; + + retval = pci_enable_device (dev); + if (retval != 0) { + printk(KERN_ERR + "%s: failed to enable AVM-B1 at i/o %#x, irq %d, err=%d\n", + driver->name, param.port, param.irq, retval); +#ifdef MODULE + cleanup_module(); +#endif + MOD_DEC_USE_COUNT; + return -EIO; + } printk(KERN_INFO "%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n", driver->name, param.port, param.irq); @@ -522,6 +558,12 @@ strncpy(driver->revision, p + 1, sizeof(driver->revision)); p = strchr(driver->revision, '$'); *p = 0; +#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 + p = strchr(revision, ':'); + strncpy(driverv4->revision, p + 1, sizeof(driverv4->revision)); + p = strchr(driverv4->revision, '$'); + *p = 0; +#endif } printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/isdn/avmb1/c4.c linux/drivers/isdn/avmb1/c4.c --- v2.4.0-test2/linux/drivers/isdn/avmb1/c4.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/avmb1/c4.c Thu Jun 29 11:37:15 2000 @@ -1,11 +1,24 @@ /* - * $Id: c4.c,v 1.8 2000/04/03 16:38:05 calle Exp $ + * $Id: c4.c,v 1.12 2000/06/19 16:51:53 keil Exp $ * * Module for AVM C4 card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: c4.c,v $ + * Revision 1.12 2000/06/19 16:51:53 keil + * don't free skb in irq context + * + * Revision 1.11 2000/06/19 15:11:24 keil + * avoid use of freed structs + * changes from 2.4.0-ac21 + * + * Revision 1.10 2000/05/29 12:29:18 keil + * make pci_enable_dev compatible to 2.2 kernel versions + * + * Revision 1.9 2000/05/19 15:43:22 calle + * added calls to pci_device_start(). + * * Revision 1.8 2000/04/03 16:38:05 calle * made suppress_pollack static. * @@ -46,6 +59,7 @@ #include #include #include +#include #include #include #include "capicmd.h" @@ -53,7 +67,7 @@ #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.8 $"; +static char *revision = "$Revision: 1.12 $"; #undef CONFIG_C4_DEBUG #undef CONFIG_C4_POLLDEBUG @@ -510,7 +524,7 @@ c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM); restore_flags(flags); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } /* ------------------------------------------------------------- */ @@ -949,8 +963,10 @@ for (i=0; i < 4; i++) { cinfo = &card->ctrlinfo[i]; - if (cinfo->capi_ctrl) + if (cinfo->capi_ctrl) { di->detach_ctr(cinfo->capi_ctrl); + cinfo->capi_ctrl = NULL; + } } free_irq(card->irq, card); @@ -1163,7 +1179,6 @@ cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info)*4, GFP_ATOMIC); if (!cinfo) { printk(KERN_WARNING "%s: no memory.\n", driver->name); - kfree(card->ctrlinfo); kfree(card->dma); kfree(card); MOD_DEC_USE_COUNT; @@ -1333,12 +1348,21 @@ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4, dev))) { struct capicardparams param; - if (pci_enable_device(dev)) - continue; - - param.port = pci_resource_start (dev, 1); + param.port = pci_resource_start(dev, 1); param.irq = dev->irq; - param.membase = pci_resource_start (dev, 0); + param.membase = pci_resource_start(dev, 0); + + retval = pci_enable_device (dev); + if (retval != 0) { + printk(KERN_ERR + "%s: failed to enable AVM-C4 at i/o %#x, irq %d, mem %#x err=%d\n", + driver->name, param.port, param.irq, param.membase, retval); +#ifdef MODULE + cleanup_module(); +#endif + MOD_DEC_USE_COUNT; + return -EIO; + } printk(KERN_INFO "%s: PCI BIOS reports AVM-C4 at i/o %#x, irq %d, mem %#x\n", diff -u --recursive --new-file v2.4.0-test2/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c --- v2.4.0-test2/linux/drivers/isdn/avmb1/capi.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/avmb1/capi.c Thu Jul 6 01:22:24 2000 @@ -1,11 +1,24 @@ /* - * $Id: capi.c,v 1.31 2000/04/03 13:29:24 calle Exp $ + * $Id: capi.c,v 1.35 2000/06/19 15:11:24 keil Exp $ * * CAPI 2.0 Interface for Linux * * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capi.c,v $ + * Revision 1.35 2000/06/19 15:11:24 keil + * avoid use of freed structs + * changes from 2.4.0-ac21 + * + * Revision 1.34 2000/06/18 16:09:54 keil + * more changes for 2.4 + * + * Revision 1.33 2000/05/18 16:35:43 calle + * Uaaahh. Bad memory leak fixed. + * + * Revision 1.32 2000/04/21 12:38:42 calle + * Bugfix: error in proc_ functions, begin-off => off-begin + * * Revision 1.31 2000/04/03 13:29:24 calle * make Tim Waugh happy (module unload races in 2.3.99-pre3). * no real problem there, but now it is much cleaner ... @@ -193,7 +206,7 @@ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ #include -static char *revision = "$Revision: 1.31 $"; +static char *revision = "$Revision: 1.35 $"; MODULE_AUTHOR("Carsten Paeth (calle@calle.in-berlin.de)"); @@ -816,7 +829,6 @@ if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { - datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2); #ifdef _DEBUG_DATAFLOW printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n", @@ -854,14 +866,14 @@ /* -------- file_operations for capidev ----------------------------- */ -static long long capi_llseek(struct file *file, - long long offset, int origin) +static loff_t +capi_llseek(struct file *file, loff_t offset, int origin) { return -ESPIPE; } -static ssize_t capi_read(struct file *file, char *buf, - size_t count, loff_t *ppos) +static ssize_t +capi_read(struct file *file, char *buf, size_t count, loff_t *ppos) { struct capidev *cdev = (struct capidev *)file->private_data; struct sk_buff *skb; @@ -911,8 +923,8 @@ return copied; } -static ssize_t capi_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) +static ssize_t +capi_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { struct capidev *cdev = (struct capidev *)file->private_data; struct sk_buff *skb; @@ -975,7 +987,8 @@ return mask; } -static int capi_ioctl(struct inode *inode, struct file *file, +static int +capi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct capidev *cdev = (struct capidev *)file->private_data; @@ -1190,7 +1203,8 @@ return -EINVAL; } -static int capi_open(struct inode *inode, struct file *file) +static int +capi_open(struct inode *inode, struct file *file) { if (file->private_data) return -EEXIST; @@ -1198,19 +1212,23 @@ if ((file->private_data = capidev_alloc(file)) == 0) return -ENOMEM; + MOD_INC_USE_COUNT; #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capi_open %d\n", GET_USE_COUNT(THIS_MODULE)); #endif return 0; } -static int capi_release(struct inode *inode, struct file *file) +static int +capi_release(struct inode *inode, struct file *file) { struct capidev *cdev = (struct capidev *)file->private_data; capincci_free(cdev, 0xffffffff); capidev_free(cdev); + file->private_data = NULL; + MOD_DEC_USE_COUNT; #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capi_release %d\n", GET_USE_COUNT(THIS_MODULE)); #endif @@ -1232,7 +1250,8 @@ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE /* -------- file_operations for capincci ---------------------------- */ -int capinc_raw_open(struct inode *inode, struct file *file) +static int +capinc_raw_open(struct inode *inode, struct file *file) { struct capiminor *mp; @@ -1256,14 +1275,14 @@ return 0; } -long long capinc_raw_llseek(struct file *file, - long long offset, int origin) +static loff_t +capinc_raw_llseek(struct file *file, loff_t offset, int origin) { return -ESPIPE; } -ssize_t capinc_raw_read(struct file *file, char *buf, - size_t count, loff_t *ppos) +static ssize_t +capinc_raw_read(struct file *file, char *buf, size_t count, loff_t *ppos) { struct capiminor *mp = (struct capiminor *)file->private_data; struct sk_buff *skb; @@ -1320,8 +1339,8 @@ return copied; } -ssize_t capinc_raw_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) +static ssize_t +capinc_raw_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { struct capiminor *mp = (struct capiminor *)file->private_data; struct sk_buff *skb; @@ -1358,7 +1377,7 @@ return count; } -unsigned int +static unsigned int capinc_raw_poll(struct file *file, poll_table * wait) { struct capiminor *mp = (struct capiminor *)file->private_data; @@ -1376,7 +1395,8 @@ return mask; } -int capinc_raw_ioctl(struct inode *inode, struct file *file, +static int +capinc_raw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct capiminor *mp = (struct capiminor *)file->private_data; @@ -1388,15 +1408,17 @@ return -EINVAL; } -int +static int capinc_raw_release(struct inode *inode, struct file *file) { struct capiminor *mp = (struct capiminor *)file->private_data; if (mp) { mp->file = 0; - if (mp->nccip == 0) + if (mp->nccip == 0) { capiminor_free(mp); + file->private_data = NULL; + } } #ifdef _DEBUG_REFCOUNT @@ -1405,7 +1427,7 @@ return 0; } -struct file_operations capinc_raw_fops = +static struct file_operations capinc_raw_fops = { owner: THIS_MODULE, llseek: capinc_raw_llseek, @@ -1875,7 +1897,7 @@ *eof = 1; if (off >= len+begin) return 0; - *start = page + (off-begin); + *start = page + (begin-off); return ((count < begin+len-off) ? count : begin+len-off); } @@ -2068,7 +2090,7 @@ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE devfs_unregister_chrdev(capi_rawmajor, "capi/r%d"); #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - devfs_unregister(devfs_find_handle(NULL, "capi20", 0, + devfs_unregister(devfs_find_handle(NULL, "capi20", capi_major, 0, DEVFS_SPECIAL_CHR, 0)); return -EIO; @@ -2091,13 +2113,13 @@ for (j = 0; j < CAPINC_NR_PORTS; j++) { char devname[32]; sprintf(devname, "capi/r%u", j); - devfs_unregister(devfs_find_handle(NULL, devname, 0, capi_rawmajor, j, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, devname, capi_rawmajor, j, DEVFS_SPECIAL_CHR, 0)); } capinc_tty_exit(); #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ (void) detach_capi_interface(&cuser); devfs_unregister_chrdev(capi_major, "capi20"); - devfs_unregister(devfs_find_handle(NULL, "capi20", 0, + devfs_unregister(devfs_find_handle(NULL, "capi20", capi_major, 0, DEVFS_SPECIAL_CHR, 0)); MOD_DEC_USE_COUNT; @@ -2123,7 +2145,7 @@ (void)proc_exit(); devfs_unregister_chrdev(capi_major, "capi20"); - devfs_unregister(devfs_find_handle(NULL, "isdn/capi20", 0, capi_major, 0, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, "isdn/capi20", capi_major, 0, DEVFS_SPECIAL_CHR, 0)); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE capinc_tty_exit(); @@ -2131,7 +2153,7 @@ for (j = 0; j < CAPINC_NR_PORTS; j++) { char devname[32]; sprintf(devname, "capi/r%u", j); - devfs_unregister(devfs_find_handle(NULL, devname, 0, capi_rawmajor, j, DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle(NULL, devname, capi_rawmajor, j, DEVFS_SPECIAL_CHR, 0)); } #endif (void) detach_capi_interface(&cuser); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/isdn/avmb1/capidrv.c linux/drivers/isdn/avmb1/capidrv.c --- v2.4.0-test2/linux/drivers/isdn/avmb1/capidrv.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/isdn/avmb1/capidrv.c Thu Jun 29 11:37:15 2000 @@ -1,11 +1,25 @@ /* - * $Id: capidrv.c,v 1.32 2000/04/07 15:19:58 calle Exp $ + * $Id: capidrv.c,v 1.36 2000/06/26 15:13:41 keil Exp $ * * ISDN4Linux Driver, using capi20 interface (kernelcapi) * * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capidrv.c,v $ + * Revision 1.36 2000/06/26 15:13:41 keil + * features should be or'ed + * + * Revision 1.35 2000/06/19 15:11:25 keil + * avoid use of freed structs + * changes from 2.4.0-ac21 + * + * Revision 1.34 2000/06/19 13:13:55 calle + * Added Modemsupport! + * + * Revision 1.33 2000/05/06 00:52:36 kai + * merged changes from kernel tree + * fixed timer and net_device->name breakage + * * Revision 1.32 2000/04/07 15:19:58 calle * remove warnings * @@ -192,7 +206,7 @@ #include "capicmd.h" #include "capidrv.h" -static char *revision = "$Revision: 1.32 $"; +static char *revision = "$Revision: 1.36 $"; static int debugmode = 0; MODULE_AUTHOR("Carsten Paeth "); @@ -327,6 +341,8 @@ return 2; case ISDN_PROTO_L2_FAX: return 4; + case ISDN_PROTO_L2_MODEM: + return 8; } } @@ -343,6 +359,7 @@ case ISDN_PROTO_L2_V11096: case ISDN_PROTO_L2_V11019: case ISDN_PROTO_L2_V11038: + case ISDN_PROTO_L2_MODEM: return 1; case ISDN_PROTO_L2_FAX: return 4; @@ -360,6 +377,7 @@ case ISDN_PROTO_L2_V11096: case ISDN_PROTO_L2_V11019: case ISDN_PROTO_L2_V11038: + case ISDN_PROTO_L2_MODEM: default: return 0; case ISDN_PROTO_L2_FAX: @@ -2269,16 +2287,19 @@ card->interface.writebuf_skb = if_sendbuf; card->interface.writecmd = 0; card->interface.readstat = if_readstat; - card->interface.features = ISDN_FEATURE_L2_X75I | - ISDN_FEATURE_L2_X75UI | - ISDN_FEATURE_L2_X75BUI | - ISDN_FEATURE_L2_HDLC | + card->interface.features = ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L2_TRANS | ISDN_FEATURE_L3_TRANS | - ISDN_FEATURE_L2_V11096 | + ISDN_FEATURE_P_UNKNOWN | + ISDN_FEATURE_L2_X75I | + ISDN_FEATURE_L2_X75UI | + ISDN_FEATURE_L2_X75BUI; + if (profp->support1 & (1<<2)) + card->interface.features |= ISDN_FEATURE_L2_V11096 | ISDN_FEATURE_L2_V11019 | - ISDN_FEATURE_L2_V11038 | - ISDN_FEATURE_P_UNKNOWN; + ISDN_FEATURE_L2_V11038; + if (profp->support1 & (1<<8)) + card->interface.features |= ISDN_FEATURE_L2_MODEM; card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */ strncpy(card->interface.id, id, sizeof(card->interface.id) - 1); @@ -2401,9 +2422,9 @@ } spin_unlock_irqrestore(&global_lock, flags); - kfree(card); - printk(KERN_INFO "%s: now down.\n", card->name); + + kfree(card); MOD_DEC_USE_COUNT; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/isdn/avmb1/kcapi.c linux/drivers/isdn/avmb1/kcapi.c --- v2.4.0-test2/linux/drivers/isdn/avmb1/kcapi.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/avmb1/kcapi.c Thu Jun 29 11:37:15 2000 @@ -1,11 +1,17 @@ /* - * $Id: kcapi.c,v 1.15 2000/04/06 15:01:25 calle Exp $ + * $Id: kcapi.c,v 1.17 2000/04/21 13:00:56 calle Exp $ * * Kernel CAPI 2.0 Module * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: kcapi.c,v $ + * Revision 1.17 2000/04/21 13:00:56 calle + * Bugfix: driver_proc_info was also wrong. + * + * Revision 1.16 2000/04/21 12:38:42 calle + * Bugfix: error in proc_ functions, begin-off => off-begin + * * Revision 1.15 2000/04/06 15:01:25 calle * Bugfix: crash in capidrv.c when reseting a capi controller. * - changed code order on remove of controller. @@ -109,7 +115,7 @@ #include #endif -static char *revision = "$Revision: 1.15 $"; +static char *revision = "$Revision: 1.17 $"; /* ------------------------------------------------------------- */ @@ -1100,7 +1106,7 @@ if (len < off) return 0; *eof = 1; - *start = page - off; + *start = page + off; return ((count < len-off) ? count : len-off); } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/isdn/avmb1/t1pci.c linux/drivers/isdn/avmb1/t1pci.c --- v2.4.0-test2/linux/drivers/isdn/avmb1/t1pci.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/avmb1/t1pci.c Thu Jun 29 11:37:15 2000 @@ -1,11 +1,18 @@ /* - * $Id: t1pci.c,v 1.7 2000/04/07 15:26:55 calle Exp $ + * $Id: t1pci.c,v 1.9 2000/05/19 15:43:22 calle Exp $ * * Module for AVM T1 PCI-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: t1pci.c,v $ + * Revision 1.9 2000/05/19 15:43:22 calle + * added calls to pci_device_start(). + * + * Revision 1.8 2000/05/06 00:52:36 kai + * merged changes from kernel tree + * fixed timer and net_device->name breakage + * * Revision 1.7 2000/04/07 15:26:55 calle * better error message if cabel not connected or T1 has no power. * @@ -49,12 +56,13 @@ #include #include #include +#include #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.7 $"; +static char *revision = "$Revision: 1.9 $"; #undef CONFIG_T1PCI_DEBUG #undef CONFIG_T1PCI_POLLDEBUG @@ -305,12 +313,21 @@ while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, dev))) { struct capicardparams param; - if (pci_enable_device(dev)) - continue; - - param.port = pci_resource_start (dev, 1); + param.port = pci_resource_start(dev, 1); param.irq = dev->irq; - param.membase = pci_resource_start (dev, 0); + param.membase = pci_resource_start(dev, 0); + + retval = pci_enable_device (dev); + if (retval != 0) { + printk(KERN_ERR + "%s: failed to enable AVM-T1-PCI at i/o %#x, irq %d, mem %#x err=%d\n", + driver->name, param.port, param.irq, param.membase, retval); +#ifdef MODULE + cleanup_module(); +#endif + MOD_DEC_USE_COUNT; + return -EIO; + } printk(KERN_INFO "%s: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n", diff -u --recursive --new-file v2.4.0-test2/linux/drivers/isdn/divert/divert_procfs.c linux/drivers/isdn/divert/divert_procfs.c --- v2.4.0-test2/linux/drivers/isdn/divert/divert_procfs.c Mon Mar 27 08:08:25 2000 +++ linux/drivers/isdn/divert/divert_procfs.c Sat Jul 8 19:26:12 2000 @@ -55,6 +55,7 @@ #include #include #include +#include #ifdef CONFIG_PROC_FS #include #else @@ -175,7 +176,7 @@ { int flags; - MOD_INC_USE_COUNT; + lock_kernel(); save_flags(flags); cli(); if_used++; @@ -185,6 +186,7 @@ (struct divert_info **) filep->private_data = &divert_info_head; restore_flags(flags); /* start_divert(); */ + unlock_kernel(); return (0); } /* isdn_divert_open */ @@ -212,7 +214,6 @@ divert_info_head = divert_info_head->next; kfree(inf); } - MOD_DEC_USE_COUNT; return (0); } /* isdn_divert_close */ @@ -345,6 +346,7 @@ return (-1); } isdn_divert_entry->proc_fops = &isdn_fops; + isdn_divert_entry->owner = THIS_MODULE; #endif /* CONFIG_PROC_FS */ return (0); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/isdn/hysdn/hysdn_procconf.c linux/drivers/isdn/hysdn/hysdn_procconf.c --- v2.4.0-test2/linux/drivers/isdn/hysdn/hysdn_procconf.c Mon Mar 27 08:08:25 2000 +++ linux/drivers/isdn/hysdn/hysdn_procconf.c Sat Jul 8 19:26:12 2000 @@ -45,6 +45,7 @@ #include #include #include +#include #include "hysdn_defs.h" @@ -286,9 +287,8 @@ struct conf_writedata *cnf; char *cp, *tmp; - MOD_INC_USE_COUNT; /* lock module */ - /* now search the addressed card */ + lock_kernel(); card = card_root; while (card) { pd = card->procconf; @@ -297,7 +297,7 @@ card = card->next; /* search next entry */ } if (!card) { - MOD_DEC_USE_COUNT; /* unlock module */ + unlock_kernel(); return (-ENODEV); /* device is unknown/invalid */ } if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL)) @@ -308,7 +308,7 @@ /* write only access -> write boot file or conf line */ if (!(cnf = kmalloc(sizeof(struct conf_writedata), GFP_KERNEL))) { - MOD_DEC_USE_COUNT; + unlock_kernel(); return (-EFAULT); } cnf->card = card; @@ -320,7 +320,7 @@ /* read access -> output card info data */ if (!(tmp = (char *) kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) { - MOD_DEC_USE_COUNT; + unlock_kernel(); return (-EFAULT); /* out of memory */ } filep->private_data = tmp; /* start of string */ @@ -354,9 +354,10 @@ *cp++ = '\n'; *cp = 0; /* end of string */ } else { /* simultaneous read/write access forbidden ! */ - MOD_DEC_USE_COUNT; /* unlock module */ + unlock_kernel(); return (-EPERM); /* no permission this time */ } + unlock_kernel(); return (0); } /* hysdn_conf_open */ @@ -402,7 +403,6 @@ if (filep->private_data) kfree(filep->private_data); /* release memory */ } - MOD_DEC_USE_COUNT; /* reduce usage count */ return (retval); } /* hysdn_conf_close */ @@ -447,6 +447,7 @@ S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) { ((struct proc_dir_entry *) card->procconf)->proc_fops = &conf_fops; + ((struct proc_dir_entry *) card->procconf)->owner = THIS_MODULE; hysdn_proclog_init(card); /* init the log file entry */ } card = card->next; /* next entry */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/isdn/hysdn/hysdn_procfs.c linux/drivers/isdn/hysdn/hysdn_procfs.c --- v2.4.0-test2/linux/drivers/isdn/hysdn/hysdn_procfs.c Thu Mar 2 14:36:22 2000 +++ linux/drivers/isdn/hysdn/hysdn_procfs.c Sat Jul 8 19:26:12 2000 @@ -33,6 +33,7 @@ #include #include #include +#include #include "hysdn_defs.h" @@ -198,7 +199,7 @@ struct procdata *pd; ulong flags; - MOD_INC_USE_COUNT; /* lock module */ + lock_kernel(); card = card_root; while (card) { pd = card->procfs; @@ -207,7 +208,7 @@ card = card->next; /* search next entry */ } if (!card) { - MOD_DEC_USE_COUNT; /* unlock module */ + unlock_kernel(); return (-ENODEV); /* device is unknown/invalid */ } filep->private_data = card; /* remember our own card */ @@ -215,7 +216,7 @@ if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { /* write only access -> boot pof data */ if (pof_boot_open(card)) { - MOD_DEC_USE_COUNT; /* unlock module */ + unlock_kernel(); return (-EPERM); /* no permission this time */ } } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { @@ -231,9 +232,10 @@ restore_flags(flags); } else { /* simultaneous read/write access forbidden ! */ - MOD_DEC_USE_COUNT; /* unlock module */ + unlock_kernel(); return (-EPERM); /* no permission this time */ } + unlock_kernel(); return (0); } /* hysdn_log_open */ @@ -295,7 +297,6 @@ } } /* read access */ - MOD_DEC_USE_COUNT; return (retval); } /* hysdn_log_close */ @@ -437,8 +438,10 @@ memset(pd, 0, sizeof(struct procdata)); sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid); - if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) + if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) { pd->log->proc_fops = &log_fops; /* set new operations table */ + pd->log->owner = THIS_MODULE; + } init_waitqueue_head(&(pd->rd_queue)); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/isdn/hysdn/hysdn_proclog.c linux/drivers/isdn/hysdn/hysdn_proclog.c --- v2.4.0-test2/linux/drivers/isdn/hysdn/hysdn_proclog.c Mon Mar 27 08:08:25 2000 +++ linux/drivers/isdn/hysdn/hysdn_proclog.c Sat Jul 8 19:26:12 2000 @@ -45,6 +45,7 @@ #include #include #include +#include #include "hysdn_defs.h" @@ -293,7 +294,7 @@ struct procdata *pd; ulong flags; - MOD_INC_USE_COUNT; /* lock module */ + lock_kernel(); card = card_root; while (card) { pd = card->proclog; @@ -302,7 +303,7 @@ card = card->next; /* search next entry */ } if (!card) { - MOD_DEC_USE_COUNT; /* unlock module */ + unlock_kernel(); return (-ENODEV); /* device is unknown/invalid */ } filep->private_data = card; /* remember our own card */ @@ -321,9 +322,10 @@ (struct log_data **) filep->private_data = &(pd->log_head); restore_flags(flags); } else { /* simultaneous read/write access forbidden ! */ - MOD_DEC_USE_COUNT; /* unlock module */ + unlock_kernel(); return (-EPERM); /* no permission this time */ } + unlock_kernel(); return (0); } /* hysdn_log_open */ @@ -385,7 +387,6 @@ } } /* read access */ - MOD_DEC_USE_COUNT; return (retval); } /* hysdn_log_close */ @@ -451,8 +452,10 @@ if ((pd = (struct procdata *) kmalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) { memset(pd, 0, sizeof(struct procdata)); sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid); - if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) + if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) { pd->log->proc_fops = &log_fops; + pd->log->owner = THIS_MODULE; + } init_waitqueue_head(&(pd->rd_queue)); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/isdn/isdn_cards.c linux/drivers/isdn/isdn_cards.c --- v2.4.0-test2/linux/drivers/isdn/isdn_cards.c Thu Aug 12 09:42:33 1999 +++ linux/drivers/isdn/isdn_cards.c Thu Jul 6 19:25:21 2000 @@ -76,6 +76,9 @@ extern void capidrv_init(void); #endif +extern int act2000_init(void); + + void isdn_cards_init(void) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c --- v2.4.0-test2/linux/drivers/isdn/isdn_common.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/isdn_common.c Thu Jun 29 18:25:51 2000 @@ -2603,7 +2603,7 @@ int i; # endif - devfs_handle = devfs_mk_dir (NULL, "isdn", 4, NULL); + devfs_handle = devfs_mk_dir (NULL, "isdn", NULL); # ifdef CONFIG_ISDN_PPP for (i = 0; i < ISDN_MAX_CHANNELS; i++) { char buf[8]; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/isdn/isdn_ppp.h linux/drivers/isdn/isdn_ppp.h --- v2.4.0-test2/linux/drivers/isdn/isdn_ppp.h Thu Aug 26 13:05:37 1999 +++ linux/drivers/isdn/isdn_ppp.h Thu Jul 6 19:25:21 2000 @@ -76,6 +76,7 @@ */ #include /* for PPP_PROTOCOL */ +#include /* for isdn_ppp info */ extern void isdn_ppp_timer_timeout(void); extern int isdn_ppp_read(int, struct file *, char *, int); extern int isdn_ppp_write(int, struct file *, const char *, int); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/Config.in linux/drivers/mtd/Config.in --- v2.4.0-test2/linux/drivers/mtd/Config.in Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/Config.in Tue Jul 4 10:10:09 2000 @@ -0,0 +1,43 @@ +mainmenu_option next_comment +comment 'Memory Technology Devices (MTD)' + +tristate 'Memory Technology Device (MTD) support' CONFIG_MTD + +if [ "$CONFIG_MTD" != "n" ]; then + dep_tristate 'Common Flash Interface (CFI) support' CONFIG_MTD_CFI $CONFIG_MTD + dep_tristate 'CFI support for Intel/Sharp Extended Command Set chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_CFI + dep_tristate 'CFI chips in virtual memory map' CONFIG_MTD_NORA $CONFIG_MTD_CFI + dep_tristate 'CFI chips in physical memory map' CONFIG_MTD_PHYSMAP $CONFIG_MTD_CFI + dep_tristate 'CFI chips on RPXLite PPC board' CONFIG_MTD_RPXLITE $CONFIG_MTD_CFI + dep_tristate 'M-Systems Disk-On-Chip 1000 support' CONFIG_MTD_DOC1000 $CONFIG_MTD + dep_tristate 'M-Systems Disk-On-Chip 2000' CONFIG_MTD_DOC2000 $CONFIG_MTD + dep_tristate 'M-Systems Disk-On-Chip Millennium' CONFIG_MTD_DOC2001 $CONFIG_MTD + if [ "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" ]; then + define_bool CONFIG_MTD_DOCPROBE y + else + if [ "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" ]; then + define_bool CONFIG_MTD_DOCPROBE m + else + define_bool CONFIG_MTD_DOCPROBE n + fi + fi + dep_tristate 'Use extra onboard system memory as MTD device' CONFIG_MTD_SLRAM $CONFIG_MTD + dep_tristate 'Octagon 5066 SBC onboard flash support' CONFIG_MTD_OCTAGON $CONFIG_MTD + dep_tristate 'Tempustech VMAX SBC301 onboard flash support' CONFIG_MTD_VMAX $CONFIG_MTD + dep_tristate 'Mixcom piggyback flash card support' CONFIG_MTD_MIXMEM $CONFIG_MTD + dep_tristate 'Ramix PMC551 PCI Mezzanine ram card support' CONFIG_MTD_PMC551 $CONFIG_MTD + if [ "$CONFIG_MTD_PMC551" != "n" ]; then + bool 'PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX + fi + dep_tristate 'Debugging RAM test driver' CONFIG_MTD_MTDRAM $CONFIG_MTD + + dep_tristate 'FTL (Flash Translation Layer) support' CONFIG_FTL $CONFIG_MTD + dep_tristate 'NFTL (NAND Flash Translation Layer) support' CONFIG_NFTL $CONFIG_MTD + if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_NFTL" != "n" ]; then + bool 'Write support for NFTL (EXPERIMENTAL)' CONFIG_NFTL_RW + fi + dep_tristate 'Direct blockdevice access to MTD devices' CONFIG_MTD_BLOCK $CONFIG_MTD + dep_tristate 'Direct chardevice access to MTD devices' CONFIG_MTD_CHAR $CONFIG_MTD +fi + +endmenu diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/Makefile linux/drivers/mtd/Makefile --- v2.4.0-test2/linux/drivers/mtd/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/Makefile Tue Jul 4 10:10:13 2000 @@ -0,0 +1,190 @@ +# $Id: Makefile,v 1.20 2000/07/04 08:58:10 dwmw2 Exp $ + +# Uncomment this to enable the DBG macro (see mtd.h) +#CFLAGS+= -DZDBG + +ifndef CONFIG_MTD +# We're being invoked outside a normal kernel build. Fake it +EXTRA_CFLAGS= -I$(shell pwd)/../include + +HWDRIVERS = slram.o docprobe.o doc1000.o nora.o physmap.o rpxlite.o vmax301.o octagon-5066.o pmc551.o mtdram.o +USERDRIVERS = ftl.o nftl.o mtdblock.o mtdchar.o +MIX_OBJS = mtdcore.o mapped.o doc2000.o doc2001.o cfi_probe.o cfi_cmdset_0001.o +MI_OBJS = $(HWDRIVERS) $(USERDRIVERS) +CFLAGS_nftl.o := -DCONFIG_NFTL_RW +else + +O_TARGET := mtdlink.o +SUB_DIRS := +ALL_SUB_DIRS := +MOD_LIST_NAME := MTD_MODULES + + +ifeq ($(CONFIG_MTD),y) + OX_OBJS += mtdcore.o mapped.o +else + ifeq ($(CONFIG_MTD),m) + MX_OBJS += mtdcore.o mapped.o + endif +endif + +ifeq ($(CONFIG_MTD_NORA),y) + O_OBJS += nora.o +else + ifeq ($(CONFIG_MTD_NORA),m) + M_OBJS += nora.o + endif +endif + +ifeq ($(CONFIG_MTD_RPXLITE),y) + O_OBJS += rpxlite.o +else + ifeq ($(CONFIG_MTD_RPXLITE),m) + M_OBJS += rpxlite.o + endif +endif + +ifeq ($(CONFIG_MTD_PHYSMAP),y) + O_OBJS += physmap.o +else + ifeq ($(CONFIG_MTD_PHYSMAP),m) + M_OBJS += physmap.o + endif +endif + +ifeq ($(CONFIG_MTD_CFI),y) + OX_OBJS += cfi_probe.o +else + ifeq ($(CONFIG_MTD_CFI),m) + MX_OBJS += cfi_probe.o + endif +endif + +ifeq ($(CONFIG_MTD_CFI_INTELEXT),y) + OX_OBJS += cfi_cmdset_0001.o +else + ifeq ($(CONFIG_MTD_CFI_INTELEXT),m) + MX_OBJS += cfi_cmdset_0001.o + endif +endif + +ifeq ($(CONFIG_MTD_DOC1000),y) + O_OBJS += doc1000.o +else + ifeq ($(CONFIG_MTD_DOC1000),m) + M_OBJS += doc1000.o + endif +endif + +ifeq ($(CONFIG_MTD_DOC2000),y) + OX_OBJS += doc2000.o +else + ifeq ($(CONFIG_MTD_DOC2000),m) + MX_OBJS += doc2000.o + endif +endif + +ifeq ($(CONFIG_MTD_DOC2001),y) + OX_OBJS += doc2001.o +else + ifeq ($(CONFIG_MTD_DOC2001),m) + MX_OBJS += doc2001.o + endif +endif + +ifeq ($(CONFIG_MTD_DOCPROBE),y) + O_OBJS += docprobe.o +else + ifeq ($(CONFIG_MTD_DOCPROBE),m) + M_OBJS += docprobe.o + endif +endif + +ifeq ($(CONFIG_MTD_SLRAM),y) + O_OBJS += slram.o +else + ifeq ($(CONFIG_MTD_SLRAM),m) + M_OBJS += slram.o + endif +endif + +ifeq ($(CONFIG_MTD_OCTAGON),y) + O_OBJS += octagon-5066.o +else + ifeq ($(CONFIG_MTD_OCTAGON),m) + M_OBJS += octagon-5066.o + endif +endif + +ifeq ($(CONFIG_MTD_PMC551),y) + O_OBJS += pmc551.o +else + ifeq ($(CONFIG_MTD_PMC551),m) + M_OBJS += pmc551.o + endif +endif + +ifeq ($(CONFIG_MTD_PMC551_BUGFIX),y) + CFLAGS_pmc551.o += -DPMC551_DRAM_BUG +endif + +ifeq ($(CONFIG_MTD_VMAX),y) + O_OBJS += vmax301.o +else + ifeq ($(CONFIG_MTD_VMAX),m) + M_OBJS += vmax301.o + endif +endif + +ifeq ($(CONFIG_MTD_MIXMEM),y) + O_OBJS += mixmem.o +else + ifeq ($(CONFIG_MTD_MIXMEM),m) + M_OBJS += mixmem.o + endif +endif + +ifeq ($(CONFIG_MTD_MTDRAM),y) + O_OBJS += mtdram.o +else + ifeq ($(CONFIG_MTD_MTDRAM),m) + M_OBJS += mtdram.o + endif +endif + +ifeq ($(CONFIG_FTL),y) + O_OBJS += ftl.o +else + ifeq ($(CONFIG_FTL),m) + M_OBJS += ftl.o + endif +endif + +ifeq ($(CONFIG_NFTL),y) + O_OBJS += nftl.o +else + ifeq ($(CONFIG_NFTL),m) + M_OBJS += nftl.o + endif +endif + +ifeq ($(CONFIG_MTD_BLOCK),y) + O_OBJS += mtdblock.o +else + ifeq ($(CONFIG_MTD_BLOCK),m) + M_OBJS += mtdblock.o + endif +endif + + +ifeq ($(CONFIG_MTD_CHAR),y) + O_OBJS += mtdchar.o +else + ifeq ($(CONFIG_MTD_CHAR),m) + M_OBJS += mtdchar.o + endif +endif + +endif + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/cfi_cmdset_0001.c linux/drivers/mtd/cfi_cmdset_0001.c --- v2.4.0-test2/linux/drivers/mtd/cfi_cmdset_0001.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/cfi_cmdset_0001.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,871 @@ +/* + * Common Flash Interface support: + * Intel Extended Vendor Command Set (ID 0x0001) + * + * (C) 2000 Red Hat. GPL'd + * + * $Id: cfi_cmdset_0001.c,v 1.20 2000/07/04 07:36:43 dwmw2 Exp $ + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE < 0x20300 +#define set_current_state(x) current->state = (x); +#endif +static int cfi_intelext_read_1_by_16 (struct mtd_info *, loff_t, size_t, size_t *, u_char *); +static int cfi_intelext_write_1_by_16(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +static int cfi_intelext_erase_1_by_16 (struct mtd_info *, struct erase_info *); +static void cfi_intelext_sync (struct mtd_info *); +static int cfi_intelext_suspend (struct mtd_info *); +static void cfi_intelext_resume (struct mtd_info *); + +static void cfi_intelext_destroy(struct mtd_info *); + +void cfi_cmdset_0001(struct map_info *, int, unsigned long); +EXPORT_SYMBOL(cfi_cmdset_0001); + +struct mtd_info *cfi_intelext_setup (struct map_info *); + +void cfi_cmdset_0001(struct map_info *map, int primary, unsigned long base) +{ + struct cfi_private *cfi = map->fldrv_priv; + int i; + struct cfi_pri_intelext *extp; + + __u16 adr = primary?cfi->cfiq.P_ADR:cfi->cfiq.A_ADR; + + printk(" Intel/Sharp Extended Query Table at 0x%4.4X\n", adr); + + if (!adr) + return; + + /* Switch it into Query Mode */ + switch(map->buswidth) { + case 1: + map->write8(map, 0x98, 0x55); + break; + case 2: + map->write16(map, 0x9898, 0xaa); + break; + case 4: + map->write32(map, 0x98989898, 0x154); + break; + } + + extp = kmalloc(sizeof(*extp), GFP_KERNEL); + if (!extp) { + printk("Failed to allocate memory\n"); + return; + } + + /* Read in the Extended Query Table */ + for (i=0; iread8(map, (base+((adr+i)*map->buswidth))); + } + + if (extp->MajorVersion != '1' || + (extp->MinorVersion < '0' || extp->MinorVersion > '2')) { + printk(" Unknown IntelExt Extended Query version %c.%c.\n", + extp->MajorVersion, extp->MinorVersion); + kfree(extp); + return; + } + + /* Do some byteswapping if necessary */ + extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport); + extp->BlkStatusRegMask = le32_to_cpu(extp->BlkStatusRegMask); + + + /* Tell the user about it in lots of lovely detail */ +#if 0 + printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport); + printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported"); + printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported"); + printk(" - Suspend Program: %s\n", extp->FeatureSupport&4?"supported":"unsupported"); + printk(" - Legacy Lock/Unlock: %s\n", extp->FeatureSupport&8?"supported":"unsupported"); + printk(" - Queued Erase: %s\n", extp->FeatureSupport&16?"supported":"unsupported"); + printk(" - Instant block lock: %s\n", extp->FeatureSupport&32?"supported":"unsupported"); + printk(" - Protection Bits: %s\n", extp->FeatureSupport&64?"supported":"unsupported"); + printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported"); + printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported"); + for (i=9; i<32; i++) { + if (extp->FeatureSupport & (1<SuspendCmdSupport); + printk(" - Program after Erase Suspend: %s\n", extp->SuspendCmdSupport&1?"supported":"unsupported"); + for (i=1; i<8; i++) { + if (extp->SuspendCmdSupport & (1<BlkStatusRegMask); + printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no"); + printk(" - Valid Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no"); + for (i=2; i<16; i++) { + if (extp->BlkStatusRegMask & (1<VccOptimal >> 8, extp->VccOptimal & 0xf); + if (extp->VppOptimal) + printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n", + extp->VppOptimal >> 8, extp->VppOptimal & 0xf); +#endif + /* OK. We like it. Take over the control of it. */ + + /* Switch it into Read Mode */ + switch(map->buswidth) { + case 1: + map->write8(map, 0xff, 0x55); + break; + case 2: + map->write16(map, 0xffff, 0xaa); + break; + case 4: + map->write32(map, 0xffffffff, 0x154); + break; + } + + + /* If there was an old setup function, decrease its use count */ + if (cfi->cmdset_setup) + put_module_symbol((unsigned long)cfi->cmdset_setup); + if (cfi->cmdset_priv) + kfree(cfi->cmdset_priv); + + for (i=0; i< cfi->numchips; i++) { + cfi->chips[i].word_write_time = 128; + cfi->chips[i].buffer_write_time = 128; + cfi->chips[i].erase_time = 1024; + } + + + cfi->cmdset_setup = cfi_intelext_setup; + cfi->cmdset_priv = extp; + MOD_INC_USE_COUNT; /* So the setup function is still there + * by the time it's called */ + + return; +} + +struct mtd_info *cfi_intelext_setup(struct map_info *map) +{ + struct cfi_private *cfi = map->fldrv_priv; + struct mtd_info *mtd; + + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); + printk("number of CFI chips: %d\n", cfi->numchips); + + if (!mtd) { + printk("Failed to allocate memory for MTD device\n"); + kfree(cfi->cmdset_priv); + return NULL; + } + + memset(mtd, 0, sizeof(*mtd)); + mtd->priv = map; + mtd->type = MTD_NORFLASH; + mtd->erasesize = 0x20000; /* FIXME */ + /* Also select the correct geometry setup too */ + mtd->size = (1 << cfi->cfiq.DevSize) * cfi->numchips; + mtd->erase = cfi_intelext_erase_1_by_16; + mtd->read = cfi_intelext_read_1_by_16; + mtd->write = cfi_intelext_write_1_by_16; + mtd->sync = cfi_intelext_sync; + mtd->suspend = cfi_intelext_suspend; + mtd->resume = cfi_intelext_resume; + mtd->flags = MTD_CAP_NORFLASH; + map->fldrv_destroy = cfi_intelext_destroy; + mtd->name = map->name; + return mtd; +} + +static inline int do_read_1_by_16_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) +{ + __u16 status; + unsigned long timeo = jiffies + HZ; + DECLARE_WAITQUEUE(wait, current); + + adr += chip->start; + + retry: + spin_lock_bh(chip->mutex); + + /* Check that the chip's ready to talk to us. + * Later, we can actually think about interrupting it + * if it's in FL_ERASING or FL_WRITING state. + * Not just yet, though. + */ + switch (chip->state) { +#if 0 + case FL_ERASING: + case FL_WRITING: + /* Suspend the operation, set state to FL_xxx_SUSPENDED */ +#endif + + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + case FL_READY: + map->write16(map, cpu_to_le16(0x0070), adr); + chip->state = FL_STATUS; + + case FL_STATUS: + status = le16_to_cpu(map->read16(map, adr)); + + if (!(status & (1<<7))) { + static int z=0; + /* Urgh. Chip not yet ready to talk to us. */ + if (time_after(jiffies, timeo)) { + spin_unlock_bh(chip->mutex); + printk("waiting for chip to be ready timed out in read"); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + + z++; + if ( 0 && !(z % 100 )) + printk("chip not ready yet before read. looping\n"); + + udelay(1); + + goto retry; + } + break; + + default: + printk("Waiting for chip, status = %d\n", chip->state); + + /* Stick ourselves on a wait queue to be woken when + someone changes the status */ + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if(signal_pending(current)) + return -EINTR; + + + timeo = jiffies + HZ; + + goto retry; + } + + map->write16(map, cpu_to_le16(0x00ff), adr); + chip->state = FL_READY; + + map->copy_from(map, buf, adr, len); + + if (chip->state == FL_ERASE_SUSPENDED || + chip->state == FL_WRITE_SUSPENDED) { + printk("Who in hell suspended the pending operation? I didn't write that code yet!\n"); + /* Restart it and set the state accordingly */ + } + + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + + return 0; +} + +static int cfi_intelext_read_1_by_16 (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long ofs; + int chipnum; + int ret = 0; + + /* ofs: offset within the first chip that the first read should start */ + chipnum = (from >> cfi->chipshift); + ofs = from - (chipnum << cfi->chipshift); + + *retlen = 0; + + while (len) { + unsigned long thislen; + + if (chipnum >= cfi->numchips) + break; + + if ((len + ofs -1) >> cfi->chipshift) + thislen = (1<chipshift) - ofs; + else + thislen = len; + + ret = do_read_1_by_16_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf); + if (ret) + break; + + *retlen += thislen; + len -= thislen; + buf += thislen; + + ofs = 0; + chipnum++; + } + return ret; +} + +static inline int do_write_1_by_16_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u16 datum) +{ + __u16 status; + unsigned long timeo = jiffies + HZ; + DECLARE_WAITQUEUE(wait, current); + int z = 0; + adr += chip->start; + + retry: + spin_lock_bh(chip->mutex); + + /* Check that the chip's ready to talk to us. + * Later, we can actually think about interrupting it + * if it's in FL_ERASING state. + * Not just yet, though. + */ + switch (chip->state) { + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + case FL_READY: + map->write16(map, cpu_to_le16(0x0070), adr); + chip->state = FL_STATUS; + timeo = jiffies + HZ; + + case FL_STATUS: + status = le16_to_cpu(map->read16(map, adr)); + + if (!(status & (1<<7))) { + + /* Urgh. Chip not yet ready to talk to us. */ + if (time_after(jiffies, timeo)) { + spin_unlock_bh(chip->mutex); + printk("waiting for chip to be ready timed out in read"); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + + z++; + if ( 0 && !(z % 100 )) + printk("chip not ready yet before write. looping\n"); + + udelay(1); + + goto retry; + } + break; + + default: + printk("Waiting for chip, status = %d\n", chip->state); + + /* Stick ourselves on a wait queue to be woken when + someone changes the status */ + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if(signal_pending(current)) + return -EINTR; + + timeo = jiffies + HZ; + + goto retry; + } + + map->write16(map, cpu_to_le16(0x0040), adr); + map->write16(map, datum, adr); + chip->state = FL_WRITING; + + timeo = jiffies + (HZ/2); + + spin_unlock_bh(chip->mutex); + udelay(chip->word_write_time); + spin_lock_bh(chip->mutex); + + z = 0; + while ( !( (status = le16_to_cpu(map->read16(map, adr))) & 0x80 ) ) { + + if (chip->state != FL_WRITING) { + /* Someone's suspended the write. Sleep */ + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if (signal_pending(current)) + return -EINTR; + + timeo = jiffies + (HZ / 2); /* FIXME */ + + spin_lock_bh(chip->mutex); + continue; + } + + /* OK Still waiting */ + if (time_after(jiffies, timeo)) { + chip->state = FL_STATUS; + spin_unlock_bh(chip->mutex); + printk("waiting for chip to be ready timed out in read"); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + + z++; + if ( 0 && !(z % 100 )) + printk("chip not ready yet after write. looping\n"); + + udelay(1); + + spin_lock_bh(chip->mutex); + continue; + } + if (!z) { + chip->word_write_time--; + if (!chip->word_write_time) + chip->word_write_time++; + else + printk("decreasing word_write_time to %d µs\n", chip->word_write_time); + } + if (z > 100) { + chip->word_write_time++; + printk("increasing word_write_time to %d µs\n", chip->word_write_time); + } + + /* Done and happy. */ + chip->state = FL_STATUS; + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + // printk("write ret OK at %lx\n", adr); + return 0; +} + + +/* This version only uses the 'word write' instruction. We should update it + * to write using 'buffer write' if it's available + */ +static int cfi_intelext_write_1_by_16 (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int ret = 0; + int chipnum; + unsigned long ofs; + + *retlen = 0; + chipnum = to >> cfi->chipshift; + ofs = to - (chipnum << cfi->chipshift); + + /* If it's not word-aligned, do the first byte write */ + if (ofs & 1) { +#if defined(__LITTLE_ENDIAN) + ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum], + ofs, 0xFF | (*buf << 8)); +#elif defined(__BIG_ENDIAN) + ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum], + ofs, 0xFF00 | (*buf)); +#else +#error define a sensible endianness +#endif + if (ret) + return ret; + + ofs++; + buf++; + (*retlen)++; + len--; + + if (ofs >> cfi->chipshift) { + chipnum ++; + ofs = 0; + if (chipnum == cfi->numchips) + return 0; + } + } + + while(len > 1) { + ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum], + ofs, *(__u16 *)buf); + if (ret) + return ret; + + ofs += 2; + buf += 2; + (*retlen) += 2; + len -= 2; + + if (ofs >> cfi->chipshift) { + chipnum ++; + ofs = 0; + if (chipnum == cfi->numchips) + return 0; + } + } + + if (len) { + /* Final byte to write */ +#if defined(__LITTLE_ENDIAN) + ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum], + ofs, 0xFF00 | (*buf)); +#elif defined(__BIG_ENDIAN) + ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum], + ofs, 0xFF | (*buf << 8)); +#else +#error define a sensible endianness +#endif + if (ret) + return ret; + + (*retlen)++; + } + + return 0; +} + + +static inline int do_erase_1_by_16_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) +{ + __u16 status; + unsigned long timeo = jiffies + HZ; + DECLARE_WAITQUEUE(wait, current); + + adr += chip->start; + + retry: + spin_lock_bh(chip->mutex); + + /* Check that the chip's ready to talk to us. */ + switch (chip->state) { + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + case FL_READY: + map->write16(map, cpu_to_le16(0x0070), adr); + chip->state = FL_STATUS; + timeo = jiffies + HZ; + + case FL_STATUS: + status = le16_to_cpu(map->read16(map, adr)); + + if (!(status & (1<<7))) { + static int z=0; + /* Urgh. Chip not yet ready to talk to us. */ + if (time_after(jiffies, timeo)) { + spin_unlock_bh(chip->mutex); + printk("waiting for chip to be ready timed out in erase"); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + + z++; + if ( 0 && !(z % 100 )) + printk("chip not ready yet before erase. looping\n"); + + udelay(1); + + goto retry; + } + break; + + default: + printk("Waiting for chip, status = %d\n", chip->state); + + /* Stick ourselves on a wait queue to be woken when + someone changes the status */ + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if(signal_pending(current)) + return -EINTR; + + timeo = jiffies + HZ; + + goto retry; + } + + map->write16(map, cpu_to_le16(0x0020), adr); + map->write16(map, cpu_to_le16(0x00D0), adr); + + chip->state = FL_ERASING; + + timeo = jiffies + (HZ*2); + spin_unlock_bh(chip->mutex); + schedule_timeout(HZ); + spin_lock_bh(chip->mutex); + + /* FIXME. Use a timer to check this, and return immediately. */ + /* Once the state machine's known to be working I'll do that */ + + while ( !( (status = le16_to_cpu(map->read16(map, adr))) & 0x80 ) ) { + static int z=0; + + if (chip->state != FL_ERASING) { + /* Someone's suspended the erase. Sleep */ + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + printk("erase suspended. Sleeping\n"); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if (signal_pending(current)) + return -EINTR; + + timeo = jiffies + (HZ*2); /* FIXME */ + spin_lock_bh(chip->mutex); + continue; + } + + /* OK Still waiting */ + if (time_after(jiffies, timeo)) { + chip->state = FL_STATUS; + spin_unlock_bh(chip->mutex); + printk("waiting for erase to complete timed out."); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + + z++; + if ( 0 && !(z % 100 )) + printk("chip not ready yet after erase. looping\n"); + + udelay(1); + + spin_lock_bh(chip->mutex); + continue; + } + + /* Done and happy. */ + chip->state = FL_STATUS; + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + //printk("erase ret OK\n"); + return 0; +} + +static int cfi_intelext_erase_1_by_16 (struct mtd_info *mtd, struct erase_info *instr) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long adr, len; + int chipnum, ret = 0; + + if (instr->addr & (mtd->erasesize - 1)) + return -EINVAL; + + if (instr->len & (mtd->erasesize -1)) + return -EINVAL; + + if ((instr->len + instr->addr) > mtd->size) + return -EINVAL; + + chipnum = instr->addr >> cfi->chipshift; + adr = instr->addr - (chipnum << cfi->chipshift); + len = instr->len; + + while(len) { + ret = do_erase_1_by_16_oneblock(map, &cfi->chips[chipnum], adr); + + if (ret) + return ret; + + adr += mtd->erasesize; + len -= mtd->erasesize; + + if (adr >> cfi->chipshift) { + adr = 0; + chipnum++; + + if (chipnum >= cfi->numchips) + break; + } + } + + if (instr->callback) + instr->callback(instr); + + return 0; +} + + + +static void cfi_intelext_sync (struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int i; + struct flchip *chip; + int ret = 0; + DECLARE_WAITQUEUE(wait, current); + + for (i=0; !ret && inumchips; i++) { + chip = &cfi->chips[i]; + + retry: + spin_lock_bh(chip->mutex); + + switch(chip->state) { + case FL_READY: + case FL_STATUS: + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + chip->oldstate = chip->state; + chip->state = FL_SYNCING; + /* No need to wake_up() on this state change - + * as the whole point is that nobody can do anything + * with the chip now anyway. + */ + spin_unlock_bh(chip->mutex); + break; + + default: + /* Not an idle state */ + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + schedule(); + + goto retry; + } + } + + /* Unlock the chips again */ + + for (i--; i >=0; i--) { + chip = &cfi->chips[i]; + + spin_lock_bh(chip->mutex); + + if (chip->state == FL_SYNCING) { + chip->state = chip->oldstate; + wake_up(&chip->wq); + } + spin_unlock_bh(chip->mutex); + } +} + + +static int cfi_intelext_suspend(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int i; + struct flchip *chip; + int ret = 0; + + for (i=0; !ret && inumchips; i++) { + chip = &cfi->chips[i]; + + spin_lock_bh(chip->mutex); + + switch(chip->state) { + case FL_READY: + case FL_STATUS: + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + chip->oldstate = chip->state; + chip->state = FL_PM_SUSPENDED; + /* No need to wake_up() on this state change - + * as the whole point is that nobody can do anything + * with the chip now anyway. + */ + spin_unlock_bh(chip->mutex); + break; + + default: + ret = -EAGAIN; + break; + } + } + + /* Unlock the chips again */ + + for (i--; i >=0; i--) { + chip = &cfi->chips[i]; + + spin_lock_bh(chip->mutex); + + if (chip->state == FL_PM_SUSPENDED) { + chip->state = chip->oldstate; + wake_up(&chip->wq); + } + spin_unlock_bh(chip->mutex); + } + + return ret; +} + +static void cfi_intelext_resume(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int i; + struct flchip *chip; + + for (i=0; inumchips; i++) { + + chip = &cfi->chips[i]; + + spin_lock_bh(chip->mutex); + + if (chip->state == FL_PM_SUSPENDED) { + chip->state = chip->oldstate; + wake_up(&chip->wq); + } + else + printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n"); + + spin_unlock_bh(chip->mutex); + } +} + +static void cfi_intelext_destroy(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + kfree(cfi->cmdset_priv); + kfree(cfi); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/cfi_probe.c linux/drivers/mtd/cfi_probe.c --- v2.4.0-test2/linux/drivers/mtd/cfi_probe.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/cfi_probe.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,501 @@ +/* + Common Flash Interface probe code. + (C) 2000 Red Hat. GPL'd. + $Id: cfi_probe.c,v 1.12 2000/07/03 13:29:16 dwmw2 Exp $ +*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +struct mtd_info *cfi_probe(struct map_info *); +EXPORT_SYMBOL(cfi_probe); + +static void print_cfi_ident(struct cfi_ident *); +static void check_cmd_set(struct map_info *, int, unsigned long); +static struct cfi_private *cfi_cfi_probe(struct map_info *); + +struct mtd_info *cfi_probe(struct map_info *map) +{ + struct mtd_info *mtd = NULL; + struct cfi_private *cfi; + /* First probe the map to see if we have CFI stuff there. */ + cfi = cfi_cfi_probe(map); + + if (!cfi) + return NULL; + + map->fldrv_priv = cfi; + + /* OK we liked it. Now find a driver for the command set it talks */ + + check_cmd_set(map, 1, cfi->chips[0].start); /* First the primary cmdset */ + check_cmd_set(map, 0, cfi->chips[0].start); /* Then the secondary */ + + /* check_cmd_set() will have used get_module_symbol to increase + the use count of the module which provides the command set + driver. If we're quitting, we have to decrease it again. + */ + + if(cfi->cmdset_setup) { + mtd = cfi->cmdset_setup(map); + + if (mtd) + return mtd; + put_module_symbol((unsigned long)cfi->cmdset_setup); + } + printk("No supported Vendor Command Set found\n"); + + kfree(cfi); + map->fldrv_priv = NULL; + return NULL; + +} + +static int cfi_probe_new_chip(struct map_info *map, unsigned long base, + struct flchip *chips, struct cfi_private *cfi) +{ + switch (map->buswidth) { + + case 1: { + unsigned char tmp = map->read8(map, base + 0x55); + + /* If there's a device there, put it in Query Mode */ + map->write8(map, 0x98, base+0x55); + + if (map->read8(map,base+0x10) == 'Q' && + map->read8(map,base+0x11) == 'R' && + map->read8(map,base+0x12) == 'Y') { + printk("%s: Found a CFI device at 0x%lx in 8 bit mode\n", map->name, base); + if (chips) { + /* Check previous chips for aliases */ + printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__); + /* Put it back into Read Mode */ + map->write8(map, 0x98, base+0x55); + } + return 1; + } else { + if (map->read8(map, base + 0x55) == 0x98) { + /* It looks like RAM. Put back the stuff we overwrote */ + map->write8(map, tmp, base+0x55); + } + return 0; + } + } + + case 2: { + __u16 tmp = map->read16(map, base + 0xaa); + + /* If there's a device there, put it into Query Mode */ + map->write16(map, 0x9898, base+0xAA); + + if (map->read16(map, base+0x20) == cpu_to_le16(0x0051) && + map->read16(map, base+0x22) == cpu_to_le16(0x0052) && + map->read16(map, base+0x24) == cpu_to_le16(0x0059)) { + printk("%s: Found a CFI device at 0x%lx in 16 bit mode\n", map->name, base); + if (chips) { + /* Check previous chips for aliases */ + int i; + + for (i=0; i < cfi->numchips; i++) { + /* This chip should be in read mode if it's one + we've already touched. */ + if (map->read16(map, chips[i].start+0x20) == cpu_to_le16(0x0051) && + map->read16(map, chips[i].start+0x22) == cpu_to_le16(0x0052) && + map->read16(map, chips[i].start+0x24) == cpu_to_le16(0x0059)){ + /* Either the old chip has got 'Q''R''Y' in a most + unfortunate place, or it's an alias of the new + chip. Double-check that it's in read mode, and check. */ + map->write16(map, 0xffff, chips[i].start+0x20); + if (map->read16(map, chips[i].start+0x20) == cpu_to_le16(0x0051) && + map->read16(map, chips[i].start+0x22) == cpu_to_le16(0x0052) && + map->read16(map, chips[i].start+0x24) == cpu_to_le16(0x0059)) { + /* Yes it's got QRY for data. Most unfortunate. + Stick the old one in read mode too. */ + map->write16(map, 0xffff, base); + if (map->read16(map, base+0x20) == cpu_to_le16(0x0051) && + map->read16(map, base+0x22) == cpu_to_le16(0x0052) && + map->read16(map, base+0x24) == cpu_to_le16(0x0059)) { + /* OK, so has the new one. Assume it's an alias */ + printk("T'was probably an alias for the chip at 0x%lx\n", chips[i].start); + return 1; + } /* else no, they're different, fall through. */ + } else { + /* No the old one hasn't got QRY for data. Therefore, + it's an alias of the new one. */ + map->write16(map, 0xffff, base+0xaa); + /* Just to be paranoid. */ + map->write16(map, 0xffff, chips[i].start+0xaa); + printk("T'was an alias for the chip at 0x%lx\n", chips[i].start); + return 1; + } + } + /* No, the old one didn't look like it's in query mode. Next. */ + } + + /* OK, if we got to here, then none of the previous chips appear to + be aliases for the current one. */ + if (cfi->numchips == MAX_CFI_CHIPS) { + printk("%s: Too many flash chips detected. Increase MAX_CFI_CHIPS from %d.\n", map->name, MAX_CFI_CHIPS); + /* Doesn't matter about resetting it to Read Mode - we're not going to talk to it anyway */ + return 1; + } + printk("Not an alias. Adding\n"); + chips[cfi->numchips].start = base; + chips[cfi->numchips].state = FL_READY; + chips[cfi->numchips].mutex = &chips[cfi->numchips]._spinlock; + cfi->numchips++; + + /* Put it back into Read Mode */ + map->write16(map, 0xffff, base+0xaa); + } + + return 1; + } + else if (map->read16(map, base+0x20) == 0x5151 && + map->read16(map, base+0x22) == 0x5252 && + map->read16(map, base+0x24) == 0x5959) { + printk("%s: Found a coupled pair of CFI devices at %lx in 8 bit mode\n", + map->name, base); + if (chips) { + /* Check previous chips for aliases */ + printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__); + + /* Put it back into Read Mode */ + map->write16(map, 0xffff, base+0xaa); + } + + return 2; + } else { + if (map->read16(map, base+0xaa) == 0x9898) { + /* It looks like RAM. Put back the stuff we overwrote */ + map->write16(map, tmp, base+0xaa); + } + return 0; + } + } + + + case 4: { + __u32 tmp = map->read32(map, base+0x154); + + /* If there's a device there, put it into Query Mode */ + map->write32(map, 0x98989898, base+0x154); + + if (map->read32(map, base+0x40) == cpu_to_le32(0x00000051) && + map->read32(map, base+0x44) == cpu_to_le32(0x00000052) && + map->read32(map, base+0x48) == cpu_to_le32(0x00000059)) { + /* This isn't actually in the CFI spec - only x8 and x16 are. */ + printk("%s: Found a CFI device at %lx in 32 bit mode\n", map->name, base); + if (chips) { + /* Check previous chips for aliases */ + printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__); + + /* Put it back into read mode */ + map->write32(map, 0xffffffff, base+0x154); + } + return 1; + } + else if (map->read32(map, base+0x40) == cpu_to_le32(0x00510051) && + map->read32(map, base+0x44) == cpu_to_le32(0x00520052) && + map->read32(map, base+0x48) == cpu_to_le32(0x00590059)) { + printk("%s: Found a coupled pair of CFI devices at location %lx in 16 bit mode\n", map->name, base); + if (chips) { + /* Check previous chips for aliases */ + printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__); + + /* Put it back into read mode */ + map->write32(map, 0xffffffff, base+0x154); + } + return 2; + } + else if (map->read32(map, base+0x40) == 0x51515151 && + map->read32(map, base+0x44) == 0x52525252 && + map->read32(map, base+0x48) == 0x59595959) { + printk("%s: Found four side-by-side CFI devices at location %lx in 8 bit mode\n", map->name, base); + if (chips) { + /* Check previous chips for aliases */ + printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__); + + /* Put it back into read mode */ + map->write32(map, 0xffffffff, base+0x154); + } + return 4; + } else { + if (map->read32(map, base+0x154) == 0x98989898) { + /* It looks like RAM. Put back the stuff we overwrote */ + map->write32(map, tmp, base+0x154); + } + return 0; + } + } + default: + printk(KERN_WARNING "cfi_cfi_probe called with strange buswidth %d\n", map->buswidth); + return 0; + } +} + +static struct cfi_private *cfi_cfi_probe(struct map_info *map) +{ + unsigned long base=0; + struct cfi_private cfi; + struct cfi_private *retcfi; + struct flchip chip[MAX_CFI_CHIPS]; + int i; + + memset(&cfi, 0, sizeof(cfi)); + + /* The first invocation (with chips == NULL) leaves the device in Query Mode */ + cfi.interleave = cfi_probe_new_chip(map, 0, NULL, NULL); + + if (!cfi.interleave) { + printk("%s: Found no CFI device at location zero\n", map->name); + /* Doesn't appear to be CFI-compliant at all */ + return NULL; + } + + /* Read the Basic Query Structure from the device */ + + for (i=0; iread8(map,base + ((0x10 + i)*map->buswidth)); + } + + /* Do any necessary byteswapping */ + cfi.cfiq.P_ID = le16_to_cpu(cfi.cfiq.P_ID); + cfi.cfiq.P_ADR = le16_to_cpu(cfi.cfiq.P_ADR); + cfi.cfiq.A_ID = le16_to_cpu(cfi.cfiq.A_ID); + cfi.cfiq.A_ADR = le16_to_cpu(cfi.cfiq.A_ADR); + cfi.cfiq.InterfaceDesc = le16_to_cpu(cfi.cfiq.InterfaceDesc); + cfi.cfiq.MaxBufWriteSize = le16_to_cpu(cfi.cfiq.MaxBufWriteSize); + +#if 1 + /* Dump the information therein */ + print_cfi_ident(&cfi.cfiq); + + for (i=0; iread8(map,base + ((0x2d + (4*i))*map->buswidth))) + + (((map->read8(map,(0x2e + (4*i))*map->buswidth)) << 8)); + __u16 EraseRegionInfoSize = (map->read8(map, base + ((0x2f + (4*i))*map->buswidth))) + + (map->read8(map, base + ((0x30 + (4*i))*map->buswidth)) << 8); + + printk(" Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks\n", + i, EraseRegionInfoSize * 256, EraseRegionInfoNum+1); + } + + printk("\n"); +#endif + + /* Switch the chip back into Read Mode, to make the alias detection work */ + switch(map->buswidth) { + case 1: + map->write8(map, 0xff, 0x55); + break; + case 2: + map->write16(map, 0xffff, 0xaa); + break; + case 4: + map->write32(map, 0xffffffff, 0x154); + break; + } + + /* OK. We've worked out what it is and we're happy with it. Now see if there are others */ + + chip[0].start = 0; + chip[0].state = FL_READY; + chip[0].mutex = &chip[0]._spinlock; + + cfi.chipshift = cfi.cfiq.DevSize; + cfi.numchips = 1; + + if (!cfi.chipshift) { + printk("cfi.chipsize is zero. This is bad. cfi.cfiq.DevSize is %d\n", cfi.cfiq.DevSize); + return NULL; + } + + for (base = (1<size; base += (1<chips[0], chip, sizeof(struct flchip) * cfi.numchips); + for (i=0; i< retcfi->numchips; i++) { + init_waitqueue_head(&retcfi->chips[i].wq); + spin_lock_init(&retcfi->chips[i]._spinlock); + } + return retcfi; +} + +static char *vendorname(__u16 vendor) +{ + switch (vendor) { + case P_ID_NONE: + return "None"; + + case P_ID_INTEL_EXT: + return "Intel/Sharp Extended"; + + case P_ID_AMD_STD: + return "AMD/Fujitsu Standard"; + + case P_ID_INTEL_STD: + return "Intel/Sharp Standard"; + + case P_ID_AMD_EXT: + return "AMD/Fujitsu Extended"; + + case P_ID_MITSUBISHI_STD: + return "Mitsubishi Standard"; + + case P_ID_MITSUBISHI_EXT: + return "Mitsubishi Extended"; + + case P_ID_RESERVED: + return "Not Allowed / Reserved for Future Use"; + + default: + return "Unknown"; + } +} + + +static void print_cfi_ident(struct cfi_ident *cfip) +{ + if (cfip->qry[0] != 'Q' || cfip->qry[1] != 'R' || cfip->qry[2] != 'Y') { + printk("Invalid CFI ident structure.\n"); + return; + } + + printk("Primary Vendor Command Set: %4.4X (%s)\n", cfip->P_ID, vendorname(cfip->P_ID)); + if (cfip->P_ADR) + printk("Primary Algorithm Table at %4.4X\n", cfip->P_ADR); + else + printk("No Primary Algorithm Table\n"); + + printk("Alternative Vendor Command Set: %4.4X (%s)\n", cfip->A_ID, vendorname(cfip->A_ID)); + if (cfip->A_ADR) + printk("Alternate Algorithm Table at %4.4X\n", cfip->A_ADR); + else + printk("No Alternate Algorithm Table\n"); + + + printk("Vcc Minimum: %x.%x V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf); + printk("Vcc Maximum: %x.%x V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf); + if (cfip->VppMin) { + printk("Vpp Minimum: %x.%x V\n", cfip->VppMin >> 4, cfip->VppMin & 0xf); + printk("Vpp Maximum: %x.%x V\n", cfip->VppMax >> 4, cfip->VppMax & 0xf); + } + else + printk("No Vpp line\n"); + + printk("Typical byte/word write timeout: %d µs\n", 1<WordWriteTimeoutTyp); + printk("Maximum byte/word write timeout: %d µs\n", (1<WordWriteTimeoutMax) * (1<WordWriteTimeoutTyp)); + + if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) { + printk("Typical full buffer write timeout: %d µs\n", 1<BufWriteTimeoutTyp); + printk("Maximum full buffer write timeout: %d µs\n", (1<BufWriteTimeoutMax) * (1<BufWriteTimeoutTyp)); + } + else + printk("Full buffer write not supported\n"); + + printk("Typical block erase timeout: %d µs\n", 1<BlockEraseTimeoutTyp); + printk("Maximum block erase timeout: %d µs\n", (1<BlockEraseTimeoutMax) * (1<BlockEraseTimeoutTyp)); + if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) { + printk("Typical chip erase timeout: %d µs\n", 1<ChipEraseTimeoutTyp); + printk("Maximum chip erase timeout: %d µs\n", (1<ChipEraseTimeoutMax) * (1<ChipEraseTimeoutTyp)); + } + else + printk("Chip erase not supported\n"); + + printk("Device size: 0x%X bytes (%d Mb)\n", 1 << cfip->DevSize, 1<< (cfip->DevSize - 20)); + printk("Flash Device Interface description: 0x%4.4X\n", cfip->InterfaceDesc); + switch(cfip->InterfaceDesc) { + case 0: + printk(" - x8-only asynchronous interface\n"); + break; + + case 1: + printk(" - x16-only asynchronous interface\n"); + break; + + case 2: + printk(" - supports x8 and x16 via BYTE# with asynchronous interface\n"); + break; + + case 3: + printk(" - x32-only asynchronous interface\n"); + break; + + case 65535: + printk(" - Not Allowed / Reserved\n"); + break; + + default: + printk(" - Unknown\n"); + break; + } + + printk("Max. bytes in buffer write: 0x%x\n", 1<< cfip->MaxBufWriteSize); + printk("Number of Erase Block Regions: %d\n", cfip->NumEraseRegions); + +} + +static void check_cmd_set(struct map_info *map, int primary, unsigned long base) +{ + __u16 adr; + struct cfi_private *cfi = map->fldrv_priv; + __u16 type = primary?cfi->cfiq.P_ID:cfi->cfiq.A_ID; + char probename[32]; + void (*probe_function)(struct map_info *, int, unsigned long); + + if (type == P_ID_NONE || type == P_ID_RESERVED) + return; + + sprintf(probename, "cfi_cmdset_%4.4X", type); + + probe_function = (void *)get_module_symbol(NULL, probename); + if (!probe_function) { + request_module(probename); + + probe_function = (void *)get_module_symbol(NULL, probename); + } + + if (probe_function) { + (*probe_function)(map, primary, base); + put_module_symbol((unsigned long)probe_function); + return; + } + + /* This was a command set we don't know about. Print only the basic info */ + adr = primary?cfi->cfiq.P_ADR:cfi->cfiq.A_ADR; + + if (!adr) { + printk(" No Extended Query Table\n"); + } + else if (map->read8(map,base+(adr*map->buswidth)) != (primary?'P':'A') || + map->read8(map,base+((adr+1)*map->buswidth)) != (primary?'R':'L') || + map->read8(map,base+((adr+2)*map->buswidth)) != (primary?'I':'T')) { + printk ("Invalid Extended Query Table at %4.4X: %2.2X %2.2X %2.2X\n", + adr, + map->read8(map,base+(adr*map->buswidth)), + map->read8(map,base+((adr+1)*map->buswidth)), + map->read8(map,base+((adr+2)*map->buswidth))); + } + else { + printk(" Extended Query Table version %c.%c\n", + map->read8(map,base+((adr+3)*map->buswidth)), + map->read8(map,base+((adr+4)*map->buswidth))); + } +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/doc1000.c linux/drivers/mtd/doc1000.c --- v2.4.0-test2/linux/drivers/mtd/doc1000.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/doc1000.c Thu Jul 6 01:22:24 2000 @@ -0,0 +1,602 @@ +/*====================================================================== + + $Id: doc1000.c,v 1.8 2000/07/03 10:01:38 dwmw2 Exp $ + + A general driver for accessing PCMCIA card memory via Bulk + Memory Services. + + This driver provides the equivalent of /dev/mem for a PCMCIA + card's attribute and common memory. It includes character + and block devices. + + Written by David Hinds, dhinds@allegro.stanford.edu + +======================================================================*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Parameters that can be set with 'insmod' */ + +static u_long base = 0xe0000; +static int erase_timeout = 10*HZ; /* in ticks */ +static int retry_limit = 4; /* write retries */ +static u_long max_tries = 4096; /* status polling */ + +MODULE_PARM(base,"l"); +MODULE_PARM(erase_timeout, "i"); +MODULE_PARM(retry_limit, "i"); +MODULE_PARM(max_tries, "i"); + +#define WINDOW_SIZE 0x2000 +#define WINDOW_MASK (WINDOW_SIZE - 1) +#define PAGEREG_LO (WINDOW_SIZE) +#define PAGEREG_HI (WINDOW_SIZE + 2) + +static struct mtd_info *mymtd; +static struct timer_list flashcard_timer; + +#define MAX_CELLS 32 +#define MAX_FLASH_DEVICES 8 + +/* A flash region is composed of one or more "cells", where we allow + simultaneous erases if they are in different cells */ + + + +struct mypriv { + u_char *baseaddr; + u_short curpage; + u_char locked; + u_short numdevices; + u_char interleave; + struct erase_info *cur_erases; + wait_queue_head_t wq; + u_char devstat[MAX_FLASH_DEVICES]; + u_long devshift; +}; + + +static void flashcard_periodic(u_long data); +static int flashcard_erase (struct mtd_info *mtd, struct erase_info *instr); +static int flashcard_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); +static int flashcard_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); +static void flashcard_sync (struct mtd_info *mtd); + +static inline void resume_erase(volatile u_char *addr); +static inline int suspend_erase(volatile u_char *addr); +static inline int byte_write (volatile u_char *addr, u_char byte); +static inline int word_write (volatile u_char *addr, __u16 word); +static inline int check_write(volatile u_char *addr); +static inline void block_erase (volatile u_char *addr); +static inline int check_erase(volatile u_char *addr); + +#ifdef CONFIG_SMP +#warning This is definitely not SMP safe. Lock the paging mechanism. +#endif + +static u_char *pagein(struct mtd_info *mtd, u_long addr) +{ + struct mypriv *priv=mtd->priv; + u_short page = addr >> 13; + + priv->baseaddr[PAGEREG_LO] = page & 0xff; + priv->baseaddr[PAGEREG_HI] = page >> 8; + priv->curpage = page; + + return &priv->baseaddr[addr & WINDOW_MASK]; +} + + +void flashcard_sync (struct mtd_info *mtd) +{ + struct mypriv *priv=mtd->priv; + + flashcard_periodic((u_long) mtd); + printk("sync..."); + if (priv->cur_erases) + interruptible_sleep_on(&priv->wq); + printk("Done.\n"); +} + +int flashcard_erase (struct mtd_info *mtd, struct erase_info *instr) +{ + u_char *pageaddr; + struct mypriv *priv=mtd->priv; + struct erase_info **tmp=&priv->cur_erases; + + if (instr->len != mtd->erasesize) + return -EINVAL; + if (instr->addr + instr->len > mtd->size) + return -EINVAL; + + pageaddr=pagein(mtd,instr->addr); + instr->mtd = mtd; + instr->dev = instr->addr >> priv->devshift; + instr->cell = (instr->addr - (instr->dev << priv->devshift)) / mtd->erasesize; + instr->next = NULL; + instr->state = MTD_ERASE_PENDING; + + while (*tmp) + { + tmp = &((*tmp) -> next); + } + + *tmp = instr; + flashcard_periodic((u_long)mtd); + return 0; +} + + +int flashcard_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + u_char *pageaddr=pagein(mtd,from); + struct mypriv *priv=mtd->priv; + u_char device = from >> priv->devshift; + u_char cell = (int) (from - (device << priv->devshift)) / mtd->erasesize; + int ret = 0, timeron = 0; + + if ((from & WINDOW_MASK) + len <= WINDOW_SIZE) + *retlen = len; + else + *retlen = WINDOW_SIZE - (from & WINDOW_MASK); + + if (priv->devstat[device]) + { + + /* There is an erase in progress or pending for this device. Stop it */ + timeron = del_timer(&flashcard_timer); + + if (priv->cur_erases && priv->cur_erases->cell == cell) + + { + /* The erase is on the current cell. Just return all 0xff */ + add_timer(&flashcard_timer); + + + printk("Cell %d currently erasing. Setting to all 0xff\n",cell); + memset(buf, 0xff, *retlen); + return 0; + } + if (priv->devstat[device] == MTD_ERASING) + { + ret = suspend_erase(pageaddr); + priv->devstat[device] = MTD_ERASE_SUSPEND; + + if (ret) + { + printk("flashcard: failed to suspend erase\n"); + add_timer (&flashcard_timer); + return ret; + } + } + + } + + writew(IF_READ_ARRAY, (u_long)pageaddr & ~1); + + ret = 0; + memcpy (buf, pageaddr, *retlen); + + writew(IF_READ_CSR, (u_long)pageaddr & ~1); + + + if (priv->devstat[device] & MTD_ERASE_SUSPEND) + { + resume_erase(pageaddr); + priv->devstat[device]=MTD_ERASING; + } + + + if (timeron) add_timer (&flashcard_timer); + + return ret; +} + + +int flashcard_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + struct mypriv *priv = (struct mypriv *)mtd->priv; + u_char *endaddr, *startaddr; + register u_char *pageaddr; + u_char device = to >> priv->devshift; +/* jiffies_t oldj=jiffies;*/ + int ret; + + while (priv->devstat[device]) + { + flashcard_sync(mtd); + } + + if ((to & WINDOW_MASK) + len <= WINDOW_SIZE) + *retlen = len; + else + *retlen = WINDOW_SIZE - (to & WINDOW_MASK); + + pageaddr = pagein(mtd, to); + startaddr = (u_char *)((u_long) pageaddr & ~1); + endaddr = pageaddr+(*retlen); + + + + /* Set up to read */ + writew(IF_READ_CSR, startaddr); + + /* Make sure it's aligned by reading the first byte if necessary */ + if (to & 1) + { + /* Unaligned access */ + + u_char cbuf; + + cbuf = *buf; + + if (!((u_long)pageaddr & 0xf)) + schedule(); + + ret = byte_write(pageaddr, cbuf); + if (ret) return ret; + + pageaddr++; buf++; + } + + + for ( ; pageaddr + 1 < endaddr; buf += 2, pageaddr += 2) + { + /* if ((u_long)pageaddr & 0xf) schedule();*/ + + ret = word_write(pageaddr, *(__u16 *)buf); + if (ret) + return ret; + } + + if (pageaddr != endaddr) + { + /* One more byte to write at the end. */ + u_char cbuf; + + cbuf = *buf; + + ret = byte_write(pageaddr, cbuf); + + if (ret) return ret; + } + + return check_write(startaddr); +/* printk("Time taken in flashcard_write: %lx jiffies\n",jiffies - oldj);*/ +} + + + + +/*====================================================================*/ + +static inline int byte_write (volatile u_char *addr, u_char byte) +{ + register u_char status; + register u_short i; + + for (i = 0; i < max_tries; i++) + { + status = readb(addr); + if (status & CSR_WR_READY) + { + writeb(IF_WRITE & 0xff, addr); + writeb(byte, addr); + return 0; + } + } + + printk(KERN_NOTICE "flashcard: byte_write timed out, status 0x%x\n",status); + return -EIO; +} + +static inline int word_write (volatile u_char *addr, __u16 word) +{ + register u_short status = 0; + register u_short i; + + for (i = 0; i < max_tries; i++) + { + status = readw(addr); + if ((status & CSR_WR_READY) == CSR_WR_READY) + { + writew(IF_WRITE, addr); + writew(word, addr); + return 0; + } + } + + printk(KERN_NOTICE "flashcard: word_write timed out at %p, status 0x%x\n", addr, status); + return -EIO; +} + +static inline void block_erase (volatile u_char *addr) +{ + writew(IF_BLOCK_ERASE, addr); + writew(IF_CONFIRM, addr); +} + + +static inline int check_erase(volatile u_char *addr) +{ + __u16 status; + +/* writew(IF_READ_CSR, addr);*/ + status = readw(addr); + + + if ((status & CSR_WR_READY) != CSR_WR_READY) + return -EBUSY; + + if (status & (CSR_ERA_ERR | CSR_VPP_LOW | CSR_WR_ERR)) + { + printk(KERN_NOTICE "flashcard: erase failed, status 0x%x\n", + status); + return -EIO; + } + + return 0; +} + +static inline int suspend_erase(volatile u_char *addr) +{ + __u16 status = 0; + u_long i; + + writew(IF_ERASE_SUSPEND, addr); + writew(IF_READ_CSR, addr); + + for (i = 0; i < max_tries; i++) + { + status = readw(addr); + if ((status & CSR_WR_READY) == CSR_WR_READY) break; + } + if (i == max_tries) + { + printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status); + return -EIO; + } + + return 0; +} + +static inline void resume_erase(volatile u_char *addr) +{ + __u16 status; + + writew(IF_READ_CSR, addr); + status = readw(addr); + + /* Only give resume signal if the erase is really suspended */ + if (status & CSR_ERA_SUSPEND) + writew(IF_CONFIRM, addr); +} + +static inline void reset_block(volatile u_char *addr) +{ + u_short i; + __u16 status; + + writew(IF_CLEAR_CSR, addr); + + for (i = 0; i < 100; i++) { + writew(IF_READ_CSR, addr); + status = readw(addr); + if (status != 0xffff) break; + udelay(1000); + } + + writew(IF_READ_CSR, addr); +} + +static inline int check_write(volatile u_char *addr) +{ + u_short status = 0, i; + + writew(IF_READ_CSR, addr); + + for (i=0; i < max_tries; i++) + { + status = readw(addr); + if (status & (CSR_WR_ERR | CSR_VPP_LOW)) + { + printk(KERN_NOTICE "flashcard: write failure at %p, status 0x%x\n", addr, status); + reset_block(addr); + return -EIO; + } + if ((status & CSR_WR_READY) == CSR_WR_READY) + return 0; + } + printk(KERN_NOTICE "flashcard: write timed out at %p, status 0x%x\n", addr, status); + return -EIO; +} + + +/*====================================================================*/ + + + +static void flashcard_periodic(unsigned long data) +{ + register struct mtd_info *mtd = (struct mtd_info *)data; + register struct mypriv *priv = mtd->priv; + struct erase_info *erase = priv->cur_erases; + u_char *pageaddr; + + del_timer (&flashcard_timer); + + if (!erase) + return; + + pageaddr = pagein(mtd, erase->addr); + + if (erase->state == MTD_ERASE_PENDING) + { + block_erase(pageaddr); + priv->devstat[erase->dev] = erase->state = MTD_ERASING; + erase->time = jiffies; + erase->retries = 0; + } + else if (erase->state == MTD_ERASING) + { + /* It's trying to erase. Check whether it's finished */ + + int ret = check_erase(pageaddr); + + if (!ret) + { + /* It's finished OK */ + priv->devstat[erase->dev] = 0; + priv->cur_erases = erase->next; + erase->state = MTD_ERASE_DONE; + if (erase->callback) + (*(erase->callback))(erase); + else + kfree(erase); + } + else if (ret == -EIO) + { + if (++erase->retries > retry_limit) + { + printk("Failed too many times. Giving up\n"); + priv->cur_erases = erase->next; + priv->devstat[erase->dev] = 0; + erase->state = MTD_ERASE_FAILED; + if (erase->callback) + (*(erase->callback))(erase); + else + kfree(erase); + } + else + priv->devstat[erase->dev] = erase->state = MTD_ERASE_PENDING; + } + else if (erase->time + erase_timeout < jiffies) + { + printk("Flash erase timed out. The world is broken.\n"); + + /* Just ignore and hope it goes away. For a while, read ops will give the CSR + and writes won't work. */ + + priv->cur_erases = erase->next; + priv->devstat[erase->dev] = 0; + erase->state = MTD_ERASE_FAILED; + if (erase->callback) + (*(erase->callback))(erase); + else + kfree(erase); + } + } + + if (priv->cur_erases) + { + flashcard_timer.expires = jiffies + HZ; + add_timer (&flashcard_timer); + } + else + wake_up_interruptible(&priv->wq); + +} + +#if defined (MODULE) && LINUX_VERSION_CODE < 0x20300 +#define init_doc1000 init_module +#define cleanup_doc1000 cleanup_module +#endif + +int __init init_doc1000(void) +{ + struct mypriv *priv; + + if (!base) + { + printk(KERN_NOTICE "flashcard: No start address for memory device.\n"); + return -EINVAL; + } + + mymtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); + + if (!mymtd) + { + printk(KERN_NOTICE "physmem: Cannot allocate memory for new MTD device.\n"); + return -ENOMEM; + } + + memset(mymtd,0,sizeof(struct mtd_info)); + + mymtd->priv = (void *) kmalloc (sizeof(struct mypriv), GFP_KERNEL); + if (!mymtd->priv) + { + kfree(mymtd); + printk(KERN_NOTICE "physmem: Cannot allocate memory for new MTD device's private data.\n"); + return -ENOMEM; + } + + + + + priv=mymtd->priv; + init_waitqueue_head(&priv->wq); + + memset (priv,0,sizeof(struct mypriv)); + + priv->baseaddr = phys_to_virt(base); + priv->numdevices = 4; + + mymtd->name = "M-Systems DiskOnChip 1000"; + + mymtd->size = 0x100000; + mymtd->flags = MTD_CLEAR_BITS | MTD_ERASEABLE; + mymtd->erase = flashcard_erase; + mymtd->point = NULL; + mymtd->unpoint = NULL; + mymtd->read = flashcard_read; + mymtd->write = flashcard_write; + + mymtd->sync = flashcard_sync; + mymtd->erasesize = 0x10000; + // mymtd->interleave = 2; + priv->devshift = 24; + mymtd->type = MTD_NORFLASH; + + if (add_mtd_device(mymtd)) + { + printk(KERN_NOTICE "MTD device registration failed!\n"); + kfree(mymtd->priv); + kfree(mymtd); + return -EAGAIN; + } + + init_timer(&flashcard_timer); + flashcard_timer.function = flashcard_periodic; + flashcard_timer.data = (u_long)mymtd; + return 0; +} + +static void __init cleanup_doc1000(void) +{ + kfree (mymtd->priv); + del_mtd_device(mymtd); + kfree(mymtd); +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/doc2000.c linux/drivers/mtd/doc2000.c --- v2.4.0-test2/linux/drivers/mtd/doc2000.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/doc2000.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,837 @@ + +/* Linux driver for Disk-On-Chip 2000 */ +/* (c) 1999 Machine Vision Holdings, Inc. */ +/* Author: David Woodhouse */ +/* $Id: doc2000.c,v 1.23 2000/07/03 10:01:38 dwmw2 Exp $ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +//#define PRERELEASE + +static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); +static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); +static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eecbuf); +static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf); +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf); +static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, const u_char *buf); +static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); + + +static struct mtd_info *doc2klist = NULL; + +/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ + +int _DoC_WaitReady (unsigned long docptr) +{ + //long c=-1; + short c=-1; + + DEBUG(2,"_DoC_WaitReady called for out-of-line wait\n"); + + /* Out-of-line routine to wait for chip response */ + while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c) + ; + + if (c == 0) + DEBUG(2, "_DoC_WaitReady timed out.\n"); + + return (c==0); +} + +static inline int DoC_WaitReady(unsigned long docptr) +{ + /* This is inline, to optimise the common case, where it's ready instantly */ + volatile char dummy; + int ret = 0; + + /* Out-of-line routine to wait for chip response */ + /* TPW: Add 4 reads - see Software Requirement 2.3.2 */ + dummy = ReadDOC(docptr, CDSNControl); + dummy = ReadDOC(docptr, CDSNControl); + dummy = ReadDOC(docptr, CDSNControl); + dummy = ReadDOC(docptr, CDSNControl); + + if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) + ret = _DoC_WaitReady(docptr); /* Call the out-of-line routine to wait */ + + /* TPW: Add 2 reads - see Software Requirement 2.3.2 */ + dummy = ReadDOC(docptr, CDSNControl); + dummy = ReadDOC(docptr, CDSNControl); + + return ret; +} + + +/* DoC_Command: Send a flash command to the flash chip */ + +static inline int DoC_Command(unsigned long docptr, unsigned char command, unsigned char xtraflags) +{ + /* Assert the CLE (Command Latch Enable) line to the flash chip */ + WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, + docptr, CDSNControl); + + /* Send the command */ + WriteDOC(command, docptr, 2k_CDSN_IO); + + /* Lower the CLE line */ + WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags | CDSN_CTRL_CE, docptr, CDSNControl); + + /* Wait for the chip to respond */ + return DoC_WaitReady(docptr); +} + +/* DoC_Address: Set the current address for the flash chip */ + +static inline int DoC_Address (unsigned long docptr, int numbytes, unsigned long ofs, + unsigned char xtraflags1, unsigned char xtraflags2) +{ + /* Assert the ALE (Address Latch Enable line to the flash chip */ + WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, + docptr, CDSNControl); + + /* Send the address */ + /* Three cases: + numbytes == 1: Send single byte, bits 0-7. + numbytes == 2: Send bits 9-16 followed by 17-23 + numbytes == 3: Send 0-7, 9-16, then 17-23 + */ + if (numbytes != 2) + WriteDOC(ofs & 0xff, docptr, 2k_CDSN_IO); + + if (numbytes != 1) { + WriteDOC((ofs >> 9) & 0xff, docptr, 2k_CDSN_IO); + WriteDOC((ofs >> 17) & 0xff, docptr, 2k_CDSN_IO); + } + /* Lower the ALE line */ + WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl); + + /* Wait for the chip to respond */ + return DoC_WaitReady(docptr); +} + +/* DoC_SelectChip: Select a given flash chip within the current floor */ + +static inline int DoC_SelectChip(unsigned long docptr, int chip) +{ + /* Select the individual flash chip requested */ + WriteDOC( chip, docptr, CDSNDeviceSelect); + + /* Wait for it to be ready */ + return DoC_WaitReady(docptr); +} + +/* DoC_SelectFloor: Select a given floor (bank of flash chips) */ + +static inline int DoC_SelectFloor(unsigned long docptr, int floor) +{ + /* Select the floor (bank) of chips required */ + WriteDOC( floor, docptr, FloorSelect); + + /* Wait for the chip to be ready */ + return DoC_WaitReady(docptr); +} + +/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */ + +int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) +{ + int mfr, id, chipshift=0; + char *mfrname=NULL, *idname=NULL; + + /* Page in the required floor/chip */ + DoC_SelectFloor(doc->virtadr, floor); + DoC_SelectChip(doc->virtadr, chip); + + /* Reset the chip */ + if (DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP)) { + DEBUG(2, "DoC_Command (reset) for %d,%d returned true\n", floor,chip); + return 0; + } + + /* Read the NAND chip ID: 1. Send ReadID command */ + if(DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP)) { + DEBUG(2,"DoC_Command (ReadID) for %d,%d returned true\n", floor,chip); + return 0; + } + + /* Read the NAND chip ID: 2. Send address byte zero + */ + DoC_Address(doc->virtadr, 1, 0, CDSN_CTRL_WP, 0); + + /* Read the manufacturer and device id codes from the device */ + mfr = ReadDOC(doc->virtadr, 2k_CDSN_IO); + id = ReadDOC(doc->virtadr, 2k_CDSN_IO); + + /* No response - return failure */ + if (mfr == 0xff || mfr == 0) + return 0; + + /* Check it's the same as the first chip we identified. + * M-Systems say that any given DiskOnChip device should only + * contain _one_ type of flash part, although that's not a + * hardware restriction. */ + if (doc->mfr) { + if (doc->mfr == mfr && doc->id == id) + return 1; /* This is another the same the first */ + else + printk(KERN_WARNING "Flash chip at floor %d, chip %d is different:\n", + floor, chip); + } + + /* Print (and store if first time) the manufacturer and ID codes. */ + + switch(mfr) { + case NAND_MFR_TOSHIBA: /* Toshiba */ + mfrname = "Toshiba"; + + switch(id) { + case 0x64: + idname = "TC5816BDC"; + chipshift = 21; + break; + + case 0x6b: + idname = "TC5832DC"; + chipshift = 22; + break; + + case 0x73: + idname = "TH58V128DC"; + chipshift = 24; + break; + + case 0x75: + idname = "TC58256FT/DC"; + chipshift = 25; + break; + + case 0xe5: + idname = "TC58V32DC"; + chipshift = 22; + break; + + case 0xe6: + idname = "TC58V64DC"; + chipshift = 23; + break; + + case 0xea: + idname = "TC58V16BDC"; + chipshift = 21; + break; + } + break; /* End of Toshiba parts */ + + case NAND_MFR_SAMSUNG: /* Samsung */ + mfrname = "Samsung"; + + switch(id) { + case 0x64: + idname = "KM29N16000"; + chipshift = 21; + + case 0x73: + idname = "KM29U128T"; + chipshift = 24; + break; + + case 0x75: + idname = "KM29U256T"; + chipshift = 25; + break; + + case 0xe3: + idname = "KM29W32000"; + chipshift = 22; + break; + + case 0xe6: + idname = "KM29U64000"; + chipshift = 23; + break; + + case 0xea: + idname = "KM29W16000"; + chipshift = 21; + break; + } + break; /* End of Samsung parts */ + } + + /* If we've identified it fully, print the full names */ + if (idname) { +#ifdef PRERELEASE + DEBUG(1, "Flash chip found: %2.2X %2.2X (%s %s)\n", + mfr,id,mfrname,idname); +#endif + /* If this is the first chip, store the id codes */ + if (!doc->mfr) { + doc->mfr = mfr; + doc->id = id; + doc->chipshift = chipshift; + return 1; + } + return 0; + } + + /* We haven't fully identified the chip. Print as much as we know. */ + if (mfrname) + printk(KERN_WARNING "Unknown %s flash chip found: %2.2X %2.2X\n", mfrname, + id, mfr); + else + printk(KERN_WARNING "Unknown flash chip found: %2.2X %2.2X\n", id, mfr); + + printk(KERN_WARNING "Please report to David.Woodhouse@mvhi.com\n"); + return 0; +} + +/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */ + +void DoC_ScanChips(struct DiskOnChip *this) +{ + int floor, chip; + int numchips[MAX_FLOORS]; + int ret = 1; + + this->numchips = 0; + this->mfr = 0; + this->id = 0; + + /* For each floor, find the number of valid chips it contains */ + for (floor = 0 ; floor < MAX_FLOORS ; floor++) { + ret = 1; + numchips[floor]=0; + for (chip = 0 ; chip < MAX_CHIPS && ret != 0; chip++ ) { + + ret = DoC_IdentChip(this, floor, chip); + if (ret) { + numchips[floor]++; + this->numchips++; + } + } + } + + /* If there are none at all that we recognise, bail */ + if (!this->numchips) { + printk("No flash chips recognised.\n"); + return; + } + + /* Allocate an array to hold the information for each chip */ + this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL); + if (!this->chips){ + printk("No memory for allocating chip info structures\n"); + return; + } + + ret = 0; + + /* Fill out the chip array with {floor, chipno} for each + * detected chip in the device. */ + for (floor = 0; floor < MAX_FLOORS; floor++) { + for (chip = 0 ; chip < numchips[floor] ; chip++) { + this->chips[ret].floor = floor; + this->chips[ret].chip = chip; + this->chips[ret].curadr = 0; + this->chips[ret].curmode = 0x50; + ret++; + } + } + + /* Calculate and print the total size of the device */ + this->totlen = this->numchips * (1 << this->chipshift); + + printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld Mb\n", this->numchips , + this->totlen >> 20); +} + + +static int DoC2k_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2) +{ + int tmp1, tmp2, retval; + if (doc1->physadr == doc2->physadr) + return 1; + + /* Use the alias resolution register which was set aside for this + * purpose. If it's value is the same on both chips, they might + * be the same chip, and we write to one and check for a change in + * the other. It's unclear if this register is usuable in the + * DoC 2000 (it's in the Millenium docs), but it seems to work. */ + tmp1 = ReadDOC(doc1->virtadr, AliasResolution); + tmp2 = ReadDOC(doc2->virtadr, AliasResolution); + if (tmp1 != tmp2) + return 0; + + WriteDOC((tmp1+1) % 0xff, doc1->virtadr, AliasResolution); + tmp2 = ReadDOC(doc2->virtadr, AliasResolution); + if (tmp2 == (tmp1+1) % 0xff) + retval = 1; + else + retval = 0; + + /* Restore register contents. May not be necessary, but do it just to + * be safe. */ + WriteDOC(tmp1, doc1->virtadr, AliasResolution); + + return retval; +} + + +void DoC2k_init(struct mtd_info *mtd) +{ + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + struct DiskOnChip *old = NULL; + + /* We must avoid being called twice for the same device. */ + + if (doc2klist) + old = (struct DiskOnChip *)doc2klist->priv; + + while (old) { + if (DoC2k_is_alias(old, this)) { + printk(KERN_NOTICE "Ignoring DiskOnChip 2000 at 0x%lX - already configured\n", + this->physadr); + iounmap((void *)this->virtadr); + kfree(mtd); + return; + } + if (old->nextdoc) + old = (struct DiskOnChip *)old->nextdoc->priv; + else + old = NULL; + } + + + mtd->name = "DiskOnChip 2000"; + printk(KERN_NOTICE "DiskOnChip 2000 found at address 0x%lX\n",this->physadr); + + mtd->type = MTD_NANDFLASH; + mtd->flags = MTD_CAP_NANDFLASH; + mtd->size = 0; + mtd->erasesize = 0x2000; + mtd->oobblock = 512; + mtd->oobsize = 16; + mtd->module = THIS_MODULE; + mtd->erase = doc_erase; + mtd->point = NULL; + mtd->unpoint = NULL; + mtd->read = doc_read; + mtd->write = doc_write; + mtd->read_ecc = doc_read_ecc; + mtd->write_ecc = doc_write_ecc; + mtd->read_oob = doc_read_oob; + mtd->write_oob = doc_write_oob; + mtd->sync = NULL; + + this->totlen = 0; + this->numchips = 0; + + this->curfloor = -1; + this->curchip = -1; + + /* Ident all the chips present. */ + DoC_ScanChips(this); + + if (!this->totlen) { + kfree(mtd); + iounmap((void *)this->virtadr); + } else { + this->nextdoc = doc2klist; + doc2klist = mtd; + mtd->size = this->totlen; + add_mtd_device(mtd); + return; + } +} + + +EXPORT_SYMBOL(DoC2k_init); + +static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + /* Just a special case of doc_read_ecc */ + return doc_read_ecc(mtd, from, len, retlen, buf, NULL); +} + +static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf) +{ + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + int di=0; /* Yes, DI is a hangover from when I was disassembling the binary driver */ + unsigned long docptr; + struct Nand *mychip; + + docptr = this->virtadr; + + /* Don't allow read past end of device */ + if (from >= this->totlen) + return -EINVAL; + + /* Don't allow a single read to cross a 512-byte block boundary */ + if (from + len > ( (from | 0x1ff) + 1)) + len = ((from | 0x1ff) + 1) - from; + + /* Find the chip which is to be used and select it */ + mychip = &this->chips[from >> (this->chipshift)]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } + else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + + if (eccbuf) { + /* Prime the ECC engine */ + WriteDOC ( DOC_ECC_RESET, docptr, ECCConf); + WriteDOC ( DOC_ECC_EN, docptr, ECCConf); + } + + DoC_Command(docptr, (from >> 8) & 1, CDSN_CTRL_WP); + DoC_Address(docptr, 3, from, CDSN_CTRL_WP , CDSN_CTRL_ECC_IO); + + for (di=0; di < len ; di++) { + buf[di] = ReadDOC(docptr, 2k_CDSN_IO); + } + + /* Let the caller know we completed it */ + *retlen = len; + + if (eccbuf) { + /* Read the ECC data through the DiskOnChip ECC logic */ + for (di=0; di<6; di++) { + eccbuf[di] = ReadDOC(docptr, 2k_CDSN_IO); + } + + /* Flush the pipeline */ + (void) ReadDOC(docptr, 2k_ECCStatus); + (void) ReadDOC(docptr, 2k_ECCStatus); + + /* Check the ECC Status */ + if (ReadDOC(docptr, 2k_ECCStatus) & 0x80) { + /* There was an ECC error */ + printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); + + /* FIXME: Implement ECC error correction, don't just whinge */ + + /* We return error, but have actually done the read. Not that + this can be told to user-space, via sys_read(), but at least + MTD-aware stuff can know about it by checking *retlen */ + return -EIO; + } +#ifdef PSYCHO_DEBUG + else + printk("ECC OK at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], eccbuf[4], + eccbuf[5]); +#endif + + /* Reset the ECC engine */ + WriteDOC(DOC_ECC_RESV, docptr , ECCConf); + + } + + return 0; +} + +static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + static char as[6]; + return doc_write_ecc(mtd, to, len, retlen, buf, as); +} + +static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf) +{ + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + int di=0; + unsigned long docptr; + struct Nand *mychip; + + docptr = this->virtadr; + + /* Don't allow write past end of device */ + if (to >= this->totlen) + return -EINVAL; +#if 0 + /* Don't allow a single write to cross a 512-byte block boundary */ + if (to + len > ( (to | 0x1ff) + 1)) + len = ((to | 0x1ff) + 1) - to; + +#else + /* Don't allow writes which aren't exactly one block */ + if (to & 0x1ff || len != 0x200) + return -EINVAL; +#endif + + /* Find the chip which is to be used and select it */ + mychip = &this->chips[to >> (this->chipshift)]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } + else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + /* Set device to main plane of flash */ + DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP); + DoC_Command(docptr, NAND_CMD_READ0, CDSN_CTRL_WP); + + if (eccbuf) { + /* Prime the ECC engine */ + WriteDOC ( DOC_ECC_RESET, docptr, ECCConf); + WriteDOC ( DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); + } + + DoC_Command(docptr, NAND_CMD_SEQIN, 0); + DoC_Address(docptr, 3, to, 0, CDSN_CTRL_ECC_IO); + + for (di=0; di < len ; di++) { + WriteDOC(buf[di], docptr, 2k_CDSN_IO); + } + + + if (eccbuf) { + WriteDOC( CDSN_CTRL_ECC_IO | CDSN_CTRL_CE , docptr, CDSNControl ); + +#if 1 + /* eduardp@m-sys.com says this shouldn't be necessary, + * but it doesn't actually work without it, so I've + * left it in for now. dwmw2. + */ + + WriteDOC( 0, docptr, 2k_CDSN_IO); + WriteDOC( 0, docptr, 2k_CDSN_IO); + WriteDOC( 0, docptr, 2k_CDSN_IO); +#endif + /* Read the ECC data through the DiskOnChip ECC logic */ + for (di=0; di<6; di++) { + eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di); + } +#ifdef PSYCHO_DEBUG + printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long) to, eccbuf[0], eccbuf[1], eccbuf[2], + eccbuf[3], eccbuf[4], eccbuf[5] ); +#endif + /* Reset the ECC engine */ + WriteDOC(DOC_ECC_RESV, docptr , ECCConf); + + } + + DoC_Command(docptr, NAND_CMD_PAGEPROG, 0); + + DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP); + /* There's an implicit DoC_WaitReady() in DoC_Command */ + + if (ReadDOC(docptr, 2k_CDSN_IO) & 1) { + printk("Error programming flash\n"); + /* Error in programming */ + *retlen = 0; + return -EIO; + } + + /* Let the caller know we completed it */ + *retlen = len; + + return 0; +} + + + +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf) +{ + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + int i; + unsigned long docptr; + struct Nand *mychip; + + docptr = this->virtadr; + + mychip = &this->chips[ofs >> this->chipshift]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } + else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + + + DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP); + DoC_Address(docptr, 3, ofs, CDSN_CTRL_WP, 0); + + for (i=0; ipriv; + int i; + unsigned long docptr; + struct Nand *mychip; + + // printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len, + // buf[0], buf[1], buf[2], buf[3], buf[8], buf[9], buf[14],buf[15]); + + docptr = this->virtadr; + + mychip = &this->chips[ofs >> this->chipshift]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } + else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP); + DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP); + + DoC_Command(docptr, NAND_CMD_SEQIN, 0); + DoC_Address(docptr, 3, ofs, 0, 0); + + for (i=0; ipriv; + unsigned long ofs = instr->addr; + unsigned long len = instr->len; + unsigned long docptr; + struct Nand *mychip; + + if(len != mtd->erasesize) + printk(KERN_WARNING "Erase not right size (%lx != %lx)n", len, mtd->erasesize); + + + docptr = this->virtadr; + + mychip = &this->chips[ofs >> this->chipshift]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } + else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + instr->state = MTD_ERASE_PENDING; + + DoC_Command(docptr, NAND_CMD_ERASE1, 0); + DoC_Address(docptr, 2, ofs, 0, 0); + DoC_Command(docptr, NAND_CMD_ERASE2, 0); + + instr->state = MTD_ERASING; + + DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP); + + if (ReadDOC(docptr, 2k_CDSN_IO) & 1) { + printk("Error writing\n"); + /* There was an error */ + instr->state = MTD_ERASE_FAILED; + } + else + instr->state = MTD_ERASE_DONE; + + if (instr->callback) + instr->callback(instr); + + return 0; +} + + + + + +/**************************************************************************** + * + * Module stuff + * + ****************************************************************************/ + +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define cleanup_doc2000 cleanup_module +#endif +#define __exit +#endif + + +static void __exit cleanup_doc2000(void) +{ + struct mtd_info *mtd; + struct DiskOnChip *this; + + while((mtd=doc2klist)) { + this = (struct DiskOnChip *)mtd->priv; + doc2klist = this->nextdoc; + + del_mtd_device(mtd); + + iounmap((void *)this->virtadr); + kfree(this->chips); + kfree(mtd); + } + +} + +#if LINUX_VERSION_CODE > 0x20300 +module_exit(cleanup_doc2000); +#endif + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/doc2001.c linux/drivers/mtd/doc2001.c --- v2.4.0-test2/linux/drivers/mtd/doc2001.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/doc2001.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,844 @@ + +/* Linux driver for Disk-On-Chip Millennium */ +/* (c) 1999 Machine Vision Holdings, Inc. */ +/* Author: David Woodhouse */ +/* $Id: doc2001.c,v 1.4 2000/07/03 10:01:38 dwmw2 Exp $ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + + +//#define PRERELEASE +#if 0 +static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); +static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); +static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eecbuf); +static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf); +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf); +static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, const u_char *buf); +static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); +#endif + +static struct mtd_info *docmillist = NULL; + +/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ + +int _DoC_WaitReady (unsigned long docptr) +{ + //long c=-1; + short c=-1; + + DEBUG(2,"_DoC_WaitReady called for out-of-line wait\n"); + + /* Out-of-line routine to wait for chip response */ + while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c) + ; + + if (c == 0) + DEBUG(2, "_DoC_WaitReady timed out.\n"); + + return (c==0); +} + +static inline int DoC_WaitReady(unsigned long docptr) +{ + /* This is inline, to optimise the common case, where it's ready instantly */ + volatile char dummy; + int ret = 0; + + /* Out-of-line routine to wait for chip response */ + /* TPW: Add 4 reads - see Software Requirement 2.3.2 */ + dummy = ReadDOC(docptr, CDSNControl); + dummy = ReadDOC(docptr, CDSNControl); + dummy = ReadDOC(docptr, CDSNControl); + dummy = ReadDOC(docptr, CDSNControl); + + if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) + ret = _DoC_WaitReady(docptr); /* Call the out-of-line routine to wait */ + + /* TPW: Add 2 reads - see Software Requirement 2.3.2 */ + dummy = ReadDOC(docptr, CDSNControl); + dummy = ReadDOC(docptr, CDSNControl); + + return ret; +} + + +/* DoC_Command: Send a flash command to the flash chip */ + +static inline int DoC_Command(unsigned long docptr, unsigned char command, unsigned char xtraflags) +{ + /* Assert the CLE (Command Latch Enable) line to the flash chip */ + WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, + docptr, CDSNControl); + + /* Send the command */ + WriteDOC(command, docptr, 2k_CDSN_IO); + + /* Lower the CLE line */ + WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags | CDSN_CTRL_CE, docptr, CDSNControl); + + /* Wait for the chip to respond */ + return DoC_WaitReady(docptr); +} + +/* DoC_Address: Set the current address for the flash chip */ + +static inline int DoC_Address (unsigned long docptr, int numbytes, unsigned long ofs, + unsigned char xtraflags1, unsigned char xtraflags2) +{ + /* Assert the ALE (Address Latch Enable line to the flash chip */ + WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, + docptr, CDSNControl); + + /* Send the address */ + /* Three cases: + numbytes == 1: Send single byte, bits 0-7. + numbytes == 2: Send bits 9-16 followed by 17-23 + numbytes == 3: Send 0-7, 9-16, then 17-23 + */ + if (numbytes != 2) + WriteDOC(ofs & 0xff, docptr, 2k_CDSN_IO); + + if (numbytes != 1) { + WriteDOC((ofs >> 9) & 0xff, docptr, 2k_CDSN_IO); + WriteDOC((ofs >> 17) & 0xff, docptr, 2k_CDSN_IO); + } + /* Lower the ALE line */ + WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl); + + /* Wait for the chip to respond */ + return DoC_WaitReady(docptr); +} + +/* DoC_SelectChip: Select a given flash chip within the current floor */ + +static inline int DoC_SelectChip(unsigned long docptr, int chip) +{ + /* Select the individual flash chip requested */ + WriteDOC( chip, docptr, CDSNDeviceSelect); + + /* Wait for it to be ready */ + return DoC_WaitReady(docptr); +} + +/* DoC_SelectFloor: Select a given floor (bank of flash chips) */ + +static inline int DoC_SelectFloor(unsigned long docptr, int floor) +{ + /* Select the floor (bank) of chips required */ + WriteDOC( floor, docptr, FloorSelect); + + /* Wait for the chip to be ready */ + return DoC_WaitReady(docptr); +} + +/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */ + +int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) +{ + int mfr, id, chipshift=0; + char *mfrname=NULL, *idname=NULL; + + /* Page in the required floor/chip */ + DoC_SelectFloor(doc->virtadr, floor); + DoC_SelectChip(doc->virtadr, chip); + + /* Reset the chip */ + if (DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP)) { + DEBUG(2, "DoC_Command (reset) for %d,%d returned true\n", floor,chip); + return 0; + } + + /* Read the NAND chip ID: 1. Send ReadID command */ + if(DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP)) { + DEBUG(2,"DoC_Command (ReadID) for %d,%d returned true\n", floor,chip); + return 0; + } + + /* Read the NAND chip ID: 2. Send address byte zero + */ + DoC_Address(doc->virtadr, 1, 0, CDSN_CTRL_WP, 0); + + /* Read the manufacturer and device id codes from the device */ + mfr = ReadDOC(doc->virtadr, 2k_CDSN_IO); + id = ReadDOC(doc->virtadr, 2k_CDSN_IO); + + /* No response - return failure */ + if (mfr == 0xff || mfr == 0) + return 0; + + /* Check it's the same as the first chip we identified. + * M-Systems say that any given DiskOnChip device should only + * contain _one_ type of flash part, although that's not a + * hardware restriction. */ + if (doc->mfr) { + if (doc->mfr == mfr && doc->id == id) + return 1; /* This is another the same the first */ + else + printk(KERN_WARNING "Flash chip at floor %d, chip %d is different:\n", + floor, chip); + } + + /* Print (and store if first time) the manufacturer and ID codes. */ + + switch(mfr) { + case NAND_MFR_TOSHIBA: /* Toshiba */ + mfrname = "Toshiba"; + + switch(id) { + case 0x64: + idname = "TC5816BDC"; + chipshift = 21; + break; + + case 0x6b: + idname = "TC5832DC"; + chipshift = 22; + break; + + case 0x73: + idname = "TH58V128DC"; + chipshift = 24; + break; + + case 0x75: + idname = "TC58256FT/DC"; + chipshift = 25; + break; + + case 0xe5: + idname = "TC58V32DC"; + chipshift = 22; + break; + + case 0xe6: + idname = "TC58V64DC"; + chipshift = 23; + break; + + case 0xea: + idname = "TC58V16BDC"; + chipshift = 21; + break; + } + break; /* End of Toshiba parts */ + + case NAND_MFR_SAMSUNG: /* Samsung */ + mfrname = "Samsung"; + + switch(id) { + case 0x64: + idname = "KM29N16000"; + chipshift = 21; + + case 0x73: + idname = "KM29U128T"; + chipshift = 24; + break; + + case 0x75: + idname = "KM29U256T"; + chipshift = 25; + break; + + case 0xe3: + idname = "KM29W32000"; + chipshift = 22; + break; + + case 0xe6: + idname = "KM29U64000"; + chipshift = 23; + break; + + case 0xea: + idname = "KM29W16000"; + chipshift = 21; + break; + } + break; /* End of Samsung parts */ + } + + /* If we've identified it fully, print the full names */ + if (idname) { +#ifdef PRERELEASE + DEBUG(1, "Flash chip found: %2.2X %2.2X (%s %s)\n", + mfr,id,mfrname,idname); +#endif + /* If this is the first chip, store the id codes */ + if (!doc->mfr) { + doc->mfr = mfr; + doc->id = id; + doc->chipshift = chipshift; + return 1; + } + return 0; + } + + /* We haven't fully identified the chip. Print as much as we know. */ + if (mfrname) + printk(KERN_WARNING "Unknown %s flash chip found: %2.2X %2.2X\n", mfrname, + id, mfr); + else + printk(KERN_WARNING "Unknown flash chip found: %2.2X %2.2X\n", id, mfr); + + printk(KERN_WARNING "Please report to David.Woodhouse@mvhi.com\n"); + return 0; +} + +/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */ + +void DoC_ScanChips(struct DiskOnChip *this) +{ + int floor, chip; + int numchips[MAX_FLOORS]; + int ret = 1; + + this->numchips = 0; + this->mfr = 0; + this->id = 0; + + /* For each floor, find the number of valid chips it contains */ + for (floor = 0 ; floor < MAX_FLOORS ; floor++) { + ret = 1; + numchips[floor]=0; + for (chip = 0 ; chip < MAX_CHIPS && ret != 0; chip++ ) { + + ret = DoC_IdentChip(this, floor, chip); + if (ret) { + numchips[floor]++; + this->numchips++; + } + } + } + + /* If there are none at all that we recognise, bail */ + if (!this->numchips) { + printk("No flash chips recognised.\n"); + return; + } + + /* Allocate an array to hold the information for each chip */ + this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL); + if (!this->chips){ + printk("No memory for allocating chip info structures\n"); + return; + } + + ret = 0; + + /* Fill out the chip array with {floor, chipno} for each + * detected chip in the device. */ + for (floor = 0; floor < MAX_FLOORS; floor++) { + for (chip = 0 ; chip < numchips[floor] ; chip++) { + this->chips[ret].floor = floor; + this->chips[ret].chip = chip; + this->chips[ret].curadr = 0; + this->chips[ret].curmode = 0x50; + ret++; + } + } + + /* Calculate and print the total size of the device */ + this->totlen = this->numchips * (1 << this->chipshift); + + printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld Mb\n", this->numchips , + this->totlen >> 20); +} + +static int DoCMil_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2) +{ + int tmp1, tmp2, retval; + if (doc1->physadr == doc2->physadr) + return 1; + + /* Use the alias resolution register which was set aside for this + * purpose. If it's value is the same on both chips, they might + * be the same chip, and we write to one and check for a change in + * the other. It's unclear if this register is usuable in the + * DoC 2000 (it's in the Millenium docs), but it seems to work. */ + tmp1 = ReadDOC(doc1->virtadr, AliasResolution); + tmp2 = ReadDOC(doc2->virtadr, AliasResolution); + if (tmp1 != tmp2) + return 0; + + WriteDOC((tmp1+1) % 0xff, doc1->virtadr, AliasResolution); + tmp2 = ReadDOC(doc2->virtadr, AliasResolution); + if (tmp2 == (tmp1+1) % 0xff) + retval = 1; + else + retval = 0; + + /* Restore register contents. May not be necessary, but do it just to + * be safe. */ + WriteDOC(tmp1, doc1->virtadr, AliasResolution); + + return retval; +} + + +void DoCMil_init(struct mtd_info *mtd) +{ + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + struct DiskOnChip *old = NULL; + + /* We must avoid being called twice for the same device. */ + + if (docmillist) + old = (struct DiskOnChip *)docmillist->priv; + + while (old) { + if (DoCMil_is_alias(this, old)) { + printk(KERN_NOTICE "Ignoring DiskOnChip Millennium at 0x%lX - already configured\n", + this->physadr); + iounmap((void *)this->virtadr); + kfree(mtd); + return; + } + if (old->nextdoc) + old = (struct DiskOnChip *)old->nextdoc->priv; + else + old = NULL; + } + + mtd->name = "DiskOnChip Millennium"; + printk(KERN_NOTICE "DiskOnChip Millennium found at address 0x%lX\n",this->physadr); + +#if 1 + printk("Unfortunately, we don't have support for the DiskOnChip Millennium yet.\n"); + iounmap((void *)this->virtadr); + kfree(mtd); + return; +#else + mtd->type = MTD_NANDFLASH; + mtd->flags = MTD_CAP_NANDFLASH; + mtd->size = 0; + mtd->erasesize = 0x2000; + mtd->oobblock = 512; + mtd->oobsize = 16; + mtd->module = THIS_MODULE; + mtd->erase = doc_erase; + mtd->point = NULL; + mtd->unpoint = NULL; + mtd->read = doc_read; + mtd->write = doc_write; + mtd->read_ecc = doc_read_ecc; + mtd->write_ecc = doc_write_ecc; + mtd->read_oob = doc_read_oob; + mtd->write_oob = doc_write_oob; + mtd->sync = NULL; + + this->totlen = 0; + this->numchips = 0; + + this->curfloor = -1; + this->curchip = -1; + + /* Ident all the chips present. */ + DoC_ScanChips(this); + + if (!this->totlen) { + kfree(mtd); + iounmap((void *)this->virtadr); + } else { + this->nextdoc = docmillist; + docmillist = mtd; + mtd->size = this->totlen; + add_mtd_device(mtd); + return; + } +#endif +} + + +EXPORT_SYMBOL(DoCMil_init); +#if 0 +static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + /* Just a special case of doc_read_ecc */ + return doc_read_ecc(mtd, from, len, retlen, buf, NULL); +} + +static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf) +{ + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + int di=0; /* Yes, DI is a hangover from when I was disassembling the binary driver */ + unsigned long docptr; + struct Nand *mychip; + + docptr = this->virtadr; + + /* Don't allow read past end of device */ + if (from >= this->totlen) + return -EINVAL; + + /* Don't allow a single read to cross a 512-byte block boundary */ + if (from + len > ( (from | 0x1ff) + 1)) + len = ((from | 0x1ff) + 1) - from; + + /* Find the chip which is to be used and select it */ + mychip = &this->chips[from >> (this->chipshift)]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } + else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + + if (eccbuf) { + /* Prime the ECC engine */ + WriteDOC ( DOC_ECC_RESET, docptr, ECCConf); + WriteDOC ( DOC_ECC_EN, docptr, ECCConf); + } + + DoC_Command(docptr, (from >> 8) & 1, CDSN_CTRL_WP); + DoC_Address(docptr, 3, from, CDSN_CTRL_WP , CDSN_CTRL_ECC_IO); + + for (di=0; di < len ; di++) { + buf[di] = ReadDOC(docptr, 2k_CDSN_IO); + } + + /* Let the caller know we completed it */ + *retlen = len; + + if (eccbuf) { + /* Read the ECC data through the DiskOnChip ECC logic */ + for (di=0; di<6; di++) { + eccbuf[di] = ReadDOC(docptr, 2k_CDSN_IO); + } + + /* Flush the pipeline */ + (void) ReadDOC(docptr, 2k_ECCStatus); + (void) ReadDOC(docptr, 2k_ECCStatus); + + /* Check the ECC Status */ + if (ReadDOC(docptr, 2k_ECCStatus) & 0x80) { + /* There was an ECC error */ + printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); + + /* FIXME: Implement ECC error correction, don't just whinge */ + + /* We return error, but have actually done the read. Not that + this can be told to user-space, via sys_read(), but at least + MTD-aware stuff can know about it by checking *retlen */ + return -EIO; + } +#ifdef PSYCHO_DEBUG + else + printk("ECC OK at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], eccbuf[4], + eccbuf[5]); +#endif + + /* Reset the ECC engine */ + WriteDOC(DOC_ECC_RESV, docptr , ECCConf); + + } + + return 0; +} + +static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + static char as[6]; + return doc_write_ecc(mtd, to, len, retlen, buf, as); +} + +static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf) +{ + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + int di=0; + unsigned long docptr; + struct Nand *mychip; + + docptr = this->virtadr; + + /* Don't allow write past end of device */ + if (to >= this->totlen) + return -EINVAL; +#if 0 + /* Don't allow a single write to cross a 512-byte block boundary */ + if (to + len > ( (to | 0x1ff) + 1)) + len = ((to | 0x1ff) + 1) - to; + +#else + /* Don't allow writes which aren't exactly one block */ + if (to & 0x1ff || len != 0x200) + return -EINVAL; +#endif + + /* Find the chip which is to be used and select it */ + mychip = &this->chips[to >> (this->chipshift)]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } + else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + /* Set device to main plane of flash */ + DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP); + DoC_Command(docptr, NAND_CMD_READ0, CDSN_CTRL_WP); + + if (eccbuf) { + /* Prime the ECC engine */ + WriteDOC ( DOC_ECC_RESET, docptr, ECCConf); + WriteDOC ( DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); + } + + DoC_Command(docptr, NAND_CMD_SEQIN, 0); + DoC_Address(docptr, 3, to, 0, CDSN_CTRL_ECC_IO); + + for (di=0; di < len ; di++) { + WriteDOC(buf[di], docptr, 2k_CDSN_IO); + } + + + if (eccbuf) { + WriteDOC( CDSN_CTRL_ECC_IO | CDSN_CTRL_CE , docptr, CDSNControl ); + +#if 1 + /* eduardp@m-sys.com says this shouldn't be necessary, + * but it doesn't actually work without it, so I've + * left it in for now. dwmw2. + */ + + WriteDOC( 0, docptr, 2k_CDSN_IO); + WriteDOC( 0, docptr, 2k_CDSN_IO); + WriteDOC( 0, docptr, 2k_CDSN_IO); +#endif + /* Read the ECC data through the DiskOnChip ECC logic */ + for (di=0; di<6; di++) { + eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di); + } +#ifdef PSYCHO_DEBUG + printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long) to, eccbuf[0], eccbuf[1], eccbuf[2], + eccbuf[3], eccbuf[4], eccbuf[5] ); +#endif + /* Reset the ECC engine */ + WriteDOC(DOC_ECC_RESV, docptr , ECCConf); + + } + + DoC_Command(docptr, NAND_CMD_PAGEPROG, 0); + + DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP); + /* There's an implicit DoC_WaitReady() in DoC_Command */ + + if (ReadDOC(docptr, 2k_CDSN_IO) & 1) { + printk("Error programming flash\n"); + /* Error in programming */ + *retlen = 0; + return -EIO; + } + + /* Let the caller know we completed it */ + *retlen = len; + + return 0; +} + + + +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf) +{ + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + int i; + unsigned long docptr; + struct Nand *mychip; + + docptr = this->virtadr; + + mychip = &this->chips[ofs >> this->chipshift]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } + else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + + + DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP); + DoC_Address(docptr, 3, ofs, CDSN_CTRL_WP, 0); + + for (i=0; ipriv; + int i; + unsigned long docptr; + struct Nand *mychip; + + // printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len, + // buf[0], buf[1], buf[2], buf[3], buf[8], buf[9], buf[14],buf[15]); + + docptr = this->virtadr; + + mychip = &this->chips[ofs >> this->chipshift]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } + else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP); + DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP); + + DoC_Command(docptr, NAND_CMD_SEQIN, 0); + DoC_Address(docptr, 3, ofs, 0, 0); + + for (i=0; ipriv; + unsigned long ofs = instr->addr; + unsigned long len = instr->len; + unsigned long docptr; + struct Nand *mychip; + + if(len != mtd->erasesize) + printk(KERN_WARNING "Erase not right size (%lx != %lx)n", len, mtd->erasesize); + + + docptr = this->virtadr; + + mychip = &this->chips[ofs >> this->chipshift]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } + else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + instr->state = MTD_ERASE_PENDING; + + DoC_Command(docptr, NAND_CMD_ERASE1, 0); + DoC_Address(docptr, 2, ofs, 0, 0); + DoC_Command(docptr, NAND_CMD_ERASE2, 0); + + instr->state = MTD_ERASING; + + DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP); + + if (ReadDOC(docptr, 2k_CDSN_IO) & 1) { + printk("Error writing\n"); + /* There was an error */ + instr->state = MTD_ERASE_FAILED; + } + else + instr->state = MTD_ERASE_DONE; + + if (instr->callback) + instr->callback(instr); + + return 0; +} + + + +#endif + +/**************************************************************************** + * + * Module stuff + * + ****************************************************************************/ + +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define cleanup_doc2001 cleanup_module +#endif +#define __exit +#endif + + +static void __exit cleanup_doc2001(void) +{ + struct mtd_info *mtd; + struct DiskOnChip *this; + + while((mtd=docmillist)) { + this = (struct DiskOnChip *)mtd->priv; + docmillist = this->nextdoc; + + del_mtd_device(mtd); + + iounmap((void *)this->virtadr); + kfree(this->chips); + kfree(mtd); + } + +} + +#if LINUX_VERSION_CODE > 0x20300 +module_exit(cleanup_doc2001); +#endif + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/docprobe.c linux/drivers/mtd/docprobe.c --- v2.4.0-test2/linux/drivers/mtd/docprobe.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/docprobe.c Thu Jul 6 01:22:24 2000 @@ -0,0 +1,270 @@ + +/* Linux driver for Disk-On-Chip devices */ +/* Probe routines common to all DoC devices */ +/* (c) 1999 Machine Vision Holdings, Inc. */ +/* Author: David Woodhouse */ +/* $Id: docprobe.c,v 1.8 2000/06/26 20:40:53 dwmw2 Exp $ */ + + + +/* DOC_PASSIVE_PROBE: + In order to ensure that the BIOS checksum is correct at boot time, and + hence that the onboard BIOS extension gets executed, the DiskOnChip + goes into reset mode when it is read sequentially: all registers + return 0xff until the chip is woken up again by writing to the + DOCControl register. + + Unfortunately, this means that the probe for the DiskOnChip is unsafe, + because one of the first things it does is write to where it thinks + the DOCControl register should be - which may well be shared memory + for another device. I've had machines which lock up when this is + attempted. Hence the possibility to do a passive probe, which will fail + to detect a chip in reset mode, but is at least guaranteed not to lock + the machine. + + If you have this problem, uncomment the following line: +#define DOC_PASSIVE_PROBE +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* Where to look for the devices? */ + +#if defined (__alpha__) || defined(__i386__) +static unsigned long __initdata doc_locations[] = { + 0xc8000, 0xca000, 0xcc000, 0xce000, + 0xd0000, 0xd2000, 0xd4000, 0xd6000, + 0xd8000, 0xda000, 0xdc000, 0xde000, + 0xe0000, 0xe2000, 0xe4000, 0xe6000, + 0xe8000, 0xea000, 0xec000, 0xee000, 0 }; +#elif defined(__ppc__) +static unsigned long __initdata doc_locations[] = { + 0xe4000000, 0}; +#else +#warning Unknown architecture for DiskOnChip. No default probe locations defined +#endif + +#ifdef CONFIG_MTD_DOC2000 +extern void DoC2k_init(struct mtd_info *); +#endif +#ifdef CONFIG_MTD_DOC2001 +extern void DoCMil_init(struct mtd_info *); +#endif + +/* doccheck: Probe a given memory window to see if there's a DiskOnChip present */ + +static inline int __init doccheck(unsigned long potential, unsigned long physadr) +{ + unsigned long window=potential; + unsigned char tmp, ChipID; +#ifndef DOC_PASSIVE_PROBE + unsigned char tmp2; +#endif + + /* Routine copied from the Linux DOC driver */ + + /* Check for 0x55 0xAA signature at beginning of window */ + if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa) + return 0; + +#ifndef DOC_PASSIVE_PROBE + /* It's not possible to cleanly detect the DiskOnChip - the + * bootup procedure will put the device into reset mode, and + * it's not possible to talk to it without actually writing + * to the DOCControl register. So we store the current contents + * of the DOCControl register's location, in case we later decide + * that it's not a DiskOnChip, and want to put it back how we + * found it. + */ + tmp2 = ReadDOC(window, DOCControl); + + /* Reset the DiskOnChip ASIC */ + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, + window, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, + window, DOCControl); + + /* Enable the DiskOnChip ASIC */ + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, + window, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, + window, DOCControl); +#endif /* !DOC_PASSIVE_PROBE */ + + ChipID = ReadDOC(window, ChipID); + + switch (ChipID) { + case DOC_ChipID_Doc2k: + /* Check the TOGGLE bit in the ECC register */ + tmp = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT; + if ((ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT) != tmp) + return ChipID; + break; + + case DOC_ChipID_DocMil: + /* Check the TOGGLE bit in the ECC register */ + tmp = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT; + if ((ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT) != tmp) + return ChipID; + break; + + default: + printk(KERN_WARNING "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n", + ChipID, physadr); + +#ifndef DOC_PASSIVE_PROBE + /* Put back the contents of the DOCControl register, in case it's not + * actually a DiskOnChip. + */ + WriteDOC(tmp2, window, DOCControl); +#endif + return 0; + } + + printk(KERN_WARNING "DiskOnChip failed TOGGLE test, dropping.\n"); + +#ifndef DOC_PASSIVE_PROBE + /* Put back the contents of the DOCControl register: it's not a DiskOnChip */ + WriteDOC(tmp2, window, DOCControl); +#endif + return 0; +} + + +static void DoC_Probe(unsigned long physadr) +{ + unsigned long docptr; + struct DiskOnChip *this; + struct mtd_info *mtd; + int ChipID; + char namebuf[15]; + char *name = namebuf; + void (*initroutine)(struct mtd_info *) = NULL; + int initroutinedynamic = 0; + + docptr = (unsigned long)ioremap(physadr, 0x2000); + + if (!docptr) + return; + + if ((ChipID = doccheck(docptr, physadr))) { + + mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL); + + if (!mtd) { + printk("Cannot allocate memory for data structures. Dropping.\n"); + iounmap((void *)docptr); + return; + } + + this = (struct DiskOnChip *)(&mtd[1]); + + memset((char *)mtd,0, sizeof(struct mtd_info)); + memset((char *)this, 0, sizeof(struct DiskOnChip)); + + mtd->priv = this; + this->virtadr = docptr; + this->physadr = physadr; + this->ChipID = ChipID; + sprintf(namebuf, "with ChipID %2.2X", ChipID); + + switch(ChipID) { + case DOC_ChipID_Doc2k: + name="2000"; +#ifdef CONFIG_MTD_DOC2000 + initroutine = &DoC2k_init; +#elif CONFIG_MODULES + initroutinedynamic=1; + initroutine = (void *)get_module_symbol(NULL, "DoC2k_init"); +#ifdef CONFIG_KMOD + if (!initroutine) { + request_module("doc2000"); + initroutine = (void *)get_module_symbol("doc2000", "DoC2k_init"); + } +#endif /* CONFIG_KMOD */ +#endif + break; + + case DOC_ChipID_DocMil: + name="Millennium"; +#ifdef CONFIG_MTD_DOC2001 + initroutine = &DocMil_init; +#elif CONFIG_MODULES + initroutinedynamic=1; + initroutine = (void *)get_module_symbol(NULL, "DoCMil_init"); +#ifdef CONFIG_KMOD + if (!initroutine) { + request_module("doc2001"); + initroutine = (void *)get_module_symbol("doc2001", "DoCMil_init"); + } +#endif /* CONFIG_KMOD */ +#endif + break; + } + if (initroutine) { + (*initroutine)(mtd); +#if defined(CONFIG_MODULES) && LINUX_VERSION_CODE >= 0x20400 + if (initroutinedynamic) + put_module_symbol(initroutine); +#endif + return; + } + printk("Cannot find driver for DiskOnChip %s at 0x%X\n", name, physadr); + } + iounmap((void *)docptr); +} + + +/**************************************************************************** + * + * Module stuff + * + ****************************************************************************/ + +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define init_doc init_module +#endif +#define __exit +#endif + +int __init init_doc(void) +{ + int i; + + printk(KERN_NOTICE "M-Systems DiskOnChip driver. (C) 1999 Machine Vision Holdings, Inc.\n"); +#ifdef PRERELEASE + printk(KERN_INFO "$Id: docprobe.c,v 1.8 2000/06/26 20:40:53 dwmw2 Exp $\n"); +#endif + + for (i=0; doc_locations[i]; i++) { + DoC_Probe(doc_locations[i]); + } + + return 0; + +} + + +#if LINUX_VERSION_CODE > 0x20300 +module_init(init_doc); +#endif + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/ftl.c linux/drivers/mtd/ftl.c --- v2.4.0-test2/linux/drivers/mtd/ftl.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/ftl.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,1458 @@ +/* This version ported to the Linux-MTD system by dwmw2@infradead.org + * $Id: ftl.c,v 1.20 2000/06/23 15:17:53 dwmw2 Exp $ + * Based on: + */ +/*====================================================================== + + A Flash Translation Layer memory card driver + + This driver implements a disk-like block device driver with an + apparent block size of 512 bytes for flash memory cards. + + ftl_cs.c 1.62 2000/02/01 00:59:04 + + 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 + . 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 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. + + LEGAL NOTE: The FTL format is patented by M-Systems. They have + granted a license for its use with PCMCIA devices: + + "M-Systems grants a royalty-free, non-exclusive license under + any presently existing M-Systems intellectual property rights + necessary for the design and development of FTL-compatible + drivers, file systems and utilities using the data formats with + PCMCIA PC Cards as described in the PCMCIA Flash Translation + Layer (FTL) Specification." + + Use of the FTL format for non-PCMCIA applications may be an + infringement of these patents. For additional information, + contact M-Systems (http://www.m-sys.com) directly. + +======================================================================*/ +#define FTL_DEBUG 5 +#ifdef FTL_DEBUG +#define DEBUGLVL debug +#endif + +#include +#include +#include +/*#define PSYCHO_DEBUG */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if (LINUX_VERSION_CODE >= 0x20100) +#include +#endif +#if (LINUX_VERSION_CODE >= 0x20303) +#include +#endif + +#include +/*====================================================================*/ +/* Stuff which really ought to be in compatmac.h */ + +#if (LINUX_VERSION_CODE < 0x20328) +#define register_disk(dev, drive, minors, ops, size) \ + do { (dev)->part[(drive)*(minors)].nr_sects = size; \ + if (size == 0) (dev)->part[(drive)*(minors)].start_sect = -1; \ + resetup_one_dev(dev, drive); } while (0); +#endif + +#if (LINUX_VERSION_CODE < 0x20320) +#define BLK_DEFAULT_QUEUE(n) blk_dev[n].request_fn +#define blk_init_queue(q, req) q = (req) +#define blk_cleanup_queue(q) q = NULL +#define request_arg_t void +#else +#define request_arg_t request_queue_t *q +#endif + + +/*====================================================================*/ + +/* Parameters that can be set with 'insmod' */ + +/* Major device # for FTL device */ +static int shuffle_freq = 50; + +MODULE_PARM(shuffle_freq, "i"); + +/*====================================================================*/ + +#ifndef FTL_MAJOR +#define FTL_MAJOR 44 +#endif + + +/* Funky stuff for setting up a block device */ +#define MAJOR_NR FTL_MAJOR +#define DEVICE_NAME "ftl" +#define DEVICE_REQUEST do_ftl_request +#define DEVICE_ON(device) +#define DEVICE_OFF(device) + +#define DEVICE_NR(minor) ((minor)>>5) +#define REGION_NR(minor) (((minor)>>3)&3) +#define PART_NR(minor) ((minor)&7) +#define MINOR_NR(dev,reg,part) (((dev)<<5)+((reg)<<3)+(part)) + +#include + +#ifdef FTL_DEBUG +static int debug = FTL_DEBUG; +MODULE_PARM(debug, "i"); +#endif + +/*====================================================================*/ + +#ifndef FTL_MAJOR +#define FTL_MAJOR 44 +#endif + +/* Maximum number of separate memory devices we'll allow */ +#define MAX_DEV 4 + +/* Maximum number of regions per device */ +#define MAX_REGION 4 + +/* Maximum number of partitions in an FTL region */ +#define PART_BITS 3 +#define MAX_PART 8 + +/* Maximum number of outstanding erase requests per socket */ +#define MAX_ERASE 8 + +/* Sector size -- shouldn't need to change */ +#define SECTOR_SIZE 512 + + +/* Each memory region corresponds to a minor device */ +typedef struct partition_t { + struct mtd_info *mtd; + u_int32_t state; + u_int32_t *VirtualBlockMap; + u_int32_t *VirtualPageMap; + u_int32_t FreeTotal; + struct eun_info_t { + u_int32_t Offset; + u_int32_t EraseCount; + u_int32_t Free; + u_int32_t Deleted; + } *EUNInfo; + struct xfer_info_t { + u_int32_t Offset; + u_int32_t EraseCount; + u_int16_t state; + } *XferInfo; + u_int16_t bam_index; + u_int32_t *bam_cache; + u_int16_t DataUnits; + u_int32_t BlocksPerUnit; + erase_unit_header_t header; +#if 0 + region_info_t region; + memory_handle_t handle; +#endif + atomic_t open; +} partition_t; + +partition_t *myparts[MAX_MTD_DEVICES]; + +static void ftl_notify_add(struct mtd_info *mtd); +static void ftl_notify_remove(struct mtd_info *mtd); + +void ftl_freepart(partition_t *part); + +static struct mtd_notifier ftl_notifier={ftl_notify_add, ftl_notify_remove, NULL}; + +/* Partition state flags */ +#define FTL_FORMATTED 0x01 + +/* Transfer unit states */ +#define XFER_UNKNOWN 0x00 +#define XFER_ERASING 0x01 +#define XFER_ERASED 0x02 +#define XFER_PREPARED 0x03 +#define XFER_FAILED 0x04 + +static struct hd_struct ftl_hd[MINOR_NR(MAX_DEV, 0, 0)]; +static int ftl_sizes[MINOR_NR(MAX_DEV, 0, 0)]; +static int ftl_blocksizes[MINOR_NR(MAX_DEV, 0, 0)]; + +static struct gendisk ftl_gendisk = { + major: FTL_MAJOR, + major_name: "ftl", + minor_shift: PART_BITS, + max_p: MAX_PART, +#if (LINUX_VERSION_CODE < 0x20328) + max_nr: MAX_DEV*MAX_PART, +#endif + part: ftl_hd, + sizes: ftl_sizes, + nr_real: 0 +}; + +/*====================================================================*/ + +static int ftl_ioctl(struct inode *inode, struct file *file, + u_int cmd, u_long arg); +static int ftl_open(struct inode *inode, struct file *file); +static release_t ftl_close(struct inode *inode, struct file *file); +static int ftl_reread_partitions(int minor); + +static void ftl_erase_callback(struct erase_info *done); + +#if LINUX_VERSION_CODE < 0x20326 +static struct file_operations ftl_blk_fops = { + open: ftl_open, + release: ftl_close, + ioctl: ftl_ioctl, + read: block_read, + write: block_write, + fsync: block_fsync +}; +#else +static struct block_device_operations ftl_blk_fops = { + open: ftl_open, + release: ftl_close, + ioctl: ftl_ioctl, +}; +#endif + +/*====================================================================== + + Scan_header() checks to see if a memory region contains an FTL + partition. build_maps() reads all the erase unit headers, builds + the erase unit map, and then builds the virtual page map. + +======================================================================*/ + +static int scan_header(partition_t *part) +{ + erase_unit_header_t header; + loff_t offset; + int ret; + part->header.FormattedSize = 0; + /* Search first megabyte for a valid FTL header */ + for (offset = 0; + offset < 0x100000; + offset += part->mtd->erasesize?part->mtd->erasesize:0x2000) { + + ret = part->mtd->read(part->mtd, offset, sizeof(header), &ret, + (unsigned char *)&header); + + if (ret) + return ret; + + if (strcmp(header.DataOrgTuple+3, "FTL100") == 0) break; + } + + if (offset == 0x100000) { + printk(KERN_NOTICE "ftl_cs: FTL header not found.\n"); + return -ENOENT; + } + if ((le16_to_cpu(header.NumEraseUnits) > 65536) || header.BlockSize != 9 || + (header.EraseUnitSize < 10) || (header.EraseUnitSize > 31) || + (header.NumTransferUnits >= le16_to_cpu(header.NumEraseUnits))) { + printk(KERN_NOTICE "ftl_cs: FTL header corrupt!\n"); + return -1; + } + if ((1 << header.EraseUnitSize) != part->mtd->erasesize) { + printk(KERN_NOTICE "ftl: FTL EraseUnitSize %x != MTD erasesize %lx\n", + 1 << header.EraseUnitSize,part->mtd->erasesize); + return -1; + } + part->header = header; + return 0; +} + +static int build_maps(partition_t *part) +{ + erase_unit_header_t header; + u_int16_t xvalid, xtrans, i; + u_int blocks, j; + int hdr_ok, ret; + ssize_t retval; + loff_t offset; + + /* Set up erase unit maps */ + part->DataUnits = le16_to_cpu(part->header.NumEraseUnits) - + part->header.NumTransferUnits; + part->EUNInfo = kmalloc(part->DataUnits * sizeof(struct eun_info_t), + GFP_KERNEL); + if (!part->EUNInfo) return -1; + for (i = 0; i < part->DataUnits; i++) + part->EUNInfo[i].Offset = 0xffffffff; + part->XferInfo = + kmalloc(part->header.NumTransferUnits * sizeof(struct xfer_info_t), + GFP_KERNEL); + if (!part->XferInfo) return -1; + + xvalid = xtrans = 0; + for (i = 0; i < le16_to_cpu(part->header.NumEraseUnits); i++) { + offset = ((i + le16_to_cpu(part->header.FirstPhysicalEUN)) + << part->header.EraseUnitSize); + ret = part->mtd->read(part->mtd, offset, sizeof(header), &retval, + (unsigned char *)&header); + + if (ret) + return ret; + + /* Is this a transfer partition? */ + hdr_ok = (strcmp(header.DataOrgTuple+3, "FTL100") == 0); + if (hdr_ok && (le16_to_cpu(header.LogicalEUN) < part->DataUnits) && + (part->EUNInfo[le16_to_cpu(header.LogicalEUN)].Offset == 0xffffffff)) { + part->EUNInfo[le16_to_cpu(header.LogicalEUN)].Offset = offset; + part->EUNInfo[le16_to_cpu(header.LogicalEUN)].EraseCount = + le32_to_cpu(header.EraseCount); + xvalid++; + } else { + if (xtrans == part->header.NumTransferUnits) { + printk(KERN_NOTICE "ftl_cs: format error: too many " + "transfer units!\n"); + return -1; + } + if (hdr_ok && (le16_to_cpu(header.LogicalEUN) == 0xffff)) { + part->XferInfo[xtrans].state = XFER_PREPARED; + part->XferInfo[xtrans].EraseCount = le32_to_cpu(header.EraseCount); + } else { + part->XferInfo[xtrans].state = XFER_UNKNOWN; + /* Pick anything reasonable for the erase count */ + part->XferInfo[xtrans].EraseCount = + le32_to_cpu(part->header.EraseCount); + } + part->XferInfo[xtrans].Offset = offset; + xtrans++; + } + } + /* Check for format trouble */ + header = part->header; + if ((xtrans != header.NumTransferUnits) || + (xvalid+xtrans != le16_to_cpu(header.NumEraseUnits))) { + printk(KERN_NOTICE "ftl_cs: format error: erase units " + "don't add up!\n"); + return -1; + } + + /* Set up virtual page map */ + blocks = le32_to_cpu(header.FormattedSize) >> header.BlockSize; + part->VirtualBlockMap = vmalloc(blocks * sizeof(u_int32_t)); + memset(part->VirtualBlockMap, 0xff, blocks * sizeof(u_int32_t)); + part->BlocksPerUnit = (1 << header.EraseUnitSize) >> header.BlockSize; + + part->bam_cache = kmalloc(part->BlocksPerUnit * sizeof(u_int32_t), + GFP_KERNEL); + if (!part->bam_cache) return -1; + + part->bam_index = 0xffff; + part->FreeTotal = 0; + + for (i = 0; i < part->DataUnits; i++) { + part->EUNInfo[i].Free = 0; + part->EUNInfo[i].Deleted = 0; + offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset); + + ret = part->mtd->read(part->mtd, offset, + part->BlocksPerUnit * sizeof(u_int32_t), &retval, + (unsigned char *)part->bam_cache); + + if (ret) + return ret; + + for (j = 0; j < part->BlocksPerUnit; j++) { + if (BLOCK_FREE(le32_to_cpu(part->bam_cache[j]))) { + part->EUNInfo[i].Free++; + part->FreeTotal++; + } else if ((BLOCK_TYPE(le32_to_cpu(part->bam_cache[j])) == BLOCK_DATA) && + (BLOCK_NUMBER(le32_to_cpu(part->bam_cache[j])) < blocks)) + part->VirtualBlockMap[BLOCK_NUMBER(le32_to_cpu(part->bam_cache[j]))] = + (i << header.EraseUnitSize) + (j << header.BlockSize); + else if (BLOCK_DELETED(le32_to_cpu(part->bam_cache[j]))) + part->EUNInfo[i].Deleted++; + } + } + + return 0; + +} /* build_maps */ + +/*====================================================================== + + Erase_xfer() schedules an asynchronous erase operation for a + transfer unit. + +======================================================================*/ + +static int erase_xfer(partition_t *part, + u_int16_t xfernum) +{ + int ret; + struct xfer_info_t *xfer; + struct erase_info *erase; + + xfer = &part->XferInfo[xfernum]; + DEBUG(1, "ftl_cs: erasing xfer unit at 0x%x\n", xfer->Offset); + xfer->state = XFER_ERASING; + + /* Is there a free erase slot? Always in MTD. */ + + + erase=kmalloc(sizeof(struct erase_info), GFP_KERNEL); + if (!erase) + return -ENOMEM; + + erase->callback = ftl_erase_callback; + erase->addr = xfer->Offset; + erase->len = 1 << part->header.EraseUnitSize; + erase->priv = (u_long)part; + + ret = part->mtd->erase(part->mtd, erase); + + if (!ret) + xfer->EraseCount++; + else + kfree(erase); + + return ret; +} /* erase_xfer */ + +/*====================================================================== + + Prepare_xfer() takes a freshly erased transfer unit and gives + it an appropriate header. + +======================================================================*/ + +static void ftl_erase_callback(struct erase_info *erase) +{ + partition_t *part; + struct xfer_info_t *xfer; + int i; + + /* Look up the transfer unit */ + part = (partition_t *)(erase->priv); + + for (i = 0; i < part->header.NumTransferUnits; i++) + if (part->XferInfo[i].Offset == erase->addr) break; + + if (i == part->header.NumTransferUnits) { + printk(KERN_NOTICE "ftl_cs: internal error: " + "erase lookup failed!\n"); + return; + } + + xfer = &part->XferInfo[i]; + if (erase->state == MTD_ERASE_DONE) + xfer->state = XFER_ERASED; + else { + xfer->state = XFER_FAILED; + printk(KERN_NOTICE "ftl_cs: erase failed: state = %d\n", + erase->state); + } + + kfree(erase); + +} /* ftl_erase_callback */ + +static int prepare_xfer(partition_t *part, int i) +{ + erase_unit_header_t header; + struct xfer_info_t *xfer; + int nbam, ret; + u_int32_t ctl; + ssize_t retlen; + loff_t offset; + + xfer = &part->XferInfo[i]; + xfer->state = XFER_FAILED; + + DEBUG(1, "ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset); + + /* Write the transfer unit header */ + header = part->header; + header.LogicalEUN = cpu_to_le16(0xffff); + header.EraseCount = cpu_to_le32(xfer->EraseCount); + + ret = part->mtd->write(part->mtd, xfer->Offset, sizeof(header), + &retlen, (u_char *)&header); + + if (ret) { + return ret; + } + + /* Write the BAM stub */ + nbam = (part->BlocksPerUnit * sizeof(u_int32_t) + + le32_to_cpu(part->header.BAMOffset) + SECTOR_SIZE - 1) / SECTOR_SIZE; + + offset = xfer->Offset + le32_to_cpu(part->header.BAMOffset); + ctl = cpu_to_le32(BLOCK_CONTROL); + + for (i = 0; i < nbam; i++, offset += sizeof(u_int32_t)) { + + ret = part->mtd->write(part->mtd, offset, sizeof(u_int32_t), + &retlen, (u_char *)&ctl); + + if (ret) + return ret; + } + xfer->state = XFER_PREPARED; + return 0; + +} /* prepare_xfer */ + +/*====================================================================== + + Copy_erase_unit() takes a full erase block and a transfer unit, + copies everything to the transfer unit, then swaps the block + pointers. + + All data blocks are copied to the corresponding blocks in the + target unit, so the virtual block map does not need to be + updated. + +======================================================================*/ + +static int copy_erase_unit(partition_t *part, u_int16_t srcunit, + u_int16_t xferunit) +{ + u_char buf[SECTOR_SIZE]; + struct eun_info_t *eun; + struct xfer_info_t *xfer; + u_int32_t src, dest, free, i; + u_int16_t unit; + int ret; + ssize_t retlen; + loff_t offset; + u_int16_t srcunitswap = cpu_to_le16(srcunit); + + eun = &part->EUNInfo[srcunit]; + xfer = &part->XferInfo[xferunit]; + DEBUG(2, "ftl_cs: copying block 0x%x to 0x%x\n", + eun->Offset, xfer->Offset); + + + /* Read current BAM */ + if (part->bam_index != srcunit) { + + offset = eun->Offset + le32_to_cpu(part->header.BAMOffset); + + ret = part->mtd->read(part->mtd, offset, + part->BlocksPerUnit * sizeof(u_int32_t), + &retlen, (u_char *) (part->bam_cache)); + + /* mark the cache bad, in case we get an error later */ + part->bam_index = 0xffff; + + if (ret) { + printk( KERN_WARNING "ftl: Failed to read BAM cache in copy_erase_unit()!\n"); + return ret; + } + } + + /* Write the LogicalEUN for the transfer unit */ + xfer->state = XFER_UNKNOWN; + offset = xfer->Offset + 20; /* Bad! */ + unit = cpu_to_le16(0x7fff); + + ret = part->mtd->write(part->mtd, offset, sizeof(u_int16_t), + &retlen, (u_char *) &unit); + + if (ret) { + printk( KERN_WARNING "ftl: Failed to write back to BAM cache in copy_erase_unit()!\n"); + return ret; + } + + /* Copy all data blocks from source unit to transfer unit */ + src = eun->Offset; dest = xfer->Offset; + + free = 0; + ret = 0; + for (i = 0; i < part->BlocksPerUnit; i++) { + switch (BLOCK_TYPE(le32_to_cpu(part->bam_cache[i]))) { + case BLOCK_CONTROL: + /* This gets updated later */ + break; + case BLOCK_DATA: + case BLOCK_REPLACEMENT: + ret = part->mtd->read(part->mtd, src, SECTOR_SIZE, + &retlen, (u_char *) buf); + if (ret) { + printk(KERN_WARNING "ftl: Error reading old xfer unit in copy_erase_unit\n"); + return ret; + } + + + ret = part->mtd->write(part->mtd, dest, SECTOR_SIZE, + &retlen, (u_char *) buf); + if (ret) { + printk(KERN_WARNING "ftl: Error writing new xfer unit in copy_erase_unit\n"); + return ret; + } + + break; + default: + /* All other blocks must be free */ + part->bam_cache[i] = cpu_to_le32(0xffffffff); + free++; + break; + } + src += SECTOR_SIZE; + dest += SECTOR_SIZE; + } + + /* Write the BAM to the transfer unit */ + ret = part->mtd->write(part->mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset), + part->BlocksPerUnit * sizeof(int32_t), &retlen, + (u_char *)part->bam_cache); + if (ret) { + printk( KERN_WARNING "ftl: Error writing BAM in copy_erase_unit\n"); + return ret; + } + + + /* All clear? Then update the LogicalEUN again */ + ret = part->mtd->write(part->mtd, xfer->Offset + 20, sizeof(u_int16_t), + &retlen, (u_char *)&srcunitswap); + + if (ret) { + printk(KERN_WARNING "ftl: Error writing new LogicalEUN in copy_erase_unit\n"); + return ret; + } + + + /* Update the maps and usage stats*/ + i = xfer->EraseCount; + xfer->EraseCount = eun->EraseCount; + eun->EraseCount = i; + i = xfer->Offset; + xfer->Offset = eun->Offset; + eun->Offset = i; + part->FreeTotal -= eun->Free; + part->FreeTotal += free; + eun->Free = free; + eun->Deleted = 0; + + /* Now, the cache should be valid for the new block */ + part->bam_index = srcunit; + + return 0; +} /* copy_erase_unit */ + +/*====================================================================== + + reclaim_block() picks a full erase unit and a transfer unit and + then calls copy_erase_unit() to copy one to the other. Then, it + schedules an erase on the expired block. + + What's a good way to decide which transfer unit and which erase + unit to use? Beats me. My way is to always pick the transfer + unit with the fewest erases, and usually pick the data unit with + the most deleted blocks. But with a small probability, pick the + oldest data unit instead. This means that we generally postpone + the next reclaimation as long as possible, but shuffle static + stuff around a bit for wear leveling. + +======================================================================*/ + +static int reclaim_block(partition_t *part) +{ + u_int16_t i, eun, xfer; + u_int32_t best; + int queued, ret; + + DEBUG(0, "ftl_cs: reclaiming space...\n"); + DEBUG(4, "NumTransferUnits == %x\n", part->header.NumTransferUnits); + /* Pick the least erased transfer unit */ + best = 0xffffffff; xfer = 0xffff; + do { + queued = 0; + for (i = 0; i < part->header.NumTransferUnits; i++) { + int n=0; + if (part->XferInfo[i].state == XFER_UNKNOWN) { + DEBUG(4,"XferInfo[%d].state == XFER_UNKNOWN\n",i); + n=1; + erase_xfer(part, i); + } + if (part->XferInfo[i].state == XFER_ERASING) { + DEBUG(4,"XferInfo[%d].state == XFER_ERASING\n",i); + n=1; + queued = 1; + } + else if (part->XferInfo[i].state == XFER_ERASED) { + DEBUG(4,"XferInfo[%d].state == XFER_ERASED\n",i); + n=1; + prepare_xfer(part, i); + } + if (part->XferInfo[i].state == XFER_PREPARED) { + DEBUG(4,"XferInfo[%d].state == XFER_PREPARED\n",i); + n=1; + if (part->XferInfo[i].EraseCount <= best) { + best = part->XferInfo[i].EraseCount; + xfer = i; + } + } + if (!n) + DEBUG(4,"XferInfo[%d].state == %x\n",i, part->XferInfo[i].state); + + } + if (xfer == 0xffff) { + if (queued) { + DEBUG(1, "ftl_cs: waiting for transfer " + "unit to be prepared...\n"); + if (part->mtd->sync) + part->mtd->sync(part->mtd); + } else { + static int ne = 0; + if (++ne < 5) + printk(KERN_NOTICE "ftl_cs: reclaim failed: no " + "suitable transfer units!\n"); + else + DEBUG(1, "ftl_cs: reclaim failed: no " + "suitable transfer units!\n"); + + return -EIO; + } + } + } while (xfer == 0xffff); + + eun = 0; + if ((jiffies % shuffle_freq) == 0) { + DEBUG(1, "ftl_cs: recycling freshest block...\n"); + best = 0xffffffff; + for (i = 0; i < part->DataUnits; i++) + if (part->EUNInfo[i].EraseCount <= best) { + best = part->EUNInfo[i].EraseCount; + eun = i; + } + } else { + best = 0; + for (i = 0; i < part->DataUnits; i++) + if (part->EUNInfo[i].Deleted >= best) { + best = part->EUNInfo[i].Deleted; + eun = i; + } + if (best == 0) { + static int ne = 0; + if (++ne < 5) + printk(KERN_NOTICE "ftl_cs: reclaim failed: " + "no free blocks!\n"); + else + DEBUG(1,"ftl_cs: reclaim failed: " + "no free blocks!\n"); + + return -EIO; + } + } + ret = copy_erase_unit(part, eun, xfer); + if (!ret) + erase_xfer(part, xfer); + else + printk(KERN_NOTICE "ftl_cs: copy_erase_unit failed!\n"); + return ret; +} /* reclaim_block */ + +/*====================================================================== + + Find_free() searches for a free block. If necessary, it updates + the BAM cache for the erase unit containing the free block. It + returns the block index -- the erase unit is just the currently + cached unit. If there are no free blocks, it returns 0 -- this + is never a valid data block because it contains the header. + +======================================================================*/ + +#ifdef PSYCHO_DEBUG +static void dump_lists(partition_t *part) +{ + int i; + printk(KERN_DEBUG "ftl_cs: Free total = %d\n", part->FreeTotal); + for (i = 0; i < part->DataUnits; i++) + printk(KERN_DEBUG "ftl_cs: unit %d: %d phys, %d free, " + "%d deleted\n", i, + part->EUNInfo[i].Offset >> part->header.EraseUnitSize, + part->EUNInfo[i].Free, part->EUNInfo[i].Deleted); +} +#endif + +static u_int32_t find_free(partition_t *part) +{ + u_int16_t stop, eun; + u_int32_t blk; + size_t retlen; + int ret; + + /* Find an erase unit with some free space */ + stop = (part->bam_index == 0xffff) ? 0 : part->bam_index; + eun = stop; + do { + if (part->EUNInfo[eun].Free != 0) break; + /* Wrap around at end of table */ + if (++eun == part->DataUnits) eun = 0; + } while (eun != stop); + + if (part->EUNInfo[eun].Free == 0) + return 0; + + /* Is this unit's BAM cached? */ + if (eun != part->bam_index) { + /* Invalidate cache */ + part->bam_index = 0xffff; + + ret = part->mtd->read(part->mtd, + part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset), + part->BlocksPerUnit * sizeof(u_int32_t), + &retlen, (u_char *) (part->bam_cache)); + + if (ret) { + printk(KERN_WARNING"ftl: Error reading BAM in find_free\n"); + return 0; + } + part->bam_index = eun; + } + + /* Find a free block */ + for (blk = 0; blk < part->BlocksPerUnit; blk++) + if (BLOCK_FREE(le32_to_cpu(part->bam_cache[blk]))) break; + if (blk == part->BlocksPerUnit) { +#ifdef PSYCHO_DEBUG + static int ne = 0; + if (++ne == 1) + dump_lists(part); +#endif + printk(KERN_NOTICE "ftl_cs: bad free list!\n"); + return 0; + } + DEBUG(2, "ftl_cs: found free block at %d in %d\n", blk, eun); + return blk; + +} /* find_free */ + +/*====================================================================== + + This gets a memory handle for the region corresponding to the + minor device number. + +======================================================================*/ + +static int ftl_open(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + partition_t *partition; + + if (minor>>4 >= MAX_MTD_DEVICES) + return -ENODEV; + + partition = myparts[minor>>4]; + + if (!partition) + return -ENODEV; + + if (partition->state != FTL_FORMATTED) + return -ENXIO; + + if (ftl_gendisk.part[minor].nr_sects == 0) + return -ENXIO; + + MOD_INC_USE_COUNT; + + if (!get_mtd_device(partition->mtd, -1)) { + MOD_DEC_USE_COUNT; + return /* -E'SBUGGEREDOFF */ -ENXIO; + } + + if ((file->f_mode & 2) && !(partition->mtd->flags & MTD_CLEAR_BITS) ) { + put_mtd_device(partition->mtd); + MOD_DEC_USE_COUNT; + return -EROFS; + } + + DEBUG(0, "ftl_cs: ftl_open(%d)\n", minor); + + atomic_inc(&partition->open); + + return 0; +} + +/*====================================================================*/ + +static release_t ftl_close(struct inode *inode, struct file *file) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + struct super_block *sb = get_super(inode->i_rdev); +#endif + int minor = MINOR(inode->i_rdev); + partition_t *part = myparts[minor >> 4]; + int i; + + DEBUG(0, "ftl_cs: ftl_close(%d)\n", minor); + + /* Flush all writes */ + fsync_dev(inode->i_rdev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + if (sb) invalidate_inodes(sb); +#endif + invalidate_buffers(inode->i_rdev); + + /* Wait for any pending erase operations to complete */ + if (part->mtd->sync) + part->mtd->sync(part->mtd); + + for (i = 0; i < part->header.NumTransferUnits; i++) { + if (part->XferInfo[i].state == XFER_ERASED) + prepare_xfer(part, i); + } + + atomic_dec(&part->open); + + put_mtd_device(part->mtd); + MOD_DEC_USE_COUNT; + release_return(0); +} /* ftl_close */ + + +/*====================================================================== + + Read a series of sectors from an FTL partition. + +======================================================================*/ + +static int ftl_read(partition_t *part, caddr_t buffer, + u_long sector, u_long nblocks) +{ + u_int32_t log_addr, bsize; + u_long i; + int ret; + size_t offset, retlen; + + DEBUG(2, "ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n", + part, sector, nblocks); + if (!(part->state & FTL_FORMATTED)) { + printk(KERN_NOTICE "ftl_cs: bad partition\n"); + return -EIO; + } + bsize = 1 << part->header.EraseUnitSize; + + for (i = 0; i < nblocks; i++) { + if (((sector+i) * SECTOR_SIZE) >= le32_to_cpu(part->header.FormattedSize)) { + printk(KERN_NOTICE "ftl_cs: bad read offset\n"); + return -EIO; + } + log_addr = part->VirtualBlockMap[sector+i]; + if (log_addr == 0xffffffff) + memset(buffer, 0, SECTOR_SIZE); + else { + offset = (part->EUNInfo[log_addr / bsize].Offset + + (log_addr % bsize)); + ret = part->mtd->read(part->mtd, offset, SECTOR_SIZE, + &retlen, (u_char *) buffer); + + if (ret) { + printk(KERN_WARNING "Error reading MTD device in ftl_read()\n"); + return ret; + } + } + buffer += SECTOR_SIZE; + } + return 0; +} /* ftl_read */ + +/*====================================================================== + + Write a series of sectors to an FTL partition + +======================================================================*/ + +static int set_bam_entry(partition_t *part, u_int32_t log_addr, + u_int32_t virt_addr) +{ + u_int32_t bsize, blk; +#ifdef PSYCHO_DEBUG + u_int32_t old_addr; +#endif + u_int16_t eun; + int ret; + size_t retlen, offset; + + DEBUG(2, "ftl_cs: set_bam_entry(0x%p, 0x%x, 0x%x)\n", + part, log_addr, virt_addr); + bsize = 1 << part->header.EraseUnitSize; + eun = log_addr / bsize; + blk = (log_addr % bsize) / SECTOR_SIZE; + offset = (part->EUNInfo[eun].Offset + blk * sizeof(u_int32_t) + + le32_to_cpu(part->header.BAMOffset)); + +#ifdef PSYCHO_DEBUG + ret = part->mtd->read(part->mtd, offset, sizeof(u_int32_t), + &retlen, (u_char *)&old_addr); + if (ret) { + printk(KERN_WARNING"ftl: Error reading old_addr in set_bam_entry: %d\n",ret); + return ret; + } + old_addr = le32_to_cpu(old_addr); + + if (((virt_addr == 0xfffffffe) && !BLOCK_FREE(old_addr)) || + ((virt_addr == 0) && (BLOCK_TYPE(old_addr) != BLOCK_DATA)) || + (!BLOCK_DELETED(virt_addr) && (old_addr != 0xfffffffe))) { + static int ne = 0; + if (++ne < 5) { + printk(KERN_NOTICE "ftl_cs: set_bam_entry() inconsistency!\n"); + printk(KERN_NOTICE "ftl_cs: log_addr = 0x%x, old = 0x%x" + ", new = 0x%x\n", log_addr, old_addr, virt_addr); + } + return -EIO; + } +#endif + if (part->bam_index == eun) { +#ifdef PSYCHO_DEBUG + if (le32_to_cpu(part->bam_cache[blk]) != old_addr) { + static int ne = 0; + if (++ne < 5) { + printk(KERN_NOTICE "ftl_cs: set_bam_entry() " + "inconsistency!\n"); + printk(KERN_NOTICE "ftl_cs: log_addr = 0x%x, cache" + " = 0x%x\n", + le32_to_cpu(part->bam_cache[blk]), old_addr); + } + return -EIO; + } +#endif + part->bam_cache[blk] = cpu_to_le32(virt_addr); + } + ret = part->mtd->write(part->mtd, offset, sizeof(u_int32_t), + &retlen, (u_char *)&part->bam_cache[blk]); + + if (ret) { + printk(KERN_NOTICE "ftl_cs: set_bam_entry() failed!\n"); + printk(KERN_NOTICE "ftl_cs: log_addr = 0x%x, new = 0x%x\n", + log_addr, virt_addr); + } + return ret; +} /* set_bam_entry */ + +static int ftl_write(partition_t *part, caddr_t buffer, + u_long sector, u_long nblocks) +{ + u_int32_t bsize, log_addr, virt_addr, old_addr, blk; + u_long i; + int ret; + size_t retlen, offset; + + DEBUG(2, "ftl_cs: ftl_write(0x%p, %ld, %ld)\n", + part, sector, nblocks); + if (!(part->state & FTL_FORMATTED)) { + printk(KERN_NOTICE "ftl_cs: bad partition\n"); + return -EIO; + } + /* See if we need to reclaim space, before we start */ + while (part->FreeTotal < nblocks) { + ret = reclaim_block(part); + if (ret) + return ret; + } + + bsize = 1 << part->header.EraseUnitSize; + + virt_addr = sector * SECTOR_SIZE | BLOCK_DATA; + for (i = 0; i < nblocks; i++) { + if (virt_addr >= le32_to_cpu(part->header.FormattedSize)) { + printk(KERN_NOTICE "ftl_cs: bad write offset\n"); + return -EIO; + } + + /* Grab a free block */ + blk = find_free(part); + if (blk == 0) { + static int ne = 0; + if (++ne < 5) + printk(KERN_NOTICE "ftl_cs: internal error: " + "no free blocks!\n"); + return -ENOSPC; + } + + /* Tag the BAM entry, and write the new block */ + log_addr = part->bam_index * bsize + blk * SECTOR_SIZE; + part->EUNInfo[part->bam_index].Free--; + part->FreeTotal--; + if (set_bam_entry(part, log_addr, 0xfffffffe)) + return -EIO; + part->EUNInfo[part->bam_index].Deleted++; + offset = (part->EUNInfo[part->bam_index].Offset + + blk * SECTOR_SIZE); + ret = part->mtd->write(part->mtd, offset, SECTOR_SIZE, &retlen, + buffer); + + if (ret) { + printk(KERN_NOTICE "ftl_cs: block write failed!\n"); + printk(KERN_NOTICE "ftl_cs: log_addr = 0x%x, virt_addr" + " = 0x%x, Offset = 0x%x\n", log_addr, virt_addr, + offset); + return -EIO; + } + + /* Only delete the old entry when the new entry is ready */ + old_addr = part->VirtualBlockMap[sector+i]; + if (old_addr != 0xffffffff) { + part->VirtualBlockMap[sector+i] = 0xffffffff; + part->EUNInfo[old_addr/bsize].Deleted++; + if (set_bam_entry(part, old_addr, 0)) + return -EIO; + } + + /* Finally, set up the new pointers */ + if (set_bam_entry(part, log_addr, virt_addr)) + return -EIO; + part->VirtualBlockMap[sector+i] = log_addr; + part->EUNInfo[part->bam_index].Deleted--; + + buffer += SECTOR_SIZE; + virt_addr += SECTOR_SIZE; + } + return 0; +} /* ftl_write */ + +/*====================================================================== + + IOCTL calls for getting device parameters. + +======================================================================*/ + +static int ftl_ioctl(struct inode *inode, struct file *file, + u_int cmd, u_long arg) +{ + struct hd_geometry *geo = (struct hd_geometry *)arg; + int ret = 0, minor = MINOR(inode->i_rdev); + partition_t *part= myparts[minor >> 4]; + u_long sect; + + if (!part) + return -ENODEV; /* How? */ + + switch (cmd) { + case HDIO_GETGEO: + ret = verify_area(VERIFY_WRITE, (long *)arg, sizeof(*geo)); + if (ret) return ret; + /* Sort of arbitrary: round size down to 4K boundary */ + sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE; + put_user(1, (char *)&geo->heads); + put_user(8, (char *)&geo->sectors); + put_user((sect>>3), (short *)&geo->cylinders); + put_user(ftl_hd[minor].start_sect, (u_long *)&geo->start); + break; + case BLKGETSIZE: + ret = verify_area(VERIFY_WRITE, (long *)arg, sizeof(long)); + if (ret) return ret; + put_user(ftl_hd[minor].nr_sects, + (long *)arg); + break; + case BLKRRPART: + ret = ftl_reread_partitions(minor); + break; +#if (LINUX_VERSION_CODE < 0x20303) + case BLKFLSBUF: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + if (!capable(CAP_SYS_ADMIN)) return -EACCES; +#endif + fsync_dev(inode->i_rdev); + invalidate_buffers(inode->i_rdev); + break; + RO_IOCTLS(inode->i_rdev, arg); +#else + case BLKROSET: + case BLKROGET: + case BLKFLSBUF: + ret = blk_ioctl(inode->i_rdev, cmd, arg); + break; +#endif + default: + ret = -EINVAL; + } + + return ret; +} /* ftl_ioctl */ + +/*====================================================================== + + Handler for block device requests + +======================================================================*/ + +static int ftl_reread_partitions(int minor) +{ + partition_t *part = myparts[minor >> 4]; + int i, whole; + + DEBUG(0, "ftl_cs: ftl_reread_partition(%d)\n", minor); + if ((atomic_read(&part->open) > 1)) { + return -EBUSY; + } + whole = minor & ~(MAX_PART-1); + + for (i = 0; i < MAX_PART; i++) { + if (ftl_hd[whole+i].nr_sects > 0) { + kdev_t rdev = MKDEV(FTL_MAJOR, whole+i); + sync_dev(rdev); + invalidate_buffers(rdev); + } + ftl_hd[whole+i].start_sect = 0; + ftl_hd[whole+i].nr_sects = 0; + } + + scan_header(part); + + register_disk(&ftl_gendisk, whole >> PART_BITS, MAX_PART, + &ftl_blk_fops, le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE); + +#ifdef PCMCIA_DEBUG + for (i = 0; i < MAX_PART; i++) { + if (ftl_hd[whole+i].nr_sects > 0) + printk(KERN_INFO " %d: start %ld size %ld\n", i, + ftl_hd[whole+i].start_sect, + ftl_hd[whole+i].nr_sects); + } +#endif + return 0; +} + +/*====================================================================== + + Handler for block device requests + +======================================================================*/ + +static void do_ftl_request(request_arg_t) +{ + int ret, minor; + partition_t *part; + + do { + // sti(); + INIT_REQUEST; + + minor = MINOR(CURRENT->rq_dev); + + part = myparts[minor >> 4]; + if (part) { + ret = 0; + + switch (CURRENT->cmd) { + case READ: + ret = ftl_read(part, CURRENT->buffer, + CURRENT->sector+ftl_hd[minor].start_sect, + CURRENT->current_nr_sectors); + if (ret) printk("ftl_read returned %d\n", ret); + break; + + case WRITE: + ret = ftl_write(part, CURRENT->buffer, + CURRENT->sector+ftl_hd[minor].start_sect, + CURRENT->current_nr_sectors); + if (ret) printk("ftl_write returned %d\n", ret); + break; + + default: + panic("ftl_cs: unknown block command!\n"); + + } + } else { + ret = 1; + printk("NULL part in ftl_request\n"); + } + + if (!ret) { + CURRENT->sector += CURRENT->current_nr_sectors; + } + + end_request((ret == 0) ? 1 : 0); + } while (1); +} /* do_ftl_request */ + +/*====================================================================*/ + +void ftl_freepart(partition_t *part) +{ + if (part->VirtualBlockMap) { + vfree(part->VirtualBlockMap); + part->VirtualBlockMap = NULL; + } + if (part->VirtualPageMap) { + kfree(part->VirtualPageMap); + part->VirtualPageMap = NULL; + } + if (part->EUNInfo) { + kfree(part->EUNInfo); + part->EUNInfo = NULL; + } + if (part->XferInfo) { + kfree(part->XferInfo); + part->XferInfo = NULL; + } + if (part->bam_cache) { + kfree(part->bam_cache); + part->bam_cache = NULL; + } + +} /* ftl_freepart */ + +static void ftl_notify_add(struct mtd_info *mtd) +{ + partition_t *partition; + int device; + + for (device=0; device < MAX_MTD_DEVICES && myparts[device]; device++) + ; + + if (device == MAX_MTD_DEVICES) { + printk(KERN_NOTICE "Maximum number of FTL partitions reached\n" + "Not scanning <%s>\n", mtd->name); + return; + } + + partition = kmalloc(sizeof(partition_t), GFP_KERNEL); + + if (!partition) { + printk(KERN_WARNING "No memory to scan for FTL on %s\n", + mtd->name); + return; + } + + memset(partition, 0, sizeof(partition_t)); + + partition->mtd = mtd; + + if ((scan_header(partition) == 0) && + (build_maps(partition) == 0)) { + + partition->state = FTL_FORMATTED; + atomic_set(&partition->open, 0); + myparts[device] = partition; + ftl_reread_partitions(device << 4); +#ifdef PCMCIA_DEBUG + printk(KERN_INFO "ftl_cs: opening %d kb FTL partition\n", + le32_to_cpu(partition->header.FormattedSize) >> 10); +#endif + } +} + +static void ftl_notify_remove(struct mtd_info *mtd) +{ + int i,j; + + /* Q: What happens if you try to remove a device which has + * a currently-open FTL partition on it? + * + * A: You don't. The ftl_open routine is responsible for + * increasing the use count of the driver module which + * it uses. + */ + + /* That's the theory, anyway :) */ + + for (i=0; i< MAX_MTD_DEVICES; i++) + if (myparts[i] && myparts[i]->mtd == mtd) { + + if (myparts[i]->state == FTL_FORMATTED) + ftl_freepart(myparts[i]); + + myparts[i]->state = 0; + for (j=0; j<16; j++) { + ftl_gendisk.part[j].nr_sects=0; + ftl_gendisk.part[j].start_sect=0; + } + kfree(myparts[i]); + myparts[i] = NULL; + } +} + + +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define init_ftl init_module +#define cleanup_ftl cleanup_module +#endif +#endif + +mod_init_t init_ftl(void) +{ + int i; + + memset(myparts, 0, sizeof(myparts)); + + DEBUG(0, "$Id: ftl.c,v 1.20 2000/06/23 15:17:53 dwmw2 Exp $\n"); + + if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) { + printk(KERN_NOTICE "ftl_cs: unable to grab major " + "device number!\n"); + return -EAGAIN; + } + + for (i = 0; i < MINOR_NR(MAX_DEV, 0, 0); i++) + ftl_blocksizes[i] = 1024; + for (i = 0; i < MAX_DEV*MAX_PART; i++) { + ftl_hd[i].nr_sects = 0; + ftl_hd[i].start_sect = 0; + } + blksize_size[FTL_MAJOR] = ftl_blocksizes; + ftl_gendisk.major = FTL_MAJOR; + blk_init_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR), &do_ftl_request); + ftl_gendisk.next = gendisk_head; + gendisk_head = &ftl_gendisk; + + register_mtd_user(&ftl_notifier); + + return 0; +} + +mod_exit_t cleanup_ftl(void) +{ + struct gendisk *gd, **gdp; + + unregister_mtd_user(&ftl_notifier); + + unregister_blkdev(FTL_MAJOR, "ftl"); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR)); + blksize_size[FTL_MAJOR] = NULL; + + for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) + if (*gdp == &ftl_gendisk) { + gd = *gdp; *gdp = gd->next; + break; + } +} + +#if LINUX_VERSION_CODE > 0x20300 +module_init(init_ftl); +module_exit(cleanup_ftl); +#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/jedec.c linux/drivers/mtd/jedec.c --- v2.4.0-test2/linux/drivers/mtd/jedec.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/jedec.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,773 @@ + +/* JEDEC Flash Interface. + * This is an older type of interface for self programming flash. It is + * commonly use in older AMD chips and is obsolete compared with CFI. + * It is called JEDEC because the JEDEC association distributes the ID codes + * for the chips. + * + * See the AMD flash databook for information on how to operate the interface. + * + * This code does not support anything wider than 8 bit flash chips, I am + * not going to guess how to send commands to them, plus I expect they will + * all speak CFI.. + * + * $Id: jedec.c,v 1.1 2000/07/04 07:21:57 jgg Exp $ + */ + +#include + +struct mtd_info *jedec_probe(struct map_info *); +int jedec_probe8(struct map_info *map,unsigned long base, + struct jedec_private *priv); +int jedec_probe16(struct map_info *map,unsigned long base, + struct jedec_private *priv); +int jedec_probe32(struct map_info *map,unsigned long base, + struct jedec_private *priv); +static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start, + unsigned long len); +static int flash_erase(struct mtd_info *mtd, struct erase_info *instr); +static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, + size_t *retlen, const u_char *buf); + +EXPORT_SYMBOL(jedec_probe); + +/* Listing of parts and sizes. We need this table to learn the sector + size of the chip and the total length */ +static const struct JEDECTable JEDEC_table[] = + {{0x01AD,"AMD Am29F016",2*1024*1024,64*1024,MTD_CAP_NORFLASH}, + {0x01D5,"AMD Am29F080",1*1024*1024,64*1024,MTD_CAP_NORFLASH}, + {0x01A4,"AMD Am29F040",512*1024,64*1024,MTD_CAP_NORFLASH}, + {}}; + +static void jedec_sync(struct mtd_info *mtd) {}; +static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); + +/* Probe entry point */ + struct jedec_private priv; + struct mtd_info __MTD; +struct mtd_info *jedec_probe(struct map_info *map) +{ + struct mtd_info *MTD = &__MTD; + unsigned long Base; + unsigned long SectorSize; + unsigned count; + unsigned I,Uniq; + char Part[200]; + memset(&priv,0,sizeof(priv)); + + if (map->bank_size == 0) + map->bank_size = map->size; + + if (map->size/map->bank_size > MAX_JEDEC_CHIPS) + { + printk("mtd: Increase MAX_JEDEC_CHIPS, too many banks.\n"); + return 0; + } + + for (Base = 0; Base < map->size; Base += map->bank_size) + { + // Perhaps zero could designate all tests? + if (map->bus_width == 0) + map->bus_width = 8; + + if (map->bus_width == 8) + jedec_probe8(map,Base,&priv); + if (map->bus_width == 16) + jedec_probe16(map,Base,&priv); + if (map->bus_width == 32) + jedec_probe32(map,Base,&priv); + } + + // Get the biggest sector size + SectorSize = 0; + for (I = 0; priv.chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + if (priv.chips[I].sectorsize > SectorSize) + SectorSize = priv.chips[I].sectorsize; + } + + // Quickly ensure that the other sector sizes are factors of the largest + for (I = 0; priv.chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + if ((SectorSize/priv.chips[I].sectorsize)*priv.chips[I].sectorsize != SectorSize) + { + printk("mtd: Failed. Device has incompatible mixed sector sizes\n"); + return 0; + } + } + + /* Generate a part name that includes the number of different chips and + other configuration information */ + count = 1; + strncpy(Part,map->name,sizeof(Part)-10); + Part[sizeof(Part)-11] = 0; + strcat(Part," "); + Uniq = 0; + for (I = 0; priv.chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + const struct JEDECTable *JEDEC; + + if (priv.chips[I+1].jedec == priv.chips[I].jedec) + { + count++; + continue; + } + + // Locate the chip in the jedec table + JEDEC = jedec_idtoinf(priv.chips[I].jedec >> 8,priv.chips[I].jedec); + if (JEDEC == 0) + { + printk("mtd: Internal Error, JEDEC not set\n"); + return 0; + } + + if (Uniq != 0) + strcat(Part,","); + Uniq++; + + if (count != 1) + sprintf(Part+strlen(Part),"%x*[%s]",count,JEDEC->name); + else + sprintf(Part+strlen(Part),"%s",JEDEC->name); + if (strlen(Part) > sizeof(Part)*2/3) + break; + count = 1; + } + + /* Determine if the chips are organized in a linear fashion, or if there + are empty banks. Note, the last bank does not count here, only the + first banks are important. Holes on non-bank boundaries can not exist + due to the way the detection algorithm works. */ + if (priv.size < map->bank_size) + map->bank_size = priv.size; + priv.is_banked = 0; + for (I = 0; I != priv.size/map->bank_size - 1; I++) + { + if (priv.bank_fill[I] != map->bank_size) + priv.is_banked = 1; + + /* This even could be eliminated, but new de-optimized read/write + functions have to be written */ + if (priv.bank_fill[I] != priv.bank_fill[0]) + { + printk("mtd: Failed. Cannot handle unsymetric banking\n"); + return 0; + } + } + if (priv.is_banked == 1) + strcat(Part,", banked"); + + xprintf("Part: '%s'\n",Part); + + memset(MTD,0,sizeof(*MTD)); + strncpy(MTD->name,Part,sizeof(MTD->name)); + MTD->name[sizeof(MTD->name)-1] = 0; + MTD->type = MTD_NORFLASH; + MTD->flags = MTD_CAP_NORFLASH; + MTD->erasesize = SectorSize*(map->bus_width/8); + MTD->size = priv.size; + //MTD->module = THIS_MODULE; // ? Maybe this should be the low level module? + MTD->erase = flash_erase; + if (priv.is_banked == 1) + MTD->read = jedec_read_banked; + else + MTD->read = jedec_read; + MTD->write = flash_write; + MTD->sync = jedec_sync; + MTD->priv = map; + map->fldrv_priv = &priv; + + return MTD; +} + +/* Helper for the JEDEC function, JEDEC numbers all have odd parity */ +static int checkparity(u_char C) +{ + u_char parity = 0; + while (C != 0) + { + parity ^= C & 1; + C >>= 1; + } + + return parity == 1; +} + + +/* Take an array of JEDEC numbers that represent interleved flash chips + and process them. Check to make sure they are good JEDEC numbers, look + them up and then add them to the chip list */ +int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count, + unsigned long base,struct jedec_private *priv) +{ + unsigned I,J; + unsigned long Size; + unsigned long SectorSize; + const struct JEDECTable *JEDEC; + + // Test #2 JEDEC numbers exhibit odd parity + for (I = 0; I != Count; I++) + { + if (checkparity(Mfg[I]) == 0 || checkparity(Id[I]) == 0) + return 0; + } + + // Finally, just make sure all the chip sizes are the same + JEDEC = jedec_idtoinf(Mfg[0],Id[0]); + + if (JEDEC == 0) + { + printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]); + return 0; + } + + Size = JEDEC->size; + SectorSize = JEDEC->sectorsize; + for (I = 0; I != Count; I++) + { + JEDEC = jedec_idtoinf(Mfg[0],Id[0]); + if (JEDEC == 0) + { + printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]); + return 0; + } + + if (Size != JEDEC->size || SectorSize != JEDEC->sectorsize) + { + printk("mtd: Failed. Interleved flash does not have matching characteristics\n"); + return 0; + } + } + + // Load the Chips + for (I = 0; I != MAX_JEDEC_CHIPS; I++) + { + if (priv->chips[I].jedec == 0) + break; + } + + if (I + Count > MAX_JEDEC_CHIPS) + { + printk("mtd: Device has too many chips. Increase MAX_JEDEC_CHIPS\n"); + return 0; + } + + // Add them to the table + for (J = 0; J != Count; J++) + { + unsigned long Bank; + + JEDEC = jedec_idtoinf(Mfg[J],Id[J]); + priv->chips[I].jedec = (Mfg[J] << 8) | Id[J]; + priv->chips[I].size = JEDEC->size; + priv->chips[I].sectorsize = JEDEC->sectorsize; + priv->chips[I].base = base + J; + priv->chips[I].datashift = J*8; + priv->chips[I].capabilities = JEDEC->capabilities; + priv->chips[I].offset = priv->size + J; + + // log2 n :| + priv->chips[I].addrshift = 0; + for (Bank = Count; Bank != 1; Bank >>= 1, priv->chips[I].addrshift++); + + // Determine how filled this bank is. + Bank = base & (~(map->bank_size-1)); + if (priv->bank_fill[Bank/map->bank_size] < base + + (JEDEC->size << priv->chips[I].addrshift) - Bank) + priv->bank_fill[Bank/map->bank_size] = base + (JEDEC->size << priv->chips[I].addrshift) - Bank; + I++; + } + + priv->size += priv->chips[I-1].size*Count; + + return priv->chips[I-1].size; +} + +/* Lookup the chip information from the JEDEC ID table. */ +const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id) +{ + __u16 Id = (mfr << 8) | id; + unsigned long I = 0; + for (I = 0; JEDEC_table[I].jedec != 0; I++) + if (JEDEC_table[I].jedec == Id) + return JEDEC_table + I; + return 0; +} + +// Look for flash using an 8 bit bus interface +int jedec_probe8(struct map_info *map,unsigned long base, + struct jedec_private *priv) +{ + return 0; +} + +// Look for flash using a 16 bit bus interface (ie 2 8-bit chips) +int jedec_probe16(struct map_info *map,unsigned long base, + struct jedec_private *priv) +{ + return 0; +} + +// Look for flash using a 32 bit bus interface (ie 4 8-bit chips) +int jedec_probe32(struct map_info *map,unsigned long base, + struct jedec_private *priv) +{ + #define flread(x) map->read32(map,base+((x)<<2)) + #define flwrite(v,x) map->write32(map,v,base+((x)<<2)) + + const unsigned long AutoSel1 = 0xAAAAAAAA; + const unsigned long AutoSel2 = 0x55555555; + const unsigned long AutoSel3 = 0x90909090; + const unsigned long Reset = 0x90909090; + __u32 OldVal; + __u8 Mfg[4]; + __u8 Id[4]; + unsigned I; + unsigned long Size; + + // Wait for any write/erase operation to settle + OldVal = flread(base); + for (I = 0; OldVal != flread(base) && I < 10000; I++) + OldVal = flread(base); + + // Reset the chip + flwrite(Reset,0x555); + + // Send the sequence + flwrite(AutoSel1,0x555); + flwrite(AutoSel2,0x2AA); + flwrite(AutoSel3,0x555); + + // Test #1, JEDEC numbers are readable from 0x??00/0x??01 + if (flread(0) != flread(0x100) || + flread(1) != flread(0x101)) + { + flwrite(Reset,0x555); + return 0; + } + + // Split up the JEDEC numbers + OldVal = flread(0); + for (I = 0; I != 4; I++) + Mfg[I] = (OldVal >> (I*8)); + OldVal = flread(1); + for (I = 0; I != 4; I++) + Id[I] = (OldVal >> (I*8)); + + Size = handle_jedecs(map,Mfg,Id,4,base,priv); + if (Size == 0) + { + flwrite(Reset,0x555); + return 0; + } + + /* Check if there is address wrap around within a single bank, if this + returns JEDEC numbers then we assume that it is wrap around. Notice + we call this routine with the JEDEC return still enabled, if two or + more flashes have a truncated address space the probe test will still + work */ + if (base + Size+0x555 < map->size && + base + Size+0x555 < (base & (~(map->bank_size-1))) + map->bank_size) + { + if (flread(base+Size) != flread(base+Size + 0x100) || + flread(base+Size + 1) != flread(base+Size + 0x101)) + { + jedec_probe32(map,base+Size,priv); + } + } + + // Reset. + flwrite(0xF0F0F0F0,0x555); + + return 1; + + #undef flread + #undef flwrite +} + +/* Linear read. */ +static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct map_info *map = (struct map_info *)mtd->priv; + + map->copy_from(map, buf, from, len); + *retlen = len; + return 0; +} + +/* Banked read. Take special care to jump past the holes in the bank + mapping. This version assumes symetry in the holes.. */ +static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct map_info *map = (struct map_info *)mtd->priv; + struct jedec_private *priv = (struct jedec_private *)map->fldrv_priv; + + *retlen = 0; + while (len > 0) + { + // Determine what bank and offset into that bank the first byte is + unsigned long bank = from & (~(priv->bank_fill[0]-1)); + unsigned long offset = from & (priv->bank_fill[0]-1); + unsigned long get = len; + if (priv->bank_fill[0] - offset < len) + get = priv->bank_fill[0] - offset; + + bank /= priv->bank_fill[0]; + map->copy_from(map,buf + *retlen,bank*map->bank_size + offset,get); + + len -= get; + *retlen += get; + from += get; + } + return 0; +} + +/* Pass the flags value that the flash return before it re-entered read + mode. */ +static void jedec_flash_failed(unsigned char code) +{ + /* Bit 5 being high indicates that there was an internal device + failure, erasure time limits exceeded or something */ + if ((code & (1 << 5)) != 0) + { + printk("mtd: Internal Flash failure\n"); + return; + } + printk("mtd: Programming didn't take\n"); +} + +/* This uses the erasure function described in the AMD Flash Handbook, + it will work for flashes with a fixed sector size only. Flashes with + a selection of sector sizes (ie the AMD Am29F800B) will need a different + routine. This routine tries to parallize erasing multiple chips/sectors + where possible */ +static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + // Does IO to the currently selected chip + #define flread(x) map->read8(map,chip->base+((x)<addrshift)) + #define flwrite(v,x) map->write8(map,v,chip->base+((x)<addrshift)) + + unsigned long Time = 0; + unsigned long NoTime = 0; + unsigned long start = instr->addr, len = instr->len; + unsigned int I; + struct map_info *map = (struct map_info *)mtd->priv; + struct jedec_private *priv = (struct jedec_private *)map->fldrv_priv; + + // Verify the arguments.. + if (start + len > mtd->size || + (start % mtd->erasesize) != 0 || + (len % mtd->erasesize) != 0 || + (len/mtd->erasesize) == 0) + return -EINVAL; + + jedec_flash_chip_scan(priv,start,len); + + // Start the erase sequence on each chip + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + unsigned long off; + struct jedec_flash_chip *chip = priv->chips + I; + + if (chip->length == 0) + continue; + + // Send the erase setup code + xprintf("Erase: "); + puth(chip->start); putc(' '); + puth(chip->base); putc(' '); + puth(chip->length); putc(' '); + puth(chip->sectorsize); putc('\n'); + + if (chip->start + chip->length > chip->size) + { + xprintf("DIE\n"); + return -EIO; + } + + flwrite(0xF0,chip->start + 0x555); + flwrite(0xAA,chip->start + 0x555); + flwrite(0x55,chip->start + 0x2AA); + flwrite(0x80,chip->start + 0x555); + flwrite(0xAA,chip->start + 0x555); + flwrite(0x55,chip->start + 0x2AA); + + // Use chip erase if possible + if (chip->start == 0 && chip->length == chip->size) + { + flwrite(0x10,0x555); + continue; + } + + /* Once we start selecting the erase sectors the delay between each + command must not exceed 50us or it will immediately start erasing + and ignore the other sectors */ +/* how do you portably turn off interrupts? + save_flags(flags); + cli();*/ + for (off = 0; off < chip->length; off += chip->sectorsize) + { + // Check to make sure we didn't timeout + flwrite(0x30,chip->start + off); + if (off == 0) + continue; + if ((flread(chip->start + off) & (1 << 3)) != 0) + { + printk("mtd: Ack! We timed out the erase timer!\n"); + return -EIO; + } + } +// restore_flags(flags); + } + + /* We could split this into a timer routine and return early, performing + background erasure.. Maybe later if the need warrents */ + + /* Poll the flash for erasure completion, specs say this can take as long + as 480 seconds to do all the sectors (for a 2 meg flash). + Erasure time is dependant on chip age, temp and wear.. */ + + /* This being a generic routine assumes a 32 bit bus. It does read32s + and bundles interleved chips into the same grouping. This will work + for all bus widths */ + Time = 0; + NoTime = 0; + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + struct jedec_flash_chip *chip = priv->chips + I; + unsigned long off = 0; + unsigned todo[4] = {0,0,0,0}; + unsigned todo_left = 0; + unsigned J; + + if (chip->length == 0) + continue; + + /* Find all chips in this data line, realistically this is all + or nothing up to the interleve count */ + for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++) + { + if ((priv->chips[J].base & (~((1<addrshift)-1))) == + (chip->base & (~((1<addrshift)-1)))) + { + todo_left++; + todo[priv->chips[J].base & ((1<addrshift)-1)] = 1; + } + } + + xprintf("todo: %x %x %x %x\n",(short)todo[0],(short)todo[1], + (short)todo[2],(short)todo[3]); + + while (1) + { + __u32 Last[4]; + unsigned long Count = 0; + + /* During erase bit 7 is held low and bit 6 toggles, we watch this, + should it stop toggling or go high then the erase is completed, + or this is not really flash ;> */ + Last[0] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[1] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[2] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); + Count = 3; + while (todo_left != 0) + { + for (J = 0; J != 4; J++) + { + __u8 Byte1 = (Last[(Count-1)%4] >> (J*8)) & 0xFF; + __u8 Byte2 = (Last[(Count-2)%4] >> (J*8)) & 0xFF; + __u8 Byte3 = (Last[(Count-3)%4] >> (J*8)) & 0xFF; + if (todo[J] == 0) + continue; + + if ((Byte1 & (1 << 7)) == 0 && Byte1 != Byte2) + { +// printk("Check %x %x %x\n",(short)J,(short)Byte1,(short)Byte2); + continue; + } + + if (Byte1 == Byte2) + { + jedec_flash_failed(Byte3); + return -EIO; + } + + todo[J] = 0; + todo_left--; + } + +/* if (NoTime == 0) + Time += HZ/10 - schedule_timeout(HZ/10);*/ + NoTime = 0; + + Last[Count % 4] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); + Count++; + + putc('.'); + +/* // Count time, max of 15s per sector (according to AMD) + if (Time > 15*len/mtd->erasesize*HZ) + { + printk("mtd: Flash Erase Timed out\n"); + return -EIO; + } */ + } + + puts("out\n"); + + // Skip to the next chip if we used chip erase + if (chip->length == chip->size) + off = chip->size; + else + off += chip->sectorsize; + + if (off >= chip->length) + break; + NoTime = 1; + } + + for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++) + { + if ((priv->chips[J].base & (~((1<addrshift)-1))) == + (chip->base & (~((1<addrshift)-1)))) + priv->chips[J].length = 0; + } + } + + puts("done\n"); + return 0; + + #undef flread + #undef flwrite +} + +/* This is the simple flash writing function. It writes to every byte, in + sequence. It takes care of how to properly address the flash if + the flash is interleved. It can only be used if all the chips in the + array are identical!*/ +static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, + size_t *retlen, const u_char *buf) +{ + /* Does IO to the currently selected chip. It takes the bank addressing + base (which is divisable by the chip size) adds the necesary lower bits + of addrshift (interleve index) and then adds the control register index. */ + #define flread(x) map->read8(map,base+(off&((1<addrshift)-1))+((x)<addrshift)) + #define flwrite(v,x) map->write8(map,v,base+(off&((1<addrshift)-1))+((x)<addrshift)) + + struct map_info *map = (struct map_info *)mtd->priv; + struct jedec_private *priv = (struct jedec_private *)map->fldrv_priv; + unsigned long base; + unsigned long off; + + if (start + len > mtd->size) + return -EIO; + + puts("Here"); + + while (len != 0) + { + struct jedec_flash_chip *chip = priv->chips; + unsigned long bank; + unsigned long boffset; + + // Compute the base of the flash. + off = start % (chip->size << chip->addrshift); + base = start - off; + + // Perform banked addressing translation. + bank = base & (~(priv->bank_fill[0]-1)); + boffset = base & (priv->bank_fill[0]-1); + bank = (bank/priv->bank_fill[0])*map->bank_size; + base = bank + boffset; + + xprintf("Flasing %X %X %X\n",base,chip->size,len); + + // Loop over this page + for (; off != (chip->size << chip->addrshift) && len != 0; start++, len--, off++,buf++) + { + unsigned char oldbyte = map->read8(map,base+off); + unsigned char Last[4]; + unsigned long Count = 0; + +// putc('.'); + + if (oldbyte == *buf) + continue; + if (((~oldbyte) & *buf) != 0) + printk("mtd: warn: Trying to set a 0 to a 1\n"); + + // Write + flwrite(0xAA,0x555); + flwrite(0x55,0x2AA); + flwrite(0xA0,0x555); + map->write8(map,*buf,base + off); + Last[0] = map->read8(map,base + off); + Last[1] = map->read8(map,base + off); + Last[2] = map->read8(map,base + off); + + /* Wait for the flash to finish the operation. We store the last 4 + status bytes that have been retrieved so we can determine why + it failed. The toggle bits keep toggling when there is a + failure */ + for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && + Count < 10000; Count++) + Last[Count % 4] = map->read8(map,base + off); + if (Last[(Count - 1) % 4] != *buf) + { + jedec_flash_failed(Last[(Count - 3) % 4]); + return -EIO; + } + } + } + *retlen = len; + return 0; +} + +/* This is used to enhance the speed of the erase routine, + when things are being done to multiple chips it is possible to + parallize the operations, particularly full memory erases of multi + chip memories benifit */ +static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start, + unsigned long len) +{ + unsigned int I; + + // Zero the records + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + priv->chips[I].start = priv->chips[I].length = 0; + + // Intersect the region with each chip + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + struct jedec_flash_chip *chip = priv->chips + I; + unsigned long ByteStart; + unsigned long ChipEndByte = chip->offset + (chip->size << chip->addrshift); + + // End is before this chip or the start is after it + if (start+len < chip->offset || + ChipEndByte - (1 << chip->addrshift) < start) + continue; + + if (start < chip->offset) + { + ByteStart = chip->offset; + chip->start = 0; + } + else + { + chip->start = (start - chip->offset + (1 << chip->addrshift)-1) >> chip->addrshift; + ByteStart = start; + } + + if (start + len >= ChipEndByte) + chip->length = (ChipEndByte - ByteStart) >> chip->addrshift; + else + chip->length = (start + len - ByteStart + (1 << chip->addrshift)-1) >> chip->addrshift; + } +} + /*}}}*/ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/map_ram.c linux/drivers/mtd/map_ram.c --- v2.4.0-test2/linux/drivers/mtd/map_ram.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/map_ram.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,110 @@ +/* + * Common code to handle map devices which are simple RAM + * (C) 2000 Red Hat. GPL'd. + * $Id: map_ram.c,v 1.2 2000/07/03 10:01:38 dwmw2 Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + + +static int mapram_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); +static int mapram_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +static int mapram_erase (struct mtd_info *, struct erase_info *); +static void mapram_nop (struct mtd_info *); + +struct mtd_info *map_ram_probe(struct map_info *); +EXPORT_SYMBOL(map_ram_probe); + +struct mtd_info *map_ram_probe(struct map_info *map) +{ + struct mtd_info *mtd; + + /* Check the first byte is RAM */ + map->write8(map, 0x55, 0); + if (map->read8(map, 0) != 0x55) + return NULL; + + map->write8(map, 0xAA, 0); + if (map->read8(map, 0) != 0xAA) + return NULL; + + /* Check the last byte is RAM */ + map->write8(map, 0x55, map->size-1); + if (map->read8(map, map->size-1) != 0x55) + return NULL; + + map->write8(map, 0xAA, map->size-1); + if (map->read8(map, map->size-1) != 0xAA) + return NULL; + + /* OK. It seems to be RAM. */ + + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); + if (!mtd) + return NULL; + + memset(mtd, 0, sizeof(*mtd)); + + map->fldrv_destroy = mapram_nop; + mtd->priv = map; + mtd->name = map->name; + mtd->type = MTD_RAM; + mtd->erasesize = 0x10000; + mtd->size = map->size; + mtd->erase = mapram_erase; + mtd->read = mapram_read; + mtd->write = mapram_write; + mtd->sync = mapram_nop; + mtd->flags = MTD_CAP_RAM | MTD_VOLATILE; + + MOD_INC_USE_COUNT; + return mtd; +} + + +static int mapram_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + struct map_info *map = (struct map_info *)mtd->priv; + + map->copy_from(map, buf, from, len); + *retlen = len; + return 0; +} + +static int mapram_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + struct map_info *map = (struct map_info *)mtd->priv; + + map->copy_to(map, to, buf, len); + *retlen = len; + return 0; +} + +static int mapram_erase (struct mtd_info *mtd, struct erase_info *instr) +{ + /* Yeah, it's inefficient. Who cares? It's faster than a _real_ + flash erase. */ + struct map_info *map = (struct map_info *)mtd->priv; + unsigned long i; + + for (i=0; ilen; i++) + map->write8(map, 0xFF, instr->addr + i); + + if (instr->callback) + instr->callback(instr); + + return 0; +} + +static void mapram_nop(struct mtd_info *mtd) +{ + /* Nothing to see here */ +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/map_rom.c linux/drivers/mtd/map_rom.c --- v2.4.0-test2/linux/drivers/mtd/map_rom.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/map_rom.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,60 @@ +/* + * Common code to handle map devices which are simple ROM + * (C) 2000 Red Hat. GPL'd. + * $Id: map_rom.c,v 1.2 2000/07/03 10:01:38 dwmw2 Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + + +static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); +static void maprom_nop (struct mtd_info *); + +struct mtd_info *map_rom_probe(struct map_info *); +EXPORT_SYMBOL(map_rom_probe); + +struct mtd_info *map_rom_probe(struct map_info *map) +{ + struct mtd_info *mtd; + + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); + if (!mtd) + return NULL; + + memset(mtd, 0, sizeof(*mtd)); + + map->fldrv_destroy = maprom_nop; + mtd->priv = map; + mtd->name = map->name; + mtd->type = MTD_ROM; + mtd->size = map->size; + mtd->read = maprom_read; + mtd->sync = maprom_nop; + mtd->flags = MTD_CAP_ROM; + + MOD_INC_USE_COUNT; + return mtd; +} + + +static int maprom_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + struct map_info *map = (struct map_info *)mtd->priv; + + map->copy_from(map, buf, from, len); + *retlen = len; + return 0; +} + +static void maprom_nop(struct mtd_info *mtd) +{ + /* Nothing to see here */ +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/mapped.c linux/drivers/mtd/mapped.c --- v2.4.0-test2/linux/drivers/mtd/mapped.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/mapped.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,674 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: mapped.c,v 1.8 2000/03/31 14:40:42 dwmw2 Exp $ +/* ###################################################################### + + Flash MTD Routines + + These routine support IDing and manipulating flash. Currently the + older JEDEC ID mechanism and a table is used for determining the + flash characterisitics, but it is trivial to add support for the + CFI specification: + http://www.pentium.com/design/flash/ in the technote section. + + ##################################################################### */ + /*}}}*/ +#include + +#include +#include +#include +#include +#include +#include +#include + +struct JEDECTable mtd_JEDEC_table[] = + {{0x01AD,"AMD Am29F016",2*1024*1024,64*1024,MTD_CAP_NORFLASH}, + {0x01D5,"AMD Am29F080",1*1024*1024,64*1024,MTD_CAP_NORFLASH}, + {}}; + +// flash_setup - Setup the mapped_mtd_info structure for normal flash /*{{{*/ +// --------------------------------------------------------------------- +/* There is a set of commands that flash manufactures follow for getting the + JEDEC id, erasing and writing. So long as your flash device supports + getting the JEDEC ID in this (standard?) way it will be supported as flash, + otherwise it is converted to ROM. Upon completion the structure is + registered with the MTD layer */ +int mtd_mapped_setup(struct mapped_mtd_info *map) +{ + DEBUG(1, "\n"); + // Must define a page function to use the defaults! + if (map->page == 0) + return -1; + + if (map->jedec_sense == 0) + map->jedec_sense = flash_jedec; + + if (map->jedec_sense(map) != 0) + return -1; + + if (map->mtd.erase == 0 && map->mtd.type == MTD_NORFLASH) + map->mtd.erase = flash_erase; + if (map->mtd.write == 0) + { + if (map->mtd.type == MTD_NORFLASH) + map->mtd.write = flash_write; + if (map->mtd.type == MTD_RAM) + map->mtd.write = ram_write; + } + if (map->mtd.read == 0) + map->mtd.read = rom_read; + + return add_mtd_device(&map->mtd); +} + /*}}}*/ +// flash_remove - Remove the flash device from the MTD layer /*{{{*/ +// --------------------------------------------------------------------- +/* Free any memory allocated for the device here */ +int mtd_mapped_remove(struct mapped_mtd_info *map) +{ + return del_mtd_device(&map->mtd); +} + /*}}}*/ + +// checkparity - Checks a number for odd parity /*{{{*/ +// --------------------------------------------------------------------- +/* Helper for the JEDEC function, JEDEC numbers all have odd parity */ +static int checkparity(u_char C) +{ + u_char parity = 0; + while (C != 0) + { + parity ^= C & 1; + C >>= 1; + } + + return parity == 1; +} + /*}}}*/ +// SetJedec - Set the jedec information for a chip /*{{{*/ +// --------------------------------------------------------------------- +/* We track the configuration of each chip separately in the chip list, + each chip can have a different type and configuration to allow for + maximum flexability. */ +void set_jedec(struct mapped_mtd_info *map,unsigned chip,unsigned char mfr, + unsigned char id) +{ + unsigned long longID = (mfr << 8) + id; + unsigned int I; + + map->mtd.type = MTD_NORFLASH; + map->mfr = mfr; + map->id = id; + + // Locate the chip in the jedec table + for (I = 0; mtd_JEDEC_table[I].jedec != 0; I++) + { + if (mtd_JEDEC_table[I].jedec == longID) + break; + } + + if (mtd_JEDEC_table[I].jedec != longID || longID == 0) + { + printk("Unknown JEDEC number %x-%x, treating as ROM\n",map->mfr, + map->id); + map->mtd.type = MTD_ROM; + return; + } + + // Setup the MTD from the JEDEC information +// map->mtd.size = mtd_JEDEC_table[I].size; +// map->mtd.erasesize = mtd_JEDEC_table[I].sectorsize; +// map->mtd.capabilities = mtd_JEDEC_table[I].capabilities; +// strncpy(map->mtd.part,mtd_JEDEC_table[I].name,sizeof(map->mtd.part)-1); + + map->chips[chip].jedec = longID; + map->chips[chip].size = mtd_JEDEC_table[I].size; + map->chips[chip].sectorsize = mtd_JEDEC_table[I].sectorsize; + map->chips[chip].capabilities = mtd_JEDEC_table[I].capabilities; + map->chips[chip].base = 0; +} + /*}}}*/ +// isjedec - Check if reading from the memory location gives jedec #s /*{{{*/ +// --------------------------------------------------------------------- +/* This is ment to be called on the flash window once it is in jedec mode */ +int isjedec(unsigned long base) +{ + // Test #1, JEDEC numbers are readable from 0x??00/0x??01 + if (readb(base + 0) != readb(base + 0x100) || + readb(base + 1) != readb(base + 0x101)) + return 0; + + // Test #2 JEDEC numbers exhibit odd parity + if (checkparity(readb(base + 0)) == 0 || checkparity(readb(base + 1)) == 0) + return 0; + return 1; +} + /*}}}*/ +// flash_jedec - JEDEC ID sensor /*{{{*/ +// --------------------------------------------------------------------- +/* The mysterious jedec flash probe sequence writes a specific pattern of + bytes to the flash. This should be general enough to work with any MTD + structure that may contain a flash chip, but note that it will corrupt + address 0x5555 on SRAM cards if the machine dies between the two + critical operations. */ +int flash_jedec(struct mapped_mtd_info *map) +{ + unsigned I; + u_char OldVal; + unsigned long base; + unsigned long baseaddr = 0; + unsigned chip = 0; + unsigned count; + + // Who has a page size this small? :> + if (map->pagesize < 0x555) + return 1; + + base = map->page(map,0); + + // Wait for any write/erase operation to settle + OldVal = readb(base); + for (I = 0; OldVal != readb(base) && I < 10000; I++) + OldVal = readb(base); + + /* Check for sram by writing to it, the write also happens to be part + of the flash reset sequence.. */ + OldVal = readb(base + 0x555); + writeb(OldVal,base + 0x555); + writeb(0xF0,base + 0x555); + if (OldVal != readb(base + 0x555)) + { + udelay(100); + + // Set it back and make sure.. + writeb(OldVal,base + 0x555); + if (OldVal == readb(base + 0x555)) + { + map->mtd.type = MTD_RAM; + return 0; + } + + writeb(0xF0,base + 0x555); + } + + // Probe for chips + while (chip < sizeof(map->chips)/sizeof(map->chips[0])) + { + // Already in jedec mode, we might be doing some address wrap around + if (chip != 0 && isjedec(base) != 0) + { + /* Try to reset this page and check if that resets the first page + to confirm */ + writeb(0xF0,base + 0x555); + if (isjedec(base) != 0) + break; + base = map->page(map,0); + if (isjedec(base) == 0) + break; + base = map->page(map,baseaddr/map->pagesize); + } + + // Send the sequence + writeb(0xAA,base + 0x555); + writeb(0x55,base + 0x2AA); + writeb(0x90,base + 0x555); + + // Check the jedec number + if (isjedec(base) == 0) + { + /* If this is the first chip it must be rom, otherwise it is the + end of the flash region */ + if (chip == 0) + { + map->mtd.type = MTD_ROM; + return 0; + } + break; + } + + // Store the jdec info + set_jedec(map,chip,readb(base + 0),readb(base + 1)); + map->chips[chip].base = baseaddr; + + // Jump to the next chip + baseaddr += map->chips[chip].size; + if (baseaddr/map->pagesize > map->maxsize) + break; + base = map->page(map,baseaddr/map->pagesize); + if (base == 0) + return -EIO; + + chip++; + } + + // Reset all of the chips + map->mtd.size = 0; + baseaddr = 0; + map->mtd.flags = 0xFFFF; + for (I = 0; map->chips[I].jedec != 0; I++) + { + // Fill in the various MTD structures + map->mtd.size += map->chips[I].size; + if (map->mtd.erasesize < map->chips[I].sectorsize) + map->mtd.erasesize = map->chips[I].sectorsize; + map->mtd.flags &= map->chips[I].capabilities; + + base = map->page(map,baseaddr/map->pagesize); + baseaddr += map->chips[chip].size; + writeb(0xF0,base + 0); // Reset + } + + /* Generate a part name that includes the number of different chips and + other configuration information */ + count = 1; + map->part[0] = 0; + for (I = 0; map->chips[I].jedec != 0; I++) + { + unsigned J; + if (map->chips[I+1].jedec == map->chips[I].jedec) + { + count++; + continue; + } + + // Locate the chip in the jedec table + for (J = 0; mtd_JEDEC_table[J].jedec != 0; J++) + { + if (mtd_JEDEC_table[J].jedec == map->chips[I].jedec) + break; + } + + if (map->part[0] != 0) + strcat(map->part,","); + + if (count != 1) + sprintf(map->part+strlen(map->part),"%u*[%s]",count, + mtd_JEDEC_table[J].name); + else + sprintf(map->part+strlen(map->part),"%s", + mtd_JEDEC_table[J].name); + count = 1; + } + return 0; +} + /*}}}*/ + +// flash_failed - Print a console message about why the failure /*{{{*/ +// --------------------------------------------------------------------- +/* Pass the flags value that the flash return before it re-entered read + mode. */ +static void flash_failed(unsigned char code) +{ + /* Bit 5 being high indicates that there was an internal device + failure, erasure time limits exceeded or something */ + if ((code & (1 << 5)) != 0) + { + printk("mtd: Internal Flash failure\n"); + return; + } + printk("mtd: Programming didn't take\n"); +} + /*}}}*/ +// flash_erase - Generic erase function /*{{{*/ +// --------------------------------------------------------------------- +/* This uses the erasure function described in the AMD Flash Handbook, + it will work for flashes with a fixed sector size only. Flashes with + a selection of sector sizes (ie the AMD Am29F800B) will need a different + routine. This routine tries to parallize erasing multiple chips/sectors + where possible */ +int flash_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + unsigned long Time = 0; + unsigned long NoTime = 0; + unsigned long start = instr->addr, len = instr->len; + unsigned int I; + struct mapped_mtd_info *map = (struct mapped_mtd_info *)mtd; + + // Verify the arguments.. + if (start + len > map->mtd.size || + (start % map->mtd.erasesize) != 0 || + (len % map->mtd.erasesize) != 0 || + (len/map->mtd.erasesize) == 0) + return -EINVAL; + + flash_chip_scan(map,start,len); + + // Start the erase sequence on each chip + for (I = 0; map->chips[I].jedec != 0; I++) + { + unsigned long off; + struct flash_chip *chip = map->chips + I; + unsigned long base; + unsigned long flags; + + if (chip->length == 0) + continue; + + if (page_jump(map,chip->base + chip->start,0x555,&base,0) != 0) + return -EIO; + + // Send the erase setup code + writeb(0xF0,base + 0x555); + writeb(0xAA,base + 0x555); + writeb(0x55,base + 0x2AA); + writeb(0x80,base + 0x555); + writeb(0xAA,base + 0x555); + writeb(0x55,base + 0x2AA); + + // Use chip erase if possible + if (chip->start == 0 && chip->length == chip->size) + { + writeb(0x10,base+0x555); + continue; + } + + /* Once we start selecting the erase sectors the delay between each + command must not exceed 50us or it will immediately start erasing + and ignore the other sectors */ + save_flags(flags); + cli(); + for (off = 0; off < chip->length; off += chip->sectorsize) + { + if (page_jump(map,chip->base + chip->start + off,1,&base,0) != 0) + return -EIO; + + // Check to make sure we didn't timeout + writeb(0x30,base); + if ((readb(base) & (1 << 3)) != 0) + { + printk("mtd: Ack! We timed out the erase timer!\n"); + return -EIO; + } + } + restore_flags(flags); + } + + /* We could split this into a timer routine and return early, performing + background erasure.. Maybe later if the need warrents */ + + /* Poll the flash for erasure completion, specs say this can take as long + as 480 seconds to do all the sectors (for a 2 meg flash). + Erasure time is dependant on chip age, temp and wear.. */ + Time = 0; + NoTime = 0; + for (I = 0; map->chips[I].jedec != 0; I++) + { + struct flash_chip *chip = map->chips + I; + unsigned long base; + unsigned long off = 0; + if (chip->length == 0) + continue; + + if (page_jump(map,chip->base + chip->start,1,&base,0) != 0) + return -EIO; + + while (1) + { + unsigned char Last[4]; + unsigned long Count = 0; + + /* During erase bit 7 is held low and bit 6 toggles, we watch this, + should it stop toggling or go high then the erase is completed, + or this is not really flash ;> */ + Last[0] = readb(base); + Last[1] = readb(base); + Last[2] = readb(base); + for (Count = 3; (Last[(Count - 1) % 4] & (1 << 7)) == 0 && + Last[(Count - 1) % 4] != Last[(Count - 2) % 4]; Count++) + { + if (NoTime == 0) + Time += HZ/10 - schedule_timeout(HZ/10); + NoTime = 0; + + Last[Count % 4] = readb(base); + + // Count time, max of 15s per sector (according to AMD) + if (Time > 15*len/mtd->erasesize*HZ) + { + printk("mtd: Flash Erase Timed out\n"); + return -EIO; + } + } + + if (Last[(Count - 1) % 4] == Last[(Count - 2) % 4]) + { + flash_failed(Last[(Count - 3) % 4]); + return -EIO; + } + + // Skip to the next chip if we used chip erase + if (chip->length == chip->size) + off = chip->size; + else + off += chip->sectorsize; + + if (off >= chip->length) + break; + if (page_jump(map,chip->base + chip->start + off,1,&base,0) != 0) + return -EIO; + NoTime = 1; + } + } + + // Paranoid verify of erasure + { + unsigned long base; + unsigned long buflen; + while (len > 0) + { + unsigned long step; + + if (page_jump(map,start,len,&base,&buflen) != 0) + return -EIO; + start += buflen; + len -= buflen; + step = buflen/128; + for (;buflen != 0; buflen -= step) + { + if (readb(base+buflen-1) != 0xFF) + { + printk("mtd: Flash Erase didn't take %lu %lu %lu\n",buflen,len,start); + return -EIO; + } + } + } + } + + return 0; +} +#if 1 + /*}}}*/ +// flash_write - Generic writing function /*{{{*/ +// --------------------------------------------------------------------- +/* This could do parallel writes on multiple chips but doesnt, memory + constraints make that infeasable. This should work with any sort of + linear flash that is not interleved */ +extern int flash_write(struct mtd_info *mtd, loff_t start, size_t len, + size_t *retlen, const u_char *buf) +{ + struct mapped_mtd_info *map = (struct mapped_mtd_info *)mtd; + unsigned long base; + unsigned long off; + DEBUG(1,"\n"); + if (start + len > mtd->size) + return -EIO; + + while (len != 0) + { + // Compute the page offset and reposition + base = map->page(map,(u_long)start/map->pagesize); + off = (u_long)start % map->pagesize; + + // Loop over this page + for (; off != map->pagesize && len != 0; start++, len--, off++,buf++) + { + unsigned char oldbyte = readb(base+off); + unsigned char Last[4]; + unsigned long Count = 0; + + if (oldbyte == *buf) + continue; + if (((~oldbyte) & *buf) != 0) + printk("mtd: warn: Trying to set a 0 to a 1\n"); + + // Write + writeb(0xAA,base + 0x555); + writeb(0x55,base + 0x2AA); + writeb(0xA0,base + 0x555); + writeb(*buf,base + off); + Last[0] = readb(base + off); + Last[1] = readb(base + off); + Last[2] = readb(base + off); + + /* Wait for the flash to finish the operation. We store the last 4 + status bytes that have been retrieved so we can determine why + it failed. The toggle bits keep toggling when there is a + failure */ + for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && + Count < 10000; Count++) + Last[Count % 4] = readb(base + off); + if (Last[(Count - 1) % 4] != *buf) + { + flash_failed(Last[(Count - 3) % 4]); + return -EIO; + } + } + } + *retlen = len; + return 0; +} +#endif + +// ram_write - Generic writing function for ram /*{{{*/ +// --------------------------------------------------------------------- +/* */ +extern int ram_write(struct mtd_info *mtd, loff_t start, size_t len, + size_t *retlen, const u_char *buf) +{ + struct mapped_mtd_info *map = (struct mapped_mtd_info *)mtd; + unsigned long base; + size_t origlen = len; + unsigned long buflen; + DEBUG(1,"\n"); + if (start + len > mtd->size) + return -EIO; + + while (len != 0) + { + // Reposition.. + if (page_jump(map,start,len,&base,&buflen) != 0) + return -EIO; + + // Copy + memcpy_toio(base,buf,buflen); + len -= buflen; + start += buflen; + } + *retlen = origlen; + return 0; +} + +// rom_read - Read handler for any sort of device /*{{{*/ +// --------------------------------------------------------------------- +/* This is a generic read function that should work with any device in the + mapped region. */ +extern int rom_read(struct mtd_info *mtd, loff_t start, size_t len, + size_t *retlen, u_char *buf) +{ + struct mapped_mtd_info *map = (struct mapped_mtd_info *)mtd; + size_t origlen = len; + unsigned long base; + unsigned long buflen; + + printk("Rom_Read\n"); + if (start + len > mtd->size) + return -EIO; + + while (len != 0) + { + // Reposition.. + if (page_jump(map,start,len,&base,&buflen) != 0) + return -EIO; + + // Copy + memcpy_fromio(buf,base,buflen); + len -= buflen; + start += buflen; + } + *retlen = origlen; + return 0; +} + +// page_jump - Move the window and return the buffer /*{{{*/ +// --------------------------------------------------------------------- +/* Unlike the page function this returns a buffer and length adjusted for + the page dimensions and the reading offset into the page, simplifies + many of the other routines */ +int page_jump(struct mapped_mtd_info *map,unsigned long start, + unsigned long len,unsigned long *base, + unsigned long *retlen) +{ + DEBUG(1,"Page Jump\n"); + if (start > map->mtd.size || start + len > map->mtd.size) + return -EINVAL; + + *base = map->page(map,start/map->pagesize); + if (*base == 0) + return -EIO; + + *base += start % map->pagesize; + + // If retlen is 0 that mean the caller requires len bytes, no quibbling. + if (retlen == 0) + { + if (len > map->pagesize - (start % map->pagesize)) + return -EIO; + return 0; + } + + // Compute the buffer paramaters and return + if (len > map->pagesize - (start % map->pagesize)) + *retlen = map->pagesize - (start % map->pagesize); + else + *retlen = len; + return 0; +} + /*}}}*/ +// flash_chip_scan - Intersect a region with the flash chip structure /*{{{*/ +// --------------------------------------------------------------------- +/* This is used to enhance the speed of the erase routine, + when things are being done to multiple chips it is possible to + parallize the operations, particularly full memory erases of multi + chip memories benifit */ + +void flash_chip_scan(struct mapped_mtd_info *map,unsigned long start, + unsigned long len) +{ + unsigned int I = 0; + + DEBUG(1,"\n"); + // Zero the records + for (I = 0; map->chips[I].jedec != 0; I++) + map->chips[I].start = map->chips[I].length = 0; + + // Intesect our region with the chip structures + for (I = 0; map->chips[I].jedec != 0 && len != 0; I++) + { + // Havent found the start yet + if (start >= map->chips[I].base + map->chips[I].size) + continue; + + // Store the portion of this chip that is being effected + map->chips[I].start = start - map->chips[I].base; + if (len <= map->chips[I].size - map->chips[I].start) + map->chips[I].length = len; + else + map->chips[I].length = map->chips[I].size - map->chips[I].start; + len -= map->chips[I].length; + start = map->chips[I].base + map->chips[I].size; + } +} + /*}}}*/ + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/mixmem.c linux/drivers/mtd/mixmem.c --- v2.4.0-test2/linux/drivers/mtd/mixmem.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/mixmem.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,151 @@ +/* + * mixmem - a block device driver for flash rom found on the + * piggyback board of the multi-purpose mixcom card + * + * Author: Gergely Madarasz + * + * Copyright (c) 1999 ITConsult-Pro Co. + * + * This code is GPL + * + */ + +#include +#include +#include +#include +#include +#include + +#define MIXCOM_ID_OFFSET 0xc10 +#define MIXCOM_PAGE_OFFSET 0xc11 +#define MIXCOM_ID_1 0x11 +#define MIXCOM_ID_2 0x13 +#define MIXMEM_PAGESIZE 4096 +#define FIRST_BLOCK_OFFSET 0x1000 + +#if LINUX_VERSION_CODE < 0x20300 +#define __exit +#endif + +static unsigned int mixmem_addrs[] = { 0xc8000, 0xd8000, 0 }; +static unsigned int mixcom_ports[] = { 0x180, 0x280, 0x380, 0 }; + +// We could store these in the mtd structure, but we only support 1 device.. +static unsigned long base_io = 0; +static unsigned long base_addr = 0; +static struct mapped_mtd_info *SSD; + +static unsigned long mixmem_page(struct mapped_mtd_info *map, + unsigned long page) +{ + outb((char)(page & 0xff), base_io+MIXCOM_PAGE_OFFSET); + outb((char)((page >> 8) & 0x7), base_io+MIXCOM_PAGE_OFFSET+1); + return base_addr; +} + +static int flash_probe(int base) +{ + int prev,curr; + unsigned long flags; + + writeb(0xf0, base); + save_flags(flags); cli(); + + prev=readw(base); + + writeb(0xaa, base+0x555); + writeb(0x55, base+0x2AA); + writeb(0x90, base+0x555); + + curr=readw(base); + + restore_flags(flags); + writeb(0xf0, base); + return(prev==curr?0:curr); +} + +static int mixmem_probe(void) +{ + int i; + int id; + int chip; + + /* This should really check to see if the io ports are in use before + writing to them */ + for(i=0;mixcom_ports[i]!=0;i++) { + id=inb(mixcom_ports[i]+MIXCOM_ID_OFFSET); + if(id==MIXCOM_ID_1 || id==MIXCOM_ID_2) { + printk("mixmem: mixcom board found at 0x%3x\n",mixcom_ports[i]); + break; + } + } + + if(mixcom_ports[i]==0) { + printk("mixmem: no mixcom board found\n"); + return -ENODEV; + } + + if (check_region(mixcom_ports[i]+MIXCOM_PAGE_OFFSET, 2)) return -EAGAIN; + + + + // What is the deal with first_block_offset? + for(i=0;mixmem_addrs[i]!=0;i++) { + chip=flash_probe(mixmem_addrs[i]+FIRST_BLOCK_OFFSET); + if(chip)break; + } + + if(mixmem_addrs[i]==0) { + printk("mixmem: no flash available\n"); + return -ENODEV; + } + base_io = mixcom_ports[i]; + base_addr = mixmem_addrs[i]; + request_region(mixcom_ports[i]+MIXCOM_PAGE_OFFSET, 2, "mixmem"); + return 0; +} + + +static void __exit cleanup_mixmem() +{ + mtd_mapped_remove(SSD); + kfree(SSD); + SSD = 0; + release_region(base_io+MIXCOM_PAGE_OFFSET, 2); +} + +//static int __init init_mixmem(void) +int __init init_mixmem(void) +{ + if (mixmem_probe() != 0) + return -EAGAIN; + + // Print out our little header.. + printk("mixcom MTD IO:0x%lx MEM:0x%lx-0x%lx\n",base_io,base_addr, + base_addr+MIXMEM_PAGESIZE); + + // Allocate some memory + SSD = (struct mapped_mtd_info *)kmalloc(sizeof(*SSD),GFP_KERNEL); + if (SSD == 0) + return 0; + memset(SSD,0,sizeof(*SSD)); + + // Setup the MTD structure + SSD->page = mixmem_page; + SSD->pagesize = MIXMEM_PAGESIZE; + SSD->maxsize = 0x7FF; + SSD->mtd.name = "mixcom piggyback"; + + // Setup the MTD, this will sense the flash parameters and so on.. + if (mtd_mapped_setup(SSD) != 0) + { + printk("Failed to register new device\n"); + cleanup_module(); + return -EAGAIN; + } + + return 0; +} +module_init(init_mixmem); +module_exit(cleanup_mixmem); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/mtdblock.c linux/drivers/mtd/mtdblock.c --- v2.4.0-test2/linux/drivers/mtd/mtdblock.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/mtdblock.c Thu Jul 6 01:22:24 2000 @@ -0,0 +1,317 @@ +/* + * Direct MTD block device access + * + * $Id: mtdblock.c,v 1.16 2000/06/23 09:34:58 dwmw2 Exp $ + */ + +#ifdef MTDBLOCK_DEBUG +#define DEBUGLVL debug +#endif + +#include +#include + +#include + +#define MAJOR_NR MTD_BLOCK_MAJOR +#define DEVICE_NAME "mtdblock" +#define DEVICE_REQUEST mtdblock_request +#define DEVICE_NR(device) (device) +#define DEVICE_ON(device) +#define DEVICE_OFF(device) +#define DEVICE_NO_RANDOM +#include + +#if LINUX_VERSION_CODE < 0x20300 +#define RQFUNC_ARG void +#define blkdev_dequeue_request(req) do {CURRENT = req->next;} while (0) +#else +#define RQFUNC_ARG request_queue_t *q +#endif + +#ifdef MTDBLOCK_DEBUG +static int debug = MTDBLOCK_DEBUG; +MODULE_PARM(debug, "i"); +#endif + +#if 1 +static void mtdblock_end_request(struct request *req, int res) +{ + if (end_that_request_first( req, res, "mtdblock" )) + return; + end_that_request_last( req ); +} +#endif + +static int mtd_sizes[MAX_MTD_DEVICES]; + + +/* Keeping a separate list rather than just getting stuff directly out of + the MTD core's mtd_table is perhaps not very nice, but I happen + to dislike the idea of directly accessing mtd_table even more. + dwmw2 31/3/0 +*/ + +static int mtdblock_open(struct inode *inode, struct file *file) +{ + struct mtd_info *mtd = NULL; + + int dev; + + DEBUG(1,"mtdblock_open\n"); + + if (inode == 0) + return -EINVAL; + + dev = MINOR(inode->i_rdev); + + MOD_INC_USE_COUNT; + + mtd = get_mtd_device(NULL, dev); + + if (!mtd) { + MOD_DEC_USE_COUNT; + return -ENODEV; + } + + mtd_sizes[dev] = mtd->size>>9; + + DEBUG(1, "ok\n"); + + return 0; +} + +static release_t mtdblock_release(struct inode *inode, struct file *file) +{ + int dev; + struct mtd_info *mtd; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + struct super_block * sb = get_super(inode->i_rdev); +#endif + DEBUG(1, "mtdblock_release\n"); + + if (inode == NULL) + release_return(-ENODEV); + + fsync_dev(inode->i_rdev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + if (sb) invalidate_inodes(sb); +#endif + invalidate_buffers(inode->i_rdev); + + dev = MINOR(inode->i_rdev); + mtd = __get_mtd_device(NULL, dev); + + if (!mtd) { + printk(KERN_WARNING "MTD device is absent on mtd_release!\n"); + MOD_DEC_USE_COUNT; + release_return(-ENODEV); + + } + + if (mtd->sync) + mtd->sync(mtd); + + put_mtd_device(mtd); + + DEBUG(1, "ok\n"); + + MOD_DEC_USE_COUNT; + release_return(0); +} + + +static void mtdblock_request(RQFUNC_ARG) +{ + struct request *current_request; + unsigned int res = 0; + struct mtd_info *mtd; + + while (1) + { + /* Grab the Request and unlink it from the request list, INIT_REQUEST + will execute a return if we are done. */ + INIT_REQUEST; + current_request = CURRENT; + + if (MINOR(current_request->rq_dev) >= MAX_MTD_DEVICES) + { + printk("mtd: Unsupported device!\n"); + end_request(0); + continue; + } + + // Grab our MTD structure + + mtd = __get_mtd_device(NULL, MINOR(current_request->rq_dev)); + if (!mtd) { + printk("MTD device %d doesn't appear to exist any more\n", CURRENT_DEV); + end_request(0); + } + + if (current_request->sector << 9 > mtd->size || + (current_request->sector + current_request->nr_sectors) << 9 > mtd->size) + { + printk("mtd: Attempt to read past end of device!\n"); + printk("size: %lx, sector: %lx, nr_sectors %lx\n", mtd->size, current_request->sector, current_request->nr_sectors); + end_request(0); + continue; + } + + /* Remove the request we are handling from the request list so nobody messes + with it */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + blkdev_dequeue_request(current_request); + + /* Now drop the lock that the ll_rw_blk functions grabbed for us + and process the request. This is necessary due to the extreme time + we spend processing it. */ + spin_unlock_irq(&io_request_lock); +#endif + + // Handle the request + switch (current_request->cmd) + { + size_t retlen; + + case READ: + if (mtd->read(mtd,current_request->sector<<9, + current_request->nr_sectors << 9, + &retlen, current_request->buffer) == 0) + res = 1; + else + res = 0; + break; + + case WRITE: +//printk("mtdblock_request WRITE sector=%d(%d)\n",current_request->sector, +// current_request->nr_sectors); + + // Read only device + if ((mtd->flags & MTD_CAP_RAM) == 0) + { + res = 0; + break; + } + + // Do the write + if (mtd->write(mtd,current_request->sector<<9, + current_request->nr_sectors << 9, + &retlen, current_request->buffer) == 0) + res = 1; + else + res = 0; + break; + + // Shouldn't happen + default: + printk("mtd: unknown request\n"); + break; + } + + // Grab the lock and re-thread the item onto the linked list +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + spin_lock_irq(&io_request_lock); + mtdblock_end_request(current_request, res); +#else + end_request(res); +#endif + } +} + + + +static int mtdblock_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + struct mtd_info *mtd; + + mtd = __get_mtd_device(NULL, MINOR(inode->i_rdev)); + + if (!mtd) return -EINVAL; + + switch (cmd) { + case BLKGETSIZE: /* Return device size */ + if (!arg) return -EFAULT; + return put_user((mtd->size >> 9), + (long *) arg); + + case BLKFLSBUF: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + if(!capable(CAP_SYS_ADMIN)) return -EACCES; +#endif + fsync_dev(inode->i_rdev); + invalidate_buffers(inode->i_rdev); + if (mtd->sync) + mtd->sync(mtd); + return 0; + + default: + return -EINVAL; + } +} + + /*}}}*/ +#if LINUX_VERSION_CODE < 0x20326 +static struct file_operations mtd_fops = +{ + open: mtdblock_open, + ioctl: mtdblock_ioctl, + release: mtdblock_release, + read: block_read, + write: block_write +}; +#else +static struct block_device_operations mtd_fops = +{ + open: mtdblock_open, + release: mtdblock_release, + ioctl: mtdblock_ioctl +}; +#endif + +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define init_mtdblock init_module +#define cleanup_mtdblock cleanup_module +#endif +#define __exit +#endif + + +int __init init_mtdblock(void) +{ + int i; + + if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { + printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", + MTD_BLOCK_MAJOR); + return EAGAIN; + } + + /* We fill it in at open() time. */ + for (i=0; i< MAX_MTD_DEVICES; i++) { + mtd_sizes[i] = 0; + } + + /* Allow the block size to default to BLOCK_SIZE. */ + blksize_size[MAJOR_NR] = NULL; + blk_size[MAJOR_NR] = mtd_sizes; + +#if LINUX_VERSION_CODE < 0x20320 + blk_dev[MAJOR_NR].request_fn = mtdblock_request; +#else + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request); +#endif + return 0; +} + +static void __exit cleanup_mtdblock(void) +{ + unregister_blkdev(MAJOR_NR,DEVICE_NAME); +} + +#if LINUX_VERSION_CODE > 0x20300 +module_init(init_mtdblock); +module_exit(cleanup_mtdblock); +#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/mtdchar.c linux/drivers/mtd/mtdchar.c --- v2.4.0-test2/linux/drivers/mtd/mtdchar.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/mtdchar.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,402 @@ +/* + * $Id: mtdchar.c,v 1.7 2000/06/30 15:54:19 dwmw2 Exp $ + * + * Character-device access to raw MTD devices. + * + */ + + +#include + +#include +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) +static loff_t mtd_lseek (struct file *file, loff_t offset, int orig) +#else +static int mtd_lseek (struct inode *inode, struct file *file, off_t offset, int orig) +#endif +{ + struct mtd_info *mtd=(struct mtd_info *)file->private_data; + + switch (orig) { + case 0: + /* SEEK_SET */ + file->f_pos = offset; + break; + case 1: + /* SEEK_CUR */ + file->f_pos += offset; + break; + case 2: + /* SEEK_END */ + file->f_pos =mtd->size + offset; + break; + default: + return -EINVAL; + } + + if (file->f_pos < 0) + file->f_pos = 0; + else if (file->f_pos >= mtd->size) + file->f_pos = mtd->size - 1; + + return file->f_pos; +} + + + +static int mtd_open(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + int devnum = minor >> 1; + struct mtd_info *mtd; + + DEBUG(0, "MTD_open\n"); + + if (devnum >= MAX_MTD_DEVICES) + return -ENODEV; + + /* You can't open the RO devices RW */ + if ((file->f_mode & 2) && (minor & 1)) + return -EACCES; + + MOD_INC_USE_COUNT; + + mtd = get_mtd_device(NULL, devnum); + + if (!mtd) { + MOD_DEC_USE_COUNT; + return -ENODEV; + } + + file->private_data = mtd; + + /* You can't open it RW if it's not a writeable device */ + if ((file->f_mode & 2) && !(mtd->flags & MTD_WRITEABLE)) { + put_mtd_device(mtd); + MOD_DEC_USE_COUNT; + return -EACCES; + } + + return 0; +} /* mtd_open */ + +/*====================================================================*/ + +static release_t mtd_close(struct inode *inode, + struct file *file) +{ + struct mtd_info *mtd; + + DEBUG(0, "MTD_close\n"); + + mtd = (struct mtd_info *)file->private_data; + + if (mtd->sync) + mtd->sync(mtd); + + put_mtd_device(mtd); + + MOD_DEC_USE_COUNT; + release_return(0); +} /* mtd_close */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) +#define FILE_POS *ppos +#else +#define FILE_POS file->f_pos +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) +static ssize_t mtd_read(struct file *file, char *buf, size_t count,loff_t *ppos) +#else +static int mtd_read(struct inode *inode,struct file *file, char *buf, int count) +#endif +{ + struct mtd_info *mtd = (struct mtd_info *)file->private_data; + size_t retlen=0; + int ret=0; + char *kbuf; + + DEBUG(0,"MTD_read\n"); + + if (FILE_POS + count > mtd->size) + count = mtd->size - FILE_POS; + + if (!count) + return 0; + + /* FIXME: Use kiovec in 2.3 or 2.2+rawio, or at + * least split the IO into smaller chunks. + */ + + kbuf = vmalloc(count); + if (!kbuf) + return -ENOMEM; + + ret = MTD_READ(mtd, FILE_POS, count, &retlen, kbuf); + if (!ret) { + FILE_POS += retlen; + if (copy_to_user(buf, kbuf, retlen)) + ret = -EFAULT; + else + ret = retlen; + + } + + vfree(kbuf); + + return ret; +} /* mtd_read */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) +static ssize_t mtd_write(struct file *file, const char *buf, size_t count,loff_t *ppos) +#else +static read_write_t mtd_write(struct inode *inode,struct file *file, const char *buf, count_t count) +#endif +{ + struct mtd_info *mtd = (struct mtd_info *)file->private_data; + char *kbuf; + size_t retlen; + int ret=0; + + DEBUG(0,"MTD_write\n"); + + if (FILE_POS == mtd->size) + return -ENOSPC; + + if (FILE_POS + count > mtd->size) + count = mtd->size - FILE_POS; + + if (!count) + return 0; + + kbuf=vmalloc(count); + + if (!kbuf) + return -ENOMEM; + + if (copy_from_user(kbuf, buf, count)) { + vfree(kbuf); + return -EFAULT; + } + + + ret = (*(mtd->write))(mtd, FILE_POS, count, &retlen, buf); + + if (!ret) { + FILE_POS += retlen; + ret = retlen; + } + + vfree(kbuf); + + return ret; +} /* mtd_write */ + +/*====================================================================== + + IOCTL calls for getting device parameters. + +======================================================================*/ +static void mtd_erase_callback (struct erase_info *instr) +{ + wake_up((wait_queue_head_t *)instr->priv); +} + +static int mtd_ioctl(struct inode *inode, struct file *file, + u_int cmd, u_long arg) +{ + struct mtd_info *mtd = (struct mtd_info *)file->private_data; + int ret = 0; + u_long size; + + DEBUG(0, "MTD_ioctl\n"); + + size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; + if (cmd & IOC_IN) { + ret = verify_area(VERIFY_READ, (char *)arg, size); + if (ret) return ret; + } + if (cmd & IOC_OUT) { + ret = verify_area(VERIFY_WRITE, (char *)arg, size); + if (ret) return ret; + } + + switch (cmd) { + case MEMGETINFO: + copy_to_user((struct mtd_info *)arg, mtd, + sizeof(struct mtd_info_user)); + break; + + case MEMERASE: + { + struct erase_info *erase=kmalloc(sizeof(struct erase_info),GFP_KERNEL); + if (!erase) + ret = -ENOMEM; + else { + wait_queue_head_t waitq; + DECLARE_WAITQUEUE(wait, current); + + init_waitqueue_head(&waitq); + + memset (erase,0,sizeof(struct erase_info)); + copy_from_user(&erase->addr, (u_long *)arg, + 2 * sizeof(u_long)); + erase->mtd = mtd; + erase->callback = mtd_erase_callback; + erase->priv = (unsigned long)&waitq; + + /* FIXME: Allow INTERRUPTIBLE. Which means + not having the wait_queue head on the stack + + Does it? Why? Who wrote this? Was it my alter + ago - the intelligent one? Or was it the stupid + one, and now I'm being clever I don't know what + it was on about? + + dwmw2. + + It was the intelligent one. If the wq_head is + on the stack, and we leave because we got + interrupted, then the wq_head is no longer + there when the callback routine tries to + wake us up --> BOOM!. + + */ + current->state = TASK_UNINTERRUPTIBLE; + add_wait_queue(&waitq, &wait); + ret = mtd->erase(mtd, erase); + if (!ret) + schedule(); + remove_wait_queue(&waitq, &wait); + current->state = TASK_RUNNING; + if (!ret) + ret = (erase->state == MTD_ERASE_FAILED); + kfree(erase); + } + break; + } + + case MEMWRITEOOB: + { + struct mtd_oob_buf buf; + void *databuf; + ssize_t retlen; + + copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf)); + + if (buf.length > 0x4096) + return -EINVAL; + + if (!mtd->write_oob) + ret = -EOPNOTSUPP; + else + ret = verify_area(VERIFY_READ, (char *)buf.ptr, buf.length); + + if (ret) + return ret; + + databuf = kmalloc(buf.length, GFP_KERNEL); + if (!databuf) + return -ENOMEM; + + copy_from_user(databuf, buf.ptr, buf.length); + + ret = (mtd->write_oob)(mtd, buf.start, buf.length, &retlen, databuf); + + copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t)); + + kfree(databuf); + break; + + } + + case MEMREADOOB: + { + struct mtd_oob_buf buf; + void *databuf; + ssize_t retlen; + + copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf)); + + if (buf.length > 0x4096) + return -EINVAL; + + if (!mtd->read_oob) + ret = -EOPNOTSUPP; + else + ret = verify_area(VERIFY_WRITE, (char *)buf.ptr, buf.length); + + if (ret) + return ret; + + databuf = kmalloc(buf.length, GFP_KERNEL); + if (!databuf) + return -ENOMEM; + + ret = (mtd->read_oob)(mtd, buf.start, buf.length, &retlen, databuf); + + copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t)); + + if (retlen) + copy_to_user(buf.ptr, databuf, retlen); + + kfree(databuf); + break; + } + + + + + + default: + printk("Invalid ioctl %x (MEMGETINFO = %x)\n",cmd, MEMGETINFO); + ret = -EINVAL; + } + + return ret; +} /* memory_ioctl */ + +static struct file_operations mtd_fops = { + + llseek: mtd_lseek, /* lseek */ + read: mtd_read, /* read */ + write: mtd_write, /* write */ + ioctl: mtd_ioctl, /* ioctl */ + open: mtd_open, /* open */ + release: mtd_close, /* release */ +}; + + +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define init_mtdchar init_module +#define cleanup_mtdchar cleanup_module +#endif +#endif + +mod_init_t init_mtdchar(void) +{ + + if (register_chrdev(MTD_CHAR_MAJOR,"mtd",&mtd_fops)) { + printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", + MTD_CHAR_MAJOR); + return EAGAIN; + } + + return 0; +} + +mod_exit_t cleanup_mtdchar(void) +{ + unregister_chrdev(MTD_CHAR_MAJOR,"mtd"); +} + +#if LINUX_VERSION_CODE > 0x20300 +module_init(init_mtdchar); +module_exit(cleanup_mtdchar); +#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/mtdcore.c linux/drivers/mtd/mtdcore.c --- v2.4.0-test2/linux/drivers/mtd/mtdcore.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/mtdcore.c Thu Jul 6 01:22:24 2000 @@ -0,0 +1,399 @@ +/* + * $Id: mtdcore.c,v 1.8 2000/06/27 13:40:05 dwmw2 Exp $ + * + * Core registration and callback routines for MTD + * drivers and users. + * + */ + +#ifdef MTD_DEBUG +#define DEBUGLVL debug +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_PROC_FS +#include +#endif + +#include + +#ifdef MTD_DEBUG +static int debug = MTD_DEBUG; +MODULE_PARM(debug, "i"); +#endif + +/* Init code required for 2.2 kernels */ + +#if LINUX_VERSION_CODE < 0x20300 + +#ifdef CONFIG_MTD_DOC1000 +extern int init_doc1000(void); +#endif +#ifdef CONFIG_MTD_DOCPROBE +extern int init_doc(void); +#endif +#ifdef CONFIG_MTD_OCTAGON +extern int init_octagon5066(void); +#endif +#ifdef CONFIG_MTD_VMAX +extern int init_vmax301(void); +#endif +#ifdef CONFIG_MTD_MIXMEM +extern int init_mixmem(void); +#endif +#ifdef CONFIG_MTD_PMC551 +extern int init_pmc551(void); +#endif +#ifdef CONFIG_MTD_NORA +extern int init_nora(void); +#endif +#ifdef CONFIG_FTL +extern int init_ftl(void); +#endif +#ifdef CONFIG_NFTL +extern int init_nftl(void); +#endif +#ifdef CONFIG_MTD_BLOCK +extern int init_mtdblock(void); +#endif +#ifdef CONFIG_MTD_CHAR +extern int init_mtdchar(void); +#endif + +#endif /* LINUX_VERSION_CODE < 0x20300 */ + + +static DECLARE_MUTEX(mtd_table_mutex); + +static struct mtd_info *mtd_table[MAX_MTD_DEVICES]; + +static struct mtd_notifier *mtd_notifiers = NULL; + + +int add_mtd_device(struct mtd_info *mtd) +{ + int i; + + down(&mtd_table_mutex); + + for (i=0; i< MAX_MTD_DEVICES; i++) + if (!mtd_table[i]) + { + struct mtd_notifier *not=mtd_notifiers; + + mtd_table[i] = mtd; + DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name); + while (not) + { + (*(not->add))(mtd); + not = not->next; + } + up(&mtd_table_mutex); + MOD_INC_USE_COUNT; + return 0; + } + + up(&mtd_table_mutex); + return 1; +} + + +int del_mtd_device (struct mtd_info *mtd) +{ + struct mtd_notifier *not=mtd_notifiers; + int i; + + down(&mtd_table_mutex); + + for (i=0; i < MAX_MTD_DEVICES; i++) + { + if (mtd_table[i] == mtd) + { + while (not) + { + (*(not->remove))(mtd); + not = not->next; + } + mtd_table[i] = NULL; + up (&mtd_table_mutex); + MOD_DEC_USE_COUNT; + return 0; + } + } + + up(&mtd_table_mutex); + return 1; +} + + + +void register_mtd_user (struct mtd_notifier *new) +{ + int i; + + down(&mtd_table_mutex); + + new->next = mtd_notifiers; + mtd_notifiers = new; + + MOD_INC_USE_COUNT; + + for (i=0; i< MAX_MTD_DEVICES; i++) + if (mtd_table[i]) + new->add(mtd_table[i]); + + up(&mtd_table_mutex); +} + + + +int unregister_mtd_user (struct mtd_notifier *old) +{ + struct mtd_notifier **prev = &mtd_notifiers; + struct mtd_notifier *cur; + int i; + + down(&mtd_table_mutex); + + while ((cur = *prev)) { + if (cur == old) { + *prev = cur->next; + + MOD_DEC_USE_COUNT; + + for (i=0; i< MAX_MTD_DEVICES; i++) + if (mtd_table[i]) + old->remove(mtd_table[i]); + + up(&mtd_table_mutex); + return 0; + } + prev = &cur->next; + } + up(&mtd_table_mutex); + return 1; +} + + +/* get_mtd_device(): + * Prepare to use an MTD device referenced either by number or address. + * + * If == -1, search the table for an MTD device located at . + * If == NULL, return the MTD device with number . + * If both are set, return the MTD device with number _only_ if it + * is located at . + */ + +struct mtd_info *__get_mtd_device(struct mtd_info *mtd, int num) +{ + struct mtd_info *ret = NULL; + int i; + + down(&mtd_table_mutex); + + if (num == -1) { + for (i=0; i< MAX_MTD_DEVICES; i++) + if (mtd_table[i] == mtd) + ret = mtd_table[i]; + } else if (num < MAX_MTD_DEVICES) { + ret = mtd_table[num]; + if (mtd && mtd != ret) + ret = NULL; + } + + up(&mtd_table_mutex); + return ret; +} + +EXPORT_SYMBOL(add_mtd_device); +EXPORT_SYMBOL(del_mtd_device); +EXPORT_SYMBOL(__get_mtd_device); +EXPORT_SYMBOL(register_mtd_user); +EXPORT_SYMBOL(unregister_mtd_user); + +/*====================================================================*/ +/* /proc/mtd support */ + +#ifdef CONFIG_PROC_FS + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) +struct proc_dir_entry *proc_mtd; +#endif + +static inline int mtd_proc_info (char *buf, int i) +{ + struct mtd_info *this = mtd_table[i]; + + if (!this) + return 0; + + return sprintf(buf, "mtd%d: %8.8lx \"%s\"\n", i, this->size, + this->name); +} + +static int mtd_read_proc ( char *page, char **start, off_t off,int count +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + ,int *eof, void *data_unused +#else + ,int unused +#endif + ) +{ + int len = 0, l, i; + off_t begin = 0; + + down(&mtd_table_mutex); + + for (i=0; i< MAX_MTD_DEVICES; i++) { + + l = mtd_proc_info(page + len, i); + len += l; + if (len+begin > off+count) + goto done; + if (len+begin < off) { + begin += len; + len = 0; + } + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + *eof = 1; +#endif + +done: + up(&mtd_table_mutex); + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0) +struct proc_dir_entry mtd_proc_entry = { + 0, /* low_ino: the inode -- dynamic */ + 3, "mtd", /* len of name and name */ + S_IFREG | S_IRUGO, /* mode */ + 1, 0, 0, /* nlinks, owner, group */ + 0, NULL, /* size - unused; operations -- use default */ + &mtd_read_proc, /* function used to read data */ + /* nothing more */ + }; +#endif + +#endif + +/*====================================================================*/ + + +#if LINUX_VERSION_CODE < 0x20300 + +static inline void init_others(void) +{ + /* Shedloads of calls to init functions of all the + * other drivers and users of MTD, which we can + * ditch in 2.3 because of the sexy new way of + * finding init routines. + */ +#ifdef CONFIG_MTD_DOC1000 + init_doc1000(); +#endif +#ifdef CONFIG_MTD_DOCPROBE + init_doc(); /* This covers both the DiskOnChip 2000 + * and the DiskOnChip Millennium. + * Theoretically all other DiskOnChip + * devices too. */ +#endif +#ifdef CONFIG_MTD_OCTAGON + init_octagon5066(); +#endif +#ifdef CONFIG_MTD_VMAX + init_vmax301(); +#endif +#ifdef CONFIGF_MTD_MIXMEM + init_mixmem(); +#endif +#ifdef CONFIG_MTD_PMC551 + init_pmc551(); +#endif +#ifdef CONFIG_MTD_NORA + init_nora(); +#endif +#ifdef CONFIG_MTD_MTDRAM + init_mtdram(); +#endif +#ifdef CONFIG_FTL + init_ftl(); +#endif +#ifdef CONFIG_NFTL + init_nftl(); +#endif +#ifdef CONFIG_MTD_BLOCK + init_mtdblock(); +#endif +#ifdef CONFIG_MTD_CHAR + init_mtdchar(); +#endif +} + +#ifdef MODULE +#define init_mtd init_module +#define cleanup_mtd cleanup_module +#endif + +#endif /* LINUX_VERSION_CODE < 0x20300 */ + +mod_init_t init_mtd(void) +{ + int i; + DEBUG(1, "INIT_MTD:\n"); + for (i=0; i= KERNEL_VERSION(2,2,0) + if ((proc_mtd = create_proc_entry( "mtd", 0, 0 ))) + proc_mtd->read_proc = mtd_read_proc; +#else + proc_register_dynamic(&proc_root,&mtd_proc_entry); +#endif + +#endif + +#if LINUX_VERSION_CODE < 0x20300 + init_others(); +#endif + + return 0; +} + +mod_exit_t cleanup_mtd(void) +{ + unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); +#ifdef CONFIG_PROC_FS +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + if (proc_mtd) + remove_proc_entry( "mtd", 0); +#else + proc_unregister(&proc_root,mtd_proc_entry.low_ino); +#endif +#endif +} + +#if LINUX_VERSION_CODE > 0x20300 +module_init(init_mtd); +module_exit(cleanup_mtd); +#endif + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/mtdram.c linux/drivers/mtd/mtdram.c --- v2.4.0-test2/linux/drivers/mtd/mtdram.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/mtdram.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,147 @@ +/* + * mtdram - a test mtd device + * $Id: mtdram.c,v 1.13 2000/07/03 10:01:38 dwmw2 Exp $ + * Author: Alexander Larsson + * + * Copyright (c) 1999 Alexander Larsson + * + * This code is GPL + * + */ + +#include + +#include +#include +#include +#include + + +#define MTDRAM_TOTAL_SIZE 1024*1024*8 +#define MTDRAM_ERASE_SIZE 4*1024 + + +// We could store these in the mtd structure, but we only support 1 device.. +static struct mtd_info *mtd_info; + + +static int +ram_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + if (instr->addr + instr->len > mtd->size) + return -EINVAL; + + memset((char *)mtd->priv + instr->addr, 0xff, instr->len); + + instr->state = MTD_ERASE_DONE; + + if (instr->callback) + (*(instr->callback))(instr); + return 0; +} + +static int ram_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) +{ + if (from + len > mtd->size) + return -EINVAL; + + *mtdbuf = mtd->priv + from; + *retlen = len; + return 0; +} + +static void ram_unpoint (struct mtd_info *mtd, u_char *addr) +{ +} + +static int ram_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + if (from + len > mtd->size) + return -EINVAL; + + memcpy(buf, mtd->priv + from, len); + + *retlen=len; + return 0; +} + +static int ram_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + if (to + len > mtd->size) + return -EINVAL; + + memcpy ((char *)mtd->priv + to, buf, len); + + *retlen=len; + return 0; +} + +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define init_mtdram init_module +#define cleanup_mtdram cleanup_module +#endif +#endif + +//static void __exit cleanup_mtdram(void) +mod_exit_t cleanup_mtdram(void) +{ + if (mtd_info) { + del_mtd_device(mtd_info); + if (mtd_info->priv) + vfree(mtd_info->priv); + kfree(mtd_info); + } +} + +extern struct module __this_module; + +mod_init_t init_mtdram(void) +{ + // Allocate some memory + mtd_info = (struct mtd_info *)kmalloc(sizeof(struct mtd_info), GFP_KERNEL); + if (mtd_info == 0) + return 0; + + memset(mtd_info, 0, sizeof(*mtd_info)); + + // Setup the MTD structure + mtd_info->name = "mtdram test device"; + mtd_info->type = MTD_RAM; + mtd_info->flags = MTD_CAP_RAM; + mtd_info->size = MTDRAM_TOTAL_SIZE; + mtd_info->erasesize = MTDRAM_ERASE_SIZE; + mtd_info->priv = vmalloc(MTDRAM_TOTAL_SIZE); + memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + mtd_info->module = THIS_MODULE; +#endif + + if (!mtd_info->priv) { + kfree(mtd_info); + mtd_info = NULL; + return -ENOMEM; + } + mtd_info->erase = ram_erase; + mtd_info->point = ram_point; + mtd_info->unpoint = ram_unpoint; + mtd_info->read = ram_read; + mtd_info->write = ram_write; + + if (add_mtd_device(mtd_info)) { + vfree(mtd_info->priv); + kfree(mtd_info); + mtd_info = NULL; + return -EIO; + } + + return 0; +} + +#if LINUX_VERSION_CODE > 0x20300 +module_init(init_mtdram); +module_exit(cleanup_mtdram); +#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/nftl.c linux/drivers/mtd/nftl.c --- v2.4.0-test2/linux/drivers/mtd/nftl.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/nftl.c Sat Jul 8 19:26:12 2000 @@ -0,0 +1,1343 @@ + +/* Linux driver for NAND Flash Translation Layer */ +/* (c) 1999 Machine Vision Holdings, Inc. */ +/* Author: David Woodhouse */ +/* $Id: nftl.c,v 1.35 2000/07/06 14:35:01 dwmw2 Exp $ */ + +/* + The contents of this file are distributed under the GNU Public + Licence version 2 ("GPL"). The legal note below refers only to the + _use_ of the code in some jurisdictions, and does not in any way + affect the copying, distribution and modification of this code, + which is permitted under the terms of the GPL. + + Section 0 of the GPL says: + + "Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope." + + You may copy, distribute and modify this code to your hearts' + content - it's just that in some jurisdictions, you may only _use_ + it under the terms of the licence below. This puts it in a similar + situation to the ISDN code, which you may need telco approval to + use, and indeed any code which has uses that may be restricted in + law. For example, certain malicious uses of the networking stack + may be illegal, but that doesn't prevent the networking code from + being under GPL. + + In fact the ISDN case is worse than this, because modification of + the code automatically invalidates its approval. Modificiation, + unlike usage, _is_ one of the rights which is protected by the + GPL. Happily, the law in those places where approval is required + doesn't actually prevent you from modifying the code - it's just + that you may not be allowed to _use_ it once you've done so - and + because usage isn't addressed by the GPL, that's just fine. + + dwmw2@infradead.org + 6/7/0 + + LEGAL NOTE: The NFTL format is patented by M-Systems. They have + granted a licence for its use with their DiskOnChip products: + + "M-Systems grants a royalty-free, non-exclusive license under + any presently existing M-Systems intellectual property rights + necessary for the design and development of NFTL-compatible + drivers, file systems and utilities to use the data formats with, + and solely to support, M-Systems' DiskOnChip products" + + A signed copy of this agreement from M-Systems is kept on file by + Red Hat UK Limited. In the unlikely event that you need access to it, + please contact dwmw2@redhat.com for assistance. */ + +#define PRERELEASE + +#ifdef NFTL_DEBUG +#define DEBUGLVL debug +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef WE_KNOW_WTF_THIS_DOES_NOT_WORK + +/* NFTL block device stuff */ +#define MAJOR_NR NFTL_MAJOR +#define DEVICE_REQUEST nftl_request +#define DEVICE_OFF(device) +#ifdef WE_KNOW_WTF_THIS_DOES_NOT_WORK +#define LOCAL_END_REQUEST +#endif +#include +#include + + +#ifdef WE_KNOW_WTF_THIS_DOES_NOT_WORK + +static void nftl_end_request(struct request *req, int res) +{ + req->sector += req->current_nr_sectors; + req->nr_sectors -= req->current_nr_sectors; + + if (end_that_request_first( req, res, "nftl" )) + return; + end_that_request_last( req ); +} +#endif + +#ifdef NFTL_DEBUG +static int debug = NFTL_DEBUG; +MODULE_PARM(debug, "i"); +#endif + + + +/* Linux-specific block device functions */ + +/* I _HATE_ the Linux block device setup more than anything else I've ever + * encountered, except ... + */ + +static int nftl_sizes[256]={0,}; +static int nftl_blocksizes[256] = {0,}; + +/* .. for the Linux partition table handling. */ + +struct hd_struct part_table[256] = {{0,0},}; + +#if LINUX_VERSION_CODE < 0x20328 +static void dummy_init (struct gendisk *crap) +{} +#endif + +static struct gendisk nftl_gendisk = { + NFTL_MAJOR, /* Major number */ + "nftl", /* Major name */ + 4, /* Bits to shift to get real from partition */ + 15, /* Number of partitions per real */ +#if LINUX_VERSION_CODE < 0x20328 + MAX_NFTLS, /* maximum number of real */ + dummy_init, /* init function */ +#endif + part_table, /* hd struct */ + nftl_sizes, /* block sizes */ + 0, /* number */ + NULL, /* internal use, not presently used */ + NULL /* next */ +}; + + +struct NFTLrecord *NFTLs[MAX_NFTLS] = {NULL}; + +static void NFTL_setup(struct mtd_info *mtd, unsigned long ofs, + struct NFTLMediaHeader *hdr) +{ + int i; + struct NFTLrecord *thisNFTL; + unsigned long temp; + int firstfree = -1; + + DEBUG(1,"NFTL_setup\n"); + + for (i=0; i < MAX_NFTLS; i++) { + if (!NFTLs[i] && firstfree==-1) + firstfree = i; + else if (NFTLs[i] && NFTLs[i]->mtd == mtd && + NFTLs[i]->MediaHdr.FirstPhysicalEUN == hdr->FirstPhysicalEUN) { + /* This is a Spare Media Header for an NFTL we've already found */ + DEBUG(1, "Spare Media Header for NFTL %d found at %lx\n",i, ofs); + NFTLs[i]->SpareMediaUnit = ofs / mtd->erasesize; + return; + } + } + + + /* OK, it's a new one. Set up all the data structures. */ +#ifdef PSYCHO_DEBUG + printk("Found new NFTL nftl%c at offset %lx\n",firstfree + 'a', ofs); +#endif + if (hdr->UnitSizeFactor != 0xff) { + printk("Sorry, we don't support UnitSizeFactor of != 1 yet\n"); + return; + } + + thisNFTL = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); + if (!thisNFTL) { + printk(KERN_WARNING "Out of memory for NFTL data structures\n"); + return; + } + init_MUTEX(&thisNFTL->mutex); + thisNFTL->EraseSize = mtd->erasesize; + memcpy(&thisNFTL->MediaHdr, hdr, sizeof(*hdr)); + thisNFTL->mtd = mtd; + thisNFTL->MediaUnit = ofs / mtd->erasesize; + thisNFTL->SpareMediaUnit = 0xffff; + thisNFTL->numvunits = le32_to_cpu(thisNFTL->MediaHdr.FormattedSize) / 8192; + thisNFTL->nr_sects = thisNFTL->numvunits * (thisNFTL->EraseSize / 512); + thisNFTL->usecount = 0; + + thisNFTL->cylinders = 1024; + thisNFTL->heads = 16; + + temp = thisNFTL->cylinders * thisNFTL->heads; + thisNFTL->sectors = thisNFTL->nr_sects / temp; + + if (thisNFTL->nr_sects % temp) { + + thisNFTL->sectors++; + temp = thisNFTL->cylinders * thisNFTL->sectors; + thisNFTL->heads = thisNFTL->nr_sects / temp; + + if (thisNFTL->nr_sects & temp) { + thisNFTL->heads++; + temp = thisNFTL->heads * thisNFTL->sectors; + + thisNFTL->cylinders = thisNFTL->nr_sects / temp; + } + } + if (thisNFTL->nr_sects != thisNFTL->heads * thisNFTL->cylinders * + thisNFTL->sectors) { + printk(KERN_WARNING "Cannot calculate an NFTL geometry to match size of 0x%lx.\n", thisNFTL->nr_sects); + printk(KERN_WARNING "Using C:%d H:%d S:%d (== %lx sects)\n", + thisNFTL->cylinders, thisNFTL->heads , + thisNFTL->sectors, + (long)thisNFTL->cylinders * (long)thisNFTL->heads * + (long)thisNFTL->sectors ); + + /* Oh no we don't + * thisNFTL->nr_sects = thisNFTL->heads * thisNFTL->cylinders * thisNFTL->sectors; + */ + } + + + thisNFTL->EUNtable = kmalloc( 2 * thisNFTL->numvunits, + GFP_KERNEL); + if (!thisNFTL->EUNtable) { + printk("ENOMEM\n"); + kfree(thisNFTL); + return; + } + memset(thisNFTL->EUNtable, 0xff, 2 * thisNFTL->numvunits); + + thisNFTL->VirtualUnitTable = kmalloc( 2 * le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits) , GFP_KERNEL); + if (!thisNFTL->VirtualUnitTable) { + printk("ENOMEM\n"); + kfree(thisNFTL->EUNtable); + kfree(thisNFTL); + return; + } + memset(thisNFTL->VirtualUnitTable, 0xff, 2 * le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits)); + + thisNFTL->ReplUnitTable = kmalloc( 2 * le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits) , GFP_KERNEL); + if (!thisNFTL->ReplUnitTable) { + printk("ENOMEM\n"); + kfree(thisNFTL->VirtualUnitTable); + kfree(thisNFTL->EUNtable); + kfree(thisNFTL); + return; + } + memset(thisNFTL->ReplUnitTable, 0xff, 2 *le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits) ); + + /* Ought to check the media header for bad blocks */ + thisNFTL->lastEUN = le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits) + + le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN) - 1; + thisNFTL->numfreeEUNs = 0; + + /* Scan each physical Erase Unit for validity and to find the + Virtual Erase Unit Chain to which it belongs */ + + for (i=le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN); + i <= thisNFTL->lastEUN; i++) { + + union nftl_uci uci; + unsigned long ofs; + size_t retlen; + ofs = i * thisNFTL->EraseSize; + + MTD_READOOB(mtd, (i * thisNFTL->EraseSize) + 512 + 8, 8, &retlen, (char *)&uci); + + if (uci.b.EraseMark != cpu_to_le16(0x3c69) || + uci.b.EraseMark1 != cpu_to_le16(0x3c69)) { + printk("EUN %d: EraseMark not 0x3c69 (0x%4.4x 0x%4.4x instead)\n", + i, le16_to_cpu(uci.b.EraseMark), le16_to_cpu(uci.b.EraseMark1)); + thisNFTL->VirtualUnitTable[i] = 0x7fff; + thisNFTL->ReplUnitTable[i] = 0xffff; + continue; + } + + MTD_READOOB(mtd, (i * thisNFTL->EraseSize) + 8, 8, &retlen, (u_char *)&uci); + + if (uci.a.VirtUnitNum != uci.a.SpareVirtUnitNum) + printk("EUN %d: VirtualUnitNumber (%x) != SpareVirtualUnitNumber (%x)\n", + i, le16_to_cpu(uci.a.VirtUnitNum), + le16_to_cpu(uci.a.SpareVirtUnitNum)); + + if (uci.a.ReplUnitNum != uci.a.SpareReplUnitNum) + printk("EUN %d: ReplacementUnitNumber (%x) != SpareReplacementUnitNumber (%x)\n", + i, le16_to_cpu(uci.a.ReplUnitNum), + le16_to_cpu(uci.a.SpareReplUnitNum)); + + /* We don't actually _do_ anything about the above, just whinge */ + + thisNFTL->VirtualUnitTable[i] = le16_to_cpu(uci.a.VirtUnitNum); + thisNFTL->ReplUnitTable[i] = le16_to_cpu(uci.a.ReplUnitNum); + + /* if (!(VUN & 0x8000) && VUN < (arraybounds)).. optimises to: */ + if (le16_to_cpu(uci.a.VirtUnitNum) < thisNFTL->numvunits) + thisNFTL->EUNtable[le16_to_cpu(uci.a.VirtUnitNum) & 0x7fff] = i; + + if (uci.a.VirtUnitNum == 0xffff) { + /* Free block */ + thisNFTL->LastFreeEUN = i; + thisNFTL->numfreeEUNs++; + } + + } + NFTLs[firstfree] = thisNFTL; + thisNFTL->LastFreeEUN = le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN); + + //#define PSYCHO_DEBUG +#ifdef PSYCHO_DEBUG + for (i=0; i < 10/* thisNFTL->numvunits*/; i++) { + u16 curEUN = thisNFTL->EUNtable[i]; + int sillycount=100; + + printk("Virtual Unit #%d: ",i); + if (!curEUN || curEUN == 0xffff) { + printk("Not present\n"); + continue; + } + printk("%d", curEUN); + + while ((curEUN = thisNFTL->ReplUnitTable[curEUN]) != 0xffff && --sillycount) { + printk(", %d", curEUN & 0xffff); + + } + printk("\n"); + } +#endif + + /* OK. Now we deal with the fact that we're in the real world. Sometimes + things don't actually happen the way they're supposed to. Find, fix, + and whinge about the most common deviations from spec that we have + been known to encounter. + */ + /* Except that I haven't implemented that bit yet :) */ + + /* Finally, set up the block device sizes */ + nftl_sizes[firstfree * 16]=thisNFTL->nr_sects; +// nftl_blocksizes[firstfree*16] = 512; + part_table[firstfree * 16].nr_sects = thisNFTL->nr_sects; +#if LINUX_VERSION_CODE < 0x20328 + resetup_one_dev(&nftl_gendisk, firstfree); +#else + grok_partitions(&nftl_gendisk, firstfree, 1<<4, thisNFTL->nr_sects); +#endif + +} + + +static void NFTL_unsetup(int i) +{ + struct NFTLrecord *thisNFTL = NFTLs[i]; + + DEBUG(1, "NFTL_unsetup %d\n", i); + + NFTLs[i] = NULL; + + if (thisNFTL->VirtualUnitTable) + kfree(thisNFTL->VirtualUnitTable); + if (thisNFTL->ReplUnitTable) + kfree(thisNFTL->ReplUnitTable); + if (thisNFTL->EUNtable) + kfree(thisNFTL->EUNtable); + + kfree(thisNFTL); +} + + + + +/* Search the MTD device for NFTL partitions */ +static void NFTL_notify_add(struct mtd_info *mtd) +{ + int i; + unsigned long ofs; + struct NFTLMediaHeader hdr; + + DEBUG(1, "NFTL_notify_add for %s\n", mtd->name); + + if (mtd) { + if (!mtd->read_oob) /* If this MTD doesn't have out-of-band data, + then there's no point continuing */ + { + DEBUG(1, "No OOB data, quitting\n"); + return; + } + DEBUG(3, "mtd->read = %p,size = %d, erasesize = %d\n", + mtd->read, mtd->size, mtd->erasesize); + for (ofs = 0; ofs < mtd->size ; ofs += mtd->erasesize) { + size_t retlen = 0; + MTD_READ(mtd, ofs, sizeof(hdr), &retlen, (u_char *)&hdr); + + if (retlen < sizeof(hdr)) + { + continue; + } + + if (!strncmp(hdr.DataOrgID, "ANAND", 6)) { + DEBUG(2, "Valid NFTL partition at ofs %ld\n", ofs); + NFTL_setup(mtd, ofs, &hdr); + } + else { + DEBUG(3,"No valid NFTL Partition at ofs %d\n", ofs); + for(i = 0; i < 6; i++) { + DEBUG(3,"%x, ", hdr.DataOrgID[i]); + } + DEBUG(3," = %s\n", hdr.DataOrgID); + DEBUG(3,"%d, %d, %d, %d\n", hdr.NumEraseUnits, hdr.FirstPhysicalEUN, + hdr.FormattedSize, hdr.UnitSizeFactor); + + } + } + return; + } +} + +static void NFTL_notify_remove(struct mtd_info *mtd) +{ + int i; + + for (i=0; i< MAX_NFTLS; i++) { + if (NFTLs[i] && NFTLs[i]->mtd == mtd) + NFTL_unsetup(i); + } +} + + +#ifdef CONFIG_NFTL_RW + +/* Actual NFTL access routines */ + + +static u16 NFTL_findfreeblock( struct NFTLrecord *thisNFTL, int desperate ) +{ + /* For a given Virtual Unit Chain: find or create a free block and + add it to the chain */ + /* We're passed the number of the last EUN in the chain, to save us from + having to look it up again */ + + u16 pot = thisNFTL->LastFreeEUN; + int silly = -1; + + /* Normally, we force a fold to happen before we run out of free blocks completely */ + + if (!desperate && thisNFTL->numfreeEUNs < 2) { + // printk("NFTL_findfreeblock: there are too few free EUNs\n"); + return 0xffff; + } + + /* Scan for a free block */ + + do { + if (thisNFTL->VirtualUnitTable[pot] == 0xffff) { + thisNFTL->LastFreeEUN = pot; + thisNFTL->numfreeEUNs--; + return pot; + } + + if (++pot > thisNFTL->lastEUN) + pot = le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN); + + if (!silly--) { + printk("Tell Dave he fucked up. LastFreeEUN = %d, FirstEUN = %d\n", + thisNFTL->LastFreeEUN, le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN)); + return 0xffff; + } + + } while (pot != thisNFTL->LastFreeEUN); + + return 0xffff; +} + + + + + +static u16 NFTL_foldchain (struct NFTLrecord *thisNFTL, u16 thisVUC, unsigned pendingblock ) +{ + u16 BlockMap[thisNFTL->EraseSize / 512]; + unsigned char BlockLastState[thisNFTL->EraseSize / 512]; + unsigned char BlockFreeFound[thisNFTL->EraseSize / 512]; + u16 thisEUN; + int block; + int silly = -1; + u16 targetEUN = 0xffff; + struct nftl_oob oob; + int inplace = 1; + + memset(BlockMap, 0xff, sizeof(BlockMap)); + memset(BlockFreeFound, 0, sizeof(BlockFreeFound)); + + thisEUN = thisNFTL->EUNtable[thisVUC]; + + if (thisEUN == 0xffff) { + printk(KERN_WARNING "Trying to fold non-existent Virtual Unit Chain %d!\n", thisVUC); + return 0xffff; + } + + /* Scan to find the Erase Unit which holds the actual data for each + 512-byte block within the Chain. + */ + + while( thisEUN <= thisNFTL->lastEUN ) { + size_t retlen; + + targetEUN = thisEUN; + + for (block = 0 ; block < thisNFTL->EraseSize / 512; block ++) { + + MTD_READOOB(thisNFTL->mtd, (thisEUN * thisNFTL->EraseSize) + (block * 512),16 , &retlen, (char *)&oob); + + if (block == 2) { + if (oob.u.c.WriteInh != 0xffffffff) { + printk("Write Inhibited on EUN %d\n", thisEUN); + inplace = 0; + } else { + /* There's no other reason not to do inplace, + except ones that come later. So we don't need + to preserve inplace */ + inplace = 1; + } + } + + BlockLastState[block] = (unsigned char) oob.b.Status & 0xff; + + switch(oob.b.Status) { + case __constant_cpu_to_le16(BLOCK_FREE): + BlockFreeFound[block]=1; + break; + + case __constant_cpu_to_le16(BLOCK_USED): + if (!BlockFreeFound[block]) + BlockMap[block] = thisEUN; + else + printk(KERN_WARNING "BLOCK_USED found after BLOCK_FREE in Virtual Unit Chain %d for block %d\n", thisVUC, block); + break; + case __constant_cpu_to_le16(BLOCK_IGNORE): + case __constant_cpu_to_le16(BLOCK_DELETED): + break; + default: + printk("Unknown status for block %d in EUN %d: %x\n",block,thisEUN, oob.b.Status); + } + } + + if (!silly--) { + printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", thisVUC); + return 0xffff; + } + + thisEUN = thisNFTL->ReplUnitTable[thisEUN] & 0x7fff; + } + + if (inplace) { + /* We're being asked to be a fold-in-place. Check + that all blocks are either present or BLOCK_FREE + in the target block. If not, we're going to have + to fold out-of-place anyway. + */ + + for (block = 0; block < thisNFTL->EraseSize / 512 ; block++) { + + if (BlockLastState[block] != (unsigned char) (cpu_to_le16(BLOCK_FREE) & 0xff) && + BlockMap[block] != targetEUN) { + DEBUG(1, "Setting inplace to 0. VUC %d, block %d was %x lastEUN, and is in EUN %d (%s) %d\n", + thisVUC, block, BlockLastState[block], BlockMap[block] , BlockMap[block]==targetEUN?"==":"!=", targetEUN); + + inplace = 0; + break; + } + } + + if ( pendingblock >= (thisVUC * (thisNFTL->EraseSize / 512)) && + pendingblock < ((thisVUC + 1)* (thisNFTL->EraseSize / 512)) && + BlockLastState[ pendingblock - (thisVUC * (thisNFTL->EraseSize / 512))] != + (unsigned char) (cpu_to_le16(BLOCK_FREE) & 0xff)) { + DEBUG(1, "Pending write not free in EUN %d. Folding out of place.\n", targetEUN); + inplace = 0; + } + + } + + if (!inplace) { + DEBUG(1, "Cannot fold Virtual Unit Chain %d in place. Trying out-of-place\n", thisVUC); + /* We need to find a targetEUN to fold into. */ + targetEUN = NFTL_findfreeblock(thisNFTL, 1); + if (targetEUN == 0xffff) { + /* Ouch. Now we're screwed. We need to do a + fold-in-place of another chain to make room + for this one. We need a better way of selecting + which chain to fold, because makefreeblock will + only ask us to fold the same one again. + */ + printk(KERN_WARNING"NFTL_findfreeblock(desperate) returns 0xffff.\n"); + return 0xffff; + } + + } + + + /* OK. We now know the location of every block in the Virtual Unit Chain, + and the Erase Unit into which we are supposed to be copying. + Go for it. + */ + + DEBUG(1,"Folding chain %d into unit %d\n", thisVUC, targetEUN); + + for (block = 0; block < thisNFTL->EraseSize / 512 ; block++) { + unsigned char movebuf[512]; + struct nftl_oob oob; + size_t retlen; + + memset(&oob, 0xff, sizeof(oob)); + + /* If it's in the target EUN already, or if it's pending write, do nothing */ + if (BlockMap[block] == targetEUN ||(pendingblock == (thisVUC * (thisNFTL->EraseSize / 512) + block))) { + /* Except if it's the first block, in which case we have to + set the UnitNumbers */ + if (block == 0) { + + thisNFTL->mtd->read_oob(thisNFTL->mtd, (thisNFTL->EraseSize * targetEUN) , + 16, &retlen, (char *)&oob); + + // printk("Setting VirtUnitNum on EUN %d to %x, was %x\n", targetEUN, thisVUC, + // le16_to_cpu(oob.u.a.VirtUnitNum)); + + oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC & 0x7fff); + + thisNFTL->mtd->write_oob(thisNFTL->mtd, (thisNFTL->EraseSize * targetEUN) , + 16, &retlen, (char *)&oob); + } + continue; + } + + oob.b.Status = BLOCK_USED; + + switch(block) { + case 0: + oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC & 0x7fff); + // printk("Setting VirtUnitNum on EUN %d to %x\n", targetEUN, thisVUC); + + oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; + break; + + case 1: + oob.u.b.WearInfo = cpu_to_le32(3); // We don't use this, but M-Systems' drivers do + oob.u.b.EraseMark = oob.u.b.EraseMark1 = cpu_to_le16(0x3c69); + break; + + case 2: + default: + oob.u.c.WriteInh = 0xffffffff; + oob.u.c.unused = 0xffffffff; + } + if (thisNFTL->mtd->read_ecc(thisNFTL->mtd, (thisNFTL->EraseSize * BlockMap[block]) + (block * 512), + 512, &retlen, movebuf, (char *)&oob) == -EIO) { + if (thisNFTL->mtd->read_ecc(thisNFTL->mtd, (thisNFTL->EraseSize * BlockMap[block]) + (block * 512), + 512, &retlen, movebuf, (char *)&oob) != -EIO) + printk("Error went away on retry.\n"); + } + + thisNFTL->mtd->write_ecc(thisNFTL->mtd, (thisNFTL->EraseSize * targetEUN) + (block * 512), + 512, &retlen, movebuf, (char *)&oob); + + + /* FIXME: Add some error checking.... */ + thisNFTL->mtd->write_oob(thisNFTL->mtd, (thisNFTL->EraseSize * targetEUN) + (block * 512), + 16, &retlen, (char *)&oob); + + } + + /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */ + + /* At this point, we have two different chains for this Virtual Unit, and no way to tell + them apart. If we crash now, we get confused. However, both contain the same data, so we + shouldn't actually lose data in this case. It's just that when we load up on a medium which + has duplicate chains, we need to free one of the chains because it's not necessary any more. + */ + + + thisEUN = thisNFTL->EUNtable[thisVUC]; + + DEBUG(1,"Want to erase\n"); + /* For each block in the old chain (except the targetEUN of course), + free it and make it available for future use */ + + while( thisEUN <= thisNFTL->lastEUN && thisEUN != targetEUN) { + size_t retlen; + struct erase_info *instr; + u16 EUNtmp; + + instr = kmalloc(sizeof(struct erase_info), GFP_KERNEL); + if (!instr) { + printk(KERN_WARNING "Out of memory for struct erase_info\n"); + + EUNtmp = thisEUN; + + thisEUN = thisNFTL->ReplUnitTable[EUNtmp] & 0x7fff; + thisNFTL->VirtualUnitTable[EUNtmp] = 0x7fff; + thisNFTL->ReplUnitTable[EUNtmp] = 0xffff; + } else { + memset(instr, 0, sizeof(struct erase_info)); + instr->addr = thisEUN * thisNFTL->EraseSize; + instr->len = thisNFTL->EraseSize; + + MTD_ERASE(thisNFTL->mtd, instr); + /* This is an async interface. Or will be. At which point + this code will break. */ + +#if 0 + MTD_READOOB(thisNFTL->mtd, (thisEUN * thisNFTL->EraseSize) + 512, 16, &retlen, (char *)&oob); + + printk("After erasing, EUN %d contains: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + thisEUN, oob.b.ECCSig[0], + oob.b.ECCSig[1], + oob.b.ECCSig[2], + oob.b.ECCSig[3], + oob.b.ECCSig[4], + oob.b.ECCSig[5]); +#endif + memset(&oob, 0xff, sizeof(oob)); + oob.u.b.WearInfo = cpu_to_le32(3); + oob.u.b.EraseMark = oob.u.b.EraseMark1 = cpu_to_le16(0x3c69); + + MTD_WRITEOOB(thisNFTL->mtd, (thisEUN * thisNFTL->EraseSize) + 512, 16, &retlen, (char *)&oob); + + EUNtmp = thisEUN; + + thisEUN = thisNFTL->ReplUnitTable[EUNtmp] & 0x7fff; + thisNFTL->VirtualUnitTable[EUNtmp] = 0xffff; + thisNFTL->ReplUnitTable[EUNtmp] = 0xffff; + + thisNFTL->numfreeEUNs++; + + } + + // shifted upwards: thisEUN = thisNFTL->ReplUnitTable[thisEUN] & 0x7fff; + + } + + /* Make this the new start of chain for thisVUC */ + thisNFTL->VirtualUnitTable[targetEUN] = thisVUC; + thisNFTL->ReplUnitTable[targetEUN] = 0xffff; + + thisNFTL->EUNtable[thisVUC] = targetEUN; + return targetEUN; + +} + +u16 NFTL_makefreeblock( struct NFTLrecord *thisNFTL , unsigned pendingblock) +{ + /* This is the part that needs some cleverness applied. + For now, I'm doing the minimum applicable to actually + get the thing to work. + Wear-levelling and other clever stuff needs to be implemented + and we also need to do some assessment of the results when + the system loses power half-way through the routine. + */ + + u16 LongestChain = 0; + u16 ChainLength = 0, thislen; + u16 chain, EUN; + + + for (chain=0; chain < thisNFTL->MediaHdr.FormattedSize / thisNFTL->EraseSize; chain++) { + EUN = thisNFTL->EUNtable[chain]; + + thislen = 0; + + while (EUN <= thisNFTL->lastEUN) { + thislen++; + // printk("VUC %d reaches len %d with EUN %d\n", chain, thislen, EUN); + EUN = thisNFTL->ReplUnitTable[EUN] & 0x7fff; + if (thislen > 0xff00) { + printk("Endless loop in Virtual Chain %d: Unit %x\n", chain, EUN); + } + if (thislen > 0xff10) { + /* Actually, don't return failure. Just ignore this chain and + get on with it. */ + thislen = 0; + break; + } + + } + + + if (thislen > ChainLength) { + // printk("New longest chain is %d with length %d\n", chain, thislen); + ChainLength = thislen; + LongestChain = chain; + } + } + + if (ChainLength < 2) { + printk(KERN_WARNING "No Virtual Unit Chains available for folding. Failing request\n"); + return 0xffff; + } + + return NFTL_foldchain (thisNFTL, LongestChain, pendingblock); +} + +/* NFTL_findwriteunit: Return the unit number into which we can write + for this block. Make it available if it isn't already +*/ + +static inline u16 NFTL_findwriteunit(struct NFTLrecord *thisNFTL, unsigned block) +{ + u16 lastEUN; + u16 thisVUC = block / (thisNFTL->EraseSize / 512); + u16 writeEUN; + unsigned long blockofs = (block * 512) & (thisNFTL->EraseSize -1); + size_t retlen; + int silly = 0x10000, silly2 = 3; + struct nftl_oob oob; + int debug=0; + + do { + + /* Scan the media to find a unit in the VUC which has + a free space for the block in question. + */ + + /* This condition catches the 0x[7f]fff cases, as well as + being a sanity check for past-end-of-media access + */ + lastEUN = 0xffff; + writeEUN = thisNFTL->EUNtable[thisVUC]; + + while(writeEUN <= thisNFTL->lastEUN) { + struct nftl_bci bci; + size_t retlen; + + lastEUN = writeEUN; + + MTD_READOOB(thisNFTL->mtd, (writeEUN * thisNFTL->EraseSize) + + blockofs,8, &retlen, (char *)&bci); + + if (debug) + printk("Status of block %d in EUN %d is %x\n", block , writeEUN, le16_to_cpu(bci.Status)); + + switch(bci.Status) { + case __constant_cpu_to_le16(BLOCK_FREE): + return writeEUN; + + case __constant_cpu_to_le16(BLOCK_DELETED): + case __constant_cpu_to_le16(BLOCK_USED): + case __constant_cpu_to_le16(BLOCK_IGNORE): + break; + default: + // Invalid block. Don't use it any more. Must implement. + break; + } + + if (!silly--) { + printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", thisVUC); + return 0xffff; + } + + /* Skip to next block in chain */ + + writeEUN = thisNFTL->ReplUnitTable[writeEUN] & 0x7fff; + } + + /* OK. We didn't find one in the existing chain, or there + is no existing chain. */ + + /* Try to find an already-free block */ + + writeEUN = NFTL_findfreeblock(thisNFTL, 0); + + if (writeEUN == 0xffff) { + /* That didn't work - there were no free blocks just + waiting to be picked up. We're going to have to fold + a chain to make room. + */ + + /* First remember the start of this chain */ + // u16 startEUN = thisNFTL->EUNtable[thisVUC]; + + //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC); + writeEUN = NFTL_makefreeblock(thisNFTL, block); + + if (writeEUN == 0xffff) { + /* Ouch. This should never happen - we should + always be able to make some room somehow. + If we get here, we've allocated more storage + space than actual media, or our makefreeblock + routine is missing something. + */ + printk(KERN_WARNING "Cannot make free space.\n"); + return 0xffff; + } + // printk("Restarting scan\n"); + lastEUN = 0xffff; + // debug = 1; + continue; +#if 0 + if (startEUN != thisNFTL->EUNtable[thisVUC]) { + /* The fold operation has moved the chain + that we're looking at. Start the scan again. + */ + continue; + } +#endif + } + + /* We've found a free block. Insert it into the chain. */ + + if (lastEUN != 0xffff) { + /* Addition to an existing chain. Make the previous + last block in the chain point to this one. + */ + + //printk("Linking EUN %d to EUN %d in VUC %d\n", + // lastEUN, writeEUN, thisVUC); + /* Both in our cache... */ + thisNFTL->ReplUnitTable[lastEUN] = writeEUN; + + + /* ... and on the flash itself */ + MTD_READOOB(thisNFTL->mtd, (lastEUN * thisNFTL->EraseSize), 16, &retlen, + (char *)&oob); + + oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = cpu_to_le16(writeEUN); + + MTD_WRITEOOB(thisNFTL->mtd, (lastEUN * thisNFTL->EraseSize), 16, &retlen, + (char *)&oob); + + thisVUC |= 0x8000; /* It's a replacement block */ + } else { + /* The first block in a new chain */ + thisNFTL->EUNtable[thisVUC] = writeEUN; + } + + /* Now set up the actual EUN we're writing into */ + + /* Both in our cache... */ + thisNFTL->VirtualUnitTable[writeEUN] = thisVUC; + thisNFTL->ReplUnitTable[writeEUN] = 0xffff; + + /* ... and on the flash itself */ + MTD_READOOB(thisNFTL->mtd, writeEUN * thisNFTL->EraseSize, 16, + &retlen, (char *)&oob); + + oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); + + MTD_WRITEOOB(thisNFTL->mtd, writeEUN * thisNFTL->EraseSize, 16, + &retlen, (char *)&oob); + + return writeEUN; + + } while (silly2--); + + printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n", thisVUC); + return 0xffff; +} + +static int NFTL_writeblock(struct NFTLrecord *thisNFTL, unsigned block, + char *buffer) +{ + u16 writeEUN; + unsigned long blockofs = (block * 512) & (thisNFTL->EraseSize -1); + size_t retlen; + u16 eccbuf[8]; + + // if (thisEUN == 0xffff) thisEUN = 0; + + writeEUN = NFTL_findwriteunit(thisNFTL, block); + +// printk("writeblock(%d): Write to Unit %d\n", block, writeEUN); + + if (writeEUN == 0xffff) { + printk(KERN_WARNING "NFTL_writeblock(): Cannot find block to write to\n"); + /* If we _still_ haven't got a block to use, we're screwed */ + return 1; + } +// printk("Writing block %lx to EUN %x\n",block, writeEUN); + + + thisNFTL->mtd->write_ecc(thisNFTL->mtd, + (writeEUN * thisNFTL->EraseSize) + blockofs, + 512, &retlen, (char *)buffer, (char *)eccbuf); + eccbuf[3] = BLOCK_USED; + eccbuf[4] = eccbuf[5] = eccbuf[6] = eccbuf[7] = 0xffff; + + thisNFTL->mtd->write_oob(thisNFTL->mtd, + (writeEUN * thisNFTL->EraseSize) + blockofs, + 16, &retlen, (char *)eccbuf); + + return 0; +} + +#endif /* CONFIG_NFTL_RW */ + +static int NFTL_readblock(struct NFTLrecord *thisNFTL, + unsigned block, char *buffer) +{ + u16 lastgoodEUN = 0xffff; + u16 thisEUN = thisNFTL->EUNtable[block / (thisNFTL->EraseSize / 512)]; + unsigned long blockofs = (block * 512) & (thisNFTL->EraseSize -1); + + int silly = -1; + + if (thisEUN == 0xffff) thisEUN = 0; + + while(thisEUN && (thisEUN & 0x7fff) != 0x7fff) { + struct nftl_bci bci; + size_t retlen; + + MTD_READOOB(thisNFTL->mtd, (thisEUN * thisNFTL->EraseSize) + blockofs,8, &retlen, (char *)&bci); + + switch(bci.Status) { + case __constant_cpu_to_le16(BLOCK_FREE): + thisEUN = 0; + break; + case __constant_cpu_to_le16(BLOCK_USED): + lastgoodEUN = thisEUN; + break; + case __constant_cpu_to_le16(BLOCK_IGNORE): + case __constant_cpu_to_le16(BLOCK_DELETED): + break; + default: + printk("Unknown status for block %d in EUN %d: %x\n",block,thisEUN, bci.Status); + } + + if (!silly--) { + printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n",block / (thisNFTL->EraseSize / 512)); + return 1; + } + if (thisEUN) + thisEUN = thisNFTL->ReplUnitTable[thisEUN] & 0x7fff; + } + if (lastgoodEUN == 0xffff) { + memset(buffer, 0, 512); + } else { + loff_t ptr = (lastgoodEUN * thisNFTL->EraseSize) + blockofs; + size_t retlen; + u_char eccbuf[6]; + thisNFTL->mtd->read_ecc(thisNFTL->mtd, ptr, 512, &retlen, buffer, eccbuf); + } + return 0; +} + + +static int nftl_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + struct NFTLrecord *thisNFTL; + + thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16]; + + if (!thisNFTL) return -EINVAL; + + + switch (cmd) { + case HDIO_GETGEO: { + struct hd_geometry g; + + g.heads = thisNFTL->heads; + g.sectors = thisNFTL->sectors; + g.cylinders = thisNFTL->cylinders; + g.start = part_table[MINOR(inode->i_rdev)].start_sect; + return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0; + } + case BLKGETSIZE: /* Return device size */ + if (!arg) return -EINVAL; + return put_user(part_table[MINOR(inode->i_rdev)].nr_sects, + (long *) arg); + + case BLKFLSBUF: + if(!capable(CAP_SYS_ADMIN)) return -EACCES; + fsync_dev(inode->i_rdev); + invalidate_buffers(inode->i_rdev); + if (thisNFTL->mtd->sync) + thisNFTL->mtd->sync(thisNFTL->mtd); + return 0; + + case BLKRRPART: + if (!capable(CAP_SYS_ADMIN)) return -EACCES; + if (thisNFTL->usecount > 1) { + // printk("Use count %d\n", thisNFTL->usecount); + return -EBUSY; + } +#if LINUX_VERSION_CODE < 0x20328 + resetup_one_dev(&nftl_gendisk, MINOR(inode->i_dev) / 16); +#else + grok_partitions(&nftl_gendisk, MINOR(inode->i_dev) / 16, 1<<4, thisNFTL->nr_sects); +#endif + return 0; + + // RO_IOCTLS(inode->i_rdev, arg); /* ref. linux/blk.h */ + default: + return -EINVAL; + } +} + + +void nftl_request(RQFUNC_ARG) +{ + unsigned int dev, block, nsect; + struct NFTLrecord *thisNFTL; + char *buffer; + struct request *req; + int res; + + while (1) { + INIT_REQUEST; /* blk.h */ + + req = CURRENT; +#ifdef WE_KNOW_WTF_THIS_DOES_NOT_WORK + blkdev_dequeue_request(req); + spin_unlock_irq(&io_request_lock); +#else + req = CURRENT; +#endif + + DEBUG(2,"NFTL_request\n"); + DEBUG(3,"NFTL %d request, %lx, %lx", req->cmd, + req->sector, req->current_nr_sectors); + dev = MINOR(req->rq_dev); + block = req->sector; + nsect = req->current_nr_sectors; + buffer = req->buffer; + res = 1; /* succeed */ + + if (dev >= MAX_NFTLS * 16) { + printk("fl: bad minor number: device=%s\n", + kdevname(req->rq_dev)); + res = 0; /* fail */ + goto repeat; + } + + thisNFTL = NFTLs[dev / 16]; + DEBUG(3,"Waiting for mutex\n"); + down(&thisNFTL->mutex); + DEBUG(3,"Got mutex\n"); + + if (block + nsect >= part_table[dev].nr_sects) { + printk("nftl%c%d: bad access: block=%d, count=%d\n", + (MINOR(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect); + up(&thisNFTL->mutex); + res = 0; /* fail */ + goto repeat; + } + + block += part_table[dev].start_sect; + + if (req->cmd == READ) { + DEBUG(2,"NFTL read\n"); + for ( ; nsect > 0; nsect-- , block++, buffer+= 512) { + /* Read a single sector to req->buffer + (512 * i) */ + + if (NFTL_readblock(thisNFTL, block, buffer)) { + DEBUG(2,"NFTL read request failed\n"); + up(&thisNFTL->mutex); + res = 0; + goto repeat; + } + } + DEBUG(2,"NFTL read request completed OK\n"); + up(&thisNFTL->mutex); + goto repeat; + } + else if (req->cmd == WRITE) { + DEBUG(2,"NFTL write request of 0x%x sectors @ %x (req->nr_sectors == %lx\n",nsect, block, req->nr_sectors); +#ifdef CONFIG_NFTL_RW + for ( ; nsect > 0; nsect-- , block++, buffer+= 512) { + /* Read a single sector to req->buffer + (512 * i) */ + + if (NFTL_writeblock(thisNFTL, block, buffer)) { + DEBUG(1,"NFTL write request failed\n"); + + up(&thisNFTL->mutex); + res = 0; + goto repeat; + } + } + DEBUG(2,"NFTL write request completed OK\n"); +#else + res=0; /* Writes always fail */ +#endif /* CONFIG_NFTL_RW */ + up(&thisNFTL->mutex); + goto repeat; + } + else { + DEBUG(0,"NFTL ??? request\n"); + up(&thisNFTL->mutex); + res = 0; + goto repeat; + } + repeat: + DEBUG(3,"end_request(%d)\n", res); +#ifdef WE_KNOW_WTF_THIS_DOES_NOT_WORK + spin_lock_irq(&io_request_lock); + nftl_end_request(req, res); +#else + end_request(res); +#endif + } +} + +static int nftl_open(struct inode *ip, struct file *fp) +{ + struct NFTLrecord *thisNFTL; + thisNFTL = NFTLs[MINOR(ip->i_rdev) / 16]; + + DEBUG(2,"NFTL_open\n"); + + if (!thisNFTL) { + DEBUG(2,"ENODEV: thisNFTL = %d, minor = %d, ip = %p, fp = %p\n", + MINOR(ip->i_rdev) / 16,ip->i_rdev,ip, fp); + return -ENODEV; + } +#ifndef CONFIG_NFTL_RW + if (fp->f_mode & FMODE_WRITE) + return -EROFS; +#endif /* !CONFIG_NFTL_RW */ + thisNFTL->usecount++; + MOD_INC_USE_COUNT; + if (!get_mtd_device(thisNFTL->mtd, -1)) { + MOD_DEC_USE_COUNT; + return /* -E'SBUGGEREDOFF */ -ENXIO; + } + + return 0; +} + +static int nftl_release(struct inode *inode, struct file *fp) +{ + struct super_block *sb = get_super(inode->i_rdev); + struct NFTLrecord *thisNFTL; + + thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16]; + + DEBUG(2, "NFTL_release\n"); + + fsync_dev(inode->i_rdev); + if (sb) + invalidate_inodes(sb); + invalidate_buffers(inode->i_rdev); + + if (thisNFTL->mtd->sync) + thisNFTL->mtd->sync(thisNFTL->mtd); + thisNFTL->usecount--; + MOD_DEC_USE_COUNT; + + put_mtd_device(thisNFTL->mtd); + + return 0; +} +#if LINUX_VERSION_CODE < 0x20326 +static struct file_operations nftl_fops = { + read: block_read, + write: block_write, + ioctl: nftl_ioctl, + open: nftl_open, + release: nftl_release, + fsync: block_fsync, +}; +#else +static struct block_device_operations nftl_fops = +{ + open: nftl_open, + release: nftl_release, + ioctl: nftl_ioctl +}; +#endif + + + +/**************************************************************************** + * + * Module stuff + * + ****************************************************************************/ + +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define init_nftl init_module +#define cleanup_nftl cleanup_module +#endif +#define __exit +#endif + +static struct mtd_notifier nftl_notifier = {NFTL_notify_add, NFTL_notify_remove, NULL}; + + +/* static int __init init_nftl(void) */ +int __init init_nftl(void) +{ + int i; + + printk(KERN_NOTICE "M-Systems NAND Flash Translation Layer driver. (C) 1999 MVHI\n"); +#ifdef PRERELEASE + printk(KERN_INFO"$Id: nftl.c,v 1.35 2000/07/06 14:35:01 dwmw2 Exp $\n"); +#endif + + if (register_blkdev(NFTL_MAJOR, "nftl", &nftl_fops)){ + printk("unable to register NFTL block device\n"); + } else { +#if LINUX_VERSION_CODE < 0x20320 + blk_dev[MAJOR_NR].request_fn = nftl_request; +#else + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request); +#endif + for (i=0; i < 256 ; i++) { + nftl_blocksizes[i] = 1024; + } + blksize_size[NFTL_MAJOR] = nftl_blocksizes; + nftl_gendisk.next = gendisk_head; + gendisk_head = &nftl_gendisk; + } + + register_mtd_user(&nftl_notifier); + + return 0; +} + +static void __exit cleanup_nftl(void) +{ + struct gendisk *gd, **gdp; + + unregister_mtd_user(&nftl_notifier); + + unregister_blkdev(NFTL_MAJOR, "nftl"); +#if LINUX_VERSION_CODE < 0x20320 + blk_dev[MAJOR_NR].request_fn = 0; +#else + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); +#endif + for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) + if (*gdp == &nftl_gendisk) { + gd = *gdp; *gdp = gd->next; + break; + } + +} + +#if LINUX_VERSION_CODE > 0x20300 +module_init(init_nftl); +module_exit(cleanup_nftl); +#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/nora.c linux/drivers/mtd/nora.c --- v2.4.0-test2/linux/drivers/mtd/nora.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/nora.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,208 @@ +/* + * $Id: nora.c,v 1.11 2000/07/04 16:42:50 dwmw2 Exp $ + * + * This is so simple I love it. + */ + +#include +#include +#include + +#include +#include + + +#define WINDOW_ADDR 0xd0000000 +#define WINDOW_SIZE 0x04000000 + +static struct mtd_info *mymtd; + +__u8 nora_read8(struct map_info *map, unsigned long ofs) +{ + return *(__u8 *)(WINDOW_ADDR + ofs); +} + +__u16 nora_read16(struct map_info *map, unsigned long ofs) +{ + return *(__u16 *)(WINDOW_ADDR + ofs); +} + +__u32 nora_read32(struct map_info *map, unsigned long ofs) +{ + return *(__u32 *)(WINDOW_ADDR + ofs); +} + +void nora_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy(to, (void *)(WINDOW_ADDR + from), len); +} + +void nora_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + *(__u8 *)(WINDOW_ADDR + adr) = d; +} + +void nora_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + *(__u16 *)(WINDOW_ADDR + adr) = d; +} + +void nora_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + *(__u32 *)(WINDOW_ADDR + adr) = d; +} + +void nora_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy((void *)(WINDOW_ADDR + to), from, len); +} + +struct map_info nora_map = { + "NORA", + WINDOW_SIZE, + 2, + nora_read8, + nora_read16, + nora_read32, + nora_copy_from, + nora_write8, + nora_write16, + nora_write32, + nora_copy_to, + 0, + 0 +}; + + +static int nora_mtd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + return mymtd->read(mymtd, from + (unsigned long)mtd->priv, len, retlen, buf); +} + +static int nora_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + return mymtd->write(mymtd, to + (unsigned long)mtd->priv, len, retlen, buf); +} + +static int nora_mtd_erase (struct mtd_info *mtd, struct erase_info *instr) +{ + instr->addr += (unsigned long)mtd->priv; + return mymtd->erase(mymtd, instr); +} + +static void nora_mtd_sync (struct mtd_info *mtd) +{ + mymtd->sync(mymtd); +} + +static int nora_mtd_suspend (struct mtd_info *mtd) +{ + return mymtd->suspend(mymtd); +} + +static void nora_mtd_resume (struct mtd_info *mtd) +{ + mymtd->resume(mymtd); +} + + +static struct mtd_info nora_mtds[4] = { /* boot, kernel, ramdisk, fs */ + { + type: MTD_NORFLASH, + flags: MTD_CAP_NORFLASH, + size: 0x60000, + erasesize: 0x20000, + name: "NORA boot firmware", + module: THIS_MODULE, + erase: nora_mtd_erase, + read: nora_mtd_read, + write: nora_mtd_write, + suspend: nora_mtd_suspend, + resume: nora_mtd_resume, + sync: nora_mtd_sync, + priv: (void *)0 + }, + { + type: MTD_NORFLASH, + flags: MTD_CAP_NORFLASH, + size: 0x1a0000, + erasesize: 0x20000, + name: "NORA kernel", + module: THIS_MODULE, + erase: nora_mtd_erase, + read: nora_mtd_read, + write: nora_mtd_write, + suspend: nora_mtd_suspend, + resume: nora_mtd_resume, + sync: nora_mtd_sync, + priv: (void *)0x60000 + }, + { + type: MTD_NORFLASH, + flags: MTD_CAP_NORFLASH, + size: 0xe00000, + erasesize: 0x20000, + name: "NORA ramdisk", + module: THIS_MODULE, + erase: nora_mtd_erase, + read: nora_mtd_read, + write: nora_mtd_write, + suspend: nora_mtd_suspend, + resume: nora_mtd_resume, + sync: nora_mtd_sync, + priv: (void *)0x200000 + }, + { + type: MTD_NORFLASH, + flags: MTD_CAP_NORFLASH, + size: 0x1000000, + erasesize: 0x20000, + name: "NORA filesystem", + module: THIS_MODULE, + erase: nora_mtd_erase, + read: nora_mtd_read, + write: nora_mtd_write, + suspend: nora_mtd_suspend, + resume: nora_mtd_resume, + sync: nora_mtd_sync, + priv: (void *)0x1000000 + } +}; + +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define init_nora init_module +#define cleanup_nora cleanup_module +#endif +#endif + +int __init init_nora(void) +{ + printk(KERN_NOTICE "nora flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); + + mymtd = do_cfi_probe(&nora_map); + if (mymtd) { +#ifdef MODULE + mymtd->module = &__this_module; +#endif + + add_mtd_device(&nora_mtds[3]); + add_mtd_device(&nora_mtds[0]); + add_mtd_device(&nora_mtds[1]); + add_mtd_device(&nora_mtds[2]); + return 0; + } + + return -ENXIO; +} + +static void __exit cleanup_nora(void) +{ + if (mymtd) { + del_mtd_device(&nora_mtds[2]); + del_mtd_device(&nora_mtds[1]); + del_mtd_device(&nora_mtds[0]); + del_mtd_device(&nora_mtds[3]); + map_destroy(mymtd); + } +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/octagon-5066.c linux/drivers/mtd/octagon-5066.c --- v2.4.0-test2/linux/drivers/mtd/octagon-5066.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/octagon-5066.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,290 @@ +// $Id: octagon-5066.c,v 1.9 2000/07/03 10:01:38 dwmw2 Exp $ +/* ###################################################################### + + Octagon 5066 MTD Driver. + + The Octagon 5066 is a SBC based on AMD's 586-WB running at 133 MHZ. It + comes with a builtin AMD 29F016 flash chip and a socketed EEPROM that + is replacable by flash. Both units are mapped through a multiplexer + into a 32k memory window at 0xe8000. The control register for the + multiplexing unit is located at IO 0x208 with a bit map of + 0-5 Page Selection in 32k increments + 6-7 Device selection: + 00 SSD off + 01 SSD 0 (Socket) + 10 SSD 1 (Flash chip) + 11 undefined + + On each SSD, the first 128k is reserved for use by the bios + (actually it IS the bios..) This only matters if you are booting off the + flash, you must not put a file system starting there. + + The driver tries to do a detection algorithm to guess what sort of devices + are plugged into the sockets. + + ##################################################################### */ + +#include +#include +#include +#include +#include + +#include + +#define WINDOW_START 0xe8000 +#define WINDOW_LENGTH 0x8000 +#define WINDOW_SHIFT 27 +#define WINDOW_MASK 0x7FFF +#define PAGE_IO 0x208 + +static volatile char page_n_dev = 0; +static unsigned long iomapadr; +static spinlock_t oct5066_spin = SPIN_LOCK_UNLOCKED; + +/* + * We use map_priv_1 to identify which device we are. + */ + +static void __oct5066_page(struct map_info *map, __u8 byte) +{ + outb(byte,PAGE_IO); + page_n_dev = byte; +} + +static inline void oct5066_page(struct map_info *map, unsigned long ofs) +{ + __u8 byte = map->map_priv_1 | (ofs >> WINDOW_SHIFT); + + if (page_n_dev != byte); + __oct5066_page(map, byte); +} + + +static __u8 oct5066_read8(struct map_info *map, unsigned long ofs) +{ + __u8 ret; + spin_lock(&oct5066_spin); + oct5066_page(map, ofs); + ret = readb(iomapadr + (ofs & WINDOW_MASK)); + spin_unlock(&oct5066_spin); + return ret; +} + +static __u16 oct5066_read16(struct map_info *map, unsigned long ofs) +{ + __u16 ret; + spin_lock(&oct5066_spin); + oct5066_page(map, ofs); + ret = readw(iomapadr + (ofs & WINDOW_MASK)); + spin_unlock(&oct5066_spin); + return ret; +} + +static __u32 oct5066_read32(struct map_info *map, unsigned long ofs) +{ + __u32 ret; + spin_lock(&oct5066_spin); + oct5066_page(map, ofs); + ret = readl(iomapadr + (ofs & WINDOW_MASK)); + spin_unlock(&oct5066_spin); + return ret; +} + +static void oct5066_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + while(len) { + unsigned long thislen = len; + if (len > (WINDOW_LENGTH - (from & WINDOW_MASK))) + thislen = WINDOW_LENGTH-(from & WINDOW_MASK); + + spin_lock(&oct5066_spin); + oct5066_page(map, from); + memcpy_fromio(to, iomapadr + from, thislen); + spin_unlock(&oct5066_spin); + to += thislen; + from += thislen; + len -= thislen; + } +} + +static void oct5066_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + spin_lock(&oct5066_spin); + oct5066_page(map, adr); + writeb(d, iomapadr + (adr & WINDOW_MASK)); + spin_unlock(&oct5066_spin); +} + +static void oct5066_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + spin_lock(&oct5066_spin); + oct5066_page(map, adr); + writew(d, iomapadr + (adr & WINDOW_MASK)); + spin_unlock(&oct5066_spin); +} + +static void oct5066_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + spin_lock(&oct5066_spin); + oct5066_page(map, adr); + writel(d, iomapadr + (adr & WINDOW_MASK)); + spin_unlock(&oct5066_spin); +} + +static void oct5066_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + while(len) { + unsigned long thislen = len; + if (len > (WINDOW_LENGTH - (to & WINDOW_MASK))) + thislen = WINDOW_LENGTH-(to & WINDOW_MASK); + + spin_lock(&oct5066_spin); + oct5066_page(map, to); + memcpy_toio(iomapadr + to, from, thislen); + spin_unlock(&oct5066_spin); + to += thislen; + from += thislen; + len -= thislen; + } +} + +static struct map_info oct5066_map[2] = { + { + "Octagon 5066 Socket", + 512 * 1024, + 1, + oct5066_read8, + oct5066_read16, + oct5066_read32, + oct5066_copy_from, + oct5066_write8, + oct5066_write16, + oct5066_write32, + oct5066_copy_to, + 1<<6 + }, + { + "Octagon 5066 Internal Flash", + 2 * 1024 * 1024, + 1, + oct5066_read8, + oct5066_read16, + oct5066_read32, + oct5066_copy_from, + oct5066_write8, + oct5066_write16, + oct5066_write32, + oct5066_copy_to, + 2<<6 + } +}; + +static struct mtd_info *oct5066_mtd[2] = {NULL, NULL}; + +// OctProbe - Sense if this is an octagon card +// --------------------------------------------------------------------- +/* Perform a simple validity test, we map the window select SSD0 and + change pages while monitoring the window. A change in the window, + controlled by the PAGE_IO port is a functioning 5066 board. This will + fail if the thing in the socket is set to a uniform value. */ +static int __init OctProbe() +{ + unsigned int Base = (1 << 6); + unsigned long I; + unsigned long Values[10]; + for (I = 0; I != 20; I++) + { + outb(Base + (I%10),PAGE_IO); + if (I < 10) + { + // Record the value and check for uniqueness + Values[I%10] = readl(iomapadr); + if (I > 0 && Values[I%10] == Values[0]) + return -EAGAIN; + } + else + { + // Make sure we get the same values on the second pass + if (Values[I%10] != readl(iomapadr)) + return -EAGAIN; + } + } + return 0; +} + +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define init_oct5066 init_module +#define cleanup_oct5066 cleanup_module +#endif +#define __exit +#endif + +void cleanup_oct5066(void) +{ + int i; + for (i=0; i<2; i++) { + if (oct5066_mtd[i]) { + del_mtd_device(oct5066_mtd[i]); + map_destroy(oct5066_mtd[i]); + } + } + iounmap((void *)iomapadr); + release_region(PAGE_IO,1); +} + +int __init init_oct5066(void) +{ + int i; + + // Do an autoprobe sequence + if (check_region(PAGE_IO,1) != 0) + { + printk("5066: Page Register in Use\n"); + return -EAGAIN; + } + iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); + if (!iomapadr) { + printk("Failed to ioremap memory region\n"); + return -EIO; + } + if (OctProbe() != 0) + { + printk("5066: Octagon Probe Failed, is this an Octagon 5066 SBC?\n"); + iounmap((void *)iomapadr); + return -EAGAIN; + } + + request_region(PAGE_IO,1,"Octagon SSD"); + + // Print out our little header.. + printk("Octagon 5066 SSD IO:0x%x MEM:0x%x-0x%x\n",PAGE_IO,WINDOW_START, + WINDOW_START+WINDOW_LENGTH); + + for (i=0; i<2; i++) { + oct5066_mtd[i] = do_cfi_probe(&oct5066_map[i]); + if (!oct5066_mtd[i]) + oct5066_mtd[i] = do_jedec_probe(&oct5066_map[i]); + if (!oct5066_mtd[i]) + oct5066_mtd[i] = do_ram_probe(&oct5066_map[i]); + if (!oct5066_mtd[i]) + oct5066_mtd[i] = do_rom_probe(&oct5066_map[i]); + if (oct5066_mtd[i]) { + oct5066_mtd[i]->module = THIS_MODULE; + add_mtd_device(oct5066_mtd[i]); + } + } + + if (!oct5066_mtd[1] && !oct5066_mtd[2]) { + cleanup_oct5066(); + return -ENXIO; + } + + return 0; +} + +#if LINUX_VERSION_CODE > 0x20300 +module_init(init_oct5066); +module_exit(cleanup_oct5066); +#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/physmap.c linux/drivers/mtd/physmap.c --- v2.4.0-test2/linux/drivers/mtd/physmap.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/physmap.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,114 @@ +/* + * $Id: physmap.c,v 1.1 2000/07/04 08:58:10 dwmw2 Exp $ + * + * Normal mappings of chips in physical memory + */ + +#include +#include +#include +#include +#include +#include + + +#define WINDOW_ADDR 0x8000000 +#define WINDOW_SIZE 0x4000000 + +static struct mtd_info *mymtd; + +__u8 physmap_read8(struct map_info *map, unsigned long ofs) +{ + return readb(map->map_priv_1 + ofs); +} + +__u16 physmap_read16(struct map_info *map, unsigned long ofs) +{ + return readw(map->map_priv_1 + ofs); +} + +__u32 physmap_read32(struct map_info *map, unsigned long ofs) +{ + return readl(map->map_priv_1 + ofs); +} + +void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy_fromio(to, map->map_priv_1 + from, len); +} + +void physmap_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + writeb(d, map->map_priv_1 + adr); +} + +void physmap_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + writew(d, map->map_priv_1 + adr); +} + +void physmap_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + writel(d, map->map_priv_1 + adr); +} + +void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy_toio(map->map_priv_1 + to, from, len); +} + +struct map_info physmap_map = { + "Physically mapped flash", + WINDOW_SIZE, + 2, + physmap_read8, + physmap_read16, + physmap_read32, + physmap_copy_from, + physmap_write8, + physmap_write16, + physmap_write32, + physmap_copy_to, + 0, + 0 +}; + +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define init_physmap init_module +#define cleanup_physmap cleanup_module +#endif +#endif + +int __init init_physmap(void) +{ + printk(KERN_NOTICE "physmap flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); + physmap_map.map_priv_1 = (unsigned long)ioremap(WINDOW_SIZE, WINDOW_ADDR); + + if (!physmap_map.map_priv_1) { + printk("Failed to ioremap\n"); + return -EIO; + } + mymtd = do_cfi_probe(&physmap_map); + if (mymtd) { +#ifdef MODULE + mymtd->module = &__this_module; +#endif + add_mtd_device(mymtd); + return 0; + } + + return -ENXIO; +} + +static void __exit cleanup_physmap(void) +{ + if (mymtd) { + del_mtd_device(mymtd); + map_destroy(mymtd); + } + if (physmap_map.map_priv_1) { + iounmap((void *)physmap_map.map_priv_1); + physmap_map.map_priv_1 = 0; + } +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/pmc551.c linux/drivers/mtd/pmc551.c --- v2.4.0-test2/linux/drivers/mtd/pmc551.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/pmc551.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,689 @@ +/* + * $Id: pmc551.c,v 1.7 2000/07/03 10:01:38 dwmw2 Exp $ + * + * PMC551 PCI Mezzanine Ram Device + * + * Author: + * Mark Ferrell + * Copyright 1999,2000 Nortel Networks + * + * License: + * As part of this driver was derrived from the slram.c driver it falls + * under the same license, which is GNU General Public License v2 + * + * Description: + * This driver is intended to support the PMC551 PCI Ram device from + * Ramix Inc. The PMC551 is a PMC Mezzanine module for cPCI embeded + * systems. The device contains a single SROM that initally programs the + * V370PDC chipset onboard the device, and various banks of DRAM/SDRAM + * onboard. This driver implements this PCI Ram device as an MTD (Memory + * Technologies Device) so that it can be used to hold a filesystem, or + * for added swap space in embeded systems. Since the memory on this + * board isn't as fast as main memory we do not try to hook it into main + * memeory as that would simply reduce performance on the system. Using + * it as a block device allows us to use it as high speed swap or for a + * high speed disk device of some sort. Which becomes very usefull on + * diskless systems in the embeded market I might add. + * + * Credits: + * Saeed Karamooz of Ramix INC. for the initial + * example code of how to initialize this device and for help with + * questions I had concerning operation of the device. + * + * Most of the MTD code for this driver was originally written for the + * slram.o module in the MTD drivers package written by David Hinds + * which allows the mapping of system + * memory into an mtd device. Since the PMC551 memory module is + * accessed in the same fashion as system memory, the slram.c code + * became a very nice fit to the needs of this driver. All we added was + * PCI detection/initialization to the driver and automaticly figure out + * the size via the PCI detection.o, later changes by Corey Minyard + * settup the card to utilize a 1M sliding apature. + * + * Corey Minyard + * * Modified driver to utilize a sliding apature instead of mapping all + * memory into kernel space which turned out to be very wastefull. + * * Located a bug in the SROM's initialization sequence that made the + * memory unussable, added a fix to code to touch up the DRAM some. + * + * Bugs/FIXME's: + * * MUST fix the init function to not spin on a register + * waiting for it to set .. this does not safely handle busted devices + * that never reset the register correctly which will cause the system to + * hang w/ a reboot beeing the only chance at recover. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if LINUX_VERSION_CODE > 0x20300 +#define PCI_BASE_ADDRESS(dev) (dev->resource[0].start) +#else +#define PCI_BASE_ADDRESS(dev) (dev->base_address[0]) +#endif + +static struct mtd_info *pmc551list = NULL; + +static int pmc551_erase (struct mtd_info *mtd, struct erase_info *instr) +{ + struct mypriv *priv = mtd->priv; + u32 start_addr_highbits; + u32 end_addr_highbits; + u32 start_addr_lowbits; + u32 end_addr_lowbits; + unsigned long end; + + end = instr->addr + instr->len; + + /* Is it too much memory? The second check find if we wrap around + past the end of a u32. */ + if ((end > mtd->size) || (end < instr->addr)) { + return -EINVAL; + } + + start_addr_highbits = instr->addr & PMC551_ADDR_HIGH_MASK; + end_addr_highbits = end & PMC551_ADDR_HIGH_MASK; + start_addr_lowbits = instr->addr & PMC551_ADDR_LOW_MASK; + end_addr_lowbits = end & PMC551_ADDR_LOW_MASK; + + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + (priv->mem_map0_base_val + | start_addr_highbits)); + if (start_addr_highbits == end_addr_highbits) { + /* The whole thing fits within one access, so just one shot + will do it. */ + memset(priv->start + start_addr_lowbits, + 0xff, + instr->len); + } else { + /* We have to do multiple writes to get all the data + written. */ + memset(priv->start + start_addr_lowbits, + 0xff, + priv->aperture_size - start_addr_lowbits); + start_addr_highbits += priv->aperture_size; + while (start_addr_highbits != end_addr_highbits) { + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + (priv->mem_map0_base_val + | start_addr_highbits)); + memset(priv->start, + 0xff, + priv->aperture_size); + start_addr_highbits += priv->aperture_size; + } + priv->curr_mem_map0_val = (priv->mem_map0_base_val + | start_addr_highbits); + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + priv->curr_mem_map0_val); + memset(priv->start, + 0xff, + end_addr_lowbits); + } + + instr->state = MTD_ERASE_DONE; + + if (instr->callback) { + (*(instr->callback))(instr); + } + + return 0; +} + + +static void pmc551_unpoint (struct mtd_info *mtd, u_char *addr) +{} + + +static int pmc551_read (struct mtd_info *mtd, + loff_t from, + size_t len, + size_t *retlen, + u_char *buf) +{ + struct mypriv *priv = (struct mypriv *)mtd->priv; + u32 start_addr_highbits; + u32 end_addr_highbits; + u32 start_addr_lowbits; + u32 end_addr_lowbits; + unsigned long end; + u_char *copyto = buf; + + + /* Is it past the end? */ + if (from > mtd->size) { + return -EINVAL; + } + + end = from + len; + start_addr_highbits = from & PMC551_ADDR_HIGH_MASK; + end_addr_highbits = end & PMC551_ADDR_HIGH_MASK; + start_addr_lowbits = from & PMC551_ADDR_LOW_MASK; + end_addr_lowbits = end & PMC551_ADDR_LOW_MASK; + + + /* Only rewrite the first value if it doesn't match our current + values. Most operations are on the same page as the previous + value, so this is a pretty good optimization. */ + if (priv->curr_mem_map0_val != + (priv->mem_map0_base_val | start_addr_highbits)) { + priv->curr_mem_map0_val = (priv->mem_map0_base_val + | start_addr_highbits); + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + priv->curr_mem_map0_val); + } + + if (start_addr_highbits == end_addr_highbits) { + /* The whole thing fits within one access, so just one shot + will do it. */ + memcpy(copyto, + priv->start + start_addr_lowbits, + len); + copyto += len; + } else { + /* We have to do multiple writes to get all the data + written. */ + memcpy(copyto, + priv->start + start_addr_lowbits, + priv->aperture_size - start_addr_lowbits); + copyto += priv->aperture_size - start_addr_lowbits; + start_addr_highbits += priv->aperture_size; + while (start_addr_highbits != end_addr_highbits) { + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + (priv->mem_map0_base_val + | start_addr_highbits)); + memcpy(copyto, + priv->start, + priv->aperture_size); + copyto += priv->aperture_size; + start_addr_highbits += priv->aperture_size; + if (start_addr_highbits >= mtd->size) { + /* Make sure we have the right value here. */ + priv->curr_mem_map0_val + = (priv->mem_map0_base_val + | start_addr_highbits); + goto out; + } + } + priv->curr_mem_map0_val = (priv->mem_map0_base_val + | start_addr_highbits); + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + priv->curr_mem_map0_val); + memcpy(copyto, + priv->start, + end_addr_lowbits); + copyto += end_addr_lowbits; + } + +out: + *retlen = copyto - buf; + return 0; +} + +static int pmc551_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + struct mypriv *priv = (struct mypriv *)mtd->priv; + u32 start_addr_highbits; + u32 end_addr_highbits; + u32 start_addr_lowbits; + u32 end_addr_lowbits; + unsigned long end; + const u_char *copyfrom = buf; + + + /* Is it past the end? */ + if (to > mtd->size) { + return -EINVAL; + } + + end = to + len; + start_addr_highbits = to & PMC551_ADDR_HIGH_MASK; + end_addr_highbits = end & PMC551_ADDR_HIGH_MASK; + start_addr_lowbits = to & PMC551_ADDR_LOW_MASK; + end_addr_lowbits = end & PMC551_ADDR_LOW_MASK; + + + /* Only rewrite the first value if it doesn't match our current + values. Most operations are on the same page as the previous + value, so this is a pretty good optimization. */ + if (priv->curr_mem_map0_val != + (priv->mem_map0_base_val | start_addr_highbits)) { + priv->curr_mem_map0_val = (priv->mem_map0_base_val + | start_addr_highbits); + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + priv->curr_mem_map0_val); + } + + if (start_addr_highbits == end_addr_highbits) { + /* The whole thing fits within one access, so just one shot + will do it. */ + memcpy(priv->start + start_addr_lowbits, + copyfrom, + len); + copyfrom += len; + } else { + /* We have to do multiple writes to get all the data + written. */ + memcpy(priv->start + start_addr_lowbits, + copyfrom, + priv->aperture_size - start_addr_lowbits); + copyfrom += priv->aperture_size - start_addr_lowbits; + start_addr_highbits += priv->aperture_size; + while (start_addr_highbits != end_addr_highbits) { + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + (priv->mem_map0_base_val + | start_addr_highbits)); + memcpy(priv->start, + copyfrom, + priv->aperture_size); + copyfrom += priv->aperture_size; + start_addr_highbits += priv->aperture_size; + if (start_addr_highbits >= mtd->size) { + /* Make sure we have the right value here. */ + priv->curr_mem_map0_val + = (priv->mem_map0_base_val + | start_addr_highbits); + goto out; + } + } + priv->curr_mem_map0_val = (priv->mem_map0_base_val + | start_addr_highbits); + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + priv->curr_mem_map0_val); + memcpy(priv->start, + copyfrom, + end_addr_lowbits); + copyfrom += end_addr_lowbits; + } + +out: + *retlen = copyfrom - buf; + return 0; +} + +/* + * Fixup routines for the V370PDC + * PCI device ID 0x020011b0 + * + * This function basicly kick starts the DRAM oboard the card and gets it + * ready to be used. Before this is done the device reads VERY erratic, so + * much that it can crash the Linux 2.2.x series kernels when a user cat's + * /proc/pci .. though that is mainly a kernel bug in handling the PCI DEVSEL + * register. FIXME: stop spinning on registers .. must implement a timeout + * mechanism + * returns the size of the memory region found. + */ +static u32 fixup_pmc551 (struct pci_dev *dev) +{ +#ifdef PMC551_DRAM_BUG + u32 dram_data; +#endif + u32 size, dcmd; + u16 cmd, i; + + /* Sanity Check */ + if(!dev) { + return -ENODEV; + } + + /* + * Get the size of the memory by reading all the DRAM size values + * and adding them up. + * + * KLUDGE ALERT: the boards we are using have invalid column and + * row mux values. We fix them here, but this will break other + * memory configurations. + */ +#ifdef PMC551_DRAM_BUG + pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data); + size = PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data); + + pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data); + size += PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data); + + pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data); + size += PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data); + + pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data); + size += PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data); +#endif /* PMC551_DRAM_BUG */ + + /* + * Oops .. something went wrong + */ + if( (size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) { + return -ENODEV; + } + + /* + * Set to be prefetchable + */ + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &dcmd ); + dcmd |= 0x8; + + /* + * Put it back the way it was + */ + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dcmd ); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &dcmd ); + + /* + * Some screen fun + */ + printk(KERN_NOTICE "pmc551: %dM (0x%x) of %sprefetchable memory at 0x%lx\n", + size/1024/1024, size, ((dcmd&0x8) == 0)?"non-":"", + PCI_BASE_ADDRESS(dev)&PCI_BASE_ADDRESS_MEM_MASK ); + + /* + * Turn on PCI memory and I/O bus access just for kicks + */ + pci_write_config_word( dev, PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_IO ); + + /* + * Config DRAM + */ + pci_write_config_word( dev, PMC551_SDRAM_MA, 0x0400 ); + pci_write_config_word( dev, PMC551_SDRAM_CMD, 0x00bf ); + + /* + * Wait untill command has gone through + * FIXME: register spinning issue + */ + do { pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd ); + } while ( (PCI_COMMAND_IO) & cmd ); + + /* + * Must be held high for some duration of time to take effect?? + */ + for ( i = 1; i<=8 ; i++) { + pci_write_config_word (dev, PMC551_SDRAM_CMD, 0x0df); + + /* + * Make certain command has gone through + * FIXME: register spinning issue + */ + do { pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); + } while ( (PCI_COMMAND_IO) & cmd ); + } + + pci_write_config_word ( dev, PMC551_SDRAM_MA, 0x0020); + pci_write_config_word ( dev, PMC551_SDRAM_CMD, 0x0ff); + + /* + * Wait until command completes + * FIXME: register spinning issue + */ + do { pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd); + } while ( (PCI_COMMAND_IO) & cmd ); + + pci_read_config_dword ( dev, PMC551_DRAM_CFG, &dcmd); + dcmd |= 0x02000000; + pci_write_config_dword ( dev, PMC551_DRAM_CFG, dcmd); + + /* + * Check to make certain fast back-to-back, if not + * then set it so + */ + pci_read_config_word( dev, PCI_STATUS, &cmd); + if((cmd&PCI_COMMAND_FAST_BACK) == 0) { + cmd |= PCI_COMMAND_FAST_BACK; + pci_write_config_word( dev, PCI_STATUS, cmd); + } + + /* + * Check to make certain the DEVSEL is set correctly, this device + * has a tendancy to assert DEVSEL and TRDY when a write is performed + * to the memory when memory is read-only + */ + if((cmd&PCI_STATUS_DEVSEL_MASK) != 0x0) { + cmd &= ~PCI_STATUS_DEVSEL_MASK; + pci_write_config_word( dev, PCI_STATUS, cmd ); + } + + /* + * Check to see the state of the memory + * FIXME: perhaps hide some of this around an #ifdef DEBUG as + * it doesn't effect or enhance cards functionality + */ + pci_read_config_dword( dev, 0x74, &dcmd ); + printk(KERN_NOTICE "pmc551: DRAM_BLK3 Flags: %s,%s\n", + ((0x2&dcmd) == 0)?"RW":"RO", + ((0x1&dcmd) == 0)?"Off":"On" ); + + pci_read_config_dword( dev, 0x70, &dcmd ); + printk(KERN_NOTICE "pmc551: DRAM_BLK2 Flags: %s,%s\n", + ((0x2&dcmd) == 0)?"RW":"RO", + ((0x1&dcmd) == 0)?"Off":"On" ); + + pci_read_config_dword( dev, 0x6C, &dcmd ); + printk(KERN_NOTICE "pmc551: DRAM_BLK1 Flags: %s,%s\n", + ((0x2&dcmd) == 0)?"RW":"RO", + ((0x1&dcmd) == 0)?"Off":"On" ); + + pci_read_config_dword( dev, 0x68, &dcmd ); + printk(KERN_NOTICE "pmc551: DRAM_BLK0 Flags: %s,%s\n", + ((0x2&dcmd) == 0)?"RW":"RO", + ((0x1&dcmd) == 0)?"Off":"On" ); + + pci_read_config_word( dev, 0x4, &cmd ); + printk( KERN_NOTICE "pmc551: Memory Access %s\n", + ((0x2&cmd) == 0)?"off":"on" ); + printk( KERN_NOTICE "pmc551: I/O Access %s\n", + ((0x1&cmd) == 0)?"off":"on" ); + + pci_read_config_word( dev, 0x6, &cmd ); + printk( KERN_NOTICE "pmc551: Devsel %s\n", + ((PCI_STATUS_DEVSEL_MASK&cmd)==0x000)?"Fast": + ((PCI_STATUS_DEVSEL_MASK&cmd)==0x200)?"Medium": + ((PCI_STATUS_DEVSEL_MASK&cmd)==0x400)?"Slow":"Invalid" ); + + printk( KERN_NOTICE "pmc551: %sFast Back-to-Back\n", + ((PCI_COMMAND_FAST_BACK&cmd) == 0)?"Not ":"" ); + + return size; +} + +/* + * Kernel version specific module stuffages + */ +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define init_pmc551 init_module +#define cleanup_pmc551 cleanup_module +#endif +#define __exit +#endif + + +/* + * PMC551 Card Initialization + */ +//static int __init init_pmc551(void) +int __init init_pmc551(void) +{ + struct pci_dev *PCI_Device = NULL; + struct mypriv *priv; + int count, found=0; + struct mtd_info *mtd; + u32 length = 0; + + + printk(KERN_NOTICE "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n"); + printk(KERN_INFO "$Id: pmc551.c,v 1.7 2000/07/03 10:01:38 dwmw2 Exp $\n"); + + if(!pci_present()) { + printk(KERN_NOTICE "pmc551: PCI not enabled.\n"); + return -ENODEV; + } + + /* + * PCU-bus chipset probe. + */ + for( count = 0; count < MAX_MTD_DEVICES; count++ ) { + + if ( (PCI_Device = pci_find_device( PCI_VENDOR_ID_V3_SEMI, + PCI_DEVICE_ID_V3_SEMI_V370PDC, PCI_Device ) ) == NULL) { + break; + } + + printk(KERN_NOTICE "pmc551: Found PCI V370PDC IRQ:%d\n", + PCI_Device->irq); + + /* + * The PMC551 device acts VERY wierd if you don't init it + * first. i.e. it will not correctly report devsel. If for + * some reason the sdram is in a wrote-protected state the + * device will DEVSEL when it is written to causing problems + * with the oldproc.c driver in + * some kernels (2.2.*) + */ + if((length = fixup_pmc551(PCI_Device)) <= 0) { + printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n"); + break; + } + + mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); + if (!mtd) { + printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n"); + break; + } + + memset(mtd, 0, sizeof(struct mtd_info)); + + priv = kmalloc (sizeof(struct mypriv), GFP_KERNEL); + if (!priv) { + printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n"); + kfree(mtd); + break; + } + memset(priv, 0, sizeof(*priv)); + mtd->priv = priv; + + priv->dev = PCI_Device; + priv->aperture_size = PMC551_APERTURE_SIZE; + priv->start = ioremap((PCI_BASE_ADDRESS(PCI_Device) + & PCI_BASE_ADDRESS_MEM_MASK), + priv->aperture_size); + priv->mem_map0_base_val = (PMC551_APERTURE_VAL + | PMC551_PCI_MEM_MAP_REG_EN + | PMC551_PCI_MEM_MAP_ENABLE); + priv->curr_mem_map0_val = priv->mem_map0_base_val; + + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + priv->curr_mem_map0_val); + + mtd->size = length; + mtd->flags = (MTD_CLEAR_BITS + | MTD_SET_BITS + | MTD_WRITEB_WRITEABLE + | MTD_VOLATILE); + mtd->erase = pmc551_erase; + mtd->point = NULL; + mtd->unpoint = pmc551_unpoint; + mtd->read = pmc551_read; + mtd->write = pmc551_write; + mtd->module = THIS_MODULE; + mtd->type = MTD_RAM; + mtd->name = "PMC551 RAM board"; + mtd->erasesize = 0x10000; + + if (add_mtd_device(mtd)) { + printk(KERN_NOTICE "pmc551: Failed to register new device\n"); + kfree(mtd->priv); + kfree(mtd); + break; + } + printk(KERN_NOTICE "Registered pmc551 memory device.\n"); + printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n", + priv->aperture_size/1024/1024, + priv->start, + priv->start + priv->aperture_size); + printk(KERN_NOTICE "Total memory is %dM\n", length/1024/1024); + priv->nextpmc551 = pmc551list; + pmc551list = mtd; + found++; + } + + if( !pmc551list ) { + printk(KERN_NOTICE "pmc551: not detected,\n"); + return -ENODEV; + } else { + return 0; + printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found); + } +} + +/* + * PMC551 Card Cleanup + */ +static void __exit cleanup_pmc551(void) +{ + int found=0; + struct mtd_info *mtd; + struct mypriv *priv; + + while((mtd=pmc551list)) { + priv = (struct mypriv *)mtd->priv; + pmc551list = priv->nextpmc551; + + if(priv->start) + iounmap(((struct mypriv *)mtd->priv)->start); + + kfree (mtd->priv); + del_mtd_device(mtd); + kfree(mtd); + found++; + } + + printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found); +} + +#if LINUX_VERSION_CODE > 0x20300 +module_init(init_pmc551); +module_exit(cleanup_pmc551); +#endif + + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/rpxlite.c linux/drivers/mtd/rpxlite.c --- v2.4.0-test2/linux/drivers/mtd/rpxlite.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/rpxlite.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,160 @@ +/* + * $Id: rpxlite.c,v 1.2 2000/07/04 12:16:26 dwmw2 Exp $ + * + * Handle the strange 16-in-32-bit mapping on the RPXLite board + */ + +#include +#include +#include +#include +#include +#include + + +#define WINDOW_ADDR 0x8000000 +#define WINDOW_SIZE 0x2000000 + +#define MAP_TO_ADR(x) ( ( ( x & ~1 ) << 1 ) | (x&1) ) + +static struct mtd_info *mymtd; + +__u8 rpxlite_read8(struct map_info *map, unsigned long ofs) +{ + return readb(map->map_priv_1 + MAP_TO_ADR(ofs)); +} + +__u16 rpxlite_read16(struct map_info *map, unsigned long ofs) +{ + return readw(map->map_priv_1 + MAP_TO_ADR(ofs)); +} + +__u32 rpxlite_read32(struct map_info *map, unsigned long ofs) +{ + return readl(map->map_priv_1 + MAP_TO_ADR(ofs)); +} + +void rpxlite_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + if (from & 1) { + *(__u8 *)to = readb(map->map_priv_1 + MAP_TO_ADR(from)); + from++; + len--; + } + /* Can't do this if it's not aligned */ + if (!((unsigned long)to & 1)) { + unsigned long fromadr = MAP_TO_ADR(from); + + while (len > 1) { + *(__u16 *)to = readw(map->map_priv_1 + fromadr); + to += 2; + fromadr += 4; + from += 2; + len -= 2; + } + } + while(len) { + *(__u8 *)to = readb(map->map_priv_1 + MAP_TO_ADR(from)); + to++; + from++; + len--; + } +} + +void rpxlite_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + writeb(d, map->map_priv_1 + MAP_TO_ADR(adr)); +} + +void rpxlite_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + writew(d, map->map_priv_1 + MAP_TO_ADR(adr)); +} + +void rpxlite_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + writel(d, map->map_priv_1 + MAP_TO_ADR(adr)); +} + +void rpxlite_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + if (to & 1) { + writeb(*(__u8 *)from, map->map_priv_1 + MAP_TO_ADR(to)); + from++; + len--; + } + /* Can't do this if it's not aligned */ + if (!((unsigned long)from & 1)) { + unsigned long toadr = map->map_priv_1 + MAP_TO_ADR(to); + + while (len > 1) { + writew(*(__u16 *)from, toadr); + from += 2; + toadr += 4; + to += 2; + len -= 2; + } + } + while(len) { + writeb(*(__u8 *)from, map->map_priv_1 + MAP_TO_ADR(to)); + to++; + from++; + len--; + } +} + +struct map_info rpxlite_map = { + "RPXLITE", + WINDOW_SIZE, + 2, + rpxlite_read8, + rpxlite_read16, + rpxlite_read32, + rpxlite_copy_from, + rpxlite_write8, + rpxlite_write16, + rpxlite_write32, + rpxlite_copy_to, + 0, + 0 +}; + +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define init_rpxlite init_module +#define cleanup_rpxlite cleanup_module +#endif +#endif + +int __init init_rpxlite(void) +{ + printk(KERN_NOTICE "rpxlite flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); + rpxlite_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 2); + + if (!rpxlite_map.map_priv_1) { + printk("Failed to ioremap\n"); + return -EIO; + } + mymtd = do_cfi_probe(&rpxlite_map); + if (mymtd) { +#ifdef MODULE + mymtd->module = &__this_module; +#endif + add_mtd_device(mymtd); + return 0; + } + + return -ENXIO; +} + +static void __exit cleanup_rpxlite(void) +{ + if (mymtd) { + del_mtd_device(mymtd); + map_destroy(mymtd); + } + if (rpxlite_map.map_priv_1) { + iounmap((void *)rpxlite_map.map_priv_1); + rpxlite_map.map_priv_1 = 0; + } +} diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/slram.c linux/drivers/mtd/slram.c --- v2.4.0-test2/linux/drivers/mtd/slram.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/slram.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,226 @@ +/*====================================================================== + + $Id: slram.c,v 1.10 2000/07/03 10:01:38 dwmw2 Exp $ + +======================================================================*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct mypriv { + u_char *start; + u_char *end; +}; + +int physmem_erase (struct mtd_info *mtd, struct erase_info *instr); +int physmem_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf); +void physmem_unpoint (struct mtd_info *mtd, u_char *addr); +int physmem_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); +int physmem_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); + + +int physmem_erase (struct mtd_info *mtd, struct erase_info *instr) +{ + struct mypriv *priv = mtd->priv; + + if (instr->addr + instr->len > mtd->size) + return -EINVAL; + + memset(priv->start + instr->addr, 0xff, instr->len); + + /* This'll catch a few races. Free the thing before returning :) + * I don't feel at all ashamed. This kind of thing is possible anyway + * with flash, but unlikely. + */ + + instr->state = MTD_ERASE_DONE; + + if (instr->callback) + (*(instr->callback))(instr); + else + kfree(instr); + + return 0; +} + + +int physmem_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) +{ + struct mypriv *priv = (struct mypriv *)mtd->priv; + + *mtdbuf = priv->start + from; + *retlen = len; + return 0; +} + +void physmem_unpoint (struct mtd_info *mtd, u_char *addr) +{ +} + +int physmem_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + struct mypriv *priv = (struct mypriv *)mtd->priv; + + memcpy (buf, priv->start + from, len); + + *retlen=len; + return 0; +} + +int physmem_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + struct mypriv *priv = (struct mypriv *)mtd->priv; + + memcpy (priv->start + to, buf, len); + + *retlen=len; + return 0; +} + + + + +/*====================================================================*/ + +/* Place your defaults here */ + +static u_long start = 100663296; +static u_long length = 33554432; +static u_long end = 0; + +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define init_slram init_module +#define cleanup_slram cleanup_module +#endif +#define __exit +#endif + +#ifdef MODULE +MODULE_PARM(start,"l"); +MODULE_PARM(length,"l"); +MODULE_PARM(end,"l"); +#endif + +struct mtd_info *mymtd; + +void __init mtd_slram_setup(char *str, int *ints) +{ + if (ints[0] > 0) + start=ints[1]; + if (ints[0] > 1) + length=ints[2]; +} + +int init_slram(void) +{ + if (!start) + { + printk(KERN_NOTICE "physmem: No start address for memory device.\n"); + return -EINVAL; + } + + if (!length && !end) + { + printk(KERN_NOTICE "physmem: No length or endpointer given.\n"); + return -EINVAL; + } + + if (!end) + end = start + length; + + if (!length) + length = end - start; + + if (start + length != end) + { + printk(KERN_NOTICE "physmem: start(%lx) + length(%lx) != end(%lx) !\n", + start, length, end); + return -EINVAL; + } + + mymtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); + + memset(mymtd, 0, sizeof(*mymtd)); + + if (mymtd) + { + memset((char *)mymtd, 0, sizeof(struct mtd_info)); + mymtd->priv = (void *) kmalloc (sizeof(struct mypriv), GFP_KERNEL); + if (!mymtd->priv) + { + kfree(mymtd); + mymtd = NULL; + } + memset(mymtd->priv, 0, sizeof(struct mypriv)); + } + + if (!mymtd) + { + printk(KERN_NOTICE "physmem: Cannot allocate new MTD device.\n"); + return -ENOMEM; + } + + + ((struct mypriv *)mymtd->priv)->start = ioremap(start, length); + ((struct mypriv *)mymtd->priv)->end = ((struct mypriv *)mymtd->priv)->start + length; + + + mymtd->name = "Raw memory"; + + mymtd->size = length; + mymtd->flags = MTD_CLEAR_BITS | MTD_SET_BITS | MTD_WRITEB_WRITEABLE | MTD_VOLATILE; + mymtd->erase = physmem_erase; + mymtd->point = physmem_point; + mymtd->unpoint = physmem_unpoint; + mymtd->read = physmem_read; + mymtd->write = physmem_write; + mymtd->module = THIS_MODULE; + mymtd->type = MTD_RAM; + mymtd->erasesize = 0x10000; + + if (add_mtd_device(mymtd)) + { + printk("Failed to register new device\n"); + kfree(mymtd->priv); + kfree(mymtd); + return -EAGAIN; + } + printk("Registered physmem device from %dKb to %dKb\n", + (int)(start / 1024), (int)(end / 1024)); + printk("Mapped from 0x%p to 0x%p\n",((struct mypriv *)mymtd->priv)->start, +((struct mypriv *)mymtd->priv)->end); + + return 0; +} + +static void __exit cleanup_slram(void) +{ + iounmap(((struct mypriv *)mymtd->priv)->start); + kfree (mymtd->priv); + del_mtd_device(mymtd); + kfree(mymtd); +} + +#if LINUX_VERSION_CODE > 0x20300 +module_init(init_slram); +module_exit(cleanup_slram); +#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/mtd/vmax301.c linux/drivers/mtd/vmax301.c --- v2.4.0-test2/linux/drivers/mtd/vmax301.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/vmax301.c Tue Jul 4 10:10:05 2000 @@ -0,0 +1,243 @@ +// $Id: vmax301.c,v 1.13 2000/07/03 10:01:38 dwmw2 Exp $ +/* ###################################################################### + + Tempustech VMAX SBC301 MTD Driver. + + The VMAx 301 is a SBC based on . It + comes with three builtin AMD 29F016B flash chips and a socket for SRAM or + more flash. Each unit has it's own 8k mapping into a settable region + (0xD8000). There are two 8k mappings for each MTD, the first is always set + to the lower 8k of the device the second is paged. Writing a 16 bit page + value to anywhere in the first 8k will cause the second 8k to page around. + + To boot the device a bios extension must be installed into the first 8k + of flash that is smart enough to copy itself down, page in the rest of + itself and begin executing. + + ##################################################################### */ + +#include +#include +#include +#include +#include +#include + +#include + + +#define WINDOW_START 0xd8000 +#define WINDOW_LENGTH 0x2000 +#define WINDOW_SHIFT 25 +#define WINDOW_MASK 0x1FFF + +/* Actually we could use two spinlocks, but we'd have to have + more private space in the struct map_info. We lose a little + performance like this, but we'd probably lose more by having + the extra indirection from having one of the map->map_priv + fields pointing to yet another private struct. +*/ +static spinlock_t vmax301_spin = SPIN_LOCK_UNLOCKED; + +static void __vmax301_page(struct map_info *map, unsigned long page) +{ + writew(page, map->map_priv_2 - WINDOW_LENGTH); + map->map_priv_1 = page; +} + +static inline void vmax301_page(struct map_info *map, + unsigned long ofs) +{ + unsigned long page = (ofs >> WINDOW_SHIFT); + if (map->map_priv_1 != page) + __vmax301_page(map, page); +} + +static __u8 vmax301_read8(struct map_info *map, unsigned long ofs) +{ + __u8 ret; + spin_lock(&vmax301_spin); + vmax301_page(map, ofs); + ret = readb(map->map_priv_2 + (ofs & WINDOW_MASK)); + spin_unlock(&vmax301_spin); + return ret; +} + +static __u16 vmax301_read16(struct map_info *map, unsigned long ofs) +{ + __u16 ret; + spin_lock(&vmax301_spin); + vmax301_page(map, ofs); + ret = readw(map->map_priv_2 + (ofs & WINDOW_MASK)); + spin_unlock(&vmax301_spin); + return ret; +} + +static __u32 vmax301_read32(struct map_info *map, unsigned long ofs) +{ + __u32 ret; + spin_lock(&vmax301_spin); + vmax301_page(map, ofs); + ret = readl(map->map_priv_2 + (ofs & WINDOW_MASK)); + spin_unlock(&vmax301_spin); + return ret; +} + +static void vmax301_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + while(len) { + unsigned long thislen = len; + if (len > (WINDOW_LENGTH - (from & WINDOW_MASK))) + thislen = WINDOW_LENGTH-(from & WINDOW_MASK); + spin_lock(&vmax301_spin); + vmax301_page(map, from); + memcpy_fromio(to, map->map_priv_2 + from, thislen); + spin_unlock(&vmax301_spin); + to += thislen; + from += thislen; + len -= thislen; + } +} + +static void vmax301_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + spin_lock(&vmax301_spin); + vmax301_page(map, adr); + writeb(d, map->map_priv_2 + (adr & WINDOW_MASK)); + spin_unlock(&vmax301_spin); +} + +static void vmax301_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + spin_lock(&vmax301_spin); + vmax301_page(map, adr); + writew(d, map->map_priv_2 + (adr & WINDOW_MASK)); + spin_unlock(&vmax301_spin); +} + +static void vmax301_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + spin_lock(&vmax301_spin); + vmax301_page(map, adr); + writel(d, map->map_priv_2 + (adr & WINDOW_MASK)); + spin_unlock(&vmax301_spin); +} + +static void vmax301_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + while(len) { + unsigned long thislen = len; + if (len > (WINDOW_LENGTH - (to & WINDOW_MASK))) + thislen = WINDOW_LENGTH-(to & WINDOW_MASK); + + spin_lock(&vmax301_spin); + vmax301_page(map, to); + memcpy_toio(map->map_priv_2 + to, from, thislen); + spin_unlock(&vmax301_spin); + to += thislen; + from += thislen; + len -= thislen; + } +} + +static struct map_info vmax_map[2] = { + { + "VMAX301 Internal Flash", + 3*2*1024*1024, + 1, + vmax301_read8, + vmax301_read16, + vmax301_read32, + vmax301_copy_from, + vmax301_write8, + vmax301_write16, + vmax301_write32, + vmax301_copy_to, + WINDOW_START + WINDOW_LENGTH, + 0xFFFFFFFF + }, + { + "VMAX301 Socket", + 0, + 1, + vmax301_read8, + vmax301_read16, + vmax301_read32, + vmax301_copy_from, + vmax301_write8, + vmax301_write16, + vmax301_write32, + vmax301_copy_to, + WINDOW_START + (3*WINDOW_LENGTH), + 0xFFFFFFFF + } +}; + +static struct mtd_info *vmax_mtd[2] = {NULL, NULL}; + +#if LINUX_VERSION_CODE < 0x20300 +#ifdef MODULE +#define init_vmax301 init_module +#define cleanup_vmax301 cleanup_module +#endif +#define __exit +#endif + +static void __exit cleanup_vmax301(void) +{ + int i; + + for (i=0; i<2; i++) { + if (vmax_mtd[i]) { + del_mtd_device(vmax_mtd[i]); + map_destroy(vmax_mtd[i]); + } + } + iounmap((void *)vmax_map[0].map_priv_1 - WINDOW_START); +} + +int __init init_vmax301(void) +{ + int i; + unsigned long iomapadr; + // Print out our little header.. + printk("Tempustech VMAX 301 MEM:0x%x-0x%x\n",WINDOW_START, + WINDOW_START+4*WINDOW_LENGTH); + + iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH*4); + if (!iomapadr) { + printk("Failed to ioremap memory region\n"); + return -EIO; + } + /* Put the address in the map's private data area. + We store the actual MTD IO address rather than the + address of the first half, because it's used more + often. + */ + vmax_map[0].map_priv_1 = iomapadr + WINDOW_START; + vmax_map[1].map_priv_1 = iomapadr + (3*WINDOW_START); + + for (i=0; i<2; i++) { + vmax_mtd[i] = do_cfi_probe(&vmax_map[i]); + if (!vmax_mtd[i]) + vmax_mtd[i] = do_jedec_probe(&vmax_map[i]); + if (!vmax_mtd[i]) + vmax_mtd[i] = do_ram_probe(&vmax_map[i]); + if (!vmax_mtd[i]) + vmax_mtd[i] = do_rom_probe(&vmax_map[i]); + if (vmax_mtd[i]) { + vmax_mtd[i]->module = THIS_MODULE; + add_mtd_device(vmax_mtd[i]); + } + } + + if (!vmax_mtd[1] && !vmax_mtd[2]) + return -ENXIO; + + return 0; +} + +#if LINUX_VERSION_CODE > 0x20300 +module_init(init_vmax301); +module_exit(cleanup_vmax301); +#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/3c509.c linux/drivers/net/3c509.c --- v2.4.0-test2/linux/drivers/net/3c509.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/net/3c509.c Fri Jul 7 15:55:24 2000 @@ -187,7 +187,7 @@ {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} }; #endif /* CONFIG_ISAPNP */ -#if defined(__ISAPNP__) || defined(MODULE) +#ifdef __ISAPNP__ static int nopnp = 0; #endif @@ -984,7 +984,9 @@ MODULE_PARM(irq,"1-8i"); MODULE_PARM(xcvr,"1-8i"); MODULE_PARM(max_interrupt_work, "i"); +#ifdef __ISAPNP__ MODULE_PARM(nopnp, "i"); +#endif int init_module(void) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/3c515.c linux/drivers/net/3c515.c --- v2.4.0-test2/linux/drivers/net/3c515.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/3c515.c Fri Jul 7 15:55:24 2000 @@ -363,8 +363,9 @@ int corkscrew_isapnp_phys_addr[3] = { 0, 0, 0 }; -#endif + static int nopnp = 0; +#endif static int corkscrew_scan(struct net_device *dev); static struct net_device *corkscrew_found_device(struct net_device *dev, @@ -439,9 +440,11 @@ static int corkscrew_scan(struct net_device *dev) { int cards_found = 0; - short i; static int ioaddr; +#ifdef __ISAPNP__ + short i; static int pnp_cards = 0; +#endif #ifdef __ISAPNP__ if(nopnp == 1) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c --- v2.4.0-test2/linux/drivers/net/3c59x.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/3c59x.c Wed Jul 5 22:15:27 2000 @@ -959,11 +959,11 @@ #endif if (pdev && vci->drv_flags & HAS_CB_FNS) { - u32 fn_st_addr; /* Cardbus function status space */ + unsigned long fn_st_addr; /* Cardbus function status space */ fn_st_addr = pci_resource_start (pdev, 2); if (fn_st_addr) vp->cb_fn_base = ioremap(fn_st_addr, 128); - printk(KERN_INFO "%s: CardBus functions mapped %8.8x->%p\n", + printk(KERN_INFO "%s: CardBus functions mapped %8.8lx->%p\n", dev->name, fn_st_addr, vp->cb_fn_base); #if 1 /* AKPM: the 575_cb and 905B LEDs seem OK without this */ if (vortex_pci_tbl[chip_idx].device != 0x5257) { @@ -1452,7 +1452,6 @@ mod_timer(&vp->timer, RUN_AT(next_tick)); if (vp->deferred) outw(FakeIntr, ioaddr + EL3_CMD); - timer_exit(&vp->timer); return; } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/8139too.c linux/drivers/net/8139too.c --- v2.4.0-test2/linux/drivers/net/8139too.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/8139too.c Wed Jul 5 22:15:27 2000 @@ -1332,7 +1332,6 @@ { struct net_device *dev = (struct net_device *) data; struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; - void *ioaddr = tp->mmio_addr; int next_tick = 60 * HZ; int mii_reg5; @@ -1342,6 +1341,7 @@ #if 0 if (!tp->duplex_lock && mii_reg5 != 0xffff) { + void *ioaddr = tp->mmio_addr; int duplex = (mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040; if (tp->full_duplex != duplex) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/8390.c linux/drivers/net/8390.c --- v2.4.0-test2/linux/drivers/net/8390.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/8390.c Mon Jun 26 18:06:55 2000 @@ -1144,13 +1144,13 @@ outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD); } -#ifdef MODULE - EXPORT_SYMBOL(ei_open); EXPORT_SYMBOL(ei_close); EXPORT_SYMBOL(ei_interrupt); EXPORT_SYMBOL(ethdev_init); EXPORT_SYMBOL(NS8390_init); + +#if defined(MODULE) int init_module(void) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.4.0-test2/linux/drivers/net/Config.in Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/Config.in Thu Jun 29 10:14:00 2000 @@ -81,9 +81,7 @@ fi tristate ' SMC Ultra support' CONFIG_ULTRA tristate ' SMC Ultra32 EISA support' CONFIG_ULTRA32 - if [ "$CONFIG_OBSOLETE" = "y" ]; then - tristate ' SMC 9194 support' CONFIG_SMC9194 - fi + tristate ' SMC 9194 support' CONFIG_SMC9194 fi bool ' Racal-Interlan (Micom) NI cards' CONFIG_NET_VENDOR_RACAL if [ "$CONFIG_NET_VENDOR_RACAL" = "y" ]; then @@ -116,7 +114,7 @@ if [ "$CONFIG_OBSOLETE" = "y" ]; then tristate ' SEEQ8005 support (EXPERIMENTAL)' CONFIG_SEEQ8005 fi - bool ' SK_G16 support' CONFIG_SK_G16 + tristate ' SK_G16 support' CONFIG_SK_G16 fi if [ "$CONFIG_MCA" = "y" ]; then tristate ' SKnet MCA support' CONFIG_SKMC diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v2.4.0-test2/linux/drivers/net/Space.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/Space.c Sun Jul 9 22:21:41 2000 @@ -79,7 +79,6 @@ extern int ni52_probe(struct net_device *); extern int ni65_probe(struct net_device *); extern int sonic_probe(struct net_device *); -extern int ioc3_probe(struct net_device *); extern int SK_init(struct net_device *); extern int seeq8005_probe(struct net_device *); extern int smc_init( struct net_device * ); @@ -95,7 +94,6 @@ extern int ethertap_probe(struct net_device *dev); extern int hplance_probe(struct net_device *dev); extern int bagetlance_probe(struct net_device *); -extern int dec_lance_probe(struct net_device *); extern int mvme147lance_probe(struct net_device *dev); extern int tc515_probe(struct net_device *dev); extern int lance_probe(struct net_device *dev); @@ -113,7 +111,6 @@ extern int de620_probe(struct net_device *); /* FDDI adapters */ -extern int dfx_probe(void); extern int apfddi_init(struct net_device *dev); extern int skfp_probe(struct net_device *dev); @@ -179,9 +176,6 @@ #ifdef CONFIG_NE3210 {ne3210_probe, 0}, #endif -#ifdef CONFIG_DEFXX - {dfx_probe, 0}, -#endif {NULL, 0}, }; @@ -376,12 +370,6 @@ struct devprobe mips_probes[] __initdata = { #ifdef CONFIG_MIPS_JAZZ_SONIC {sonic_probe, 0}, -#endif -#ifdef CONFIG_SGI_IOC3_ETH - {ioc3_probe, 0}, -#endif -#ifdef CONFIG_DECLANCE /* DECstation on-board controller */ - {dec_lance_probe, 0}, /* and maybe TURBOchannel option boards */ #endif #ifdef CONFIG_BAGETLANCE /* Lance-based Baget ethernet boards */ {bagetlance_probe, 0}, diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/acenic_firmware.h linux/drivers/net/acenic_firmware.h --- v2.4.0-test2/linux/drivers/net/acenic_firmware.h Fri May 12 14:18:55 2000 +++ linux/drivers/net/acenic_firmware.h Thu Jul 6 19:27:48 2000 @@ -17,9 +17,6 @@ #define tigonFwSbssLen 0x38 #define tigonFwBssAddr 0x00015dd0 #define tigonFwBssLen 0x2080 -u32 tigonFwText[]; -u32 tigonFwData[]; -u32 tigonFwRodata[]; #ifndef CONFIG_ACENIC_OMIT_TIGON_I /* Generated by genfw.c */ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { @@ -4595,6 +4592,10 @@ 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x30001, 0x1, 0x30201, 0x0, 0x0, 0x0 }; +#else +#define tigonFwText NULL +#define tigonFwData NULL +#define tigonFwRodata NULL #endif /* Generated by genfw.c */ #define tigon2FwReleaseMajor 0xc diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/am79c961a.h linux/drivers/net/am79c961a.h --- v2.4.0-test2/linux/drivers/net/am79c961a.h Wed Apr 26 16:34:07 2000 +++ linux/drivers/net/am79c961a.h Mon Jun 26 12:04:42 2000 @@ -73,7 +73,8 @@ #define MODE_COLL 0x0010 #define MODE_DRETRY 0x0020 #define MODE_INTLOOP 0x0040 -#define MODE_PORT0 0x0080 +#define MODE_PORT_AUI 0x0000 +#define MODE_PORT_10BT 0x0080 #define MODE_DRXPA 0x2000 #define MODE_DRXBA 0x4000 #define MODE_PROMISC 0x8000 @@ -105,6 +106,7 @@ #define TST_LCAR 0x0800 #define TST_LCOL 0x1000 #define TST_UFLO 0x4000 +#define TST_BUFF 0x8000 struct dev_priv { struct enet_statistics stats; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/appletalk/ltpc.c linux/drivers/net/appletalk/ltpc.c --- v2.4.0-test2/linux/drivers/net/appletalk/ltpc.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/appletalk/ltpc.c Wed Jul 5 10:56:13 2000 @@ -1239,6 +1239,7 @@ return 0; } +#ifndef MODULE /* handles "ltpc=io,irq,dma" kernel command lines */ static int __init ltpc_setup(char *str) { @@ -1270,6 +1271,12 @@ } __setup("ltpc=", ltpc_setup); +#endif /* MODULE */ + +MODULE_PARM(debug, "i"); +MODULE_PARM(io, "i"); +MODULE_PARM(irq, "i"); +MODULE_PARM(dma, "i"); #ifdef MODULE @@ -1279,12 +1286,7 @@ 0x0, 0, 0, 0, 0, NULL, ltpc_probe }; -MODULE_PARM(debug, "i"); -MODULE_PARM(io, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(dma, "i"); - -int init_module(void) +int __init init_module(void) { int err, result; @@ -1306,8 +1308,9 @@ return 0; } } +#endif -void cleanup_module(void) +static void __exit ltpc_cleanup(void) { long timeout; @@ -1360,5 +1363,5 @@ if(debug&DEBUG_VERBOSE) printk("returning from cleanup_module\n"); } -#endif /* MODULE */ +module_exit(ltpc_cleanup); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/arcnet/arcnet.c linux/drivers/net/arcnet/arcnet.c --- v2.4.0-test2/linux/drivers/net/arcnet/arcnet.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/arcnet/arcnet.c Thu Jun 29 11:11:22 2000 @@ -672,21 +672,20 @@ unsigned long flags; struct arcnet_local *lp = (struct arcnet_local *) dev->priv; int status = ASTATUS(); + char *msg; save_flags(flags); cli(); if (status & TXFREEflag) { /* transmit _DID_ finish */ - BUGMSG(D_NORMAL, "tx timeout - missed IRQ? (status=%Xh, mask=%Xh, dest=%02Xh)\n", - status, lp->intmask, lp->lasttrans_dest); - lp->stats.tx_errors++; + msg = " - missed IRQ?"; } else { - BUGMSG(D_EXTRA, "tx timed out (status=%Xh, intmask=%Xh, dest=%02Xh)\n", - status, lp->intmask, lp->lasttrans_dest); - lp->stats.tx_errors++; + msg = ""; lp->stats.tx_aborted_errors++; + lp->timed_out = 1; ACOMMAND(NOTXcmd | (lp->cur_tx << 3)); } + lp->stats.tx_errors++; /* make sure we didn't miss a TX IRQ */ AINTMASK(0); @@ -694,6 +693,12 @@ AINTMASK(lp->intmask); restore_flags(flags); + + if (jiffies - lp->last_timeout > 10*HZ) { + BUGMSG(D_EXTRA, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n", + msg, status, lp->intmask, lp->lasttrans_dest); + lp->last_timeout = jiffies; + } } @@ -778,12 +783,12 @@ didsomething++; } /* a transmit finished, and we're interested in it. */ - if (status & lp->intmask & TXFREEflag) { + if ((status & lp->intmask & TXFREEflag) || lp->timed_out) { lp->intmask &= ~TXFREEflag; BUGMSG(D_DURING, "TX IRQ (stat=%Xh)\n", status); - if (lp->cur_tx != -1 && !(status & TXACKflag)) { + if (lp->cur_tx != -1 && !(status & TXACKflag) && !lp->timed_out) { if (lp->lasttrans_dest != 0) { BUGMSG(D_EXTRA, "transmit was not acknowledged! " "(status=%Xh, dest=%02Xh)\n", @@ -801,6 +806,7 @@ release_arcbuf(dev, lp->cur_tx); lp->cur_tx = -1; + lp->timed_out = 0; didsomething++; /* send another packet if there is one */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/arcnet/com90xx.c linux/drivers/net/arcnet/com90xx.c --- v2.4.0-test2/linux/drivers/net/arcnet/com90xx.c Tue May 23 15:31:35 2000 +++ linux/drivers/net/arcnet/com90xx.c Thu Jun 29 11:11:22 2000 @@ -562,7 +562,8 @@ /* verify that the ARCnet signature byte is present */ if (readb(lp->mem_start) != TESTvalue) { - BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); + if (really_reset) + BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); return 1; } /* enable extended (512-byte) packets */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/atp.c linux/drivers/net/atp.c --- v2.4.0-test2/linux/drivers/net/atp.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/atp.c Wed Jul 5 10:56:12 2000 @@ -125,7 +125,7 @@ #include static void atp_timed_checker(unsigned long ignored); static struct net_device *atp_timed_dev; -static struct timer_list atp_timer = {NULL, NULL, 0, 0, atp_timed_checker}; +static struct timer_list atp_timer = { function: atp_timed_checker }; #endif /* Index to functions, as function prototypes. */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/bonding.c linux/drivers/net/bonding.c --- v2.4.0-test2/linux/drivers/net/bonding.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/bonding.c Wed Jul 5 22:15:27 2000 @@ -126,8 +126,6 @@ slave->dev->flags = master->flags; slave->dev->set_multicast_list(slave->dev); } - - return 0; } static int bond_enslave(struct net_device *master, struct net_device *dev) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c --- v2.4.0-test2/linux/drivers/net/cs89x0.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/cs89x0.c Wed Jul 5 11:54:11 2000 @@ -1558,7 +1558,10 @@ #if DEBUGGING net_debug = debug; +#else + debug = 0; #endif + dev_cs89x0.irq = irq; dev_cs89x0.base_addr = io; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/defxx.c linux/drivers/net/defxx.c --- v2.4.0-test2/linux/drivers/net/defxx.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/defxx.c Wed Jul 5 10:56:13 2000 @@ -195,16 +195,12 @@ * device open. Updated transmit path to post a * single fragment which includes PRH->end of data. * Mar 2000 AC Did various cleanups for 2.3.x + * Jun 2000 jgarzik PCI and resource alloc cleanups */ -/* Version information string - should be updated prior to each new release!!! */ - -static const char *version = "defxx.c:v1.05 2000/03/26 Lawrence V. Stefani (stefani@lkg.dec.com) and others\n"; - /* Include files */ #include - #include #include #include @@ -226,6 +222,10 @@ #include "defxx.h" +/* Version information string - should be updated prior to each new release!!! */ +static char version[] __initdata = + "defxx.c:v1.05a 2000/06/11 Lawrence V. Stefani (stefani@lkg.dec.com) and others\n"; + #define DYNAMIC_BUFFERS 1 #define SKBUFF_RX_COPYBREAK 200 @@ -235,10 +235,6 @@ */ #define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX+128) -/* Define global routines */ - -int dfx_probe(void); - /* Define module-wide (static) routines */ static struct net_device *dfx_alloc_device(u16 iobase); @@ -428,22 +424,92 @@ */ static struct net_device *bp_root; +static int version_disp; +static int have_pci_driver; + +static struct pci_device_id dfx_pci_tbl[] __initdata = { + { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, PCI_ANY_ID, PCI_ANY_ID, }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, dfx_pci_tbl); -int __init dfx_probe(void) +static int __init dfx_init_one (struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct net_device *dev; + DFX_board_t *bp; /* board pointer */ + int port; + + if (!version_disp) { /* display version info if adapter is found */ + version_disp = 1; /* set display flag to TRUE so that */ + printk (version); /* we only display this string ONCE */ + } + + if (pci_enable_device (pdev)) + goto err_out; + pci_set_master (pdev); + + /* Get I/O base address from PCI Configuration Space */ + port = pci_resource_start (pdev, 1); + + if (!request_region (port, PFI_K_CSR_IO_LEN, "defxx")) { + printk (KERN_ERR + "defxx: I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", + port, (port + PFI_K_CSR_IO_LEN - 1)); + goto err_out; + } + + /* Allocate a new device structure for this adapter */ + dev = dfx_alloc_device (port); + if (dev == NULL) { + printk (KERN_ERR "defxx: alloc device failed\n"); + goto err_out_region; + } + + /* Initialize board structure with bus-specific info */ + bp = (DFX_board_t *) dev->priv; + bp->dev = dev; + bp->next = bp_root; + bp_root = dev; + bp->bus_type = DFX_BUS_TYPE_PCI; + bp->pci_dev = pdev; + + /* + * FIXME FIXME FIXME + * Suck! The original driver didn't clean up after + * itself at this stage, so we won't either. Someone + * needs to go back and see what (if anything) we need + * to free here... -jgarzik + */ + if (dfx_driver_init (dev) != DFX_K_SUCCESS) { + dev->base_addr = 0; /* clear port address field in device structure on failure */ + goto err_out_region; + } + + return 0; + +err_out_region: + release_region (port, PFI_K_CSR_IO_LEN); +err_out: + return -ENODEV; +}; + +static struct pci_driver dfx_driver = { + name: "defxx", + id_table: dfx_pci_tbl, + probe: dfx_init_one, +}; + +static int __init dfx_probe(void) { int i; /* used in for loops */ - int version_disp; /* was version info string already displayed? */ - int port_len; /* length of port address range (in bytes) */ u16 port; /* temporary I/O (port) address */ - struct pci_dev * pdev = NULL; /* PCI device record */ - u16 command; /* PCI Configuration space Command register val */ u32 slot_id; /* EISA hardware (slot) ID read from adapter */ DFX_board_t *bp; /* board pointer */ struct net_device *dev; DBG_printk("In dfx_probe...\n"); - version_disp = 0; /* default to version string not displayed */ already_probed = 1; /* set global flag */ /* Scan for FDDI EISA controllers */ @@ -463,9 +529,7 @@ port = (i << 12); /* recalc base addr */ /* Verify port address range is not already being used */ - - port_len = PI_ESIC_K_CSR_IO_LEN; - if (check_region(port, port_len) == 0) + if (request_region(port, PI_ESIC_K_CSR_IO_LEN, "defxx")) { /* Allocate a new device structure for this adapter */ @@ -485,70 +549,17 @@ } } else - printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1)); + printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", + port, (port + PI_ESIC_K_CSR_IO_LEN-1)); } } /* Scan for FDDI PCI controllers */ - - if (pci_present()) /* is PCI even present? */ - while ((pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, pdev))) - { - if (!version_disp) /* display version info if adapter is found */ - { - version_disp = 1; /* set display flag to TRUE so that */ - printk(version); /* we only display this string ONCE */ - } - - if (pci_enable_device(pdev)) - continue; - - /* Verify that I/O enable bit is set (PCI slot is enabled) */ - - pci_read_config_word(pdev, PCI_COMMAND, &command); - if ((command & PCI_COMMAND_IO) == 0) - printk(KERN_ERR "defxx: I/O enable bit not set! Verify that slot is enabled\n"); - else - { - /* Turn off memory mapped space and enable mastering */ - - command |= PCI_COMMAND_MASTER; - command &= ~PCI_COMMAND_MEMORY; - pci_write_config_word(pdev, PCI_COMMAND, command); - - /* Get I/O base address from PCI Configuration Space */ - - port = pci_resource_start (pdev, 1); - - /* Verify port address range is not already being used */ - - port_len = PFI_K_CSR_IO_LEN; - - if (check_region(port, port_len) == 0) - { - /* Allocate a new device structure for this adapter */ - - dev = dfx_alloc_device(port); - if (dev != NULL) - { - /* Initialize board structure with bus-specific info */ - - bp = (DFX_board_t *) dev->priv; - bp->dev = dev; - bp->next = bp_root; - bp_root = dev; - bp->bus_type = DFX_BUS_TYPE_PCI; - bp->pci_dev = pdev; - if (dfx_driver_init(dev) == DFX_K_SUCCESS) - num_boards++; /* only increment global board count on success */ - else - dev->base_addr = 0; /* clear port address field in device structure on failure */ - } - } - else - printk(KERN_ERR "defxx: I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1)); - } - } + i = pci_register_driver (&dfx_driver); + if (i > 0) { + num_boards += i; + have_pci_driver = 1; + } /* * If we're at this point we're going through dfx_probe() for the first @@ -556,10 +567,7 @@ * Otherwise, return failure (-ENODEV). */ - if (num_boards > 0) - return(0); - else - return(-ENODEV); + return (num_boards > 0) ? 0 : -ENODEV; } @@ -3464,28 +3472,34 @@ } -#ifdef MODULE - -int init_module(void) -{ - if(dfx_probe()<0) - return -ENODEV; - return 0; -} -void cleanup_module(void) +static void __exit dfx_cleanup(void) { while(bp_root!=NULL) { struct net_device *tmp=bp_root; DFX_board_t *priv=tmp->priv; bp_root=priv->next; + + /* FIXME: need to unregister FDDI device here? + * The original driver didn't do it, but I think so.. + * -jgarzik + */ + + if (priv->bus_type == DFX_BUS_TYPE_EISA) + release_region(tmp->base_addr, PI_ESIC_K_CSR_IO_LEN); + else + release_region(tmp->base_addr, PFI_K_CSR_IO_LEN); + kfree(tmp->priv); kfree(tmp); } + if (have_pci_driver) + pci_unregister_driver(&dfx_driver); } -#endif +module_init(dfx_probe); +module_exit(dfx_cleanup); /* diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/eepro.c linux/drivers/net/eepro.c --- v2.4.0-test2/linux/drivers/net/eepro.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/eepro.c Mon Jun 26 18:06:55 2000 @@ -23,6 +23,7 @@ This is a compatibility hardware problem. Versions: + 0.12b misc fixes (aris, 06/26/2000) 0.12a port of version 0.12a of 2.2.x kernels to 2.3.x (aris (aris@conectiva.com.br), 05/19/2000) 0.11e some tweaks about multiple cards support (PdP, jul/aug 1999) @@ -95,7 +96,7 @@ */ static const char *version = - "eepro.c: v0.12a 04/26/2000 aris@conectiva.com.br\n"; + "eepro.c: v0.12b 04/26/2000 aris@conectiva.com.br\n"; #include @@ -509,6 +510,20 @@ /* ack for tx int */ #define eepro_ack_tx(ioaddr) outb (TX_INT, ioaddr + STATUS_REG) +/* a complete sel reset */ +#define eepro_complete_selreset(ioaddr) { eepro_dis_int(ioaddr);\ + lp->stats.tx_errors++;\ + eepro_sel_reset(ioaddr);\ + lp->tx_end = \ + (XMT_LOWER_LIMIT << 8);\ + lp->tx_start = lp->tx_end;\ + lp->tx_last = 0;\ + dev->trans_start = jiffies;\ + netif_wake_queue(dev);\ + eepro_en_int(ioaddr);\ + eepro_en_rx(ioaddr);\ + } + /* Check for a network adaptor of this type, and return '0' if one exists. If dev->base_addr == 0, probe all likely locations. If dev->base_addr == 1, always return failure. @@ -738,7 +753,8 @@ */ if (net_debug > 3) - printk(", %dK RCV buffer", (int)(dev->mem_end)/1024); + printk(", %dK RCV buffer", (int)(dev->mem_end - + dev->mem_start)/1024); /* ............... */ @@ -1085,23 +1101,7 @@ one for the the log file */ printk (KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name, "network cable problem"); - lp->stats.tx_errors++; - - /* Try to restart the adaptor. */ - eepro_sel_reset(ioaddr); - - /* Do I also need to flush the transmit buffers here? YES? */ - lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT; - lp->tx_last = 0; - - dev->trans_start = jiffies; - netif_wake_queue (dev); - - /* enabling interrupts */ - eepro_en_int(ioaddr); - - /* enabling rx */ - eepro_en_rx(ioaddr); + eepro_complete_selreset(ioaddr); } @@ -1375,7 +1375,7 @@ /* Re-enable RX and TX interrupts */ eepro_en_int(ioaddr); } - eepro_en_rx(ioaddr); + eepro_complete_selreset(ioaddr); } /* The horrible routine to read a word from the serial EEPROM. */ @@ -1481,7 +1481,8 @@ end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; } - else end = (XMT_LOWER_LIMIT << 8) + (end - XMT_RAM); + else end = (XMT_LOWER_LIMIT << 8) + (end - + (XMT_UPPER_LIMIT <<8)); } outw(last, ioaddr + HOST_ADDRESS_REG); outw(XMT_CMD, ioaddr + IO_PORT); @@ -1542,8 +1543,6 @@ printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name); return; } - eepro_en_int(ioaddr); - netif_stop_queue(dev); if (net_debug > 5) printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name); @@ -1561,9 +1560,6 @@ if (net_debug > 5) printk(KERN_DEBUG "%s: entering eepro_rx routine.\n", dev->name); - /* clear all interrupts */ - eepro_clear_int(ioaddr); - /* Set the read pointer to the start of the RCV */ outw(rcv_car, ioaddr + HOST_ADDRESS_REG); @@ -1642,9 +1638,6 @@ if (net_debug > 5) printk(KERN_DEBUG "%s: exiting eepro_rx routine.\n", dev->name); - - /* enable tx/rx interrupts */ - eepro_en_int(ioaddr); } static void @@ -1734,6 +1727,12 @@ boguscount--; } + /* if it reached here then it's probable that the adapter won't + * interrupt again for tx. in other words: tx timeout what will take + * a lot of time to happen, so we'll do a complete selreset. + */ + if (!boguscount) + eepro_complete_selreset(ioaddr); } #define MAX_EEPRO 8 diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c --- v2.4.0-test2/linux/drivers/net/eepro100.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/eepro100.c Thu Jun 29 16:31:13 2000 @@ -1145,16 +1145,11 @@ /* We must continue to monitor the media. */ sp->timer.expires = RUN_AT(2*HZ); /* 2.0 sec. */ add_timer(&sp->timer); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,43) - timer_exit(&sp->timer); -#endif /* LINUX_VERSION_CODE */ } static void speedo_show_state(struct net_device *dev) { struct speedo_private *sp = (struct speedo_private *)dev->priv; - long ioaddr = dev->base_addr; - int phy_num = sp->phy[0] & 0x1f; int i; /* Print a few items for debugging. */ @@ -1181,6 +1176,8 @@ (unsigned)sp->rx_ringp[i]->status : 0); #if 0 + long ioaddr = dev->base_addr; + int phy_num = sp->phy[0] & 0x1f; for (i = 0; i < 16; i++) { /* FIXME: what does it mean? --SAW */ if (i == 6) i = 21; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/epic100.c linux/drivers/net/epic100.c --- v2.4.0-test2/linux/drivers/net/epic100.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/epic100.c Thu Jun 29 10:10:39 2000 @@ -25,6 +25,9 @@ LK1.1.2 (jgarzik): * Merge becker version 1.09 + LK1.1.3: + * Major bugfix to 1.09 driver (Francis Romieu) + */ /* The user-configurable values. @@ -90,7 +93,7 @@ /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = -"epic100.c:v1.09+LK1.1.2 4/28/2000 Written by Donald Becker \n"; +"epic100.c:v1.09+LK1.1.3 6/17/2000 Written by Donald Becker \n"; static char version2[] __devinitdata = " http://www.scyld.com/network/epic100.html\n"; @@ -576,6 +579,7 @@ struct epic_private *ep = (struct epic_private *)dev->priv; long ioaddr = dev->base_addr; int i; + int retval; ep->full_duplex = ep->force_fd; @@ -584,9 +588,9 @@ MOD_INC_USE_COUNT; - if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, dev->name, dev)) { + if ((retval = request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, dev->name, dev))) { MOD_DEC_USE_COUNT; - return -EAGAIN; + return retval; } epic_init_ring(dev); @@ -1142,8 +1146,8 @@ printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", dev->name, inl(ioaddr + INTSTAT)); + del_timer_sync(&ep->timer); epic_pause(dev); - del_timer(&ep->timer); free_irq(dev->irq, dev); /* Free all the skbuffs in the Rx queue. */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/hamradio/baycom_par.c linux/drivers/net/hamradio/baycom_par.c --- v2.4.0-test2/linux/drivers/net/hamradio/baycom_par.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/hamradio/baycom_par.c Wed Jul 5 12:59:11 2000 @@ -63,6 +63,7 @@ * 0.7 10.08.1999 Check if parport can do SPP and is safe to access during interrupt contexts * 0.8 12.02.2000 adapted to softnet driver interface * removed direct parport access, uses parport driver methods + * 0.9 03.07.2000 fix interface name handling */ /*****************************************************************************/ @@ -101,7 +102,7 @@ static const char bc_drvname[] = "baycom_par"; static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_par: version 0.8 compiled " __TIME__ " " __DATE__ "\n"; +KERN_INFO "baycom_par: version 0.9 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ @@ -512,14 +513,15 @@ */ for (i = 0; i < NR_PORTS; i++) { struct net_device *dev = baycom_device+i; - sprintf(dev->name, "bcp%d", i); + char ifname[IFNAMSIZ]; + sprintf(ifname, "bcp%d", i); if (!mode[i]) set_hw = 0; if (!set_hw) iobase[i] = 0; j = hdlcdrv_register_hdlcdrv(dev, &par96_ops, sizeof(struct baycom_state), - dev->name, iobase[i], 0, 0); + ifname, iobase[i], 0, 0); if (!j) { bc = (struct baycom_state *)dev->priv; if (set_hw && baycom_setmode(bc, mode[i])) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/hamradio/baycom_ser_fdx.c linux/drivers/net/hamradio/baycom_ser_fdx.c --- v2.4.0-test2/linux/drivers/net/hamradio/baycom_ser_fdx.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/hamradio/baycom_ser_fdx.c Wed Jul 5 12:59:11 2000 @@ -66,6 +66,7 @@ * 0.7 03.08.1999 adapt to Linus' new __setup/__initcall * 0.8 10.08.1999 use module_init/module_exit * 0.9 12.02.2000 adapted to softnet driver interface + * 0.10 03.07.2000 fix interface name handling */ /*****************************************************************************/ @@ -88,7 +89,7 @@ static const char bc_drvname[] = "baycom_ser_fdx"; static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_ser_fdx: version 0.9 compiled " __TIME__ " " __DATE__ "\n"; +KERN_INFO "baycom_ser_fdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ @@ -628,14 +629,15 @@ */ for (i = 0; i < NR_PORTS; i++) { struct net_device *dev = baycom_device+i; - sprintf(dev->name, "bcsf%d", i); + char ifname[IFNAMSIZ]; + sprintf(ifname, "bcsf%d", i); if (!mode[i]) set_hw = 0; if (!set_hw) iobase[i] = irq[i] = 0; j = hdlcdrv_register_hdlcdrv(dev, &ser12_ops, sizeof(struct baycom_state), - dev->name, iobase[i], irq[i], 0); + ifname, iobase[i], irq[i], 0); if (!j) { bc = (struct baycom_state *)dev->priv; if (set_hw && baycom_setmode(bc, mode[i])) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/hamradio/baycom_ser_hdx.c linux/drivers/net/hamradio/baycom_ser_hdx.c --- v2.4.0-test2/linux/drivers/net/hamradio/baycom_ser_hdx.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/hamradio/baycom_ser_hdx.c Wed Jul 5 12:59:11 2000 @@ -56,6 +56,7 @@ * 0.7 03.08.1999 adapt to Linus' new __setup/__initcall * 0.8 10.08.1999 use module_init/module_exit * 0.9 12.02.2000 adapted to softnet driver interface + * 0.10 03.07.2000 fix interface name handling */ /*****************************************************************************/ @@ -78,7 +79,7 @@ static const char bc_drvname[] = "baycom_ser_hdx"; static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_ser_hdx: version 0.9 compiled " __TIME__ " " __DATE__ "\n"; +KERN_INFO "baycom_ser_hdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ @@ -668,14 +669,15 @@ */ for (i = 0; i < NR_PORTS; i++) { struct net_device *dev = baycom_device+i; - sprintf(dev->name, "bcsh%d", i); + char ifname[IFNAMSIZ]; + sprintf(ifname, "bcsh%d", i); if (!mode[i]) set_hw = 0; if (!set_hw) iobase[i] = irq[i] = 0; j = hdlcdrv_register_hdlcdrv(dev, &ser12_ops, sizeof(struct baycom_state), - dev->name, iobase[i], irq[i], 0); + ifname, iobase[i], irq[i], 0); if (!j) { bc = (struct baycom_state *)dev->priv; if (set_hw && baycom_setmode(bc, mode[i])) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/hamradio/dmascc.c linux/drivers/net/hamradio/dmascc.c --- v2.4.0-test2/linux/drivers/net/hamradio/dmascc.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/hamradio/dmascc.c Sun Jul 9 10:10:44 2000 @@ -1,8 +1,10 @@ /* - * $Id: dmascc.c,v 1.3 1998/09/07 04:41:56 kudielka Exp $ + * $Id: dmascc.c,v 1.27 2000/06/01 14:46:23 oe1kib Exp $ * * Driver for high-speed SCC boards (those with DMA support) - * Copyright (C) 1997 Klaus Kudielka + * Copyright (C) 1997-2000 Klaus Kudielka + * + * S5SCC/DMA support by Janko Koleznik S52HI * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,20 +19,22 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * */ #include #include -#include #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -40,68 +44,31 @@ #include #include #include +#include #include #include "z8530.h" -/* Linux 2.0 compatibility */ - -#if LINUX_VERSION_CODE < 0x20100 - - -#define __init -#define __initdata -#define __initfunc(x) x - -#define MODULE_AUTHOR(x) -#define MODULE_DESCRIPTION(x) -#define MODULE_PARM(x,y) - -#define copy_to_user(x,y,z) memcpy_tofs(x,y,z) -#define copy_from_user(x,y,z) memcpy_fromfs(x,y,z) -#define test_and_set_bit(x,y) set_bit(x,y) -#define register_netdevice(x) register_netdev(x) -#define unregister_netdevice(x) unregister_netdev(x) -#define dev_kfree_skb(x) dev_kfree_skb(x,FREE_WRITE) -#define SET_DEV_INIT(x) (x=dmascc_dev_init) - -#define SHDLCE 0x01 /* WR15 */ - -#define AUTOEOM 0x02 /* WR7' */ -#define RXFIFOH 0x08 -#define TXFIFOE 0x20 - -static int dmascc_dev_init(struct net_device *dev) -{ - return 0; -} - -static void dev_init_buffers(struct net_device *dev) -{ - int i; - - for (i = 0; i < DEV_NUMBUFFS; i++) - skb_queue_head_init(&dev->buffs[i]); -} - - -#else - - -#include -#include - -#define SET_DEV_INIT(x) - +/* Linux 2.2 and 2.3 compatibility */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,14) +#define net_device device +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) +#define netif_start_queue(dev) { dev->tbusy = 0; } +#define netif_stop_queue(dev) { dev->tbusy = 1; } +#define netif_wake_queue(dev) { dev->tbusy = 0; mark_bh(NET_BH); } +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,47) +#define netif_running(dev) (dev->flags & IFF_UP) #endif /* Number of buffers per channel */ -#define NUM_TX_BUF 2 /* NUM_TX_BUF >= 1 (2 recommended) */ -#define NUM_RX_BUF 2 /* NUM_RX_BUF >= 1 (2 recommended) */ -#define BUF_SIZE 2016 +#define NUM_TX_BUF 2 /* NUM_TX_BUF >= 1 (min. 2 recommended) */ +#define NUM_RX_BUF 6 /* NUM_RX_BUF >= 1 (min. 2 recommended) */ +#define BUF_SIZE 1576 /* BUF_SIZE >= mtu + hard_header_len */ /* Cards supported */ @@ -112,13 +79,18 @@ 0, 8, 3686400, 7372800 } #define HW_TWIN { "Gracilis PackeTwin", 0x200, 0x10, 0x10, 32, \ 0, 4, 6144000, 6144000 } +#define HW_S5 { "S5SCC/DMA", 0x200, 0x10, 0x10, 32, \ + 0, 8, 4915200, 9830400 } + +#define HARDWARE { HW_PI, HW_PI2, HW_TWIN, HW_S5 } -#define HARDWARE { HW_PI, HW_PI2, HW_TWIN } +#define TMR_0_HZ 25600 /* Frequency of timer 0 */ #define TYPE_PI 0 #define TYPE_PI2 1 #define TYPE_TWIN 2 -#define NUM_TYPES 3 +#define TYPE_S5 3 +#define NUM_TYPES 4 #define MAX_NUM_DEVS 32 @@ -188,16 +160,44 @@ /* Status values */ -/* tx_state */ -#define TX_IDLE 0 -#define TX_OFF 1 -#define TX_TXDELAY 2 -#define TX_ACTIVE 3 -#define TX_SQDELAY 4 +#define IDLE 0 +#define TX_HEAD 1 +#define TX_DATA 2 +#define TX_PAUSE 3 +#define TX_TAIL 4 +#define RTS_OFF 5 +#define WAIT 6 +#define DCD_ON 7 +#define RX_ON 8 +#define DCD_OFF 9 + + +/* Ioctls */ + +#define SIOCGSCCPARAM SIOCDEVPRIVATE +#define SIOCSSCCPARAM (SIOCDEVPRIVATE+1) /* Data types */ +struct scc_param { + int pclk_hz; /* frequency of BRG input (don't change) */ + int brg_tc; /* BRG terminal count; BRG disabled if < 0 */ + int nrzi; /* 0 (nrz), 1 (nrzi) */ + int clocks; /* see dmascc_cfg documentation */ + int txdelay; /* [1/TMR_0_HZ] */ + int txtimeout; /* [1/HZ] */ + int txtail; /* [1/TMR_0_HZ] */ + int waittime; /* [1/TMR_0_HZ] */ + int slottime; /* [1/TMR_0_HZ] */ + int persist; /* 1 ... 256 */ + int dma; /* -1 (disable), 0, 1, 3 */ + int txpause; /* [1/TMR_0_HZ] */ + int rtsoff; /* [1/TMR_0_HZ] */ + int dcdon; /* [1/TMR_0_HZ] */ + int dcdoff; /* [1/TMR_0_HZ] */ +}; + struct scc_hardware { char *name; int io_region; @@ -211,10 +211,17 @@ }; struct scc_priv { - struct enet_statistics stats; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) + char name[IFNAMSIZ]; +#endif + int type; + int chip; + struct net_device *dev; struct scc_info *info; + struct net_device_stats stats; int channel; - int cmd, data, tmr; + int card_base, scc_cmd, scc_data; + int tmr_cnt, tmr_ctrl, tmr_mode; struct scc_param param; char rx_buf[NUM_RX_BUF][BUF_SIZE]; int rx_len[NUM_RX_BUF]; @@ -226,17 +233,13 @@ int tx_len[NUM_TX_BUF]; int tx_ptr; int tx_head, tx_tail, tx_count; - int tx_sem, tx_state; + int state; unsigned long tx_start; - int status; + int rr0; }; struct scc_info { - int type; - int chip; - int open; - int scc_base; - int tmr_base; + int irq_used; int twin_serial_cfg; struct net_device dev[2]; struct scc_priv priv[2]; @@ -247,25 +250,33 @@ /* Function declarations */ int dmascc_init(void) __init; -static int setup_adapter(int io, int h, int n) __init; +static int setup_adapter(int card_base, int type, int n) __init; + +static void write_scc(struct scc_priv *priv, int reg, int val); +static void write_scc_data(struct scc_priv *priv, int val, int fast); +static int read_scc(struct scc_priv *priv, int reg); +static int read_scc_data(struct scc_priv *priv); -static inline void write_scc(int ctl, int reg, int val); -static inline int read_scc(int ctl, int reg); static int scc_open(struct net_device *dev); static int scc_close(struct net_device *dev); static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static int scc_send_packet(struct sk_buff *skb, struct net_device *dev); -static struct enet_statistics *scc_get_stats(struct net_device *dev); +static struct net_device_stats *scc_get_stats(struct net_device *dev); static int scc_set_mac_address(struct net_device *dev, void *sa); + static void scc_isr(int irq, void *dev_id, struct pt_regs * regs); static inline void z8530_isr(struct scc_info *info); -static void rx_isr(struct net_device *dev); -static void special_condition(struct net_device *dev, int rc); +static void rx_isr(struct scc_priv *priv); +static void special_condition(struct scc_priv *priv, int rc); static void rx_bh(void *arg); -static void tx_isr(struct net_device *dev); -static void es_isr(struct net_device *dev); -static void tm_isr(struct net_device *dev); -static inline void delay(struct net_device *dev, int t); +static void tx_isr(struct scc_priv *priv); +static void es_isr(struct scc_priv *priv); +static void tm_isr(struct scc_priv *priv); + +static inline void tx_on(struct scc_priv *priv); +static inline void rx_on(struct scc_priv *priv); +static inline void rx_off(struct scc_priv *priv); +static void start_timer(struct scc_priv *priv, int t, int r15); static inline unsigned char random(void); @@ -287,7 +298,6 @@ static unsigned long rand; - /* Module functions */ #ifdef MODULE @@ -298,14 +308,12 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NUM_DEVS) "i"); -int init_module(void) -{ +int init_module(void) { return dmascc_init(); } -void cleanup_module(void) -{ +void cleanup_module(void) { int i; struct scc_info *info; @@ -315,15 +323,17 @@ /* Unregister devices */ for (i = 0; i < 2; i++) { if (info->dev[i].name) + rtnl_lock(); unregister_netdevice(&info->dev[i]); + rtnl_unlock(); } /* Reset board */ - if (info->type == TYPE_TWIN) - outb_p(0, info->dev[0].base_addr + TWIN_SERIAL_CFG); - write_scc(info->priv[0].cmd, R9, FHWRES); + if (info->priv[0].type == TYPE_TWIN) + outb(0, info->dev[0].base_addr + TWIN_SERIAL_CFG); + write_scc(&info->priv[0], R9, FHWRES); release_region(info->dev[0].base_addr, - hw[info->type].io_size); + hw[info->priv[0].type].io_size); /* Free memory */ first = info->next; @@ -335,8 +345,7 @@ #else -void __init dmascc_setup(char *str, int *ints) -{ +void __init dmascc_setup(char *str, int *ints) { int i; for (i = 0; i < MAX_NUM_DEVS && i < ints[0]; i++) @@ -349,8 +358,7 @@ /* Initialization functions */ -int __init dmascc_init(void) -{ +int __init dmascc_init(void) { int h, i, j, n; int base[MAX_NUM_DEVS], tcmd[MAX_NUM_DEVS], t0[MAX_NUM_DEVS], t1[MAX_NUM_DEVS]; @@ -402,18 +410,18 @@ for (i = 0; i < hw[h].num_devs; i++) if (base[i]) { /* Timer 0: LSB+MSB, Mode 3, TMR_0_HZ */ - outb_p(0x36, tcmd[i]); - outb_p((hw[h].tmr_hz/TMR_0_HZ) & 0xFF, t0[i]); - outb_p((hw[h].tmr_hz/TMR_0_HZ) >> 8, t0[i]); + outb(0x36, tcmd[i]); + outb((hw[h].tmr_hz/TMR_0_HZ) & 0xFF, t0[i]); + outb((hw[h].tmr_hz/TMR_0_HZ) >> 8, t0[i]); /* Timer 1: LSB+MSB, Mode 0, HZ/10 */ - outb_p(0x70, tcmd[i]); - outb_p((TMR_0_HZ/HZ*10) & 0xFF, t1[i]); - outb_p((TMR_0_HZ/HZ*10) >> 8, t1[i]); + outb(0x70, tcmd[i]); + outb((TMR_0_HZ/HZ*10) & 0xFF, t1[i]); + outb((TMR_0_HZ/HZ*10) >> 8, t1[i]); start[i] = jiffies; delay[i] = 0; counting[i] = 1; /* Timer 2: LSB+MSB, Mode 0 */ - outb_p(0xb0, tcmd[i]); + outb(0xb0, tcmd[i]); } time = jiffies; /* Wait until counter registers are loaded */ @@ -424,8 +432,8 @@ for (i = 0; i < hw[h].num_devs; i++) if (base[i] && counting[i]) { /* Read back Timer 1: latch; read LSB; read MSB */ - outb_p(0x40, tcmd[i]); - t_val = inb_p(t1[i]) + (inb_p(t1[i]) << 8); + outb(0x40, tcmd[i]); + t_val = inb(t1[i]) + (inb(t1[i]) << 8); /* Also check whether counter did wrap */ if (t_val == 0 || t_val > TMR_0_HZ/HZ*10) counting[i] = 0; delay[i] = jiffies - start[i]; @@ -452,31 +460,46 @@ return -EIO; } -int __init setup_adapter(int io, int h, int n) -{ + +int __init setup_adapter(int card_base, int type, int n) { int i, irq, chip; struct scc_info *info; struct net_device *dev; struct scc_priv *priv; unsigned long time; unsigned int irqs; - int tmr = io + hw[h].tmr_offset; - int scc = io + hw[h].scc_offset; - int cmd = scc + SCCA_CMD; + int tmr_base = card_base + hw[type].tmr_offset; + int scc_base = card_base + hw[type].scc_offset; char *chipnames[] = CHIPNAMES; - /* Reset 8530 */ - write_scc(cmd, R9, FHWRES | MIE | NV); + /* Allocate memory */ + info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA); + if (!info) { + printk("dmascc: could not allocate memory for %s at %#3x\n", + hw[type].name, card_base); + return -1; + } + + /* Initialize what is necessary for write_scc and write_scc_data */ + memset(info, 0, sizeof(struct scc_info)); + priv = &info->priv[0]; + priv->type = type; + priv->card_base = card_base; + priv->scc_cmd = scc_base + SCCA_CMD; + priv->scc_data = scc_base + SCCA_DATA; + + /* Reset SCC */ + write_scc(priv, R9, FHWRES | MIE | NV); /* Determine type of chip by enabling SDLC/HDLC enhancements */ - write_scc(cmd, R15, SHDLCE); - if (!read_scc(cmd, R15)) { + write_scc(priv, R15, SHDLCE); + if (!read_scc(priv, R15)) { /* WR7' not present. This is an ordinary Z8530 SCC. */ chip = Z8530; } else { /* Put one character in TX FIFO */ - write_scc(cmd, R8, 0); - if (read_scc(cmd, R0) & Tx_BUF_EMP) { + write_scc_data(priv, 0, 0); + if (read_scc(priv, R0) & Tx_BUF_EMP) { /* TX FIFO not full. This is a Z85230 ESCC with a 4-byte FIFO. */ chip = Z85230; } else { @@ -484,93 +507,76 @@ chip = Z85C30; } } - write_scc(cmd, R15, 0); + write_scc(priv, R15, 0); /* Start IRQ auto-detection */ sti(); irqs = probe_irq_on(); /* Enable interrupts */ - switch (h) { - case TYPE_PI: - case TYPE_PI2: - outb_p(0, io + PI_DREQ_MASK); - write_scc(cmd, R15, CTSIE); - write_scc(cmd, R0, RES_EXT_INT); - write_scc(cmd, R1, EXT_INT_ENAB); - break; - case TYPE_TWIN: - outb_p(0, io + TWIN_DMA_CFG); - inb_p(io + TWIN_CLR_TMR1); - inb_p(io + TWIN_CLR_TMR2); - outb_p(TWIN_EI, io + TWIN_SERIAL_CFG); - break; + if (type == TYPE_TWIN) { + outb(0, card_base + TWIN_DMA_CFG); + inb(card_base + TWIN_CLR_TMR1); + inb(card_base + TWIN_CLR_TMR2); + outb((info->twin_serial_cfg = TWIN_EI), card_base + TWIN_SERIAL_CFG); + } else { + write_scc(priv, R15, CTSIE); + write_scc(priv, R0, RES_EXT_INT); + write_scc(priv, R1, EXT_INT_ENAB); } /* Start timer */ - outb_p(1, tmr + TMR_CNT1); - outb_p(0, tmr + TMR_CNT1); + outb(1, tmr_base + TMR_CNT1); + outb(0, tmr_base + TMR_CNT1); + /* Wait and detect IRQ */ time = jiffies; while (jiffies - time < 2 + HZ / TMR_0_HZ); irq = probe_irq_off(irqs); /* Clear pending interrupt, disable interrupts */ - switch (h) { - case TYPE_PI: - case TYPE_PI2: - write_scc(cmd, R1, 0); - write_scc(cmd, R15, 0); - write_scc(cmd, R0, RES_EXT_INT); - break; - case TYPE_TWIN: - inb_p(io + TWIN_CLR_TMR1); - outb_p(0, io + TWIN_SERIAL_CFG); - break; + if (type == TYPE_TWIN) { + inb(card_base + TWIN_CLR_TMR1); + } else { + write_scc(priv, R1, 0); + write_scc(priv, R15, 0); + write_scc(priv, R0, RES_EXT_INT); } if (irq <= 0) { printk("dmascc: could not find irq of %s at %#3x (irq=%d)\n", - hw[h].name, io, irq); - return -1; - } - - /* Allocate memory */ - info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA); - if (!info) { - printk("dmascc: could not allocate memory for %s at %#3x\n", - hw[h].name, io); + hw[type].name, card_base, irq); + kfree_s(info, sizeof(struct scc_info)); return -1; } /* Set up data structures */ - memset(info, 0, sizeof(struct scc_info)); - info->type = h; - info->chip = chip; - info->scc_base = io + hw[h].scc_offset; - info->tmr_base = io + hw[h].tmr_offset; - info->twin_serial_cfg = 0; for (i = 0; i < 2; i++) { dev = &info->dev[i]; priv = &info->priv[i]; + priv->type = type; + priv->chip = chip; + priv->dev = dev; priv->info = info; priv->channel = i; - priv->cmd = info->scc_base + (i ? SCCB_CMD : SCCA_CMD); - priv->data = info->scc_base + (i ? SCCB_DATA : SCCA_DATA); - priv->tmr = info->tmr_base + (i ? TMR_CNT2 : TMR_CNT1); - priv->param.pclk_hz = hw[h].pclk_hz; + priv->card_base = card_base; + priv->scc_cmd = scc_base + (i ? SCCB_CMD : SCCA_CMD); + priv->scc_data = scc_base + (i ? SCCB_DATA : SCCA_DATA); + priv->tmr_cnt = tmr_base + (i ? TMR_CNT2 : TMR_CNT1); + priv->tmr_ctrl = tmr_base + TMR_CTRL; + priv->tmr_mode = i ? 0xb0 : 0x70; + priv->param.pclk_hz = hw[type].pclk_hz; priv->param.brg_tc = -1; priv->param.clocks = TCTRxCP | RCRTxCP; - priv->param.txdelay = TMR_0_HZ * 10 / 1000; - priv->param.txtime = HZ * 3; - priv->param.sqdelay = TMR_0_HZ * 1 / 1000; - priv->param.slottime = TMR_0_HZ * 10 / 1000; - priv->param.waittime = TMR_0_HZ * 100 / 1000; - priv->param.persist = 32; + priv->param.persist = 256; + priv->param.dma = -1; priv->rx_task.routine = rx_bh; - priv->rx_task.data = dev; + priv->rx_task.data = priv; dev->priv = priv; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) + if (sizeof(dev->name) == sizeof(char *)) dev->name = priv->name; +#endif sprintf(dev->name, "dmascc%i", 2*n+i); - dev->base_addr = io; + dev->base_addr = card_base; dev->irq = irq; dev->open = scc_open; dev->stop = scc_close; @@ -580,7 +586,6 @@ dev->hard_header = ax25_encapsulate; dev->rebuild_header = ax25_rebuild_header; dev->set_mac_address = scc_set_mac_address; - SET_DEV_INIT(dev->init); dev->type = ARPHRD_AX25; dev->hard_header_len = 73; dev->mtu = 1500; @@ -589,203 +594,298 @@ memcpy(dev->broadcast, ax25_broadcast, 7); memcpy(dev->dev_addr, ax25_test, 7); dev_init_buffers(dev); + rtnl_lock(); if (register_netdevice(dev)) { printk("dmascc: could not register %s\n", dev->name); } + rtnl_unlock(); } - request_region(io, hw[h].io_size, "dmascc"); + request_region(card_base, hw[type].io_size, "dmascc"); info->next = first; first = info; - printk("dmascc: found %s (%s) at %#3x, irq %d\n", hw[h].name, - chipnames[chip], io, irq); + printk("dmascc: found %s (%s) at %#3x, irq %d\n", hw[type].name, + chipnames[chip], card_base, irq); return 0; } /* Driver functions */ -static inline void write_scc(int ctl, int reg, int val) -{ - outb_p(reg, ctl); - outb_p(val, ctl); +static void write_scc(struct scc_priv *priv, int reg, int val) { + unsigned long flags; + switch (priv->type) { + case TYPE_S5: + if (reg) outb(reg, priv->scc_cmd); + outb(val, priv->scc_cmd); + return; + case TYPE_TWIN: + if (reg) outb_p(reg, priv->scc_cmd); + outb_p(val, priv->scc_cmd); + return; + default: + save_flags(flags); + cli(); + outb_p(0, priv->card_base + PI_DREQ_MASK); + if (reg) outb_p(reg, priv->scc_cmd); + outb_p(val, priv->scc_cmd); + outb(1, priv->card_base + PI_DREQ_MASK); + restore_flags(flags); + return; + } } -static inline int read_scc(int ctl, int reg) -{ - outb_p(reg, ctl); - return inb_p(ctl); +static void write_scc_data(struct scc_priv *priv, int val, int fast) { + unsigned long flags; + switch (priv->type) { + case TYPE_S5: + outb(val, priv->scc_data); + return; + case TYPE_TWIN: + outb_p(val, priv->scc_data); + return; + default: + if (fast) outb_p(val, priv->scc_data); + else { + save_flags(flags); + cli(); + outb_p(0, priv->card_base + PI_DREQ_MASK); + outb_p(val, priv->scc_data); + outb(1, priv->card_base + PI_DREQ_MASK); + restore_flags(flags); + } + return; + } } -static int scc_open(struct net_device *dev) -{ +static int read_scc(struct scc_priv *priv, int reg) { + int rc; + unsigned long flags; + switch (priv->type) { + case TYPE_S5: + if (reg) outb(reg, priv->scc_cmd); + return inb(priv->scc_cmd); + case TYPE_TWIN: + if (reg) outb_p(reg, priv->scc_cmd); + return inb_p(priv->scc_cmd); + default: + save_flags(flags); + cli(); + outb_p(0, priv->card_base + PI_DREQ_MASK); + if (reg) outb_p(reg, priv->scc_cmd); + rc = inb_p(priv->scc_cmd); + outb(1, priv->card_base + PI_DREQ_MASK); + restore_flags(flags); + return rc; + } +} + + +static int read_scc_data(struct scc_priv *priv) { + int rc; + unsigned long flags; + switch (priv->type) { + case TYPE_S5: + return inb(priv->scc_data); + case TYPE_TWIN: + return inb_p(priv->scc_data); + default: + save_flags(flags); + cli(); + outb_p(0, priv->card_base + PI_DREQ_MASK); + rc = inb_p(priv->scc_data); + outb(1, priv->card_base + PI_DREQ_MASK); + restore_flags(flags); + return rc; + } +} + + +static int scc_open(struct net_device *dev) { struct scc_priv *priv = dev->priv; struct scc_info *info = priv->info; - int io = dev->base_addr; - int cmd = priv->cmd; + int card_base = priv->card_base; + + MOD_INC_USE_COUNT; /* Request IRQ if not already used by other channel */ - if (!info->open) { - if (request_irq(dev->irq, scc_isr, SA_INTERRUPT, "dmascc", info)) + if (!info->irq_used) { + if (request_irq(dev->irq, scc_isr, 0, "dmascc", info)) { + MOD_DEC_USE_COUNT; return -EAGAIN; + } } + info->irq_used++; /* Request DMA if required */ - if (dev->dma && request_dma(dev->dma, "dmascc")) { - if (!info->open) free_irq(dev->irq, info); - return -EAGAIN; + if (priv->param.dma >= 0) { + if (request_dma(priv->param.dma, "dmascc")) { + if (--info->irq_used == 0) free_irq(dev->irq, info); + MOD_DEC_USE_COUNT; + return -EAGAIN; + } else { + unsigned long flags = claim_dma_lock(); + clear_dma_ff(priv->param.dma); + release_dma_lock(flags); + } } /* Initialize local variables */ priv->rx_ptr = 0; priv->rx_over = 0; priv->rx_head = priv->rx_tail = priv->rx_count = 0; - priv->tx_state = TX_IDLE; + priv->state = IDLE; priv->tx_head = priv->tx_tail = priv->tx_count = 0; priv->tx_ptr = 0; - priv->tx_sem = 0; /* Reset channel */ - write_scc(cmd, R9, (priv->channel ? CHRB : CHRA) | MIE | NV); + write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV); /* X1 clock, SDLC mode */ - write_scc(cmd, R4, SDLC | X1CLK); + write_scc(priv, R4, SDLC | X1CLK); /* DMA */ - write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN); + write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN); /* 8 bit RX char, RX disable */ - write_scc(cmd, R3, Rx8); + write_scc(priv, R3, Rx8); /* 8 bit TX char, TX disable */ - write_scc(cmd, R5, Tx8); + write_scc(priv, R5, Tx8); /* SDLC address field */ - write_scc(cmd, R6, 0); + write_scc(priv, R6, 0); /* SDLC flag */ - write_scc(cmd, R7, FLAG); - switch (info->chip) { + write_scc(priv, R7, FLAG); + switch (priv->chip) { case Z85C30: /* Select WR7' */ - write_scc(cmd, R15, SHDLCE); + write_scc(priv, R15, SHDLCE); /* Auto EOM reset */ - write_scc(cmd, R7, AUTOEOM); - write_scc(cmd, R15, 0); + write_scc(priv, R7, AUTOEOM); + write_scc(priv, R15, 0); break; case Z85230: /* Select WR7' */ - write_scc(cmd, R15, SHDLCE); - /* RX FIFO half full (interrupt only), Auto EOM reset, - TX FIFO empty (DMA only) */ - write_scc(cmd, R7, AUTOEOM | (dev->dma ? TXFIFOE : RXFIFOH)); - write_scc(cmd, R15, 0); + write_scc(priv, R15, SHDLCE); + /* The following bits are set (see 2.5.2.1): + - Automatic EOM reset + - Interrupt request if RX FIFO is half full + This bit should be ignored in DMA mode (according to the + documentation), but actually isn't. The receiver doesn't work if + it is set. Thus, we have to clear it in DMA mode. + - Interrupt/DMA request if TX FIFO is completely empty + a) If set, the ESCC behaves as if it had no TX FIFO (Z85C30 + compatibility). + b) If cleared, DMA requests may follow each other very quickly, + filling up the TX FIFO. + Advantage: TX works even in case of high bus latency. + Disadvantage: Edge-triggered DMA request circuitry may miss + a request. No more data is delivered, resulting + in a TX FIFO underrun. + Both PI2 and S5SCC/DMA seem to work fine with TXFIFOE cleared. + The PackeTwin doesn't. I don't know about the PI, but let's + assume it behaves like the PI2. + */ + if (priv->param.dma >= 0) { + if (priv->type == TYPE_TWIN) write_scc(priv, R7, AUTOEOM | TXFIFOE); + else write_scc(priv, R7, AUTOEOM); + } else { + write_scc(priv, R7, AUTOEOM | RXFIFOH); + } + write_scc(priv, R15, 0); break; } /* Preset CRC, NRZ(I) encoding */ - write_scc(cmd, R10, CRCPS | (priv->param.nrzi ? NRZI : NRZ)); + write_scc(priv, R10, CRCPS | (priv->param.nrzi ? NRZI : NRZ)); /* Configure baud rate generator */ if (priv->param.brg_tc >= 0) { /* Program BR generator */ - write_scc(cmd, R12, priv->param.brg_tc & 0xFF); - write_scc(cmd, R13, (priv->param.brg_tc>>8) & 0xFF); + write_scc(priv, R12, priv->param.brg_tc & 0xFF); + write_scc(priv, R13, (priv->param.brg_tc>>8) & 0xFF); /* BRG source = SYS CLK; enable BRG; DTR REQ function (required by PackeTwin, not connected on the PI2); set DPLL source to BRG */ - write_scc(cmd, R14, SSBR | DTRREQ | BRSRC | BRENABL); + write_scc(priv, R14, SSBR | DTRREQ | BRSRC | BRENABL); /* Enable DPLL */ - write_scc(cmd, R14, SEARCH | DTRREQ | BRSRC | BRENABL); + write_scc(priv, R14, SEARCH | DTRREQ | BRSRC | BRENABL); } else { /* Disable BR generator */ - write_scc(cmd, R14, DTRREQ | BRSRC); + write_scc(priv, R14, DTRREQ | BRSRC); } /* Configure clocks */ - if (info->type == TYPE_TWIN) { + if (priv->type == TYPE_TWIN) { /* Disable external TX clock receiver */ - outb_p((info->twin_serial_cfg &= + outb((info->twin_serial_cfg &= ~(priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)), - io + TWIN_SERIAL_CFG); + card_base + TWIN_SERIAL_CFG); } - write_scc(cmd, R11, priv->param.clocks); - if ((info->type == TYPE_TWIN) && !(priv->param.clocks & TRxCOI)) { + write_scc(priv, R11, priv->param.clocks); + if ((priv->type == TYPE_TWIN) && !(priv->param.clocks & TRxCOI)) { /* Enable external TX clock receiver */ - outb_p((info->twin_serial_cfg |= + outb((info->twin_serial_cfg |= (priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)), - io + TWIN_SERIAL_CFG); + card_base + TWIN_SERIAL_CFG); } /* Configure PackeTwin */ - if (info->type == TYPE_TWIN) { + if (priv->type == TYPE_TWIN) { /* Assert DTR, enable interrupts */ - outb_p((info->twin_serial_cfg |= TWIN_EI | + outb((info->twin_serial_cfg |= TWIN_EI | (priv->channel ? TWIN_DTRB_ON : TWIN_DTRA_ON)), - io + TWIN_SERIAL_CFG); + card_base + TWIN_SERIAL_CFG); } /* Read current status */ - priv->status = read_scc(cmd, R0); - /* Enable SYNC, DCD, and CTS interrupts */ - write_scc(cmd, R15, DCDIE | CTSIE | SYNCIE); - - /* Configure PI2 DMA */ - if (info->type <= TYPE_PI2) outb_p(1, io + PI_DREQ_MASK); + priv->rr0 = read_scc(priv, R0); + /* Enable DCD interrupt */ + write_scc(priv, R15, DCDIE); netif_start_queue(dev); - info->open++; - MOD_INC_USE_COUNT; return 0; } -static int scc_close(struct net_device *dev) -{ +static int scc_close(struct net_device *dev) { struct scc_priv *priv = dev->priv; struct scc_info *info = priv->info; - int io = dev->base_addr; - int cmd = priv->cmd; + int card_base = priv->card_base; netif_stop_queue(dev); - info->open--; - if (info->type == TYPE_TWIN) + if (priv->type == TYPE_TWIN) { /* Drop DTR */ - outb_p((info->twin_serial_cfg &= + outb((info->twin_serial_cfg &= (priv->channel ? ~TWIN_DTRB_ON : ~TWIN_DTRA_ON)), - io + TWIN_SERIAL_CFG); - - /* Reset channel, free DMA */ - write_scc(cmd, R9, (priv->channel ? CHRB : CHRA) | MIE | NV); - if (dev->dma) { - if (info->type == TYPE_TWIN) outb_p(0, io + TWIN_DMA_CFG); - free_dma(dev->dma); + card_base + TWIN_SERIAL_CFG); } - if (!info->open) { - if (info->type <= TYPE_PI2) outb_p(0, io + PI_DREQ_MASK); - free_irq(dev->irq, info); + /* Reset channel, free DMA and IRQ */ + write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV); + if (priv->param.dma >= 0) { + if (priv->type == TYPE_TWIN) outb(0, card_base + TWIN_DMA_CFG); + free_dma(priv->param.dma); } + if (--info->irq_used == 0) free_irq(dev->irq, info); + MOD_DEC_USE_COUNT; return 0; } -static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - int rc; +static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct scc_priv *priv = dev->priv; switch (cmd) { case SIOCGSCCPARAM: - if(copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param))) - return -EFAULT; + if (copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param))) + return -EFAULT; return 0; case SIOCSSCCPARAM: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (netif_running(dev)) - return -EAGAIN; - if(copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param))) - return -EFAULT; - dev->dma = priv->param.dma; + if (!capable(CAP_NET_ADMIN)) return -EPERM; + if (netif_running(dev)) return -EAGAIN; + if (copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param))) + return -EFAULT; return 0; default: return -EINVAL; @@ -793,165 +893,150 @@ } -static int scc_send_packet(struct sk_buff *skb, struct net_device *dev) -{ +static int scc_send_packet(struct sk_buff *skb, struct net_device *dev) { struct scc_priv *priv = dev->priv; - struct scc_info *info = priv->info; - int cmd = priv->cmd; unsigned long flags; int i; - /* Block a timer-based transmit from overlapping */ + /* Temporarily stop the scheduler feeding us packets */ netif_stop_queue(dev); - + /* Transfer data to DMA buffer */ i = priv->tx_head; memcpy(priv->tx_buf[i], skb->data+1, skb->len-1); priv->tx_len[i] = skb->len-1; + /* Clear interrupts while we touch our circular buffers */ save_flags(flags); cli(); - /* Set the busy flag if we just filled up the last buffer */ + /* Move the ring buffer's head */ priv->tx_head = (i + 1) % NUM_TX_BUF; priv->tx_count++; - if (priv->tx_count != NUM_TX_BUF) - netif_wake_queue(dev); + + /* If we just filled up the last buffer, leave queue stopped. + The higher layers must wait until we have a DMA buffer + to accept the data. */ + if (priv->tx_count < NUM_TX_BUF) netif_wake_queue(dev); /* Set new TX state */ - if (priv->tx_state == TX_IDLE) { + if (priv->state == IDLE) { /* Assert RTS, start timer */ - priv->tx_state = TX_TXDELAY; - if (info->type <= TYPE_PI2) outb_p(0, dev->base_addr + PI_DREQ_MASK); - write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8); - if (info->type <= TYPE_PI2) outb_p(1, dev->base_addr + PI_DREQ_MASK); + priv->state = TX_HEAD; priv->tx_start = jiffies; - delay(dev, priv->param.txdelay); + write_scc(priv, R5, TxCRC_ENAB | RTS | TxENAB | Tx8); + write_scc(priv, R15, 0); + start_timer(priv, priv->param.txdelay, 0); } + /* Turn interrupts back on and free buffer */ restore_flags(flags); - dev_kfree_skb(skb); - priv->tx_sem = 0; return 0; } -static struct enet_statistics *scc_get_stats(struct net_device *dev) -{ +static struct net_device_stats *scc_get_stats(struct net_device *dev) { struct scc_priv *priv = dev->priv; return &priv->stats; } -static int scc_set_mac_address(struct net_device *dev, void *sa) -{ +static int scc_set_mac_address(struct net_device *dev, void *sa) { memcpy(dev->dev_addr, ((struct sockaddr *)sa)->sa_data, dev->addr_len); return 0; } -static void scc_isr(int irq, void *dev_id, struct pt_regs * regs) -{ +static void scc_isr(int irq, void *dev_id, struct pt_regs * regs) { struct scc_info *info = dev_id; - int is, io = info->dev[0].base_addr; - - /* We're a fast IRQ handler and are called with interrupts disabled */ - /* IRQ sharing doesn't make sense due to ISA's edge-triggered - interrupts, hence it is safe to return if we have found and - processed a single device. */ + /* At this point interrupts are enabled, and the interrupt under service + is already acknowledged, but masked off. - /* Interrupt processing: We loop until we know that the IRQ line is + Interrupt processing: We loop until we know that the IRQ line is low. If another positive edge occurs afterwards during the ISR, another interrupt will be triggered by the interrupt controller - as soon as the IRQ level is enabled again (see asm/irq.h). */ + as soon as the IRQ level is enabled again (see asm/irq.h). - switch (info->type) { - case TYPE_PI: - case TYPE_PI2: - outb_p(0, io + PI_DREQ_MASK); - z8530_isr(info); - outb_p(1, io + PI_DREQ_MASK); - return; - case TYPE_TWIN: - while ((is = ~inb_p(io + TWIN_INT_REG)) & + Bottom-half handlers will be processed after scc_isr(). This is + important, since we only have small ringbuffers and want new data + to be fetched/delivered immediately. */ + + if (info->priv[0].type == TYPE_TWIN) { + int is, card_base = info->priv[0].card_base; + while ((is = ~inb(card_base + TWIN_INT_REG)) & TWIN_INT_MSK) { if (is & TWIN_SCC_MSK) { z8530_isr(info); } else if (is & TWIN_TMR1_MSK) { - inb_p(io + TWIN_CLR_TMR1); - tm_isr(&info->dev[0]); + inb(card_base + TWIN_CLR_TMR1); + tm_isr(&info->priv[0]); } else { - inb_p(io + TWIN_CLR_TMR2); - tm_isr(&info->dev[1]); + inb(card_base + TWIN_CLR_TMR2); + tm_isr(&info->priv[1]); } } - /* No interrupts pending from the PackeTwin */ - return; - } + } else z8530_isr(info); } -static inline void z8530_isr(struct scc_info *info) -{ - int is, a_cmd; - - a_cmd = info->scc_base + SCCA_CMD; +static inline void z8530_isr(struct scc_info *info) { + int is, i = 100; - while ((is = read_scc(a_cmd, R3))) { + while ((is = read_scc(&info->priv[0], R3)) && i--) { if (is & CHARxIP) { - rx_isr(&info->dev[0]); + rx_isr(&info->priv[0]); } else if (is & CHATxIP) { - tx_isr(&info->dev[0]); + tx_isr(&info->priv[0]); } else if (is & CHAEXT) { - es_isr(&info->dev[0]); + es_isr(&info->priv[0]); } else if (is & CHBRxIP) { - rx_isr(&info->dev[1]); + rx_isr(&info->priv[1]); } else if (is & CHBTxIP) { - tx_isr(&info->dev[1]); + tx_isr(&info->priv[1]); } else { - es_isr(&info->dev[1]); + es_isr(&info->priv[1]); } + write_scc(&info->priv[0], R0, RES_H_IUS); + i++; + } + if (i < 0) { + printk("dmascc: stuck in ISR with RR3=0x%02x.\n", is); } /* Ok, no interrupts pending from this 8530. The INT line should be inactive now. */ } -static void rx_isr(struct net_device *dev) -{ - struct scc_priv *priv = dev->priv; - int cmd = priv->cmd; - - if (dev->dma) { +static void rx_isr(struct scc_priv *priv) { + if (priv->param.dma >= 0) { /* Check special condition and perform error reset. See 2.4.7.5. */ - special_condition(dev, read_scc(cmd, R1)); - write_scc(cmd, R0, ERR_RES); + special_condition(priv, read_scc(priv, R1)); + write_scc(priv, R0, ERR_RES); } else { /* Check special condition for each character. Error reset not necessary. Same algorithm for SCC and ESCC. See 2.4.7.1 and 2.4.7.4. */ int rc; - while (read_scc(cmd, R0) & Rx_CH_AV) { - rc = read_scc(cmd, R1); + while (read_scc(priv, R0) & Rx_CH_AV) { + rc = read_scc(priv, R1); if (priv->rx_ptr < BUF_SIZE) - priv->rx_buf[priv->rx_head][priv->rx_ptr++] = read_scc(cmd, R8); + priv->rx_buf[priv->rx_head][priv->rx_ptr++] = + read_scc_data(priv); else { priv->rx_over = 2; - read_scc(cmd, R8); + read_scc_data(priv); } - special_condition(dev, rc); + special_condition(priv, rc); } } } -static void special_condition(struct net_device *dev, int rc) -{ - struct scc_priv *priv = dev->priv; - int cb, cmd = priv->cmd; +static void special_condition(struct scc_priv *priv, int rc) { + int cb; unsigned long flags; /* See Figure 2-15. Only overrun and EOF need to be checked. */ @@ -959,18 +1044,15 @@ if (rc & Rx_OVR) { /* Receiver overrun */ priv->rx_over = 1; - if (!dev->dma) write_scc(cmd, R0, ERR_RES); + if (priv->param.dma < 0) write_scc(priv, R0, ERR_RES); } else if (rc & END_FR) { /* End of frame. Get byte count */ - if (dev->dma) { - flags=claim_dma_lock(); - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - cb = BUF_SIZE - get_dma_residue(dev->dma) - 2; - release_dma_lock(flags); - + if (priv->param.dma >= 0) { + flags = claim_dma_lock(); + cb = BUF_SIZE - get_dma_residue(priv->param.dma) - 2; + release_dma_lock(flags); } else { - cb = priv->rx_ptr - 2; + cb = priv->rx_ptr - 2; } if (priv->rx_over) { /* We had an overrun */ @@ -980,36 +1062,32 @@ priv->rx_over = 0; } else if (rc & CRC_ERR) { /* Count invalid CRC only if packet length >= minimum */ - if (cb >= 8) { + if (cb >= 15) { priv->stats.rx_errors++; priv->stats.rx_crc_errors++; } } else { - if (cb >= 8) { - /* Put good frame in FIFO */ - priv->rx_len[priv->rx_head] = cb; - priv->rx_head = (priv->rx_head + 1) % NUM_RX_BUF; - priv->rx_count++; - if (priv->rx_count == NUM_RX_BUF) { - /* Disable receiver if FIFO full */ - write_scc(cmd, R3, Rx8); + if (cb >= 15) { + if (priv->rx_count < NUM_RX_BUF - 1) { + /* Put good frame in FIFO */ + priv->rx_len[priv->rx_head] = cb; + priv->rx_head = (priv->rx_head + 1) % NUM_RX_BUF; + priv->rx_count++; + /* Mark bottom half handler */ + queue_task(&priv->rx_task, &tq_immediate); + mark_bh(IMMEDIATE_BH); + } else { priv->stats.rx_errors++; priv->stats.rx_over_errors++; } - /* Mark bottom half handler */ - queue_task(&priv->rx_task, &tq_immediate); - mark_bh(IMMEDIATE_BH); } } /* Get ready for new frame */ - if (dev->dma) { - - flags=claim_dma_lock(); - set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]); - set_dma_count(dev->dma, BUF_SIZE); - enable_dma(dev->dma); + if (priv->param.dma >= 0) { + flags = claim_dma_lock(); + set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]); + set_dma_count(priv->param.dma, BUF_SIZE); release_dma_lock(flags); - } else { priv->rx_ptr = 0; } @@ -1017,12 +1095,8 @@ } -static void rx_bh(void *arg) -{ - struct net_device *dev = arg; - struct scc_priv *priv = dev->priv; - struct scc_info *info = priv->info; - int cmd = priv->cmd; +static void rx_bh(void *arg) { + struct scc_priv *priv = arg; int i = priv->rx_tail; int cb; unsigned long flags; @@ -1045,20 +1119,15 @@ data = skb_put(skb, cb+1); data[0] = 0; memcpy(&data[1], priv->rx_buf[i], cb); - skb->dev = dev; + skb->dev = priv->dev; skb->protocol = ntohs(ETH_P_AX25); skb->mac.raw = skb->data; netif_rx(skb); priv->stats.rx_packets++; + priv->stats.rx_bytes += cb; } save_flags(flags); cli(); - /* Enable receiver if RX buffers have been unavailable */ - if ((priv->rx_count == NUM_RX_BUF) && (priv->status & DCD)) { - if (info->type <= TYPE_PI2) outb_p(0, dev->base_addr + PI_DREQ_MASK); - write_scc(cmd, R3, RxENABLE | Rx8 | RxCRC_ENAB); - if (info->type <= TYPE_PI2) outb_p(1, dev->base_addr + PI_DREQ_MASK); - } /* Move tail */ priv->rx_tail = i = (i + 1) % NUM_RX_BUF; priv->rx_count--; @@ -1068,265 +1137,277 @@ } -static void tx_isr(struct net_device *dev) -{ - struct scc_priv *priv = dev->priv; - int cmd = priv->cmd; +static void tx_isr(struct scc_priv *priv) { int i = priv->tx_tail, p = priv->tx_ptr; /* Suspend TX interrupts if we don't want to send anything. See Figure 2-22. */ if (p == priv->tx_len[i]) { - write_scc(cmd, R0, RES_Tx_P); + write_scc(priv, R0, RES_Tx_P); return; } /* Write characters */ - while ((read_scc(cmd, R0) & Tx_BUF_EMP) && p < priv->tx_len[i]) { - write_scc(cmd, R8, priv->tx_buf[i][p++]); + while ((read_scc(priv, R0) & Tx_BUF_EMP) && p < priv->tx_len[i]) { + write_scc_data(priv, priv->tx_buf[i][p++], 0); } - priv->tx_ptr = p; + /* Reset EOM latch of Z8530 */ + if (!priv->tx_ptr && p && priv->chip == Z8530) + write_scc(priv, R0, RES_EOM_L); + + priv->tx_ptr = p; } -static void es_isr(struct net_device *dev) -{ - struct scc_priv *priv = dev->priv; - struct scc_info *info = priv->info; - int i, cmd = priv->cmd; - int st, dst, res; +static void es_isr(struct scc_priv *priv) { + int i, rr0, drr0, res; unsigned long flags; - /* Read status and reset interrupt bit */ - st = read_scc(cmd, R0); - write_scc(cmd, R0, RES_EXT_INT); - dst = priv->status ^ st; - priv->status = st; - - /* Since the EOM latch is reset automatically, we assume that - it has been zero if and only if we are in the TX_ACTIVE state. - Otherwise we follow 2.4.9.6. */ - - /* Transmit underrun */ - if ((priv->tx_state == TX_ACTIVE) && (st & TxEOM)) { + /* Read status, reset interrupt bit (open latches) */ + rr0 = read_scc(priv, R0); + write_scc(priv, R0, RES_EXT_INT); + drr0 = priv->rr0 ^ rr0; + priv->rr0 = rr0; + + /* Transmit underrun (2.4.9.6). We can't check the TxEOM flag, since + it might have already been cleared again by AUTOEOM. */ + if (priv->state == TX_DATA) { /* Get remaining bytes */ i = priv->tx_tail; - if (dev->dma) { - flags=claim_dma_lock(); - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - res = get_dma_residue(dev->dma); + if (priv->param.dma >= 0) { + disable_dma(priv->param.dma); + flags = claim_dma_lock(); + res = get_dma_residue(priv->param.dma); release_dma_lock(flags); } else { res = priv->tx_len[i] - priv->tx_ptr; - if (res) write_scc(cmd, R0, RES_Tx_P); priv->tx_ptr = 0; } - /* Remove frame from FIFO */ - priv->tx_tail = (i + 1) % NUM_TX_BUF; - priv->tx_count--; - /* Check if another frame is available and we are allowed to transmit */ - if (priv->tx_count && (jiffies - priv->tx_start) < priv->param.txtime) { - if (dev->dma) { - flags=claim_dma_lock(); - set_dma_addr(dev->dma, (int) priv->tx_buf[priv->tx_tail]); - set_dma_count(dev->dma, priv->tx_len[priv->tx_tail]); - enable_dma(dev->dma); - release_dma_lock(flags); - } else { - /* If we have an ESCC, we are allowed to write data bytes - immediately. Otherwise we have to wait for the next - TX interrupt. See Figure 2-22. */ - if (info->chip == Z85230) { - tx_isr(dev); - } - } - } else { - /* No frame available. Disable interrupts. */ - priv->tx_state = TX_SQDELAY; - delay(dev, priv->param.sqdelay); - write_scc(cmd, R15, DCDIE | CTSIE | SYNCIE); - write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN); - } - /* Update packet statistics */ + /* Disable DREQ / TX interrupt */ + if (priv->param.dma >= 0 && priv->type == TYPE_TWIN) + outb(0, priv->card_base + TWIN_DMA_CFG); + else + write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN); if (res) { + /* Update packet statistics */ priv->stats.tx_errors++; priv->stats.tx_fifo_errors++; + /* Other underrun interrupts may already be waiting */ + write_scc(priv, R0, RES_EXT_INT); + write_scc(priv, R0, RES_EXT_INT); } else { + /* Update packet statistics */ priv->stats.tx_packets++; + priv->stats.tx_bytes += priv->tx_len[i]; + /* Remove frame from FIFO */ + priv->tx_tail = (i + 1) % NUM_TX_BUF; + priv->tx_count--; + /* Inform upper layers */ + netif_wake_queue(priv->dev); + } + /* Switch state */ + write_scc(priv, R15, 0); + if (priv->tx_count && + (jiffies - priv->tx_start) < priv->param.txtimeout) { + priv->state = TX_PAUSE; + start_timer(priv, priv->param.txpause, 0); + } else { + priv->state = TX_TAIL; + start_timer(priv, priv->param.txtail, 0); } - /* Inform upper layers */ - netif_wake_queue(dev); } /* DCD transition */ - if ((priv->tx_state < TX_TXDELAY) && (dst & DCD)) { - /* Transmitter state change */ - priv->tx_state = TX_OFF; - /* Enable or disable receiver */ - if (st & DCD) { - if (dev->dma) { - /* Program DMA controller */ - flags=claim_dma_lock(); - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - set_dma_mode(dev->dma, DMA_MODE_READ); - set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]); - set_dma_count(dev->dma, BUF_SIZE); - enable_dma(dev->dma); - release_dma_lock(flags); - /* Configure PackeTwin DMA */ - if (info->type == TYPE_TWIN) { - outb_p((dev->dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3, - dev->base_addr + TWIN_DMA_CFG); - } - /* Sp. cond. intr. only, ext int enable */ - write_scc(cmd, R1, EXT_INT_ENAB | INT_ERR_Rx | - WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB); - } else { - /* Intr. on all Rx characters and Sp. cond., ext int enable */ - write_scc(cmd, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT | - WT_FN_RDYFN); - } - if (priv->rx_count < NUM_RX_BUF) { - /* Enable receiver */ - write_scc(cmd, R3, RxENABLE | Rx8 | RxCRC_ENAB); + if (drr0 & DCD) { + if (rr0 & DCD) { + switch (priv->state) { + case IDLE: + case WAIT: + priv->state = DCD_ON; + write_scc(priv, R15, 0); + start_timer(priv, priv->param.dcdon, 0); } } else { - /* Disable DMA */ - if (dev->dma) - { - flags=claim_dma_lock(); - disable_dma(dev->dma); - release_dma_lock(flags); - } - /* Disable receiver */ - write_scc(cmd, R3, Rx8); - /* DMA disable, RX int disable, Ext int enable */ - write_scc(cmd, R1, EXT_INT_ENAB | WT_RDY_RT | WT_FN_RDYFN); - /* Transmitter state change */ - if (random() > priv->param.persist) - delay(dev, priv->param.slottime); - else { - if (priv->tx_count) { - priv->tx_state = TX_TXDELAY; - write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8); - priv->tx_start = jiffies; - delay(dev, priv->param.txdelay); - } else { - priv->tx_state = TX_IDLE; - } + switch (priv->state) { + case RX_ON: + rx_off(priv); + priv->state = DCD_OFF; + write_scc(priv, R15, 0); + start_timer(priv, priv->param.dcdoff, 0); } } } /* CTS transition */ - if ((info->type <= TYPE_PI2) && (dst & CTS) && (~st & CTS)) { - /* Timer has expired */ - tm_isr(dev); - } - - /* /SYNC/HUNT transition */ - if ((dst & SYNC_HUNT) && (~st & SYNC_HUNT)) { - /* Reset current frame and clear RX FIFO */ - while (read_scc(cmd, R0) & Rx_CH_AV) read_scc(cmd, R8); - priv->rx_over = 0; - if (dev->dma) { - flags=claim_dma_lock(); - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]); - set_dma_count(dev->dma, BUF_SIZE); - enable_dma(dev->dma); - release_dma_lock(flags); + if ((drr0 & CTS) && (~rr0 & CTS) && priv->type != TYPE_TWIN) + tm_isr(priv); + +} + + +static void tm_isr(struct scc_priv *priv) { + switch (priv->state) { + case TX_HEAD: + case TX_PAUSE: + tx_on(priv); + priv->state = TX_DATA; + break; + case TX_TAIL: + write_scc(priv, R5, TxCRC_ENAB | Tx8); + priv->state = RTS_OFF; + if (priv->type != TYPE_TWIN) write_scc(priv, R15, 0); + start_timer(priv, priv->param.rtsoff, 0); + break; + case RTS_OFF: + write_scc(priv, R15, DCDIE); + priv->rr0 = read_scc(priv, R0); + if (priv->rr0 & DCD) { + priv->stats.collisions++; + rx_on(priv); + priv->state = RX_ON; } else { - priv->rx_ptr = 0; + priv->state = WAIT; + start_timer(priv, priv->param.waittime, DCDIE); } + break; + case WAIT: + if (priv->tx_count) { + priv->state = TX_HEAD; + priv->tx_start = jiffies; + write_scc(priv, R5, TxCRC_ENAB | RTS | TxENAB | Tx8); + write_scc(priv, R15, 0); + start_timer(priv, priv->param.txdelay, 0); + } else { + priv->state = IDLE; + if (priv->type != TYPE_TWIN) write_scc(priv, R15, DCDIE); + } + break; + case DCD_ON: + case DCD_OFF: + write_scc(priv, R15, DCDIE); + priv->rr0 = read_scc(priv, R0); + if (priv->rr0 & DCD) { + rx_on(priv); + priv->state = RX_ON; + } else { + priv->state = WAIT; + start_timer(priv, + random()/priv->param.persist*priv->param.slottime, + DCDIE); + } + break; } } -static void tm_isr(struct net_device *dev) -{ - struct scc_priv *priv = dev->priv; - struct scc_info *info = priv->info; - int cmd = priv->cmd; +static inline void tx_on(struct scc_priv *priv) { + int i, n; unsigned long flags; - switch (priv->tx_state) { - case TX_OFF: - if (~priv->status & DCD) { - if (random() > priv->param.persist) delay(dev, priv->param.slottime); - else { - if (priv->tx_count) { - priv->tx_state = TX_TXDELAY; - write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8); - priv->tx_start = jiffies; - delay(dev, priv->param.txdelay); - } else { - priv->tx_state = TX_IDLE; - } - } - } - break; - case TX_TXDELAY: - priv->tx_state = TX_ACTIVE; - if (dev->dma) { - /* Program DMA controller */ - - flags=claim_dma_lock(); - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - set_dma_mode(dev->dma, DMA_MODE_WRITE); - set_dma_addr(dev->dma, (int) priv->tx_buf[priv->tx_tail]); - set_dma_count(dev->dma, priv->tx_len[priv->tx_tail]); - enable_dma(dev->dma); - release_dma_lock(flags); - - /* Configure PackeTwin DMA */ - if (info->type == TYPE_TWIN) { - outb_p((dev->dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3, - dev->base_addr + TWIN_DMA_CFG); - } - /* Enable interrupts and DMA. On the PackeTwin, the DTR//REQ pin - is used for TX DMA requests, but we enable the WAIT/DMA request - pin, anyway */ - write_scc(cmd, R15, TxUIE | DCDIE | CTSIE | SYNCIE); - write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB); - } else { - write_scc(cmd, R15, TxUIE | DCDIE | CTSIE | SYNCIE); - write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB); - tx_isr(dev); + if (priv->param.dma >= 0) { + n = (priv->chip == Z85230) ? 3 : 1; + /* Program DMA controller */ + flags = claim_dma_lock(); + set_dma_mode(priv->param.dma, DMA_MODE_WRITE); + set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n); + set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n); + release_dma_lock(flags); + /* Enable TX underrun interrupt */ + write_scc(priv, R15, TxUIE); + /* Configure DREQ */ + if (priv->type == TYPE_TWIN) + outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3, + priv->card_base + TWIN_DMA_CFG); + else + write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB); + /* Write first byte(s) */ + save_flags(flags); + cli(); + for (i = 0; i < n; i++) + write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1); + enable_dma(priv->param.dma); + restore_flags(flags); + } else { + write_scc(priv, R15, TxUIE); + write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB); + tx_isr(priv); + } + /* Reset EOM latch if we do not have the AUTOEOM feature */ + if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L); +} + + +static inline void rx_on(struct scc_priv *priv) { + unsigned long flags; + + /* Clear RX FIFO */ + while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv); + priv->rx_over = 0; + if (priv->param.dma >= 0) { + /* Program DMA controller */ + flags = claim_dma_lock(); + set_dma_mode(priv->param.dma, DMA_MODE_READ); + set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]); + set_dma_count(priv->param.dma, BUF_SIZE); + release_dma_lock(flags); + enable_dma(priv->param.dma); + /* Configure PackeTwin DMA */ + if (priv->type == TYPE_TWIN) { + outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3, + priv->card_base + TWIN_DMA_CFG); } - if (info->chip == Z8530) write_scc(cmd, R0, RES_EOM_L); - break; - case TX_SQDELAY: - /* Disable transmitter */ - write_scc(cmd, R5, TxCRC_ENAB | Tx8); - /* Transmitter state change: Switch to TX_OFF and wait at least - 1 slottime. */ - priv->tx_state = TX_OFF; - if (~priv->status & DCD) delay(dev, priv->param.waittime); + /* Sp. cond. intr. only, ext int enable, RX DMA enable */ + write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx | + WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB); + } else { + /* Reset current frame */ + priv->rx_ptr = 0; + /* Intr. on all Rx characters and Sp. cond., ext int enable */ + write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT | + WT_FN_RDYFN); } + write_scc(priv, R0, ERR_RES); + write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB); } -static inline void delay(struct net_device *dev, int t) -{ - struct scc_priv *priv = dev->priv; - int tmr = priv->tmr; +static inline void rx_off(struct scc_priv *priv) { + /* Disable receiver */ + write_scc(priv, R3, Rx8); + /* Disable DREQ / RX interrupt */ + if (priv->param.dma >= 0 && priv->type == TYPE_TWIN) + outb(0, priv->card_base + TWIN_DMA_CFG); + else + write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN); + /* Disable DMA */ + if (priv->param.dma >= 0) disable_dma(priv->param.dma); +} + + +static void start_timer(struct scc_priv *priv, int t, int r15) { + unsigned long flags; - outb_p(t & 0xFF, tmr); - outb_p((t >> 8) & 0xFF, tmr); + outb(priv->tmr_mode, priv->tmr_ctrl); + if (t == 0) { + tm_isr(priv); + } else if (t > 0) { + save_flags(flags); + cli(); + outb(t & 0xFF, priv->tmr_cnt); + outb((t >> 8) & 0xFF, priv->tmr_cnt); + if (priv->type != TYPE_TWIN) { + write_scc(priv, R15, r15 | CTSIE); + priv->rr0 |= CTS; + } + restore_flags(flags); + } } -static inline unsigned char random(void) -{ +static inline unsigned char random(void) { /* See "Numerical Recipes in C", second edition, p. 284 */ rand = rand * 1664525L + 1013904223L; return (unsigned char) (rand >> 24); } - diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/hamradio/soundmodem/sm.c linux/drivers/net/hamradio/soundmodem/sm.c --- v2.4.0-test2/linux/drivers/net/hamradio/soundmodem/sm.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/hamradio/soundmodem/sm.c Wed Jul 5 12:59:11 2000 @@ -46,6 +46,7 @@ * removed some pre-2.2 kernel compatibility cruft * 0.10 10.08.1999 Check if parport can do SPP and is safe to access during interrupt contexts * 0.11 12.02.2000 adapted to softnet driver interface + * 0.12 03.07.2000 fix interface name handling */ /*****************************************************************************/ @@ -65,7 +66,7 @@ /*static*/ const char sm_drvname[] = "soundmodem"; static const char sm_drvinfo[] = KERN_INFO "soundmodem: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "soundmodem: version 0.11 compiled " __TIME__ " " __DATE__ "\n"; +KERN_INFO "soundmodem: version 0.12 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ @@ -648,8 +649,9 @@ */ for (i = 0; i < NR_PORTS; i++) { struct net_device *dev = sm_device+i; - sprintf(dev->name, "sm%d", i); + char ifname[IFNAMSIZ]; + sprintf(ifname, "sm%d", i); if (!mode[i]) set_hw = 0; else { @@ -671,7 +673,7 @@ } if (!set_hw) iobase[i] = irq[i] = 0; - j = hdlcdrv_register_hdlcdrv(dev, &sm_ops, sizeof(struct sm_state), dev->name, iobase[i], irq[i], dma[i]); + j = hdlcdrv_register_hdlcdrv(dev, &sm_ops, sizeof(struct sm_state), ifname, iobase[i], irq[i], dma[i]); if (!j) { sm = (struct sm_state *)dev->priv; sm->hdrv.ptt_out.dma2 = dma2[i]; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/irda/nsc-ircc.c linux/drivers/net/irda/nsc-ircc.c --- v2.4.0-test2/linux/drivers/net/irda/nsc-ircc.c Mon Mar 27 08:08:26 2000 +++ linux/drivers/net/irda/nsc-ircc.c Wed Jul 5 10:56:13 2000 @@ -1989,7 +1989,6 @@ static void nsc_ircc_wakeup(struct nsc_ircc_cb *self) { - struct net_device *dev = self->netdev; int iobase; if (!self->io.suspended) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/irda/smc-ircc.c linux/drivers/net/irda/smc-ircc.c --- v2.4.0-test2/linux/drivers/net/irda/smc-ircc.c Sat Feb 26 22:31:47 2000 +++ linux/drivers/net/irda/smc-ircc.c Wed Jul 5 10:56:13 2000 @@ -83,7 +83,9 @@ static void ircc_dma_xmit(struct ircc_cb *self, int iobase, int bofs); static void ircc_change_speed(void *priv, __u32 speed); static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs); +#if 0 /* unused */ static int ircc_is_receiving(struct ircc_cb *self); +#endif /* unused */ static int ircc_net_open(struct net_device *dev); static int ircc_net_close(struct net_device *dev); @@ -789,7 +791,6 @@ */ static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase) { - unsigned long flags; struct sk_buff *skb; int len, msgcnt; @@ -893,6 +894,7 @@ spin_unlock(&self->lock); } +#if 0 /* unused */ /* * Function ircc_is_receiving (self) * @@ -915,6 +917,7 @@ return status; } +#endif /* unused */ /* * Function ircc_net_open (dev) @@ -990,8 +993,6 @@ static void ircc_suspend(struct ircc_cb *self) { - int i = 10; - MESSAGE("%s, Suspending\n", driver_name); if (self->io.suspended) @@ -1004,7 +1005,6 @@ static void ircc_wakeup(struct ircc_cb *self) { - struct net_device *dev = self->netdev; unsigned long flags; if (!self->io.suspended) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/ncr885e.c linux/drivers/net/ncr885e.c --- v2.4.0-test2/linux/drivers/net/ncr885e.c Tue May 23 15:31:35 2000 +++ linux/drivers/net/ncr885e.c Wed Jul 5 10:56:12 2000 @@ -1144,18 +1144,11 @@ unsigned char *p; int i; - dev = init_etherdev(NULL, 0 ); - - /* construct private data for the 885 ethernet */ - dev->priv = kmalloc( sizeof( struct ncr885e_private ), GFP_KERNEL ); - - if ( dev->priv == NULL ) { - release_region( ioaddr, NCR885E_TOTAL_SIZE ); + dev = init_etherdev( NULL, sizeof( struct ncr885e_private ) ); + if (!dev) return -ENOMEM; - } - sp = (struct ncr885e_private *) dev->priv; - memset( sp, 0, sizeof( struct ncr885e_private )); + sp = dev->priv; /* snag the station address and display it */ for( i = 0; i < 3; i++ ) { @@ -1210,7 +1203,8 @@ unsigned short cmd; unsigned char irq, latency; - while(( pdev = pci_find_device( PCI_VENDOR_ID_NCR, + /* use 'if' not 'while' where because driver only supports one device */ + if (( pdev = pci_find_device( PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C885_ETHERNET, pdev )) != NULL ) { @@ -1219,47 +1213,27 @@ printk( KERN_INFO "%s", version ); } + if (pci_enable_device(pdev)) + continue; + /* Use I/O space */ - pci_read_config_dword( pdev, PCI_BASE_ADDRESS_0, &ioaddr ); - pci_read_config_byte( pdev, PCI_INTERRUPT_LINE, &irq ); + ioaddr = pci_resource_start (pdev, 0); + irq = pdev->irq; - ioaddr &= ~3; /* Adjust around the Grackle... */ #ifdef CONFIG_GEMINI ioaddr |= 0xfe000000; #endif - if ( check_region( ioaddr, NCR885E_TOTAL_SIZE )) + if ( !request_region( ioaddr, NCR885E_TOTAL_SIZE, "ncr885e" )) continue; /* finish off the probe */ if ( !(ncr885e_probe1(ioaddr, irq ))) { - chips++; - - /* Access is via I/O space, bus master enabled... */ - pci_read_config_word( pdev, PCI_COMMAND, &cmd ); - - if ( !(cmd & PCI_COMMAND_MASTER) ) { - printk( KERN_INFO " PCI master bit not set! Now setting.\n"); - cmd |= PCI_COMMAND_MASTER; - pci_write_config_word( pdev, PCI_COMMAND, cmd ); - } - - if ( !(cmd & PCI_COMMAND_IO) ) { - printk( KERN_INFO " Enabling I/O space.\n" ); - cmd |= PCI_COMMAND_IO; - pci_write_config_word( pdev, PCI_COMMAND, cmd ); - } - - pci_read_config_byte( pdev, PCI_LATENCY_TIMER, &latency ); - - if ( latency < 10 ) { - printk( KERN_INFO " PCI latency timer (CFLT) is unreasonably" - " low at %d. Setting to 255.\n", latency ); - pci_write_config_byte( pdev, PCI_LATENCY_TIMER, 255 ); - } - } + pci_set_master (pdev); + } else + release_region( ioaddr, NCR885E_TOTAL_SIZE ); } if ( !chips ) @@ -1401,14 +1375,10 @@ static void __exit cleanup_module(void) { - struct ncr885e_private *np; - if ( root_dev ) { - unregister_netdev( root_dev ); - np = (struct ncr885e_private *) root_dev->priv; release_region( root_dev->base_addr, NCR885E_TOTAL_SIZE ); - kfree( root_dev->priv ); + kfree( root_dev ); root_dev = NULL; } } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/ne.c linux/drivers/net/ne.c --- v2.4.0-test2/linux/drivers/net/ne.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/ne.c Sat Jul 8 19:38:16 2000 @@ -229,7 +229,7 @@ for (i = 0; pci_clone_list[i].vendor != 0; i++) { struct pci_dev *pdev = NULL; - unsigned int pci_ioaddr; + unsigned int pci_ioaddr = 0; while ((pdev = pci_find_device(pci_clone_list[i].vendor, pci_clone_list[i].dev_id, pdev))) { if (pci_enable_device(pdev)) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/pcmcia/aironet4500_cs.c linux/drivers/net/pcmcia/aironet4500_cs.c --- v2.4.0-test2/linux/drivers/net/pcmcia/aironet4500_cs.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/pcmcia/aironet4500_cs.c Wed Jul 5 10:56:13 2000 @@ -602,7 +602,7 @@ -static int aironet_cs_init(void) +static int __init aironet_cs_init(void) { servinfo_t serv; @@ -619,7 +619,7 @@ return 0; } -static void aironet_cs_exit(void) +static void __exit aironet_cs_exit(void) { DEBUG(0, "awc_cs: unloading %c ",'\n'); unregister_pcmcia_driver(&dev_info); @@ -635,5 +635,5 @@ } module_init(aironet_cs_init); -module_exit(aironet_cs_init); +module_exit(aironet_cs_exit); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/pppoe.c linux/drivers/net/pppoe.c --- v2.4.0-test2/linux/drivers/net/pppoe.c Tue May 23 15:31:35 2000 +++ linux/drivers/net/pppoe.c Wed Jul 5 22:15:27 2000 @@ -5,7 +5,9 @@ * PPPoE --- PPP over Ethernet (RFC 2516) * * - * Version: 0.5.0 + * Version: 0.5.1 + * + * 030700 : Fixed connect logic to allow for disconnect * * Author: Michal Ostrowski * @@ -545,7 +547,7 @@ goto end; error = -EBUSY; - if (sk->state & PPPOX_CONNECTED) + if ((sk->state & PPPOX_CONNECTED) && sp->sa_addr.pppoe.sid) goto end; dev = dev_get_by_name(sp->sa_addr.pppoe.dev); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/sgiseeq.c linux/drivers/net/sgiseeq.c --- v2.4.0-test2/linux/drivers/net/sgiseeq.c Tue May 23 15:31:35 2000 +++ linux/drivers/net/sgiseeq.c Sun Jul 9 22:21:41 2000 @@ -326,6 +326,7 @@ skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); sp->stats.rx_packets++; + sp->stats.rx_bytes += len; } else { printk ("%s: Memory squeeze, deferring packet.\n", dev->name); @@ -500,6 +501,7 @@ /* Setup... */ skblen = skb->len; len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; + sp->stats.tx_bytes += len; entry = sp->tx_new; td = &sp->srings.tx_desc[entry]; @@ -690,7 +692,7 @@ int sgiseeq_probe(struct net_device *dev) { - static int initialized; + static int initialized = 0; char *ep; if (initialized) /* Already initialized? */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/shaper.c linux/drivers/net/shaper.c --- v2.4.0-test2/linux/drivers/net/shaper.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/shaper.c Thu Jun 29 10:09:01 2000 @@ -300,7 +300,6 @@ { struct shaper *sh=(struct shaper *)data; shaper_kick(sh); - timer_exit(&sh->timer); } /* diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/sk98lin/skvpd.c linux/drivers/net/sk98lin/skvpd.c --- v2.4.0-test2/linux/drivers/net/sk98lin/skvpd.c Tue Nov 23 22:42:21 1999 +++ linux/drivers/net/sk98lin/skvpd.c Wed Jul 5 10:56:13 2000 @@ -233,6 +233,7 @@ 2: error, data verify error */ +#if 0 /* unused */ static int VpdWriteDWord( SK_AC *pAC, /* pAC pointer */ SK_IOC IoC, /* IO Context */ @@ -264,6 +265,7 @@ } return(0) ; } +#endif /* unused */ /* * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c --- v2.4.0-test2/linux/drivers/net/sk_g16.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/sk_g16.c Wed Jul 5 10:56:13 2000 @@ -19,6 +19,8 @@ * Paul Gortmaker, 03/97: Fix for v2.1.x to use read{b,w} * write{b,w} and memcpy -> memcpy_{to,from}io * + * Jeff Garzik, 06/2000, Modularize + * -*/ static const char *rcsid = "$Id: sk_g16.c,v 1.1 1994/06/30 16:25:15 root Exp $"; @@ -53,8 +55,10 @@ * - Try to find out if the board is in 8 Bit or 16 Bit slot. * If in 8 Bit mode don't use IRQ 11. * - (Try to make it slightly faster.) + * - Power management support */ +#include #include #include #include @@ -455,7 +459,8 @@ /* static variables */ static SK_RAM *board; /* pointer to our memory mapped board components */ - +static struct net_device *SK_dev; +unsigned long SK_ioaddr; static spinlock_t SK_lock = SPIN_LOCK_UNLOCKED; /* Macros */ @@ -537,7 +542,7 @@ int __init SK_init(struct net_device *dev) { - int ioaddr = 0; /* I/O port address used for POS regs */ + int ioaddr; /* I/O port address used for POS regs */ int *port, ports[] = SK_IO_PORTS; /* SK_G16 supported ports */ /* get preconfigured base_addr from dev which is done in Space.c */ @@ -548,15 +553,23 @@ if (base_addr > 0x0ff) /* Check a single specified address */ { + int rc = -ENODEV; + + ioaddr = base_addr; + /* Check if on specified address is a SK_G16 */ + if (!request_region(ioaddr, ETHERCARD_TOTAL_SIZE, "sk_g16")) + return -EBUSY; if ( (inb(SK_POS0) == SK_IDLOW) || (inb(SK_POS1) == SK_IDHIGH) ) { - return SK_probe(dev, base_addr); + rc = SK_probe(dev, ioaddr); } - return -ENODEV; /* Sorry, but on specified address NO SK_G16 */ + if (rc) + release_region(ioaddr, ETHERCARD_TOTAL_SIZE); + return rc; } else if (base_addr > 0) /* Don't probe at all */ { @@ -571,7 +584,7 @@ /* Check if I/O Port region is used by another board */ - if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE)) + if (!request_region(ioaddr, ETHERCARD_TOTAL_SIZE, "sk_g16")) { continue; /* Try next Port address */ } @@ -581,6 +594,7 @@ if ( !(inb(SK_POS0) == SK_IDLOW) || !(inb(SK_POS1) == SK_IDHIGH) ) { + release_region(ioaddr, ETHERCARD_TOTAL_SIZE); continue; /* Try next Port address */ } @@ -590,6 +604,8 @@ { return 0; /* Card found and initialized */ } + + release_region(ioaddr, ETHERCARD_TOTAL_SIZE); } dev->base_addr = base_addr; /* Write back original base_addr */ @@ -598,6 +614,61 @@ } /* End of SK_init */ + +MODULE_AUTHOR("Patrick J.D. Weichmann"); +MODULE_DESCRIPTION("Schneider & Koch G16 Ethernet Device Driver"); +MODULE_PARM(io, "i"); +MODULE_PARM_DESC(io, "0 to probe common ports (unsafe), or the I/O base of the board"); + + +#ifdef MODULE +static int io = 0; /* 0 == probe */ + +static int __init SK_init_module (void) +{ + int rc; + + SK_dev = init_etherdev (NULL, 0); + if (!SK_dev) + return -ENOMEM; + + rc = SK_init (SK_dev); + if (rc) { + unregister_netdev (SK_dev); + kfree (SK_dev); + SK_dev = NULL; + } + + return rc; +} +#endif /* MODULE */ + + +static void __exit SK_cleanup_module (void) +{ + if (SK_dev) { + if (SK_dev->priv) { + kfree(SK_dev->priv); + SK_dev->priv = NULL; + } + unregister_netdev(SK_dev); + kfree(SK_dev); + SK_dev = NULL; + } + if (SK_ioaddr) { + release_region(SK_ioaddr, ETHERCARD_TOTAL_SIZE); + SK_ioaddr = 0; + } + +} + + +#ifdef MODULE +module_init(SK_init_module); +#endif +module_exit(SK_cleanup_module); + + /*- * Function : SK_probe @@ -774,9 +845,6 @@ } memset((char *) dev->priv, 0, sizeof(struct priv)); /* clear memory */ - /* Grab the I/O Port region */ - request_region(ioaddr, ETHERCARD_TOTAL_SIZE,"sk_g16"); - /* Assign our Device Driver functions */ dev->open = SK_open; @@ -817,6 +885,9 @@ SK_print_ram(dev); #endif + SK_dev = dev; + SK_ioaddr = ioaddr; + return 0; /* Initialization done */ } /* End of SK_probe() */ @@ -1078,8 +1149,7 @@ /* Prepare LANCE Control and Status Registers */ - save_flags(flags); - cli(); + spin_lock_irqsave(&SK_lock, flags); SK_write_reg(CSR3, CSR3_ACON); /* Ale Control !!!THIS MUST BE SET!!!! */ @@ -1114,7 +1184,7 @@ SK_write_reg(CSR0, CSR0_INIT); - restore_flags(flags); + spin_unlock_irqrestore(&SK_lock, flags); /* Wait until LANCE finished initialization */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/sk_mca.c linux/drivers/net/sk_mca.c --- v2.4.0-test2/linux/drivers/net/sk_mca.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/sk_mca.c Mon Jun 26 11:31:28 2000 @@ -95,10 +95,8 @@ #include #include -#ifdef MODULE #include #include -#endif #include #include diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/skfp/ecm.c linux/drivers/net/skfp/ecm.c --- v2.4.0-test2/linux/drivers/net/skfp/ecm.c Sun Feb 20 21:12:39 2000 +++ linux/drivers/net/skfp/ecm.c Wed Jul 5 10:56:13 2000 @@ -432,8 +432,8 @@ static void prop_actions(smc) struct s_smc *smc ; { - int port_in ; - int port_out ; + int port_in = 0 ; + int port_out = 0 ; RS_SET(smc,RS_EVENT) ; switch (smc->s.sas) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/skfp/ess.c linux/drivers/net/skfp/ess.c --- v2.4.0-test2/linux/drivers/net/skfp/ess.c Sun Feb 20 21:12:39 2000 +++ linux/drivers/net/skfp/ess.c Wed Jul 5 10:56:13 2000 @@ -64,8 +64,8 @@ static const u_short plist_raf_chg_req[] = { SMT_P320B, SMT_P320F, SMT_P3210, SMT_P001A, 0 } ; -static const struct fddi_addr smt_sba_da = {0x80,0x01,0x43,0x00,0x80,0x0C} ; -static const struct fddi_addr null_addr = {0,0,0,0,0,0} ; +static const struct fddi_addr smt_sba_da = {{0x80,0x01,0x43,0x00,0x80,0x0C}} ; +static const struct fddi_addr null_addr = {{0,0,0,0,0,0}} ; /* ------------------------------------------------------------- diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/skfp/fplustm.c linux/drivers/net/skfp/fplustm.c --- v2.4.0-test2/linux/drivers/net/skfp/fplustm.c Fri May 12 14:18:55 2000 +++ linux/drivers/net/skfp/fplustm.c Wed Jul 5 10:56:13 2000 @@ -69,9 +69,9 @@ } \ } -const struct fddi_addr fddi_broadcast = {0xff,0xff,0xff,0xff,0xff,0xff}; -static const struct fddi_addr null_addr = {0,0,0,0,0,0} ; -static const struct fddi_addr dbeacon_multi = {0x01,0x80,0xc2,0x00,0x01,0x00}; +const struct fddi_addr fddi_broadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; +static const struct fddi_addr null_addr = {{0,0,0,0,0,0}}; +static const struct fddi_addr dbeacon_multi = {{0x01,0x80,0xc2,0x00,0x01,0x00}}; static const u_short my_said = 0xffff ; /* short address (n.u.) */ static const u_short my_sagp = 0xffff ; /* short group address (n.u.) */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/skfp/smt.c linux/drivers/net/skfp/smt.c --- v2.4.0-test2/linux/drivers/net/skfp/smt.c Sun Feb 20 21:12:39 2000 +++ linux/drivers/net/skfp/smt.c Wed Jul 5 10:56:13 2000 @@ -51,7 +51,7 @@ #define LAST_CLASS (SMT_PMF_SET) static const struct fddi_addr SMT_Unknown = { - 0,0,0x1f,0,0,0 + { 0,0,0x1f,0,0,0 } } ; /* diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/skfp/srf.c linux/drivers/net/skfp/srf.c --- v2.4.0-test2/linux/drivers/net/skfp/srf.c Sun Feb 20 21:12:39 2000 +++ linux/drivers/net/skfp/srf.c Wed Jul 5 10:56:13 2000 @@ -391,7 +391,7 @@ int i ; static const struct fddi_addr SMT_SRF_DA = { - 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 + { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 } } ; /* diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/slhc.c linux/drivers/net/slhc.c --- v2.4.0-test2/linux/drivers/net/slhc.c Tue May 23 15:31:35 2000 +++ linux/drivers/net/slhc.c Thu Jul 6 19:27:48 2000 @@ -56,6 +56,7 @@ #include #include #include +#include #ifdef CONFIG_INET /* Entire module is for IP only */ @@ -78,7 +79,6 @@ #include #include #include -#include #include int last_retran; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/slip.c linux/drivers/net/slip.c --- v2.4.0-test2/linux/drivers/net/slip.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/slip.c Thu Jun 29 10:09:01 2000 @@ -1479,7 +1479,6 @@ } out: spin_unlock(&sl->lock); - timer_exit(&sl->outfill_timer); } static void sl_keepalive(unsigned long sls) @@ -1511,7 +1510,6 @@ out: spin_unlock(&sl->lock); - timer_exit(&sl->keepalive_timer); } #endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/smc9194.c linux/drivers/net/smc9194.c --- v2.4.0-test2/linux/drivers/net/smc9194.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/smc9194.c Wed Jul 5 10:56:13 2000 @@ -1591,9 +1591,8 @@ #ifdef MODULE -static char devicename[9] = { 0, }; static struct net_device devSMC9194 = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ + "", /* device name is inserted by linux/drivers/net/net_init.c */ 0, 0, 0, 0, 0, 0, /* I/O address, IRQ */ 0, 0, 0, NULL, smc_init }; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/starfire.c linux/drivers/net/starfire.c --- v2.4.0-test2/linux/drivers/net/starfire.c Tue May 23 15:31:35 2000 +++ linux/drivers/net/starfire.c Thu Jun 29 10:14:01 2000 @@ -26,6 +26,9 @@ LK1.1.2 (jgarzik): - Merge Becker version 0.15 + + LK1.1.3 (Andrew Morton) + - Timer cleanups */ /* The user-configurable values. @@ -100,7 +103,7 @@ /* These identify the driver base version and may not be removed. */ static char version1[] __devinitdata = -"starfire.c:v0.15+LK1.1.2 4/28/2000 Written by Donald Becker \n"; +"starfire.c:v0.15+LK1.1.3 6/17/2000 Written by Donald Becker \n"; static char version2[] __devinitdata = " Updates and info at http://www.scyld.com/network/starfire.html\n"; @@ -536,15 +539,16 @@ { struct netdev_private *np = (struct netdev_private *)dev->priv; long ioaddr = dev->base_addr; - int i; + int i, retval; /* Do we ever need to reset the chip??? */ MOD_INC_USE_COUNT; - if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) { + retval = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev); + if (retval) { MOD_DEC_USE_COUNT; - return -EAGAIN; + return retval; } /* Disable the Rx and Tx, and reset the chip. */ @@ -1260,6 +1264,8 @@ netif_stop_queue(dev); + del_timer_sync(&np->timer); + if (debug > 1) { printk(KERN_DEBUG "%s: Shutting down ethercard, status was Int %4.4x.\n", dev->name, readl(ioaddr + IntrStatus)); @@ -1271,8 +1277,6 @@ writel(0, ioaddr + IntrEnable); /* Stop the chip's Tx and Rx processes. */ - - del_timer(&np->timer); #ifdef __i386__ if (debug > 2) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c --- v2.4.0-test2/linux/drivers/net/sunlance.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/sunlance.c Wed Jul 5 22:15:25 2000 @@ -1,4 +1,4 @@ -/* $Id: sunlance.c,v 1.101 2000/06/19 06:24:46 davem Exp $ +/* $Id: sunlance.c,v 1.102 2000/06/30 10:18:35 davem Exp $ * lance.c: Linux/Sparc/Lance driver * * Written 1995, 1996 by Miguel de Icaza @@ -1287,10 +1287,8 @@ static void lance_set_multicast_retry(unsigned long _opaque) { struct net_device *dev = (struct net_device *) _opaque; - struct lance_private *lp = (struct lance_private *) dev->priv; lance_set_multicast(dev); - timer_exit(&lp->multicast_timer); } static void lance_free_hwresources(struct lance_private *lp) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/tokenring/ibmtr.c linux/drivers/net/tokenring/ibmtr.c --- v2.4.0-test2/linux/drivers/net/tokenring/ibmtr.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/tokenring/ibmtr.c Wed Jul 5 10:56:13 2000 @@ -295,7 +295,9 @@ struct tok_info *ti=0; __u32 cd_chanid; unsigned char *tchanid, ctemp; +#ifndef PCMCIA unsigned long timeout; +#endif #ifndef MODULE #ifndef PCMCIA diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/tulip/21142.c linux/drivers/net/tulip/21142.c --- v2.4.0-test2/linux/drivers/net/tulip/21142.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/tulip/21142.c Thu Jun 29 10:14:01 2000 @@ -198,7 +198,7 @@ && (csr12 & 2) == 2) || (tp->nway && (csr5 & (TPLnkFail)))) { /* Link blew? Maybe restart NWay. */ - del_timer(&tp->timer); + del_timer_sync(&tp->timer); t21142_start_nway(dev); tp->timer.expires = RUN_AT(3*HZ); add_timer(&tp->timer); @@ -208,7 +208,7 @@ dev->name, medianame[dev->if_port], (csr12 & 2) ? "failed" : "good"); if ((csr12 & 2) && ! tp->medialock) { - del_timer(&tp->timer); + del_timer_sync(&tp->timer); t21142_start_nway(dev); tp->timer.expires = RUN_AT(3*HZ); add_timer(&tp->timer); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/tulip/interrupt.c linux/drivers/net/tulip/interrupt.c --- v2.4.0-test2/linux/drivers/net/tulip/interrupt.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/tulip/interrupt.c Thu Jun 29 10:14:01 2000 @@ -298,6 +298,10 @@ tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; tulip_outl_csr(tp, tp->csr6 | csr6_st | csr6_sr, CSR6); } + /* + * NB: t21142_lnk_change() does a del_timer_sync(), so be careful if this + * call is ever done under the spinlock + */ if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) { if (tp->link_change) (tp->link_change)(dev, csr5); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c --- v2.4.0-test2/linux/drivers/net/tulip/tulip_core.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/tulip/tulip_core.c Thu Jun 29 10:14:01 2000 @@ -19,7 +19,7 @@ */ -static const char version[] = "Linux Tulip driver version 0.9.6 (May 31, 2000)\n"; +static const char version[] = "Linux Tulip driver version 0.9.7 (June 17, 2000)\n"; #include #include "tulip.h" @@ -401,11 +401,12 @@ static int tulip_open(struct net_device *dev) { + int retval; MOD_INC_USE_COUNT; - - if (request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev)) { + + if ((retval = request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev))) { MOD_DEC_USE_COUNT; - return -EBUSY; + return retval; } tulip_init_ring (dev); @@ -639,7 +640,7 @@ struct tulip_private *tp = (struct tulip_private *) dev->priv; unsigned long flags; - del_timer (&tp->timer); + del_timer_sync (&tp->timer); spin_lock_irqsave (&tp->lock, flags); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/wan/comx-proto-lapb.c linux/drivers/net/wan/comx-proto-lapb.c --- v2.4.0-test2/linux/drivers/net/wan/comx-proto-lapb.c Tue May 23 15:31:35 2000 +++ linux/drivers/net/wan/comx-proto-lapb.c Wed Jul 5 10:56:13 2000 @@ -518,11 +518,7 @@ NULL }; -#ifdef MODULE -#define comx_proto_lapb_init init_module -#endif - -__initfunc(int comx_proto_lapb_init(void)) +int __init comx_proto_lapb_init(void) { int ret; @@ -532,11 +528,13 @@ return comx_register_protocol(&comx25_protocol); } -#ifdef MODULE -void cleanup_module(void) +static void __exit comx_proto_lapb_exit(void) { comx_unregister_protocol(comxlapb_protocol.name); comx_unregister_protocol(comx25_protocol.name); } -#endif /* MODULE */ +#ifdef MODULE +module_init(comx_proto_lapb_init); +#endif +module_exit(comx_proto_lapb_exit); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/wan/cosa.c linux/drivers/net/wan/cosa.c --- v2.4.0-test2/linux/drivers/net/wan/cosa.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/wan/cosa.c Thu Jun 29 18:25:51 2000 @@ -395,7 +395,7 @@ cosa_cards[i].num = -1; for (i=0; io[i] != 0 && i < MAX_CARDS; i++) cosa_probe(io[i], irq[i], dma[i]); - devfs_handle = devfs_mk_dir (NULL, "cosa", 4, NULL); + devfs_handle = devfs_mk_dir (NULL, "cosa", NULL); devfs_register_series (devfs_handle, "%u", nr_cards, DEVFS_FL_DEFAULT, cosa_major, 0, S_IFCHR | S_IRUSR | S_IWUSR, diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/wan/hostess_sv11.c linux/drivers/net/wan/hostess_sv11.c --- v2.4.0-test2/linux/drivers/net/wan/hostess_sv11.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/wan/hostess_sv11.c Wed Jul 5 10:56:13 2000 @@ -222,19 +222,17 @@ { struct z8530_dev *dev; struct sv11_device *sv; - int i; unsigned long flags; /* * Get the needed I/O space */ - if(check_region(iobase, 8)) + if(!request_region(iobase, 8, "Comtrol SV11")) { printk(KERN_WARNING "hostess: I/O 0x%X already in use.\n", iobase); return NULL; } - request_region(iobase, 8, "Comtrol SV11"); sv=(struct sv11_device *)kmalloc(sizeof(struct sv11_device), GFP_KERNEL); if(!sv) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/wan/lmc/lmc_main.c linux/drivers/net/wan/lmc/lmc_main.c --- v2.4.0-test2/linux/drivers/net/wan/lmc/lmc_main.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/wan/lmc/lmc_main.c Wed Jul 5 10:56:14 2000 @@ -1043,7 +1043,6 @@ { int pci_index = 0; unsigned long pci_ioaddr; - unsigned short pci_command; unsigned int pci_irq_line; u16 vendor, subvendor, device, subdevice; u32 foundaddr = 0; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog --- v2.4.0-test2/linux/drivers/parport/ChangeLog Fri Jun 23 21:55:09 2000 +++ linux/drivers/parport/ChangeLog Wed Jul 5 12:56:01 2000 @@ -1,3 +1,30 @@ +2000-06-30 Petr Vandrovec + + * procfs.c (do_hardware_modes): Generated string can be up to 34 + chars long. + +2000-06-20 Gunther Mayer + + * parport_pc.c (parport_pc_compat_write_block_pio): Warn about + change_mode failures. + (parport_pc_ecp_write_block_pio): Likewise. + (parport_pc_ecp_read_block_pio): Likewise. + +2000-06-20 Gunther Mayer + + * parport_pc.c (parport_SPP_supported): Warn more about possibly + incorrect parameters. + +2000-06-15 Tim Waugh + + * parport_pc.c (parport_ECP_supported): Set PARPORT_MODE_COMPAT + for ECP ports, since they can all do hardware accelerated + compatibility mode (I assume). + +2000-06-13 Tim Waugh + + * parport_pc.c (cleanup_module): Remark about possible bugs. + 2000-06-13 Tim Waugh * procfs.c: Break 'hardware' out into separate files. diff -u --recursive --new-file v2.4.0-test2/linux/drivers/parport/daisy.c linux/drivers/parport/daisy.c --- v2.4.0-test2/linux/drivers/parport/daisy.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/parport/daisy.c Sat Jul 8 19:47:19 2000 @@ -14,6 +14,10 @@ * 13-03-1999: Get DeviceID from non-IEEE 1284.3 devices too. * 22-02-2000: Count devices that are actually detected. * + * The block comments above the functions in this file are + * licensed as part of the generated file + * Documentation/DocBook/parportbook.sgml under the GNU Free + * Documentation License. */ #include diff -u --recursive --new-file v2.4.0-test2/linux/drivers/parport/ieee1284.c linux/drivers/parport/ieee1284.c --- v2.4.0-test2/linux/drivers/parport/ieee1284.c Tue May 23 15:31:35 2000 +++ linux/drivers/parport/ieee1284.c Sat Jul 8 19:47:19 2000 @@ -8,6 +8,11 @@ * * This file is responsible for IEEE 1284 negotiation, and for handing * read/write requests to low-level drivers. + * + * The block comments above the functions in this file are + * licensed as part of the generated file + * Documentation/DocBook/parportbook.sgml under the GNU Free + * Documentation License. */ #include diff -u --recursive --new-file v2.4.0-test2/linux/drivers/parport/init.c linux/drivers/parport/init.c --- v2.4.0-test2/linux/drivers/parport/init.c Mon Mar 27 08:08:27 2000 +++ linux/drivers/parport/init.c Wed Jul 5 17:57:27 2000 @@ -20,7 +20,9 @@ #ifndef MODULE static int io[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 }; +#ifdef CONFIG_PARPORT_PC static int io_hi[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 }; +#endif static int irq[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_IRQ_PROBEONLY }; static int dma[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_DMA_NONE }; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c --- v2.4.0-test2/linux/drivers/parport/parport_pc.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/parport/parport_pc.c Wed Jul 5 12:56:01 2000 @@ -714,7 +714,9 @@ /* Set up parallel port FIFO mode.*/ parport_pc_data_forward (port); /* Must be in PS2 mode */ parport_pc_frob_control (port, PARPORT_CONTROL_STROBE, 0); - change_mode (port, ECR_PPF); /* Parallel port FIFO */ + r = change_mode (port, ECR_PPF); /* Parallel port FIFO */ + if (r) printk (KERN_DEBUG "%s: Warning change_mode ECR_PPF failed\n", port->name); + port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; /* Write the data to the FIFO. */ @@ -793,7 +795,8 @@ PARPORT_CONTROL_STROBE | PARPORT_CONTROL_AUTOFD, 0); - change_mode (port, ECR_ECP); /* ECP FIFO */ + r = change_mode (port, ECR_ECP); /* ECP FIFO */ + if (r) printk (KERN_DEBUG "%s: Warning change_mode ECR_ECP failed\n", port->name); port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; /* Write the data to the FIFO. */ @@ -917,7 +920,8 @@ PARPORT_CONTROL_STROBE | PARPORT_CONTROL_AUTOFD, 0); - change_mode (port, ECR_ECP); /* ECP FIFO */ + r = change_mode (port, ECR_ECP); /* ECP FIFO */ + if (r) printk (KERN_DEBUG "%s: Warning change_mode ECR_ECP failed\n", port->name); port->ieee1284.phase = IEEE1284_PH_REV_DATA; /* Do the transfer. */ @@ -1412,6 +1416,12 @@ /* * Checks for port existence, all ports support SPP MODE + * Returns: + * 0 : No parallel port at this adress + * PARPORT_MODE_PCSPP : SPP port detected + * (if the user specified an ioport himself, + * this shall always be the case!) + * */ static int __devinit parport_SPP_supported(struct parport *pb) { @@ -1447,8 +1457,8 @@ if (user_specified) /* That didn't work, but the user thinks there's a * port here. */ - printk (KERN_DEBUG "0x%lx: CTR: wrote 0x%02x, read 0x%02x\n", - pb->base, w, r); + printk (KERN_DEBUG "parport 0x%lx (WARNING): CTR: " + "wrote 0x%02x, read 0x%02x\n", pb->base, w, r); /* Try the data register. The data lines aren't tri-stated at * this stage, so we expect back what we wrote. */ @@ -1463,11 +1473,15 @@ return PARPORT_MODE_PCSPP; } - if (user_specified) + if (user_specified) { /* Didn't work, but the user is convinced this is the * place. */ - printk (KERN_DEBUG "0x%lx: DATA: wrote 0x%02x, read 0x%02x\n", - pb->base, w, r); + printk (KERN_DEBUG "parport 0x%lx (WARNING): DATA: " + "wrote 0x%02x, read 0x%02x\n", pb->base, w, r); + printk (KERN_DEBUG "parport 0x%lx: You gave this address, " + "but there is probably no parallel port there!\n", + pb->base); + } /* It's possible that we can't read the control register or * the data register. In that case just believe the user. */ @@ -1692,7 +1706,7 @@ /* Go back to mode 000 */ frob_econtrol (pb, 0xe0, ECR_SPP << 5); - pb->modes |= PARPORT_MODE_ECP; + pb->modes |= PARPORT_MODE_ECP | PARPORT_MODE_COMPAT; return 1; } @@ -2598,6 +2612,7 @@ void cleanup_module(void) { + /* We ought to keep track of which ports are actually ours. */ struct parport *p = parport_enumerate(), *tmp; if (!user_specified) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/parport/procfs.c linux/drivers/parport/procfs.c --- v2.4.0-test2/linux/drivers/parport/procfs.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/parport/procfs.c Wed Jul 5 11:55:45 2000 @@ -198,7 +198,7 @@ size_t *lenp) { struct parport *port = (struct parport *)table->extra1; - char buffer[20]; + char buffer[40]; int len = 0; if (filp->f_pos) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/parport/share.c linux/drivers/parport/share.c --- v2.4.0-test2/linux/drivers/parport/share.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/parport/share.c Sat Jul 8 19:47:19 2000 @@ -9,6 +9,11 @@ * * based on work by Grant Guenther * and Philip Blundell + * + * The block comments above the functions in this file are + * licensed as part of the generated file + * Documentation/DocBook/parportbook.sgml under the GNU Free + * Documentation License. */ #undef PARPORT_DEBUG_SHARING /* undef for production */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids --- v2.4.0-test2/linux/drivers/pci/pci.ids Fri Jun 23 21:55:09 2000 +++ linux/drivers/pci/pci.ids Thu Jun 29 11:18:21 2000 @@ -4,7 +4,7 @@ # Maintained by Martin Mares # If you have any new entries, send them to the maintainer. # -# $Id: pci.ids,v 1.60 2000/05/01 19:53:05 mj Exp $ +# $Id: pci.ids,v 1.62 2000/06/28 10:56:36 mj Exp $ # # Vendors, devices and subsystems. Please keep sorted. @@ -406,6 +406,7 @@ 1014 0143 Yotta Input Controller (ytin) 0144 Yotta Video Compositor Output 1014 0145 Yotta Output Controller (ytout) + 0156 405GP PLB to PCI Bridge ffff MPIC-2 interrupt controller 1015 LSI Logic Corp of Canada 1016 ICL Personal Systems @@ -570,6 +571,10 @@ 0001 PowerEdge Expandable RAID Controller 2/Si 0002 PowerEdge Expandable RAID Controller 3/Di 0003 PowerEdge Expandable RAID Controller 3/Si + 0004 PowerEdge Expandable RAID Controller 3/Si + 0005 PowerEdge Expandable RAID Controller 3/Di + 0006 PowerEdge Expandable RAID Controller 3/Di + 0008 PowerEdge Expandable RAID Controller 3/Di 1029 Siemens Nixdorf IS 102a LSI Logic 0000 HYDRA @@ -919,6 +924,7 @@ 8009 CXD1947Q i.LINK Controller 8039 CXD3222 i.LINK Controller 8056 Rockwell HCF 56K modem + 808a Memory Stick Controller 104e Oak Technology, Inc 0017 OTI-64017 0107 OTI-107 [Spitfire] @@ -1250,6 +1256,7 @@ 036c Bt879(??) Video Capture 13e9 0070 Win/TV (Video Section) 036e Bt878 + 0070 13eb WinTV/GO 127a 0001 Bt878 Mediastream Controller NTSC 127a 0002 Bt878 Mediastream Controller PAL BG 127a 0003 Bt878a Mediastream Controller PAL BG @@ -1297,6 +1304,7 @@ 1851 1851 FlyVideo'98 EZ - video 1852 1852 FlyVideo'98 (with FM Tuner) 0878 Bt878 + 0070 13eb WinTV/GO 127a 0001 Bt878 Video Capture (Audio Section) 127a 0002 Bt878 Video Capture (Audio Section) 127a 0003 Bt878 Video Capture (Audio Section) @@ -1461,8 +1469,6 @@ 5055 3c555 Laptop Hurricane 5057 3c575 [Megahertz] 10/100 LAN CardBus 10b7 5a57 3C575 Megahertz 10/100 LAN Cardbus PC Card - 5b57 3c575 [Megahertz] 10/100 LAN CardBus - 10b7 5a57 3C575 Megahertz 10/100 LAN Cardbus 5157 3c575 [Megahertz] 10/100 LAN CardBus 10b7 5b57 3C575 Megahertz 10/100 LAN Cardbus PC Card 5257 3CCFE575CT Cyclone CardBus @@ -1472,9 +1478,11 @@ 5951 3c595 100BaseT4 [Vortex] 5952 3c595 100Base-MII [Vortex] 5970 3c597 EISA Fast Demon/Vortex + 5b57 3c595 [Megahertz] 10/100 LAN CardBus + 10b7 5b57 3C575 Megahertz 10/100 LAN Cardbus PC Card 6560 3CCFE656 Cyclone CardBus - 6562 3CCFEM656 Cyclone CardBus - 6564 3CCFEM656 Cyclone CardBus (0x6564) + 6562 3CCFEM656 [id 6562] Cyclone CardBus + 6564 3CCFEM656 [id 6564] Cyclone CardBus 7646 3cSOHO100-TX Hurricane 8811 Token ring 9000 3c900 10BaseT [Boomerang] @@ -1509,14 +1517,15 @@ 1028 0098 3C905B Fast Etherlink XL 10/100 1028 0099 3C905B Fast Etherlink XL 10/100 10b7 9055 3C905B Fast Etherlink XL 10/100 + 9056 3c905B-T4 9058 3c905B-Combo [Deluxe Etherlink XL 10/100] 905a 3c905B-FX [Fast Etherlink XL FX 10/100] 9200 3c905C-TX [Fast Etherlink] 10b7 1000 3C905C-TX Fast Etherlink for PC Management NIC 9800 3c980-TX [Fast Etherlink XL Server Adapter] 10b7 9800 3c980-TX Fast Etherlink XL Server Adapter - 9805 3c980-TX [10/100 Base-TX NIC(Python-T)] - 10b7 9805 3c980 10/100 Base-TX NIC(Python-T) + 9805 3c980-TX 10/100baseTX NIC [Python-T] + 10b7 9805 3c980 10/100baseTX NIC [Python-T] 10b8 Standard Microsystems Corp [SMC] 0005 83C170QF 1055 e000 LANEPIC @@ -1683,6 +1692,7 @@ 0010 Mutara V08 [NV2] 0020 Riva TnT 128 [NV04] 1043 0200 V3400 TNT + 1048 0c18 Erazor II SGRAM 1092 0550 Viper V550 1092 0552 Viper V550 1092 4804 Viper V550 @@ -1751,11 +1761,13 @@ 1043 400a AGP-V6800 DDR SGRAM 1043 400b AGP-V6800 DDR SDRAM 1102 102e CT6971 GeForce 256 DDR + 14af 5021 3D Prophet DDR-DVI 0103 Quadro (GeForce 256 GL) 0110 NV11 0111 NV11 DDR 0113 NV11 GL 0150 NV15 (Geforce2 GTS) + 107d 2840 WinFast GeForce2 GTS with TV output 0151 NV15 DDR (Geforce2 GTS) 0152 NV15 Bladerunner (Geforce2 GTS) 0153 NV15 GL (Quadro2) @@ -2051,10 +2063,18 @@ 111a Efficient Networks, Inc 0000 155P-MF1 (FPGA) 0002 155P-MF1 (ASIC) - 0003 ENI-25P ATM Adapter + 0003 ENI-25P ATM 111a 0000 ENI-25p Miniport ATM Adapter - 0005 Speedstream 30xx ATM Adapter - 111a 0001 SS-3010 Miniport ATM Adapter + 0005 SpeedStream (LANAI) + 111a 0001 ENI-3010 ATM + 111a 0101 ENI-3010 ATM + 111a 0009 ENI-3060 ADSL (VPI=0) + 111a 0109 ENI-3060CO ADSL (VPI=0) + 111a 0809 ENI-3060 ADSL (VPI=0 or 8) + 111a 0909 ENI-3060CO ADSL (VPI=0 or 8) + 111a 0a09 ENI-3060 ADSL (VPI=<0..15>) + 0007 SpeedStream ADSL + 111a 1001 ENI-3061 ADSL [ASIC] 111b Teledyne Electronic Systems 111c Tricord Systems Inc. 0001 Powerbis Bridge @@ -2114,7 +2134,7 @@ 1133 e004 DIVA 2.0 U e010 DIVA Server BRI-2M 1133 e010 DIVA Server BRI-2M - e014 DIVA Server PRO-30M + e014 DIVA Server PRI-30M 1133 e014 DIVA Server PRI-30M 1134 Mercury Computer Systems 0001 Raceway Bridge @@ -2281,7 +2301,8 @@ 0008 CNB20HE 0009 CNB20LE 0010 CIOB30 - 0011 CMIC_HE + 0011 CMIC-HE + 0200 OSB4 0201 CSB5 1167 Mutoh Industries Inc 1168 Thine Electronics Inc @@ -2422,7 +2443,7 @@ 11ad f003 LNE100TX 11ad ffff LNE100TX 1385 f004 FA310TX - c115 LNE100TX Fast Ethernet Adapter + c115 LNE100TX [Linksys EtherFast 10/100] 11ae Aztech System Ltd 11af Avid Technology Inc. 11b0 V3 Semiconductor Inc. @@ -2723,7 +2744,17 @@ 1220 AMCC 5933 TMS320C80 DSP/Imaging board 1221 Contec Co., Ltd 1222 Ancor Communications, Inc. -1223 Heurikon/Computer Products +1223 Artesyn Communication Products + 0003 PM/Link + 0004 PM/T1 + 0005 PM/E1 + 0008 PM/SLS + 0009 BajaSpan Resource Target + 000a BajaSpan Section 0 + 000b BajaSpan Section 1 + 000c BajaSpan Section 2 + 000d BajaSpan Section 3 + 000e PM/PPC 1224 Interactive Images 1225 Power I/O, Inc. 1227 Tech-Source @@ -4506,25 +4537,25 @@ 1a21 82840 840 (Carmel) Chipset Host Bridge (Hub A) 1a23 82840 840 (Carmel) Chipset AGP Bridge 1a24 82840 840 (Carmel) Chipset PCI Bridge (Hub B) - 2410 82801AA 82810 Chipset ISA Bridge (LPC) - 2411 82801AA 82810 Chipset IDE - 2412 82801AA 82810 Chipset USB - 2413 82801AA 82810 Chipset SMBus - 2415 82801AA 82810 AC'97 Audio + 2410 82801AA ISA Bridge (LPC) + 2411 82801AA IDE + 2412 82801AA USB + 2413 82801AA SMBus + 2415 82801AA AC'97 Audio 11d4 0040 SoundMAX Integrated Digital Audio 11d4 0048 SoundMAX Integrated Digital Audio 11d4 5340 SoundMAX Integrated Digital Audio - 2416 82801AA 82810 AC'97 Modem - 2418 82801AA 82810 PCI Bridge - 2420 82801AB 82810 Chipset ISA Bridge (LPC) - 2421 82801AB 82810 Chipset IDE - 2422 82801AB 82810 Chipset USB - 2423 82801AB 82810 Chipset SMBus - 2425 82801AB 82810 AC'97 Audio + 2416 82801AA AC'97 Modem + 2418 82801AA PCI Bridge + 2420 82801AB ISA Bridge (LPC) + 2421 82801AB IDE + 2422 82801AB USB + 2423 82801AB SMBus + 2425 82801AB AC'97 Audio 11d4 0040 SoundMAX Integrated Digital Audio 11d4 0048 SoundMAX Integrated Digital Audio - 2426 82801AB 82810 AC'97 Modem - 2428 82801AB 82810 PCI Bridge + 2426 82801AB AC'97 Modem + 2428 82801AB PCI Bridge 2440 82820 820 (Camino 2) Chipset ISA Bridge (ICH2) 2442 82820 820 (Camino 2) Chipset USB (Hub A) 2443 82820 820 (Camino 2) Chipset SMBus diff -u --recursive --new-file v2.4.0-test2/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c --- v2.4.0-test2/linux/drivers/pcmcia/cs.c Thu May 11 15:30:07 2000 +++ linux/drivers/pcmcia/cs.c Wed Jul 5 13:14:49 2000 @@ -309,50 +309,63 @@ static void unreset_socket(u_long i); static void parse_events(void *info, u_int events); -int register_ss_entry(int nsock, struct pccard_operations * ss_entry) +socket_info_t *pcmcia_register_socket (int slot, + struct pccard_operations * ss_entry, + int use_bus_pm) { - int i, ns; socket_info_t *s; + int i; - DEBUG(0, "cs: register_ss_entry(%d, 0x%p)\n", nsock, ss_entry); + DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", ss_entry); - for (ns = 0; ns < nsock; ns++) { - s = kmalloc(sizeof(struct socket_info_t), GFP_KERNEL); - memset(s, 0, sizeof(socket_info_t)); - - s->ss_entry = ss_entry; - s->sock = ns; - s->setup.data = sockets; - s->setup.function = &setup_socket; - s->shutdown.data = sockets; - s->shutdown.function = &shutdown_socket; - /* base address = 0, map = 0 */ - s->cis_mem.flags = 0; - s->cis_mem.speed = cis_speed; - s->erase_busy.next = s->erase_busy.prev = &s->erase_busy; - spin_lock_init(&s->lock); - - for (i = 0; i < sockets; i++) - if (socket_table[i] == NULL) break; - socket_table[i] = s; - if (i == sockets) sockets++; + s = kmalloc(sizeof(struct socket_info_t), GFP_KERNEL); + memset(s, 0, sizeof(socket_info_t)); + + s->ss_entry = ss_entry; + s->sock = slot; + s->setup.data = sockets; + s->setup.function = &setup_socket; + s->shutdown.data = sockets; + s->shutdown.function = &shutdown_socket; + /* base address = 0, map = 0 */ + s->cis_mem.flags = 0; + s->cis_mem.speed = cis_speed; + s->use_bus_pm = use_bus_pm; + s->erase_busy.next = s->erase_busy.prev = &s->erase_busy; + spin_lock_init(&s->lock); + + for (i = 0; i < sockets; i++) + if (socket_table[i] == NULL) break; + socket_table[i] = s; + if (i == sockets) sockets++; - init_socket(s); - ss_entry->inquire_socket(ns, &s->cap); + init_socket(s); + ss_entry->inquire_socket(slot, &s->cap); #ifdef CONFIG_PROC_FS - if (proc_pccard) { - char name[3]; - sprintf(name, "%02d", i); - s->proc = proc_mkdir(name, proc_pccard); - if (s->proc) - ss_entry->proc_setup(ns, s->proc); + if (proc_pccard) { + char name[3]; + sprintf(name, "%02d", i); + s->proc = proc_mkdir(name, proc_pccard); + if (s->proc) + ss_entry->proc_setup(slot, s->proc); #ifdef PCMCIA_DEBUG - if (s->proc) - create_proc_read_entry("clients", 0, s->proc, - proc_read_clients, s); + if (s->proc) + create_proc_read_entry("clients", 0, s->proc, + proc_read_clients, s); #endif - } + } #endif + return s; +} /* pcmcia_register_socket */ + +int register_ss_entry(int nsock, struct pccard_operations * ss_entry) +{ + int ns; + + DEBUG(0, "cs: register_ss_entry(%d, 0x%p)\n", nsock, ss_entry); + + for (ns = 0; ns < nsock; ns++) { + pcmcia_register_socket (ns, ss_entry, 0); } return 0; @@ -360,49 +373,57 @@ /*====================================================================*/ -void unregister_ss_entry(struct pccard_operations * ss_entry) +void pcmcia_unregister_socket(socket_info_t *s) { - int i, j; - socket_info_t *s = NULL; + int j, socket = -1; client_t *client; + for (j = 0; j < MAX_SOCK; j++) + if (socket_table [j] == s) { + socket = j; + break; + } + if (socket < 0) + return; + #ifdef CONFIG_PROC_FS - for (i = 0; i < sockets; i++) { - s = socket_table[i]; - if (s->ss_entry != ss_entry) continue; - if (proc_pccard) { - char name[3]; - sprintf(name, "%02d", i); + if (proc_pccard) { + char name[3]; + sprintf(name, "%02d", socket); #ifdef PCMCIA_DEBUG - remove_proc_entry("clients", s->proc); + remove_proc_entry("clients", s->proc); #endif - remove_proc_entry(name, proc_pccard); - } + remove_proc_entry(name, proc_pccard); } #endif - for (;;) { - for (i = 0; i < sockets; i++) { - s = socket_table[i]; - if (s->ss_entry == ss_entry) break; - } - if (i == sockets) - break; - shutdown_socket(i); - release_cis_mem(s); - while (s->clients) { - client = s->clients; - s->clients = s->clients->next; - kfree(client); - } - s->ss_entry = NULL; - kfree(s); - socket_table[i] = NULL; - for (j = i; j < sockets-1; j++) - socket_table[j] = socket_table[j+1]; - sockets--; + shutdown_socket(socket); + release_cis_mem(s); + while (s->clients) { + client = s->clients; + s->clients = s->clients->next; + kfree(client); + } + s->ss_entry = NULL; + kfree(s); + + socket_table[socket] = NULL; + for (j = socket; j < sockets-1; j++) + socket_table[j] = socket_table[j+1]; + sockets--; +} /* pcmcia_unregister_socket */ + +void unregister_ss_entry(struct pccard_operations * ss_entry) +{ + int i; + + for (i = 0; i < sockets; i++) { + socket_info_t *socket = socket_table[i]; + if (socket->ss_entry == ss_entry) + pcmcia_unregister_socket (socket); + else + i++; } - } /* unregister_ss_entry */ /*====================================================================== @@ -675,35 +696,51 @@ ======================================================================*/ +void pcmcia_suspend_socket (socket_info_t *s) +{ + if ((s->state & SOCKET_PRESENT) && !(s->state & SOCKET_SUSPEND)) { + send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW); + suspend_socket(s); + s->state |= SOCKET_SUSPEND; + } +} + +void pcmcia_resume_socket (socket_info_t *s) +{ + int stat; + + /* Do this just to reinitialize the socket */ + init_socket(s); + get_socket_status(s, &stat); + + /* If there was or is a card here, we need to do something + about it... but parse_events will sort it all out. */ + if ((s->state & SOCKET_PRESENT) || (stat & SS_DETECT)) + parse_events(s, SS_DETECT); +} + static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data) { - int i, stat; + int i; socket_info_t *s; - + + /* only for busses that don't suspend/resume slots directly */ + switch (rqst) { case PM_SUSPEND: DEBUG(1, "cs: received suspend notification\n"); for (i = 0; i < sockets; i++) { - s = socket_table[i]; - if ((s->state & SOCKET_PRESENT) && - !(s->state & SOCKET_SUSPEND)){ - send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW); - suspend_socket(s); - s->state |= SOCKET_SUSPEND; - } + s = socket_table [i]; + if (!s->use_bus_pm) + pcmcia_suspend_socket (socket_table [i]); } break; case PM_RESUME: DEBUG(1, "cs: received resume notification\n"); for (i = 0; i < sockets; i++) { - s = socket_table[i]; - /* Do this just to reinitialize the socket */ - init_socket(s); - get_socket_status(s, &stat); - /* If there was or is a card here, we need to do something - about it... but parse_events will sort it all out. */ - if ((s->state & SOCKET_PRESENT) || (stat & SS_DETECT)) - parse_events(s, SS_DETECT); + s = socket_table [i]; + if (!s->use_bus_pm) + pcmcia_resume_socket (socket_table [i]); } break; } @@ -2330,6 +2367,11 @@ #ifdef CONFIG_PROC_FS EXPORT_SYMBOL(proc_pccard); #endif + +EXPORT_SYMBOL(pcmcia_register_socket); +EXPORT_SYMBOL(pcmcia_unregister_socket); +EXPORT_SYMBOL(pcmcia_suspend_socket); +EXPORT_SYMBOL(pcmcia_resume_socket); static int __init init_pcmcia_cs(void) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/pcmcia/cs_internal.h linux/drivers/pcmcia/cs_internal.h --- v2.4.0-test2/linux/drivers/pcmcia/cs_internal.h Wed Feb 16 17:03:52 2000 +++ linux/drivers/pcmcia/cs_internal.h Mon Jul 10 13:22:53 2000 @@ -160,6 +160,7 @@ #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc; #endif + int use_bus_pm; } socket_info_t; /* Flags in config state */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/pcmcia/pci_socket.c linux/drivers/pcmcia/pci_socket.c --- v2.4.0-test2/linux/drivers/pcmcia/pci_socket.c Fri Jan 21 18:19:16 2000 +++ linux/drivers/pcmcia/pci_socket.c Wed Jul 5 13:14:49 2000 @@ -28,6 +28,14 @@ #include "pci_socket.h" + +extern struct socket_info_t *pcmcia_register_socket (int slot, + struct pccard_operations *vtable, int use_bus_pm); +extern void pcmcia_unregister_socket (struct socket_info_t *socket); +extern void pcmcia_suspend_socket (struct socket_info_t *socket); +extern void pcmcia_resume_socket (struct socket_info_t *socket); + + /* * Arbitrary define. This is the array of active cardbus * entries. @@ -161,45 +169,87 @@ pci_proc_setup }; -static int __init add_pci_socket(int nr, struct pci_dev *dev, struct pci_socket_ops *ops) +static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_socket_ops *ops) { pci_socket_t *socket = nr + pci_socket_array; memset(socket, 0, sizeof(*socket)); socket->dev = dev; socket->op = ops; + dev->driver_data = socket; init_waitqueue_head(&socket->wait); return socket->op->open(socket); } -static int __init pci_socket_init(void) +static int __devinit +cardbus_probe (struct pci_dev *dev, const struct pci_device_id *id) { - struct pci_dev *dev = NULL; - int nr = 0; + int s; - while ((dev = pci_find_class(PCI_CLASS_BRIDGE_CARDBUS << 8, dev)) != NULL) { - printk("Adding cardbus controller %d: %s\n", nr, dev->name); - add_pci_socket(nr, dev, ¥ta_operations); - nr++; + for (s = 0; s < MAX_SOCKETS; s++) { + if (pci_socket_array [s].dev == 0) { + add_pci_socket (s, dev, ¥ta_operations); + pci_socket_array [s].pcmcia_socket = + pcmcia_register_socket (s, + &pci_socket_operations, + 1); + return 0; + } } + return -1; +} - if (nr <= 0) - return -1; - register_ss_entry(nr, &pci_socket_operations); - return 0; +static void __devexit cardbus_remove (struct pci_dev *dev) +{ + pci_socket_t *socket = (pci_socket_t *) dev->driver_data; + + pcmcia_unregister_socket (socket->pcmcia_socket); + if (socket->op && socket->op->close) + socket->op->close(socket); + dev->driver_data = 0; } -static void __exit pci_socket_exit(void) +static void cardbus_suspend (struct pci_dev *dev) { - int i; + pci_socket_t *socket = (pci_socket_t *) dev->driver_data; + pcmcia_suspend_socket (socket->pcmcia_socket); +} - unregister_ss_entry(&pci_socket_operations); - for (i = 0; i < MAX_SOCKETS; i++) { - pci_socket_t *socket = pci_socket_array + i; +static void cardbus_resume (struct pci_dev *dev) +{ + pci_socket_t *socket = (pci_socket_t *) dev->driver_data; + pcmcia_resume_socket (socket->pcmcia_socket); +} - if (socket->op && socket->op->close) - socket->op->close(socket); - } + +static struct pci_device_id cardbus_table [] = { { + class: PCI_CLASS_BRIDGE_CARDBUS << 8, + class_mask: ~0, + + vendor: PCI_ANY_ID, + device: PCI_ANY_ID, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, +}, { /* all zeroes */ } +}; + +static struct pci_driver pci_cardbus_driver = { + name: "cardbus", + id_table: cardbus_table, + probe: cardbus_probe, + remove: cardbus_remove, + suspend: cardbus_suspend, + resume: cardbus_resume, +}; + +static int __devinit pci_socket_init(void) +{ + return pci_module_init (&pci_cardbus_driver); +} + +static void __devexit pci_socket_exit (void) +{ + pci_unregister_driver (&pci_cardbus_driver); } module_init(pci_socket_init); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/pcmcia/pci_socket.h linux/drivers/pcmcia/pci_socket.h --- v2.4.0-test2/linux/drivers/pcmcia/pci_socket.h Fri Jan 21 18:19:16 2000 +++ linux/drivers/pcmcia/pci_socket.h Wed Jul 5 13:14:49 2000 @@ -8,6 +8,7 @@ #define __PCI_SOCKET_H struct pci_socket_ops; +struct socket_info_t; typedef struct pci_socket { struct pci_dev *dev; @@ -19,6 +20,7 @@ socket_cap_t cap; wait_queue_head_t wait; unsigned int events; + struct socket_info_t *pcmcia_socket; /* A few words of private data for the low-level driver.. */ unsigned int private[8]; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/pnp/isapnp.c linux/drivers/pnp/isapnp.c --- v2.4.0-test2/linux/drivers/pnp/isapnp.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/pnp/isapnp.c Mon Jun 26 11:32:04 2000 @@ -527,9 +527,11 @@ ptr->next = irq; else (*res)->irq = irq; +#ifdef CONFIG_PCI for (i=0; i<16; i++) if (irq->map & i) pcibios_penalize_isa_irq(i); +#endif } /* diff -u --recursive --new-file v2.4.0-test2/linux/drivers/pnp/isapnp_proc.c linux/drivers/pnp/isapnp_proc.c --- v2.4.0-test2/linux/drivers/pnp/isapnp_proc.c Sat Feb 26 22:31:48 2000 +++ linux/drivers/pnp/isapnp_proc.c Sat Jul 8 19:26:12 2000 @@ -28,6 +28,7 @@ #include #include #include +#include #include struct isapnp_info_buffer { @@ -169,11 +170,12 @@ kfree(buffer); return -ENOMEM; } + lock_kernel(); buffer->curr = buffer->buffer; file->private_data = buffer; - MOD_INC_USE_COUNT; if (mode == O_RDONLY) isapnp_info_read(buffer); + unlock_kernel(); return 0; } @@ -189,7 +191,6 @@ isapnp_info_write(buffer); vfree(buffer->buffer); kfree(buffer); - MOD_DEC_USE_COUNT; return 0; } @@ -286,6 +287,7 @@ if (!e) return -ENOMEM; e->proc_fops = &isapnp_proc_bus_file_operations; + e->owner = THIS_MODULE; e->data = dev; e->size = 256; return 0; @@ -367,8 +369,10 @@ isapnp_proc_entry = NULL; p = create_proc_entry("isapnp", S_IFREG | S_IRUGO | S_IWUSR, &proc_root); - if (p) + if (p) { p->proc_fops = &isapnp_info_entry_operations; + p->owner = THIS_MODULE; + } isapnp_proc_entry = p; isapnp_proc_bus_dir = proc_mkdir("isapnp", proc_bus); isapnp_proc_devices_entry = create_proc_info_entry("devices", 0, diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c --- v2.4.0-test2/linux/drivers/sbus/audio/audio.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/sbus/audio/audio.c Wed Jul 5 22:15:25 2000 @@ -1,4 +1,4 @@ -/* $Id: audio.c,v 1.52 2000/06/22 11:42:27 davem Exp $ +/* $Id: audio.c,v 1.53 2000/07/06 01:41:34 davem Exp $ * drivers/sbus/audio/audio.c * * Copyright 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) @@ -2175,7 +2175,7 @@ /* Unregister ourselves with devfs */ for (i=0; i < sizeof (dev_list) / sizeof (*dev_list); i++) { sparcaudio_mkname (name_buf, dev_list[i].name, drv->index); - de = devfs_find_handle (devfs_handle, name_buf, 0, 0, 0, + de = devfs_find_handle (devfs_handle, name_buf, 0, 0, DEVFS_SPECIAL_CHR, 0); devfs_unregister (de); } @@ -2219,7 +2219,7 @@ if (devfs_register_chrdev(SOUND_MAJOR, "sparcaudio", &sparcaudio_fops)) return -EIO; - devfs_handle = devfs_mk_dir (NULL, "sound", 0, NULL); + devfs_handle = devfs_mk_dir (NULL, "sound", NULL); #ifdef CONFIG_SPARCAUDIO_AMD7930 amd7930_init(); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sbus/char/bpp.c linux/drivers/sbus/char/bpp.c --- v2.4.0-test2/linux/drivers/sbus/char/bpp.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/sbus/char/bpp.c Thu Jun 29 18:25:51 2000 @@ -1029,7 +1029,7 @@ instances[idx].opened = 0; probeLptPort(idx); } - devfs_handle = devfs_mk_dir (NULL, "bpp", 3, NULL); + devfs_handle = devfs_mk_dir (NULL, "bpp", NULL); devfs_register_series (devfs_handle, "%u", BPP_NO, DEVFS_FL_DEFAULT, BPP_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &bpp_fops, NULL); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sbus/char/jsflash.c linux/drivers/sbus/char/jsflash.c --- v2.4.0-test2/linux/drivers/sbus/char/jsflash.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/sbus/char/jsflash.c Wed Jul 5 22:15:25 2000 @@ -400,7 +400,7 @@ togo = abuf.size; if ((togo & 3) || (p & 3)) return -EINVAL; - uptr = (char *) abuf.data; + uptr = (char *) (unsigned long) abuf.data; if (verify_area(VERIFY_READ, uptr, togo)) return -EFAULT; while (togo != 0) { @@ -701,5 +701,6 @@ misc_deregister(&jsf_dev); if (unregister_blkdev(JSFD_MAJOR, "jsfd") != 0) printk("jsfd: cleanup_module failed\n"); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); } #endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c --- v2.4.0-test2/linux/drivers/sbus/char/sab82532.c Thu May 11 15:30:07 2000 +++ linux/drivers/sbus/char/sab82532.c Wed Jul 5 22:15:25 2000 @@ -1,4 +1,4 @@ -/* $Id: sab82532.c,v 1.45 2000/05/08 22:23:08 ecd Exp $ +/* $Id: sab82532.c,v 1.46 2000/07/06 01:41:37 davem Exp $ * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -2173,7 +2173,7 @@ static inline void __init show_serial_version(void) { - char *revision = "$Revision: 1.45 $"; + char *revision = "$Revision: 1.46 $"; char *version, *p; version = strchr(revision, ' '); @@ -2391,9 +2391,6 @@ /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ save_flags(flags); cli(); - timer_active &= ~(1 << RS_TIMER); - timer_table[RS_TIMER].fn = NULL; - timer_table[RS_TIMER].expires = 0; remove_bh(SERIAL_BH); if ((e1 = tty_unregister_driver(&serial_driver))) printk("SERIAL: failed to unregister serial driver (%d)\n", diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sbus/char/vfc_dev.c linux/drivers/sbus/char/vfc_dev.c --- v2.4.0-test2/linux/drivers/sbus/char/vfc_dev.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/sbus/char/vfc_dev.c Thu Jun 29 18:25:51 2000 @@ -672,7 +672,7 @@ kfree(vfc_dev_lst); return -EIO; } - devfs_handle = devfs_mk_dir (NULL, "vfc", 3, NULL); + devfs_handle = devfs_mk_dir (NULL, "vfc", NULL); instance = 0; for_all_sbusdev(sdev, sbus) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c --- v2.4.0-test2/linux/drivers/sbus/char/zs.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/sbus/char/zs.c Wed Jul 5 22:15:25 2000 @@ -1,4 +1,4 @@ -/* $Id: zs.c,v 1.57 2000/04/26 09:36:32 davem Exp $ +/* $Id: zs.c,v 1.58 2000/07/06 01:41:38 davem Exp $ * zs.c: Zilog serial port driver for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -824,20 +824,6 @@ tty_hangup(tty); } - -/* - * This subroutine is called when the RS_TIMER goes off. It is used - * by the serial driver to handle ports that do not have an interrupt - * (irq=0). This doesn't work at all for 16450's, as a sun has a Z8530. - */ - -static void zs_timer(void) -{ - printk("zs_timer called\n"); - prom_halt(); - return; -} - static int startup(struct sun_serial * info) { unsigned long flags; @@ -913,14 +899,6 @@ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; /* - * Set up serial timers... - */ -#if 0 /* Works well and stops the machine. */ - timer_table[RS_TIMER].expires = jiffies + 2; - timer_active |= 1 << RS_TIMER; -#endif - - /* * and set the speed of the serial port */ change_speed(info); @@ -1928,7 +1906,7 @@ static void show_serial_version(void) { - char *revision = "$Revision: 1.57 $"; + char *revision = "$Revision: 1.58 $"; char *version, *p; version = strchr(revision, ' '); @@ -2404,8 +2382,6 @@ /* Setup base handler, and timer table. */ init_bh(SERIAL_BH, do_serial_bh); - timer_table[RS_TIMER].fn = zs_timer; - timer_table[RS_TIMER].expires = 0; show_serial_version(); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c --- v2.4.0-test2/linux/drivers/scsi/BusLogic.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/scsi/BusLogic.c Mon Jul 10 13:06:35 2000 @@ -1082,8 +1082,8 @@ #else BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", NULL, Bus, Device); - BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, " - "but FlashPoint\n", NULL, IO_Address, PCI_Address); + BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, irq %d, " + "but FlashPoint\n", NULL, IO_Address, PCI_Address, IRQ_Channel); BusLogic_Error("BusLogic: support was omitted in this kernel " "configuration.\n", NULL); #endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c --- v2.4.0-test2/linux/drivers/scsi/NCR5380.c Thu May 11 15:30:07 2000 +++ linux/drivers/scsi/NCR5380.c Fri Jul 7 15:55:24 2000 @@ -2245,7 +2245,9 @@ register unsigned char p = *phase; register unsigned char *d = *data; unsigned char tmp; +#if defined(PSEUDO_DMA) && !defined(UNSAFE) unsigned long flags; +#endif int foo; #if defined(REAL_DMA_POLL) int cnt, toPIO; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/NCR53C9x.h linux/drivers/scsi/NCR53C9x.h --- v2.4.0-test2/linux/drivers/scsi/NCR53C9x.h Thu Nov 11 20:11:43 1999 +++ linux/drivers/scsi/NCR53C9x.h Sun Jul 9 22:22:57 2000 @@ -144,7 +144,12 @@ #ifndef MULTIPLE_PAD_SIZES +#ifdef CONFIG_CPU_HAS_WB +#include +#define esp_write(__reg, __val) do{(__reg) = (__val); wbflush();} while(0) +#else #define esp_write(__reg, __val) ((__reg) = (__val)) +#endif #define esp_read(__reg) (__reg) struct ESP_regs { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c --- v2.4.0-test2/linux/drivers/scsi/aic7xxx.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/aic7xxx.c Mon Jun 26 12:01:33 2000 @@ -9092,7 +9092,7 @@ p->flags |= AHC_TERM_ENB_SE_LOW | AHC_TERM_ENB_SE_HIGH; } } - p->sc = *sc; + memcpy(&p->sc, sc, sizeof(struct seeprom_config)); } p->discenable = 0; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/atp870u.c linux/drivers/scsi/atp870u.c --- v2.4.0-test2/linux/drivers/scsi/atp870u.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/atp870u.c Fri Jul 7 15:55:24 2000 @@ -1627,7 +1627,6 @@ struct Scsi_Host *shpnt = NULL; int tmpcnt = 0; int count = 0; - int result; static unsigned short devid[8] = { 0x8002, 0x8010, 0x8020, 0x8030, 0x8040, 0x8050, 0x8060, 0 diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/dec_esp.c linux/drivers/scsi/dec_esp.c --- v2.4.0-test2/linux/drivers/scsi/dec_esp.c Sat Feb 26 22:31:48 2000 +++ linux/drivers/scsi/dec_esp.c Sun Jul 9 22:22:57 2000 @@ -38,28 +38,42 @@ #include #include +/* + * Once upon a time the pmaz code used to be working but + * it hasn't been maintained for quite some time. + * It isn't working anymore but I'll leave here as a + * starting point. #define this an be prepared for tons + * of warnings and errors :) + */ +#undef PMAZ_A + static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count); static void dma_drain(struct NCR_ESP *esp); -static void pmaz_dma_drain(struct NCR_ESP *esp); -static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp); +static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp); static void dma_dump_state(struct NCR_ESP *esp); static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length); static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length); static void dma_ints_off(struct NCR_ESP *esp); static void dma_ints_on(struct NCR_ESP *esp); -static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length); -static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length); -static void pmaz_dma_ints_off(struct NCR_ESP *esp); -static void pmaz_dma_ints_on(struct NCR_ESP *esp); static int dma_irq_p(struct NCR_ESP *esp); static int dma_ports_p(struct NCR_ESP *esp); static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write); static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp); static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp); +static void dma_advance_sg(Scsi_Cmnd * sp); + +#ifdef PMAZ_A +static void pmaz_dma_drain(struct NCR_ESP *esp); +static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length); +static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length); +static void pmaz_dma_ints_off(struct NCR_ESP *esp); +static void pmaz_dma_ints_on(struct NCR_ESP *esp); static void pmaz_dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write); static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp); -// static void pmaz_dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp); -static void dma_advance_sg(Scsi_Cmnd * sp); +static void pmaz_dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp); + +volatile int *scsi_pmaz_dma_ptr_tc; +#endif #define TC_ESP_RAM_SIZE 0x20000 #define ESP_TGT_DMA_SIZE ((TC_ESP_RAM_SIZE/7) & ~(sizeof(int)-1)) @@ -89,18 +103,18 @@ volatile unsigned long *scsi_sdr0; volatile unsigned long *scsi_sdr1; -volatile int *scsi_pmaz_dma_ptr_tc; - static void scsi_dma_int(int, void *, struct pt_regs *); /***************************************************************** Detection */ int dec_esp_detect(Scsi_Host_Template * tpnt) { - struct NCR_ESP *esp; - struct ConfigDev *esp_dev; + struct NCR_ESP *esp; + struct ConfigDev *esp_dev; +#ifdef PMAZ_A int slot, i; unsigned long mem_start; volatile unsigned char *buffer; +#endif if (IOASIC) { esp_dev = 0; @@ -150,10 +164,10 @@ /* SCSI chip speed */ esp->cfreq = 25000000; - /* + /* * we don't give the address of DMA channel, but the number * of DMA channel, so we can use the jazz DMA functions - * + * */ esp->dregs = JAZZ_SCSI_DMA; @@ -164,7 +178,7 @@ esp->esp_command = (volatile unsigned char *) cmd_buffer; /* get virtual dma address for command buffer */ - esp->esp_command_dvma = KSEG1ADDR((volatile unsigned char *) cmd_buffer); + esp->esp_command_dvma = (__u32) KSEG1ADDR((volatile unsigned char *) cmd_buffer); esp->irq = SCSI_INT; request_irq(esp->irq, esp_intr, SA_INTERRUPT, "NCR 53C94 SCSI", @@ -181,8 +195,9 @@ } +#ifdef PMAZ_A if (TURBOCHANNEL) { - while ((slot = search_tc_card("PMAZ-AA")) >= 0) { + while ((slot = search_tc_card("PMAZ_AA")) >= 0) { claim_tc_card(slot); mem_start = get_tc_base_addr(slot); @@ -242,12 +257,13 @@ esp->dma_mmu_release_scsi_sgl = 0; esp->dma_advance_sg = 0; - request_irq(esp->irq, esp_intr, SA_INTERRUPT, "PMAZ-AA", NULL); + request_irq(esp->irq, esp_intr, SA_INTERRUPT, "PMAZ_AA", NULL); esp->scsi_id = 7; esp->diff = 0; esp_initialize(esp); } } +#endif if(nesps) { printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use); @@ -321,20 +337,14 @@ } } -static void pmaz_dma_drain(struct NCR_ESP *esp) -{ - memcpy((volatile void *) (KSEG0ADDR(esp_virt_buffer)), - (void *) scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], scsi_current_length); -} - static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp) { return sp->SCp.this_residual;; } - + static void dma_dump_state(struct NCR_ESP *esp) { -/* +/* ESPLOG(("esp%d: dma -- enable <%08x> residue <%08x\n", esp->esp_id, vdma_get_enable((int)esp->dregs), vdma_get_resdiue((int)esp->dregs))); */ @@ -400,6 +410,66 @@ enable_irq(SCSI_DMA_INT); } +static int dma_irq_p(struct NCR_ESP *esp) +{ + return (esp->eregs->esp_status & ESP_STAT_INTR); +} + +static int dma_ports_p(struct NCR_ESP *esp) +{ +/* + * FIXME: what's this good for? + */ + return 1; +} + +static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) +{ + /* + * On the Sparc, DMA_ST_WRITE means "move data from device to memory" + * so when (write) is true, it actually means READ! + */ + if (write) { + dma_init_read(esp, addr, count); + } else { + dma_init_write(esp, addr, count); + } +} + +/* + * These aren't used yet + */ +static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp) +{ + sp->SCp.have_data_in = PHYSADDR(sp->SCp.buffer); + sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.have_data_in); +} + +static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp) +{ + int sz = sp->SCp.buffers_residual; + struct mmu_sglist *sg = (struct mmu_sglist *) sp->SCp.buffer; + + while (sz >= 0) { + sg[sz].dvma_addr = PHYSADDR(sg[sz].addr); + sz--; + } + sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address); +} + +static void dma_advance_sg(Scsi_Cmnd * sp) +{ + sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address); +} + +#ifdef PMAZ_A + +static void pmaz_dma_drain(struct NCR_ESP *esp) +{ + memcpy((void *) (KSEG0ADDR(esp_virt_buffer)), + (void *) scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], scsi_current_length); +} + static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length) { @@ -413,7 +483,7 @@ static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length) { - memcpy(scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], KSEG0ADDR((void *) vaddress), length); + memcpy((void *)scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], KSEG0ADDR((void *) vaddress), length); *scsi_pmaz_dma_ptr_tc = TC_ESP_DMAR_WRITE | TC_ESP_DMA_ADDR(scsi_pmaz_dma_ptrs_tc[scsi_cur_buff]); @@ -427,35 +497,9 @@ { } -static int dma_irq_p(struct NCR_ESP *esp) -{ - return (esp->eregs->esp_status & ESP_STAT_INTR); -} - -static int dma_ports_p(struct NCR_ESP *esp) -{ -/* - * FIXME: what's this good for? - */ - return 1; -} - -static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) -{ - /* - * On the Sparc, DMA_ST_WRITE means "move data from device to memory" - * so when (write) is true, it actually means READ! - */ - if (write) { - dma_init_read(esp, addr, count); - } else { - dma_init_write(esp, addr, count); - } -} - static void pmaz_dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) { - /* + /* * On the Sparc, DMA_ST_WRITE means "move data from device to memory" * so when (write) is true, it actually means READ! */ @@ -474,35 +518,10 @@ scsi_pmaz_dma_buff_used[x] = 0; } - static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp) { sp->SCp.have_data_in = (int) sp->SCp.ptr = (char *) KSEG0ADDR((sp->request_buffer)); } -/* - * These aren't used yet - */ -static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp) -{ - sp->SCp.have_data_in = PHYSADDR(sp->SCp.buffer); - sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.have_data_in); -} - -static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp) -{ - int sz = sp->SCp.buffers_residual; - struct mmu_sglist *sg = (struct mmu_sglist *) sp->SCp.buffer; - - while (sz >= 0) { - sg[sz].dvma_addr = PHYSADDR(sg[sz].addr); - sz--; - } - sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address); -} - -static void dma_advance_sg(Scsi_Cmnd * sp) -{ - sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address); -} +#endif \ No newline at end of file diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c --- v2.4.0-test2/linux/drivers/scsi/fdomain.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/fdomain.c Thu Jul 6 19:25:21 2000 @@ -693,7 +693,7 @@ static int fdomain_isa_detect( int *irq, int *iobase ) { int i, j; - int base; + int base = 0xdeadbeef; int flag = 0; #if DEBUG_DETECT diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/gdth.c linux/drivers/scsi/gdth.c --- v2.4.0-test2/linux/drivers/scsi/gdth.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/gdth.c Mon Jun 26 18:06:55 2000 @@ -1493,7 +1493,7 @@ ha->more_proc = FALSE; if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO, INVALID_CHANNEL,sizeof(gdth_binfo_str))) { - ha->binfo = *(gdth_binfo_str *)ha->pscratch; + memcpy(&ha->binfo, (gdth_binfo_str *)ha->pscratch, sizeof(gdth_binfo_str)); if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_FEATURES, INVALID_CHANNEL,sizeof(gdth_bfeat_str))) { TRACE2(("BOARD_INFO/BOARD_FEATURES supported\n")); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/gdth_proc.c linux/drivers/scsi/gdth_proc.c --- v2.4.0-test2/linux/drivers/scsi/gdth_proc.c Fri Jan 28 15:09:08 2000 +++ linux/drivers/scsi/gdth_proc.c Wed Jul 5 11:24:41 2000 @@ -1057,7 +1057,6 @@ oldto = scp->timeout_per_command; scp->timeout_per_command = timeout; -#if LINUX_VERSION_CODE >= 0x02014B if (timeout == 0) { del_timer(&scp->eh_timeout); scp->eh_timeout.data = (unsigned long) NULL; @@ -1069,17 +1068,5 @@ scp->eh_timeout.expires = jiffies + timeout; add_timer(&scp->eh_timeout); } -#else - if (timeout > 0) { - if (timer_table[SCSI_TIMER].expires == 0) { - timer_table[SCSI_TIMER].expires = jiffies + timeout; - timer_active |= 1 << SCSI_TIMER; - } else { - if (jiffies + timeout < timer_table[SCSI_TIMER].expires) - timer_table[SCSI_TIMER].expires = jiffies + timeout; - } - } -#endif - return oldto; } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- v2.4.0-test2/linux/drivers/scsi/hosts.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/hosts.c Mon Jun 26 11:40:38 2000 @@ -668,7 +668,7 @@ #endif /* Put I2O last so that host specific controllers always win */ #ifdef CONFIG_I2O_SCSI - I2OSCSI + I2OSCSI, #endif /* "Removable host adapters" below this line (Parallel Port/USB/other) */ #ifdef CONFIG_SCSI_PPA diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/inia100.c linux/drivers/scsi/inia100.c --- v2.4.0-test2/linux/drivers/scsi/inia100.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/inia100.c Wed Jul 5 17:57:27 2000 @@ -228,7 +228,6 @@ }; unsigned int dRegValue; - unsigned short command; WORD wBIOS, wBASE; BYTE bPCIBusNum, bInterrupt, bPCIDeviceNum; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/qlogicfc.c linux/drivers/scsi/qlogicfc.c --- v2.4.0-test2/linux/drivers/scsi/qlogicfc.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/qlogicfc.c Wed Jul 5 22:15:31 2000 @@ -72,12 +72,21 @@ #define pci64_map_sg(d,s,n,dir) pci_map_sg((d),(s),(n),(dir)) #define pci64_unmap_single(d,a,s,dir) pci_unmap_single((d),(a),(s),(dir)) #define pci64_unmap_sg(d,s,n,dir) pci_unmap_sg((d),(s),(n),(dir)) +#if BITS_PER_LONG > 32 +#define pci64_dma_hi32(a) ((u32) (0xffffffff & (((u64)(a))>>32))) +#define pci64_dma_lo32(a) ((u32) (0xffffffff & (((u64)(a))))) +#else #define pci64_dma_hi32(a) 0 #define pci64_dma_lo32(a) (a) +#endif /* BITS_PER_LONG */ #define pci64_dma_build(hi,lo) (lo) #define sg_dma64_address(s) sg_dma_address(s) #define sg_dma64_len(s) sg_dma_len(s) +#if BITS_PER_LONG > 32 +#define PCI64_DMA_BITS 64 +#else #define PCI64_DMA_BITS 32 +#endif /* BITS_PER_LONG */ #endif #include "qlogicfc.h" @@ -101,15 +110,12 @@ #define ISP2x00_FABRIC 1 /* Macros used for debugging */ -/* -#define DEBUG_ISP2x00 1 -#define DEBUG_ISP2x00_INT 1 -#define DEBUG_ISP2x00_INTR 1 -#define DEBUG_ISP2x00_SETUP 1 - -#define DEBUG_ISP2x00_FABRIC 1 -*/ -/* #define TRACE_ISP 1 */ +#define DEBUG_ISP2x00 0 +#define DEBUG_ISP2x00_INT 0 +#define DEBUG_ISP2x00_INTR 0 +#define DEBUG_ISP2x00_SETUP 0 +#define DEBUG_ISP2x00_FABRIC 0 +#define TRACE_ISP 0 #define DEFAULT_LOOP_COUNT 1000000000 @@ -1233,7 +1239,7 @@ for (i = in_ptr; i != (in_ptr - 1) && hostdata->handle_ptrs[i]; i = ((i + 1) % (QLOGICFC_REQ_QUEUE_LEN + 1))); if (!hostdata->handle_ptrs[i]) { - cmd->handle = i; + cmd->handle = cpu_to_le32(i); hostdata->handle_ptrs[i] = Cmnd; hostdata->handle_serials[i] = Cmnd->serial_number; } else { @@ -1358,6 +1364,13 @@ break; } } + /* + * TEST_UNIT_READY commands from scsi_scan will fail due to "overlapped + * commands attempted" unless we setup at least a simple queue (midlayer + * will embelish this once it can do an INQUIRY command to the device) + */ + else + cmd->control_flags |= cpu_to_le16(CFLAG_SIMPLE_TAG); outw(in_ptr, host->io_port + MBOX4); hostdata->req_in_ptr = in_ptr; @@ -1541,12 +1554,14 @@ DEBUG_INTR(printk("qlogicfc%d : response queue depth %d\n", hostdata->host_id, RES_QUEUE_DEPTH(in_ptr, out_ptr))); while (out_ptr != in_ptr) { + unsigned le_hand; sts = (struct Status_Entry *) &hostdata->res[out_ptr*QUEUE_ENTRY_LEN]; out_ptr = (out_ptr + 1) & RES_QUEUE_LEN; TRACE("done", out_ptr, Cmnd); DEBUG_INTR(isp2x00_print_status_entry(sts)); - if (sts->hdr.entry_type == ENTRY_STATUS && (Cmnd = hostdata->handle_ptrs[sts->handle])) { + le_hand = le32_to_cpu(sts->handle); + if (sts->hdr.entry_type == ENTRY_STATUS && (Cmnd = hostdata->handle_ptrs[le_hand])) { Cmnd->result = isp2x00_return_status(Cmnd, sts); hostdata->queued--; @@ -1565,10 +1580,10 @@ * we dont have to call done because the upper * level should already know its aborted. */ - if (hostdata->handle_serials[sts->handle] != Cmnd->serial_number + if (hostdata->handle_serials[le_hand] != Cmnd->serial_number || le16_to_cpu(sts->completion_status) == CS_ABORTED){ - hostdata->handle_serials[sts->handle] = 0; - hostdata->handle_ptrs[sts->handle] = NULL; + hostdata->handle_serials[le_hand] = 0; + hostdata->handle_ptrs[le_hand] = NULL; outw(out_ptr, host->io_port + MBOX5); continue; } @@ -1589,7 +1604,7 @@ continue; } - hostdata->handle_ptrs[sts->handle] = NULL; + hostdata->handle_ptrs[le_hand] = NULL; if (sts->completion_status == cpu_to_le16(CS_RESET_OCCURRED) || (sts->status_flags & cpu_to_le16(STF_BUS_RESET))) @@ -1912,23 +1927,14 @@ } #endif -#ifdef __BIG_ENDIAN - { - u64 val; - memcpy(&val, &hostdata->control_block.node_name, sizeof(u64)); - hostdata->wwn = ((val & 0xff00ff00ff00ff00ULL) >> 8) - | ((val & 0x00ff00ff00ff00ffULL) << 8); - } -#else - hostdata->wwn = (u64) (hostdata->control_block.node_name[0]) << 56; - hostdata->wwn |= (u64) (hostdata->control_block.node_name[0] & 0xff00) << 48; - hostdata->wwn |= (u64) (hostdata->control_block.node_name[1] & 0xff00) << 24; - hostdata->wwn |= (u64) (hostdata->control_block.node_name[1] & 0x00ff) << 48; - hostdata->wwn |= (u64) (hostdata->control_block.node_name[2] & 0x00ff) << 24; - hostdata->wwn |= (u64) (hostdata->control_block.node_name[2] & 0xff00) << 8; - hostdata->wwn |= (u64) (hostdata->control_block.node_name[3] & 0x00ff) << 8; - hostdata->wwn |= (u64) (hostdata->control_block.node_name[3] & 0xff00) >> 8; -#endif + hostdata->wwn = (u64) (cpu_to_le16(hostdata->control_block.node_name[0])) << 56; + hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[0]) & 0xff00) << 48; + hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[1]) & 0xff00) << 24; + hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[1]) & 0x00ff) << 48; + hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[2]) & 0x00ff) << 24; + hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[2]) & 0xff00) << 8; + hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[3]) & 0x00ff) << 8; + hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[3]) & 0xff00) >> 8; /* FIXME: If the DMA transfer goes one way only, this should use PCI_DMA_TODEVICE and below as well. */ busaddr = pci64_map_single(hostdata->pci_dev, &hostdata->control_block, sizeof(hostdata->control_block), diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/qlogicfc.h linux/drivers/scsi/qlogicfc.h --- v2.4.0-test2/linux/drivers/scsi/qlogicfc.h Sat Feb 26 22:31:48 2000 +++ linux/drivers/scsi/qlogicfc.h Mon Jun 26 12:02:16 2000 @@ -62,7 +62,7 @@ * determined for each queue request anew. */ -#if PCI64_DMA_BITS > 32 +#if BITS_PER_LONG > 32 #define DATASEGS_PER_COMMAND 2 #define DATASEGS_PER_CONT 5 #else diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v2.4.0-test2/linux/drivers/scsi/scsi.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/scsi.c Sun Jul 9 22:14:37 2000 @@ -136,7 +136,6 @@ */ extern void scsi_times_out(Scsi_Cmnd * SCpnt); void scsi_build_commandblocks(Scsi_Device * SDpnt); -static int scsi_unregister_device(struct Scsi_Device_Template *tpnt); /* * These are the interface to the old error handling code. It should go away @@ -1529,7 +1528,7 @@ /* Yes we're here... */ - scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", 4, NULL); + scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", NULL); /* * This makes /proc/scsi and /proc/scsi/scsi visible. */ @@ -2293,6 +2292,8 @@ MOD_DEC_USE_COUNT; } +static int scsi_unregister_device(struct Scsi_Device_Template *tpnt); + /* * This entry point should be called by a loadable module if it is trying * add a high level scsi driver to the system. @@ -2646,7 +2647,7 @@ scsi_loadable_module_flag = 1; - scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", 4, NULL); + scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", NULL); scsi_host_no_init (scsihosts); /* * This is where the processing takes place for most everything diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c --- v2.4.0-test2/linux/drivers/scsi/scsi_lib.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/scsi_lib.c Wed Jul 5 13:18:05 2000 @@ -87,6 +87,7 @@ SCpnt->request.cmd = SPECIAL; SCpnt->request.special = (void *) SCpnt; SCpnt->request.q = NULL; + SCpnt->request.free_list = NULL; SCpnt->request.nr_segments = 0; /* diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/scsi_scan.c linux/drivers/scsi/scsi_scan.c --- v2.4.0-test2/linux/drivers/scsi/scsi_scan.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/scsi_scan.c Wed Jul 5 13:15:19 2000 @@ -278,7 +278,6 @@ * is pointless work. */ scsi_initialize_queue(SDpnt, shpnt); - blk_queue_headactive(&SDpnt->request_queue, 0); SDpnt->request_queue.queuedata = (void *) SDpnt; /* Make sure we have something that is valid for DMA purposes */ scsi_result = ((!shpnt->unchecked_isa_dma) @@ -425,8 +424,10 @@ } /* Last device block does not exist. Free memory. */ - if (SDpnt != NULL) + if (SDpnt != NULL) { + blk_cleanup_queue(&SDpnt->request_queue); kfree((char *) SDpnt); + } /* If we allocated a buffer so we could do DMA, free it now */ if (scsi_result != &scsi_result0[0] && scsi_result != NULL) { @@ -594,7 +595,7 @@ sprintf (devname, "host%d/bus%d/target%d/lun%d", SDpnt->host->host_no, SDpnt->channel, SDpnt->id, SDpnt->lun); if (SDpnt->de) printk ("DEBUG: dir: \"%s\" already exists\n", devname); - else SDpnt->de = devfs_mk_dir (scsi_devfs_handle, devname, 0, NULL); + else SDpnt->de = devfs_mk_dir (scsi_devfs_handle, devname, NULL); for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) @@ -691,8 +692,6 @@ * is pointless work. */ scsi_initialize_queue(SDpnt, shpnt); - blk_queue_headactive(&SDpnt->request_queue, 0); - SDpnt->request_queue.queuedata = (void *) SDpnt; SDpnt->host = shpnt; initialize_merge_fn(SDpnt); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v2.4.0-test2/linux/drivers/scsi/sd.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/sd.c Sat Jul 8 19:33:40 2000 @@ -1332,7 +1332,6 @@ } for (i = 0; i <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++) { - blk_cleanup_queue(BLK_DEFAULT_QUEUE(SD_MAJOR(i))); blk_size[SD_MAJOR(i)] = NULL; hardsect_size[SD_MAJOR(i)] = NULL; read_ahead[SD_MAJOR(i)] = 0; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c --- v2.4.0-test2/linux/drivers/scsi/seagate.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/seagate.c Fri Jul 7 15:55:24 2000 @@ -498,7 +498,7 @@ { int clock; ULOOP( 1*1000*1000 ) { - volatile int x = STATUS; + STATUS; if (TIMEOUT) break; } } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/st.c linux/drivers/scsi/st.c --- v2.4.0-test2/linux/drivers/scsi/st.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/st.c Mon Jun 26 12:33:03 2000 @@ -12,7 +12,7 @@ Copyright 1992 - 2000 Kai Makisara email Kai.Makisara@metla.fi - Last modified: Sun Apr 23 23:41:32 2000 by makisara@kai.makisara.local + Last modified: Sat Jun 17 15:21:49 2000 by makisara@kai.makisara.local Some small formal changes - aeb, 950809 Last modified: 18-JAN-1998 Richard Gooch Devfs support @@ -65,10 +65,10 @@ #include "constants.h" -static int buffer_kbs = 0; -static int write_threshold_kbs = 0; +static int buffer_kbs; +static int write_threshold_kbs; static int max_buffers = (-1); -static int max_sg_segs = 0; +static int max_sg_segs; MODULE_AUTHOR("Kai Makisara"); MODULE_DESCRIPTION("SCSI Tape Driver"); @@ -138,7 +138,7 @@ static Scsi_Tape **scsi_tapes = NULL; -static int modes_defined = FALSE; +static int modes_defined; static ST_buffer *new_tape_buffer(int, int); static int enlarge_buffer(ST_buffer *, int, int); @@ -870,7 +870,7 @@ static int scsi_tape_flush(struct file *filp) { int result = 0, result2; - static unsigned char cmd[MAX_COMMAND_SIZE]; + unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request *SRpnt; Scsi_Tape *STp; ST_mode *STm; @@ -1027,7 +1027,7 @@ ssize_t retval = 0; int write_threshold; int doing_write = 0; - static unsigned char cmd[MAX_COMMAND_SIZE]; + unsigned char cmd[MAX_COMMAND_SIZE]; const char *b_point; Scsi_Request *SRpnt = NULL; Scsi_Tape *STp; @@ -1380,7 +1380,7 @@ static long read_tape(Scsi_Tape *STp, long count, Scsi_Request ** aSRpnt) { int transfer, blks, bytes; - static unsigned char cmd[MAX_COMMAND_SIZE]; + unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request *SRpnt; ST_mode *STm; ST_partstat *STps; @@ -2945,24 +2945,34 @@ if (mtc.mt_op == MTSETPART) { if (!STp->can_partitions || - mtc.mt_count < 0 || mtc.mt_count >= ST_NBR_PARTITIONS) - return (-EINVAL); + mtc.mt_count < 0 || mtc.mt_count >= ST_NBR_PARTITIONS) { + retval = (-EINVAL); + goto out; + } if (mtc.mt_count >= STp->nbr_partitions && - (STp->nbr_partitions = nbr_partitions(STp)) < 0) - return (-EIO); - if (mtc.mt_count >= STp->nbr_partitions) - return (-EINVAL); + (STp->nbr_partitions = nbr_partitions(STp)) < 0) { + retval = (-EIO); + goto out; + } + if (mtc.mt_count >= STp->nbr_partitions) { + retval = (-EINVAL); + goto out; + } STp->new_partition = mtc.mt_count; retval = 0; goto out; } if (mtc.mt_op == MTMKPART) { - if (!STp->can_partitions) - return (-EINVAL); + if (!STp->can_partitions) { + retval = (-EINVAL); + goto out; + } if ((i = st_int_ioctl(STp, MTREW, 0)) < 0 || - (i = partition_tape(STp, mtc.mt_count)) < 0) - return i; + (i = partition_tape(STp, mtc.mt_count)) < 0) { + retval = i; + goto out; + } for (i = 0; i < ST_NBR_PARTITIONS; i++) { STp->ps[i].rw = ST_IDLE; STp->ps[i].at_sm = 0; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/scsi/tmscsim.c linux/drivers/scsi/tmscsim.c --- v2.4.0-test2/linux/drivers/scsi/tmscsim.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/tmscsim.c Thu Jul 6 19:27:48 2000 @@ -165,6 +165,7 @@ #include "constants.h" #include "sd.h" #include +#include #include "dc390.h" diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sgi/Config.in linux/drivers/sgi/Config.in --- v2.4.0-test2/linux/drivers/sgi/Config.in Sat Feb 26 22:31:48 2000 +++ linux/drivers/sgi/Config.in Sun Jul 9 22:32:58 2000 @@ -5,6 +5,9 @@ comment 'SGI devices' bool 'SGI Zilog85C30 serial support' CONFIG_SGI_SERIAL +if [ "$CONFIG_SGI_SERIAL" = "y" ]; then + bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE +fi bool 'SGI DS1286 RTC support' CONFIG_SGI_DS1286 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sgi/char/ds1286.c linux/drivers/sgi/char/ds1286.c --- v2.4.0-test2/linux/drivers/sgi/char/ds1286.c Sat Feb 26 22:31:48 2000 +++ linux/drivers/sgi/char/ds1286.c Sun Jul 9 22:32:58 2000 @@ -1,4 +1,4 @@ -/* $Id: ds1286.c,v 1.7 2000/02/23 00:41:21 ralf Exp $ +/* $Id: ds1286.c,v 1.6 1999/10/09 00:01:31 ralf Exp $ * * Real Time Clock interface for Linux * diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sgi/char/graphics.c linux/drivers/sgi/char/graphics.c --- v2.4.0-test2/linux/drivers/sgi/char/graphics.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/sgi/char/graphics.c Sun Jul 9 22:32:58 2000 @@ -1,4 +1,4 @@ -/* $Id: graphics.c,v 1.23 2000/02/23 00:41:21 ralf Exp $ +/* $Id: graphics.c,v 1.22 2000/02/18 00:24:43 ralf Exp $ * * gfx.c: support for SGI's /dev/graphics, /dev/opengl * diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sgi/char/sgicons.c linux/drivers/sgi/char/sgicons.c --- v2.4.0-test2/linux/drivers/sgi/char/sgicons.c Fri Jun 25 17:39:34 1999 +++ linux/drivers/sgi/char/sgicons.c Sun Jul 9 22:32:58 2000 @@ -1,4 +1,4 @@ -/* $Id: sgicons.c,v 1.11 1999/01/04 16:07:19 ralf Exp $ +/* $Id: sgicons.c,v 1.10 1998/08/25 09:18:58 ralf Exp $ * * sgicons.c: Setting up and registering console I/O on the SGI. * diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sgi/char/sgiserial.c linux/drivers/sgi/char/sgiserial.c --- v2.4.0-test2/linux/drivers/sgi/char/sgiserial.c Sat Feb 26 22:31:49 2000 +++ linux/drivers/sgi/char/sgiserial.c Sun Jul 9 22:32:58 2000 @@ -665,19 +665,6 @@ } -/* - * This subroutine is called when the RS_TIMER goes off. It is used - * by the serial driver to handle ports that do not have an interrupt - * (irq=0). This doesn't work at all for 16450's, as a sun has a Z8530. - */ - -static void rs_timer(void) -{ - printk("rs_timer called\n"); - prom_halt(); - return; -} - static int startup(struct sgi_serial * info) { volatile unsigned char junk; @@ -751,14 +738,6 @@ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; /* - * Set up serial timers... - */ -#if 0 /* Works well and stops the machine. */ - timer_table[RS_TIMER].expires = jiffies + 2; - timer_active |= 1 << RS_TIMER; -#endif - - /* * and set the speed of the serial port */ change_speed(info); @@ -1842,8 +1821,6 @@ /* Setup base handler, and timer table. */ init_bh(SERIAL_BH, do_serial_bh); - timer_table[RS_TIMER].fn = rs_timer; - timer_table[RS_TIMER].expires = 0; show_serial_version(); @@ -2247,7 +2224,8 @@ /* * Register console. */ -void __init serial_console_init(void) +void __init sgi_serial_console_init(void) { register_console(&sgi_console_driver); } +__initcall(rs_init); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sgi/char/shmiq.c linux/drivers/sgi/char/shmiq.c --- v2.4.0-test2/linux/drivers/sgi/char/shmiq.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/sgi/char/shmiq.c Sun Jul 9 22:32:58 2000 @@ -1,4 +1,4 @@ -/* $Id: shmiq.c,v 1.20 2000/02/24 00:13:10 ralf Exp $ +/* $Id: shmiq.c,v 1.19 2000/02/23 00:41:21 ralf Exp $ * * shmiq.c: shared memory input queue driver * written 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -56,6 +56,7 @@ #include #include +#include #include #include #include @@ -236,8 +237,8 @@ } return -EINVAL; + bad_file: - unlock_kernel (); return -EBADF; } @@ -250,51 +251,62 @@ struct vm_area_struct *vma; int v; - switch (cmd){ + switch (cmd) { /* * The address space is already mapped as a /dev/zero * mapping. FIXME: check that /dev/zero is what the user * had mapped before :-) */ - case QIOCATTACH: { - unsigned long vaddr; - int s; - - v = verify_area (VERIFY_READ, (void *) arg, sizeof (struct shmiqreq)); - if (v) - return v; - if (copy_from_user (&req, (void *) arg, sizeof (req))) - return -EFAULT; - /* Do not allow to attach to another region if it has been already attached */ - if (shmiqs [minor].mapped){ - printk ("SHMIQ:The thingie is already mapped\n"); - return -EINVAL; - } + case QIOCATTACH: { + unsigned long vaddr; + int s; + + v = verify_area (VERIFY_READ, (void *) arg, + sizeof (struct shmiqreq)); + if (v) + return v; + if (copy_from_user(&req, (void *) arg, sizeof (req))) + return -EFAULT; + /* + * Do not allow to attach to another region if it has + * already been attached + */ + if (shmiqs [minor].mapped) { + printk("SHMIQ:The thingie is already mapped\n"); + return -EINVAL; + } + + vaddr = (unsigned long) req.user_vaddr; + vma = find_vma (current->mm, vaddr); + if (!vma) { + printk ("SHMIQ: could not find %lx the vma\n", + vaddr); + return -EINVAL; + } + s = req.arg * sizeof (struct shmqevent) + + sizeof (struct sharedMemoryInputQueue); + v = sys_munmap (vaddr, s); + down(¤t->mm->mmap_sem); + do_munmap(current->mm, vaddr, s); + do_mmap(filp, vaddr, s, PROT_READ | PROT_WRITE, + MAP_PRIVATE|MAP_FIXED, 0); + up(¤t->mm->mmap_sem); + shmiqs[minor].events = req.arg; + shmiqs[minor].mapped = 1; - vaddr = (unsigned long) req.user_vaddr; - vma = find_vma (current->mm, vaddr); - if (!vma){ - printk ("SHMIQ: could not find %lx the vma\n", vaddr); - return -EINVAL; + return 0; } - s = req.arg * sizeof (struct shmqevent) + sizeof (struct sharedMemoryInputQueue); - down(¤t->mm->mmap_sem); - do_munmap (current->mm, vaddr, s); - do_mmap (filp, vaddr, s, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 0); - up(¤t->mm->mmap_sem); - shmiqs [minor].events = req.arg; - shmiqs [minor].mapped = 1; - return 0; - } } + return -EINVAL; } -unsigned long -shmiq_nopage (struct vm_area_struct *vma, unsigned long address, int write_access) +struct page * +shmiq_nopage (struct vm_area_struct *vma, unsigned long address, + int write_access) { /* Do not allow for mremap to expand us */ - return 0; + return NULL; } static struct vm_operations_struct qcntl_mmap = { @@ -336,14 +348,12 @@ return error; } - + static int shmiq_qcntl_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { int minor = MINOR (inode->i_rdev); - lock_kernel (); - if (minor-- == 0) return shmiq_ioctl (inode, filp, cmd, arg); @@ -387,6 +397,7 @@ shmiqs [minor].opened = 1; shmiqs [minor].shmiq_vaddr = 0; unlock_kernel (); + return 0; } @@ -427,6 +438,7 @@ vfree (shmiqs [minor].shmiq_vaddr); shmiqs [minor].shmiq_vaddr = 0; unlock_kernel (); + return 0; } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sgi/char/streamable.c linux/drivers/sgi/char/streamable.c --- v2.4.0-test2/linux/drivers/sgi/char/streamable.c Sat Feb 26 22:31:49 2000 +++ linux/drivers/sgi/char/streamable.c Sun Jul 9 22:32:58 2000 @@ -1,4 +1,4 @@ -/* $Id: streamable.c,v 1.11 2000/02/23 00:41:21 ralf Exp $ +/* $Id: streamable.c,v 1.10 2000/02/05 06:47:30 ralf Exp $ * * streamable.c: streamable devices. /dev/gfx * (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -52,14 +52,14 @@ static int sgi_gfx_open (struct inode *inode, struct file *file) { - printk ("GFX: Opened by %ld\n", current->pid); + printk ("GFX: Opened by %d\n", current->pid); return 0; } static int sgi_gfx_close (struct inode *inode, struct file *file) { - printk ("GFX: Closed by %ld\n", current->pid); + printk ("GFX: Closed by %d\n", current->pid); return 0; } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sgi/char/usema.c linux/drivers/sgi/char/usema.c --- v2.4.0-test2/linux/drivers/sgi/char/usema.c Thu Feb 10 17:11:14 2000 +++ linux/drivers/sgi/char/usema.c Sun Jul 9 22:32:58 2000 @@ -67,7 +67,7 @@ struct irix_usema *usema = file->private_data; int retval; - printk("[%s:%ld] wants ioctl 0x%xd (arg 0x%lx)", + printk("[%s:%d] wants ioctl 0x%xd (arg 0x%lx)", current->comm, current->pid, cmd, arg); switch(cmd) { @@ -79,7 +79,7 @@ usattach_t *attach = (usattach_t *)arg; retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t)); if (retval) { - printk("[%s:%ld] sgi_usema_ioctl(UIOCATTACHSEMA): " + printk("[%s:%d] sgi_usema_ioctl(UIOCATTACHSEMA): " "verify_area failure", current->comm, current->pid); return retval; @@ -87,7 +87,7 @@ if (usema == 0) return -EINVAL; - printk("UIOCATTACHSEMA: attaching usema %p to process %ld\n", + printk("UIOCATTACHSEMA: attaching usema %p to process %d\n", usema, current->pid); /* XXX what is attach->us_handle for? */ return sgi_usema_attach(attach, usema); @@ -101,12 +101,12 @@ retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t)); if (retval) { - printk("[%s:%ld] sgi_usema_ioctl(UIOC*BLOCK): " + printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): " "verify_area failure", current->comm, current->pid); return retval; } - printk("UIOC*BLOCK: putting process %ld to sleep on usema %p", + printk("UIOC*BLOCK: putting process %d to sleep on usema %p", current->pid, usema); if (cmd == UIOCNOIBLOCK) interruptible_sleep_on(&usema->proc_list); @@ -121,13 +121,13 @@ retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t)); if (retval) { - printk("[%s:%ld] sgi_usema_ioctl(UIOC*BLOCK): " + printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): " "verify_area failure", current->comm, current->pid); return retval; } - printk("[%s:%ld] releasing usema %p", + printk("[%s:%d] releasing usema %p", current->comm, current->pid, usema); wake_up(&usema->proc_list); return 0; @@ -141,7 +141,7 @@ { struct irix_usema *usema = filp->private_data; - printk("[%s:%ld] wants to poll usema %p", + printk("[%s:%d] wants to poll usema %p", current->comm, current->pid, usema); return 0; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c --- v2.4.0-test2/linux/drivers/sound/cmpci.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/sound/cmpci.c Wed Jul 5 10:56:14 2000 @@ -312,7 +312,6 @@ /* --------------------------------------------------------------------- */ static struct cm_state *devs = NULL; -static struct cm_state *devaudio = NULL; static unsigned long wavetable_mem = 0; /* --------------------------------------------------------------------- */ @@ -2462,10 +2461,8 @@ err_irq: if(s->iosynth) release_region(s->iosynth, CM_EXTENT_SYNTH); - err_region1: if(s->iomidi) release_region(s->iomidi, CM_EXTENT_MIDI); - err_region4: release_region(s->iobase, CM_EXTENT_CODEC); err_region5: kfree_s(s, sizeof(struct cm_state)); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c --- v2.4.0-test2/linux/drivers/sound/esssolo1.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/sound/esssolo1.c Wed Jul 5 10:56:14 2000 @@ -273,6 +273,7 @@ write_seq(s, data); } +#if 0 /* unused */ static unsigned char read_ctrl(struct solo1_state *s, unsigned char reg) { unsigned char r; @@ -282,6 +283,7 @@ read_seq(s, &r); return r; } +#endif /* unused */ static void write_mixer(struct solo1_state *s, unsigned char reg, unsigned char data) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sound/i810_audio.c linux/drivers/sound/i810_audio.c --- v2.4.0-test2/linux/drivers/sound/i810_audio.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/sound/i810_audio.c Wed Jul 5 11:18:05 2000 @@ -1627,12 +1627,11 @@ state->card->free_pcm_channel(state->card, dmabuf->channel->num); } - kfree(state->card->states[state->virt]); - state->card->states[state->virt] = NULL; - state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); - /* we're covered by the open_sem */ up(&state->open_sem); + + kfree(state->card->states[state->virt]); + state->card->states[state->virt] = NULL; return 0; } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sound/nm256_audio.c linux/drivers/sound/nm256_audio.c --- v2.4.0-test2/linux/drivers/sound/nm256_audio.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/sound/nm256_audio.c Thu Jul 6 19:29:31 2000 @@ -379,7 +379,7 @@ card->abuf1 + card->curPlayPos, rem); if (amt > rem) - nm256_writeBuffer8 (card, buffer, 1, card->abuf1, + nm256_writeBuffer8 (card, buffer + rem, 1, card->abuf1, amt - rem); } else diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sound/os.h linux/drivers/sound/os.h --- v2.4.0-test2/linux/drivers/sound/os.h Sun Nov 8 13:56:10 1998 +++ linux/drivers/sound/os.h Fri Jul 7 15:57:23 2000 @@ -4,11 +4,9 @@ #define MANUAL_PNP #undef DO_TIMINGS -#ifdef MODULE -#define __NO_VERSION__ #include #include -#endif + #if LINUX_VERSION_CODE > 131328 #define LINUX21X #endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c --- v2.4.0-test2/linux/drivers/sound/sb_common.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/sound/sb_common.c Wed Jul 5 10:56:14 2000 @@ -28,7 +28,6 @@ #include "sound_config.h" #include "sound_firmware.h" -#include "soundmodule.h" #include "mpu401.h" diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c --- v2.4.0-test2/linux/drivers/sound/sonicvibes.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/sound/sonicvibes.c Wed Jul 5 10:56:14 2000 @@ -535,7 +535,7 @@ static unsigned setpll(struct sv_state *s, unsigned char reg, unsigned rate) { unsigned long flags; - unsigned char r, m, n; + unsigned char r, m=0, n=0; unsigned xm, xn, xr, xd, metric = ~0U; /* the warnings about m and n used uninitialized are bogus and may safely be ignored */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c --- v2.4.0-test2/linux/drivers/sound/sound_core.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/sound/sound_core.c Wed Jul 5 11:00:22 2000 @@ -63,7 +63,7 @@ extern int msnd_pinnacle_init(void); #endif #ifdef CONFIG_SOUND_CMPCI -extern init_cmpci(void); +extern int init_cmpci(void); #endif /* @@ -559,7 +559,7 @@ printk(KERN_ERR "soundcore: sound device already in use.\n"); return -EBUSY; } - devfs_handle = devfs_mk_dir (NULL, "sound", 0, NULL); + devfs_handle = devfs_mk_dir (NULL, "sound", NULL); /* * Now init non OSS drivers */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sound/sound_syms.c linux/drivers/sound/sound_syms.c --- v2.4.0-test2/linux/drivers/sound/sound_syms.c Tue Mar 7 14:32:26 2000 +++ linux/drivers/sound/sound_syms.c Wed Jul 5 10:56:14 2000 @@ -53,7 +53,8 @@ EXPORT_SYMBOL(softoss_dev); /* Locking */ -#include "soundmodule.h" +extern struct notifier_block *sound_locker; +extern void sound_notifier_chain_register(struct notifier_block *); EXPORT_SYMBOL(sound_locker); EXPORT_SYMBOL(sound_notifier_chain_register); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c --- v2.4.0-test2/linux/drivers/sound/soundcard.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/sound/soundcard.c Wed Jul 5 10:56:14 2000 @@ -43,7 +43,7 @@ #include #include #include -#include "soundmodule.h" +#include struct notifier_block *sound_locker=(struct notifier_block *)0; @@ -572,7 +572,7 @@ else { devfs_handle_t de; - de = devfs_find_handle (NULL, name_buf, 0, 0, 0, + de = devfs_find_handle (NULL, name_buf, 0, 0, DEVFS_SPECIAL_CHR, 0); devfs_unregister (de); } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sound/sscape.c linux/drivers/sound/sscape.c --- v2.4.0-test2/linux/drivers/sound/sscape.c Fri Mar 10 16:40:44 2000 +++ linux/drivers/sound/sscape.c Wed Jul 5 10:56:14 2000 @@ -272,12 +272,14 @@ return data; } +#if 0 /* unused */ static int host_command1(struct sscape_info *devc, int cmd) { unsigned char buf[10]; buf[0] = (unsigned char) (cmd & 0xff); return host_write(devc, buf, 1); } +#endif /* unused */ static int host_command2(struct sscape_info *devc, int cmd, int parm1) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sound/trident.c linux/drivers/sound/trident.c --- v2.4.0-test2/linux/drivers/sound/trident.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/sound/trident.c Thu Jul 6 19:26:13 2000 @@ -538,7 +538,7 @@ } -static void trident_free_pcm_channel(struct trident_card *card, int channel) +static void trident_free_pcm_channel(struct trident_card *card, unsigned int channel) { int bank; @@ -551,7 +551,7 @@ card->banks[bank].bitmap &= ~(1 << (channel)); } -static void ali_free_pcm_channel(struct trident_card *card, int channel) +static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel) { int bank; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/sound/vidc.c linux/drivers/sound/vidc.c --- v2.4.0-test2/linux/drivers/sound/vidc.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/sound/vidc.c Mon Jun 26 12:04:42 2000 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "sound_config.h" diff -u --recursive --new-file v2.4.0-test2/linux/drivers/tc/zs.c linux/drivers/tc/zs.c --- v2.4.0-test2/linux/drivers/tc/zs.c Tue May 23 15:31:35 2000 +++ linux/drivers/tc/zs.c Sun Jul 9 22:30:36 2000 @@ -559,10 +559,6 @@ } } -static void rs_timer(void) -{ -} - static int startup(struct dec_serial * info) { unsigned long flags; @@ -1576,7 +1572,6 @@ { struct dec_serial **pp; int i, n, n_chips = 0, n_channels, chip, channel; - unsigned long flags; /* * did we get here by accident? @@ -1665,8 +1660,6 @@ /* Setup base handler, and timer table. */ init_bh(SERIAL_BH, do_serial_bh); - timer_table[RS_TIMER].fn = rs_timer; - timer_table[RS_TIMER].expires = 0; /* Find out how many Z8530 SCCs we have */ if (zs_chain == 0) @@ -1839,7 +1832,6 @@ { struct dec_serial *info; int i; - unsigned char nine; info = zs_soft + co->index; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/Config.in linux/drivers/usb/Config.in --- v2.4.0-test2/linux/drivers/usb/Config.in Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/Config.in Mon Jul 10 14:33:04 2000 @@ -38,6 +38,14 @@ bool ' USB ConnectTech WhiteHEAT Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_WHITEHEAT bool ' USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO bool ' USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA + bool ' USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN + if [ "$CONFIG_USB_SERIAL_KEYSPAN" != "n" ]; then + bool ' USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28 + bool ' USB Keyspan USA-28X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28X + bool ' USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19 + bool ' USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X + bool ' USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W + fi bool ' USB Digi International AccelePort USB Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_DIGI_ACCELEPORT bool ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET fi @@ -60,7 +68,8 @@ dep_tristate ' USB ADMtek Pegasus-based device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV - dep_tristate ' Microtek X6USB scanner support (EXPERIMENTAL)' CONFIG_USB_MICROTEK $CONFIG_SCSI + dep_tristate ' Microtek X6USB scanner support (EXPERIMENTAL)' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI + dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB fi comment 'USB HID' diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/Makefile linux/drivers/usb/Makefile --- v2.4.0-test2/linux/drivers/usb/Makefile Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/Makefile Mon Jul 10 14:33:03 2000 @@ -7,7 +7,7 @@ SUB_DIRS := MOD_SUB_DIRS := $(SUB_DIRS) MOD_IN_SUB_DIRS := $(SUB_DIRS) -ALL_SUB_DIRS := $(SUB_DIRS) serial +ALL_SUB_DIRS := $(SUB_DIRS) serial storage # The target object and module list name. @@ -49,6 +49,15 @@ endif endif +ifeq ($(CONFIG_USB_STORAGE),y) + SUB_DIRS += storage + obj-y += storage/usb-storage.o +else + ifeq ($(CONFIG_USB_STORAGE),m) + MOD_IN_SUB_DIRS += storage + endif +endif + # Each configuration option enables a list of files. @@ -73,8 +82,7 @@ obj-$(CONFIG_USB_AUDIO) += audio.o obj-$(CONFIG_USB_IBMCAM) += ibmcam.o obj-$(CONFIG_USB_DC2XX) += dc2xx.o -obj-$(CONFIG_USB_MDC800) += mdc800.o -obj-$(CONFIG_USB_STORAGE) += usb-storage.o +obj-$(CONFIG_USB_MDC800) += mdc800.o obj-$(CONFIG_USB_USS720) += uss720.o obj-$(CONFIG_USB_DABUSB) += dabusb.o obj-$(CONFIG_USB_PLUSB) += plusb.o @@ -83,6 +91,7 @@ obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_USB_MICROTEK) += microtek.o +obj-$(CONFIG_USB_BLUETOOTH) += bluetooth.o # Extract lists of the multi-part drivers. # The 'int-*' lists are the intermediate files used to build the multi's. diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/bluetooth.c linux/drivers/usb/bluetooth.c --- v2.4.0-test2/linux/drivers/usb/bluetooth.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/bluetooth.c Mon Jul 10 14:33:03 2000 @@ -0,0 +1,820 @@ +/* + * bluetooth.c Version 0.1 + * + * Copyright (c) 2000 Greg Kroah-Hartman + * + * USB Bluetooth driver, based on the Bluetooth Spec version 1.0B + * + * + * (07/09/2000) Version 0.1 gkh + * Initial release. Has support for sending ACL data (which is really just + * a HCI frame.) Raw HCI commands and HCI events are not supported. + * A ioctl will probably be needed for the HCI commands and events in the + * future. All isoch endpoints are ignored at this time also. + * This driver should work for all currently shipping USB Bluetooth + * devices at this time :) + * + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG +#include + +/* Module information */ +MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/"); +MODULE_DESCRIPTION("USB Bluetooth driver"); + + +/* Class, SubClass, and Protocol codes that describe a Bluetooth device */ +#define WIRELESS_CLASS_CODE 0xe0 +#define RF_SUBCLASS_CODE 0x01 +#define BLUETOOTH_PROGRAMMING_PROTOCOL_CODE 0x01 + + +#define BLUETOOTH_TTY_MAJOR 240 /* Prototype number for now */ +#define BLUETOOTH_TTY_MINORS 8 + +#define USB_BLUETOOTH_MAGIC 0x6d02 /* magic number for bluetooth struct */ + +/* parity check flag */ +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + + + +struct usb_bluetooth { + int magic; + struct usb_device * dev; + struct tty_driver * tty_driver; /* the tty_driver for this device */ + struct tty_struct * tty; /* the coresponding tty for this port */ + + unsigned char minor; /* the starting minor number for this device */ + char active; /* someone has this device open */ + + unsigned char * interrupt_in_buffer; + struct urb * interrupt_in_urb; + + unsigned char * bulk_in_buffer; + struct urb * read_urb; + + unsigned char * bulk_out_buffer; + int bulk_out_size; + struct urb * write_urb; + + wait_queue_head_t write_wait; + + struct tq_struct tqueue; /* task queue for line discipline waking up */ +}; + + + +/* local function prototypes */ +static int bluetooth_open (struct tty_struct *tty, struct file *filp); +static void bluetooth_close (struct tty_struct *tty, struct file *filp); +static int bluetooth_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count); +static int bluetooth_write_room (struct tty_struct *tty); +static int bluetooth_chars_in_buffer (struct tty_struct *tty); +static void bluetooth_throttle (struct tty_struct *tty); +static void bluetooth_unthrottle (struct tty_struct *tty); +static int bluetooth_ioctl (struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); +static void bluetooth_set_termios (struct tty_struct *tty, struct termios *old); + +static void * usb_bluetooth_probe (struct usb_device *dev, unsigned int ifnum); +static void usb_bluetooth_disconnect (struct usb_device *dev, void *ptr); + +static struct usb_driver usb_bluetooth_driver = { + name: "bluetooth", + probe: usb_bluetooth_probe, + disconnect: usb_bluetooth_disconnect, +}; + +static int bluetooth_refcount; +static struct tty_driver bluetooth_tty_driver; +static struct tty_struct * bluetooth_tty[BLUETOOTH_TTY_MINORS]; +static struct termios * bluetooth_termios[BLUETOOTH_TTY_MINORS]; +static struct termios * bluetooth_termios_locked[BLUETOOTH_TTY_MINORS]; +static struct usb_bluetooth *bluetooth_table[BLUETOOTH_TTY_MINORS] = {NULL, }; + + +static inline int bluetooth_paranoia_check (struct usb_bluetooth *bluetooth, const char *function) +{ + if (!bluetooth) { + dbg("%s - bluetooth == NULL", function); + return -1; + } + if (bluetooth->magic != USB_BLUETOOTH_MAGIC) { + dbg("%s - bad magic number for bluetooth", function); + return -1; + } + + return 0; +} + + +static inline struct usb_bluetooth* get_usb_bluetooth (struct usb_bluetooth *bluetooth, const char *function) +{ + if (!bluetooth || + bluetooth_paranoia_check (bluetooth, function)) { + /* then say that we dont have a valid usb_bluetooth thing, which will + * end up genrating -ENODEV return values */ + return NULL; + } + + return bluetooth; +} + + +static inline struct usb_bluetooth *get_bluetooth_by_minor (int minor) +{ + return bluetooth_table[minor]; +} + + + +/***************************************************************************** + * Driver tty interface functions + *****************************************************************************/ +static int bluetooth_open (struct tty_struct *tty, struct file * filp) +{ + struct usb_bluetooth *bluetooth; + + dbg(__FUNCTION__); + + /* initialize the pointer incase something fails */ + tty->driver_data = NULL; + + /* get the bluetooth object associated with this tty pointer */ + bluetooth = get_bluetooth_by_minor (MINOR(tty->device)); + + if (bluetooth_paranoia_check (bluetooth, __FUNCTION__)) { + return -ENODEV; + } + + if (bluetooth->active) { + dbg (__FUNCTION__ " - device already open"); + return -EINVAL; + } + + /* set up our structure making the tty driver remember our object, and us it */ + tty->driver_data = bluetooth; + bluetooth->tty = tty; + + bluetooth->active = 1; + + /*Start reading from the device*/ + if (usb_submit_urb(bluetooth->read_urb)) + dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed"); + + return 0; +} + + +static void bluetooth_close (struct tty_struct *tty, struct file * filp) +{ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); + + if (!bluetooth) { + return; + } + + dbg(__FUNCTION__); + + if (!bluetooth->active) { + dbg (__FUNCTION__ " - device not opened"); + return; + } + + /* shutdown any bulk reads that might be going on */ + usb_unlink_urb (bluetooth->write_urb); + usb_unlink_urb (bluetooth->read_urb); + + bluetooth->active = 0; +} + + +static int bluetooth_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) +{ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); + + if (!bluetooth) { + return -ENODEV; + } + + dbg(__FUNCTION__ " - %d byte(s)", count); + + if (!bluetooth->active) { + dbg (__FUNCTION__ " - device not opened"); + return -EINVAL; + } + + if (count == 0) { + dbg(__FUNCTION__ " - write request of 0 bytes"); + return (0); + } + + if (bluetooth->write_urb->status == -EINPROGRESS) { + dbg (__FUNCTION__ " - already writing"); + return (0); + } + + count = (count > bluetooth->bulk_out_size) ? bluetooth->bulk_out_size : count; + +#ifdef DEBUG + { + int i; + printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", count); + for (i = 0; i < count; ++i) { + printk ("%.2x ", buf[i]); + } + printk ("\n"); + } +#endif + + if (from_user) { + copy_from_user(bluetooth->write_urb->transfer_buffer, buf, count); + } + else { + memcpy (bluetooth->write_urb->transfer_buffer, buf, count); + } + + /* send the data out the bulk bluetooth */ + bluetooth->write_urb->transfer_buffer_length = count; + + if (usb_submit_urb(bluetooth->write_urb)) + dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed"); + + return count; +} + + +static int bluetooth_write_room (struct tty_struct *tty) +{ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); + int room = 0; + + if (!bluetooth) { + return -ENODEV; + } + + dbg(__FUNCTION__); + + if (!bluetooth->active) { + dbg (__FUNCTION__ " - device not open"); + return -EINVAL; + } + + if (bluetooth->write_urb->status != -EINPROGRESS) + room = bluetooth->bulk_out_size; + + dbg(__FUNCTION__ " - returns %d", room); + return room; +} + + +static int bluetooth_chars_in_buffer (struct tty_struct *tty) +{ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); + int chars = 0; + + if (!bluetooth) { + return -ENODEV; + } + + if (!bluetooth->active) { + dbg (__FUNCTION__ " - device not open"); + return -EINVAL; + } + + + if (bluetooth->write_urb->status == -EINPROGRESS) + chars = bluetooth->write_urb->transfer_buffer_length; + + dbg (__FUNCTION__ " - returns %d", chars); + return chars; +} + + +static void bluetooth_throttle (struct tty_struct * tty) +{ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); + + if (!bluetooth) { + return; + } + + dbg(__FUNCTION__); + + if (!bluetooth->active) { + dbg (__FUNCTION__ " - device not open"); + return; + } + + /* FIXME!!! */ + + return; +} + + +static void bluetooth_unthrottle (struct tty_struct * tty) +{ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); + + if (!bluetooth) { + return; + } + + dbg(__FUNCTION__); + + if (!bluetooth->active) { + dbg (__FUNCTION__ " - device not open"); + return; + } + + /* FIXME!!! */ + + return; +} + + +static int bluetooth_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) +{ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); + + if (!bluetooth) { + return -ENODEV; + } + + dbg(__FUNCTION__ " - cmd 0x%.4x", cmd); + + if (!bluetooth->active) { + dbg (__FUNCTION__ " - device not open"); + return -ENODEV; + } + + /* FIXME!!! */ + + return -ENOIOCTLCMD; +} + + +static void bluetooth_set_termios (struct tty_struct *tty, struct termios * old) +{ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); + + if (!bluetooth) { + return; + } + + dbg(__FUNCTION__); + + if (!bluetooth->active) { + dbg (__FUNCTION__ " - device not open"); + return; + } + + /* FIXME!!! */ + + return; +} + + +/***************************************************************************** + * urb callback functions + *****************************************************************************/ + +static void bluetooth_int_callback (struct urb *urb) +{ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__); + unsigned char *data = urb->transfer_buffer; + int i; + + dbg(__FUNCTION__); + + if (!bluetooth) { + dbg(__FUNCTION__ " - bad bluetooth pointer, exiting"); + return; + } + + if (urb->status) { + dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status); + return; + } + +#ifdef DEBUG + if (urb->actual_length) { + printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", urb->actual_length); + for (i = 0; i < urb->actual_length; ++i) { + printk ("%.2x ", data[i]); + } + printk ("\n"); + } +#endif + + /* Don't really know what else to do with this data yet. */ + /* FIXME!!! */ + + return; +} + + +static void bluetooth_read_bulk_callback (struct urb *urb) +{ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__); + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + int i; + + dbg(__FUNCTION__); + + if (!bluetooth) { + dbg(__FUNCTION__ " - bad bluetooth pointer, exiting"); + return; + } + + if (urb->status) { + dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status); + return; + } + +#ifdef DEBUG + if (urb->actual_length) { + printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", urb->actual_length); + for (i = 0; i < urb->actual_length; ++i) { + printk ("%.2x ", data[i]); + } + printk ("\n"); + } +#endif + + tty = bluetooth->tty; + if (urb->actual_length) { + for (i = 0; i < urb->actual_length ; ++i) { + tty_insert_flip_char(tty, data[i], 0); + } + tty_flip_buffer_push(tty); + } + + /* Continue trying to always read */ + if (usb_submit_urb(urb)) + dbg(__FUNCTION__ " - failed resubmitting read urb"); + + return; +} + + +static void bluetooth_write_bulk_callback (struct urb *urb) +{ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__); + + dbg(__FUNCTION__); + + if (!bluetooth) { + dbg(__FUNCTION__ " - bad bluetooth pointer, exiting"); + return; + } + + if (urb->status) { + dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status); + return; + } + + queue_task(&bluetooth->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); + + return; +} + + +static void bluetooth_softint(void *private) +{ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)private, __FUNCTION__); + struct tty_struct *tty; + + dbg(__FUNCTION__); + + if (!bluetooth) { + return; + } + + tty = bluetooth->tty; + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { + dbg(__FUNCTION__ " - write wakeup call."); + (tty->ldisc.write_wakeup)(tty); + } + + wake_up_interruptible(&tty->write_wait); +} + + +static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum) +{ + struct usb_bluetooth *bluetooth = NULL; + struct usb_interface_descriptor *interface; + struct usb_endpoint_descriptor *endpoint; + struct usb_endpoint_descriptor *interrupt_in_endpoint[8]; + struct usb_endpoint_descriptor *bulk_in_endpoint[8]; + struct usb_endpoint_descriptor *bulk_out_endpoint[8]; + int minor; + int buffer_size; + int i; + int num_interrupt_in = 0; + int num_bulk_in = 0; + int num_bulk_out = 0; + + /* see if this device has the proper class signature */ + if ((dev->descriptor.bDeviceClass != WIRELESS_CLASS_CODE) || + (dev->descriptor.bDeviceSubClass != RF_SUBCLASS_CODE) || + (dev->descriptor.bDeviceProtocol != BLUETOOTH_PROGRAMMING_PROTOCOL_CODE)) { + dbg (__FUNCTION__ " - class signature %d, %d, %d did not match", + dev->descriptor.bDeviceClass, dev->descriptor.bDeviceSubClass, + dev->descriptor.bDeviceProtocol); + return NULL; + } + + /* find the endpoints that we need */ + interface = &dev->actconfig->interface[ifnum].altsetting[0]; + for (i = 0; i < interface->bNumEndpoints; ++i) { + endpoint = &interface->endpoint[i]; + + if ((endpoint->bEndpointAddress & 0x80) && + ((endpoint->bmAttributes & 3) == 0x02)) { + /* we found a bulk in endpoint */ + dbg("found bulk in"); + bulk_in_endpoint[num_bulk_in] = endpoint; + ++num_bulk_in; + } + + if (((endpoint->bEndpointAddress & 0x80) == 0x00) && + ((endpoint->bmAttributes & 3) == 0x02)) { + /* we found a bulk out endpoint */ + dbg("found bulk out"); + bulk_out_endpoint[num_bulk_out] = endpoint; + ++num_bulk_out; + } + + if ((endpoint->bEndpointAddress & 0x80) && + ((endpoint->bmAttributes & 3) == 0x03)) { + /* we found a interrupt in endpoint */ + dbg("found interrupt in"); + interrupt_in_endpoint[num_interrupt_in] = endpoint; + ++num_interrupt_in; + } + } + + /* according to the spec, we can only have 1 bulk_in, 1 bulk_out, and 1 interrupt_in endpoints */ + if ((num_bulk_in != 1) || + (num_bulk_out != 1) || + (num_interrupt_in != 1)) { + dbg (__FUNCTION__ " - improper number of endpoints. Bluetooth driver not bound."); + return NULL; + } + + MOD_INC_USE_COUNT; + info("USB Bluetooth converter detected"); + + for (minor = 0; minor < BLUETOOTH_TTY_MINORS && bluetooth_table[minor]; ++minor) + ; + if (bluetooth_table[minor]) { + err("No more free Bluetooth devices"); + MOD_DEC_USE_COUNT; + return NULL; + } + + if (!(bluetooth = kmalloc(sizeof(struct usb_bluetooth), GFP_KERNEL))) { + err("Out of memory"); + MOD_DEC_USE_COUNT; + return NULL; + } + + memset(bluetooth, 0, sizeof(struct usb_bluetooth)); + + bluetooth->dev = dev; + bluetooth->minor = minor; + bluetooth->tqueue.routine = bluetooth_softint; + bluetooth->tqueue.data = bluetooth; + + /* set up the endpoint information */ + endpoint = bulk_in_endpoint[0]; + bluetooth->read_urb = usb_alloc_urb (0); + if (!bluetooth->read_urb) { + err("No free urbs available"); + goto probe_error; + } + buffer_size = endpoint->wMaxPacketSize; + bluetooth->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL); + if (!bluetooth->bulk_in_buffer) { + err("Couldn't allocate bulk_in_buffer"); + goto probe_error; + } + FILL_BULK_URB(bluetooth->read_urb, dev, usb_rcvbulkpipe(dev, endpoint->bEndpointAddress), + bluetooth->bulk_in_buffer, buffer_size, bluetooth_read_bulk_callback, bluetooth); + + endpoint = bulk_out_endpoint[0]; + bluetooth->write_urb = usb_alloc_urb(0); + if (!bluetooth->write_urb) { + err("No free urbs available"); + goto probe_error; + } + buffer_size = endpoint->wMaxPacketSize; + bluetooth->bulk_out_size = buffer_size; + bluetooth->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL); + if (!bluetooth->bulk_out_buffer) { + err("Couldn't allocate bulk_out_buffer"); + goto probe_error; + } + FILL_BULK_URB(bluetooth->write_urb, dev, usb_sndbulkpipe(dev, endpoint->bEndpointAddress), + bluetooth->bulk_out_buffer, buffer_size, bluetooth_write_bulk_callback, bluetooth); + + endpoint = interrupt_in_endpoint[0]; + bluetooth->interrupt_in_urb = usb_alloc_urb(0); + if (!bluetooth->interrupt_in_urb) { + err("No free urbs available"); + goto probe_error; + } + buffer_size = endpoint->wMaxPacketSize; + bluetooth->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL); + if (!bluetooth->interrupt_in_buffer) { + err("Couldn't allocate interrupt_in_buffer"); + goto probe_error; + } + FILL_INT_URB(bluetooth->interrupt_in_urb, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), + bluetooth->interrupt_in_buffer, buffer_size, bluetooth_int_callback, + bluetooth, endpoint->bInterval); + + /* initialize the devfs nodes for this device and let the user know what bluetooths we are bound to */ + tty_register_devfs (&bluetooth_tty_driver, 0, minor); + info("Bluetooth converter now attached to ttyBLUE%d (or usb/ttblue/%d for devfs)", minor, minor); + + return bluetooth; /* success */ + +probe_error: + if (bluetooth->read_urb) + usb_free_urb (bluetooth->read_urb); + if (bluetooth->bulk_in_buffer) + kfree (bluetooth->bulk_in_buffer); + if (bluetooth->write_urb) + usb_free_urb (bluetooth->write_urb); + if (bluetooth->bulk_out_buffer) + kfree (bluetooth->bulk_out_buffer); + if (bluetooth->interrupt_in_urb) + usb_free_urb (bluetooth->interrupt_in_urb); + if (bluetooth->interrupt_in_buffer) + kfree (bluetooth->interrupt_in_buffer); + + bluetooth_table[minor] = NULL; + + /* free up any memory that we allocated */ + kfree (bluetooth); + MOD_DEC_USE_COUNT; + return NULL; +} + + +static void usb_bluetooth_disconnect(struct usb_device *dev, void *ptr) +{ + struct usb_bluetooth *bluetooth = (struct usb_bluetooth *) ptr; + + if (bluetooth) { + bluetooth->active = 0; + + if (bluetooth->read_urb) { + usb_unlink_urb (bluetooth->read_urb); + usb_free_urb (bluetooth->read_urb); + } + if (bluetooth->bulk_in_buffer) + kfree (bluetooth->bulk_in_buffer); + + if (bluetooth->write_urb) { + usb_unlink_urb (bluetooth->write_urb); + usb_free_urb (bluetooth->write_urb); + } + if (bluetooth->bulk_out_buffer) + kfree (bluetooth->bulk_out_buffer); + + if (bluetooth->interrupt_in_urb) { + usb_unlink_urb (bluetooth->interrupt_in_urb); + usb_free_urb (bluetooth->interrupt_in_urb); + } + if (bluetooth->interrupt_in_buffer) + kfree (bluetooth->interrupt_in_buffer); + + tty_unregister_devfs (&bluetooth_tty_driver, bluetooth->minor); + + info("Bluetooth converter now disconnected from ttyBLUE%d", bluetooth->minor); + + bluetooth_table[bluetooth->minor] = NULL; + + /* free up any memory that we allocated */ + kfree (bluetooth); + + } else { + info("device disconnected"); + } + + MOD_DEC_USE_COUNT; +} + + +static struct tty_driver bluetooth_tty_driver = { + magic: TTY_DRIVER_MAGIC, + driver_name: "usb-bluetooth", + name: "usb/ttblue/%d", + major: BLUETOOTH_TTY_MAJOR, + minor_start: 0, + num: BLUETOOTH_TTY_MINORS, + type: TTY_DRIVER_TYPE_SERIAL, + subtype: SERIAL_TYPE_NORMAL, + flags: TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS, + + refcount: &bluetooth_refcount, + table: bluetooth_tty, + termios: bluetooth_termios, + termios_locked: bluetooth_termios_locked, + + open: bluetooth_open, + close: bluetooth_close, + write: bluetooth_write, + write_room: bluetooth_write_room, + ioctl: bluetooth_ioctl, + set_termios: bluetooth_set_termios, + throttle: bluetooth_throttle, + unthrottle: bluetooth_unthrottle, + chars_in_buffer: bluetooth_chars_in_buffer, +}; + + +int usb_bluetooth_init(void) +{ + int i; + int result; + + /* Initalize our global data */ + for (i = 0; i < BLUETOOTH_TTY_MINORS; ++i) { + bluetooth_table[i] = NULL; + } + + info ("USB Bluetooth support registered"); + + /* register the tty driver */ + bluetooth_tty_driver.init_termios = tty_std_termios; + bluetooth_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + if (tty_register_driver (&bluetooth_tty_driver)) { + err(__FUNCTION__ " - failed to register tty driver"); + return -1; + } + + /* register the USB driver */ + result = usb_register(&usb_bluetooth_driver); + if (result < 0) { + tty_unregister_driver(&bluetooth_tty_driver); + err("usb_register failed for the USB bluetooth driver. Error number %d", result); + return -1; + } + + return 0; +} + + +void usb_bluetooth_exit(void) +{ + usb_deregister(&usb_bluetooth_driver); + tty_unregister_driver(&bluetooth_tty_driver); +} + + +module_init(usb_bluetooth_init); +module_exit(usb_bluetooth_exit); + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/devio.c linux/drivers/usb/devio.c --- v2.4.0-test2/linux/drivers/usb/devio.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/devio.c Wed Jul 5 11:16:40 2000 @@ -514,6 +514,7 @@ extern struct list_head usb_driver_list; +#if 0 static int finddriver(struct usb_driver **driver, char *name) { struct list_head *tmp; @@ -533,6 +534,7 @@ return -EINVAL; } +#endif /* * file operations @@ -715,6 +717,27 @@ return 0; } +static int proc_clearhalt(struct dev_state *ps, void *arg) +{ + unsigned int ep; + int pipe; + int ret; + + get_user_ret(ep, (unsigned int *)arg, -EFAULT); + if ((ret = findintfep(ps->dev, ep)) < 0) + return ret; + if ((ret = checkintf(ps, ret))) + return ret; + if (ep & USB_DIR_IN) + pipe = usb_rcvbulkpipe(ps->dev, ep & 0x7f); + else + pipe = usb_sndbulkpipe(ps->dev, ep & 0x7f); + + usb_clear_halt(ps->dev, pipe); + return 0; +} + + static int proc_getdriver(struct dev_state *ps, void *arg) { struct usbdevfs_getdriver gd; @@ -1119,6 +1142,12 @@ case USBDEVFS_RESET: ret = proc_resetdevice(ps); + break; + + case USBDEVFS_CLEAR_HALT: + ret = proc_clearhalt(ps, (void *)arg); + if (ret >= 0) + inode->i_mtime = CURRENT_TIME; break; case USBDEVFS_GETDRIVER: diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/ibmcam.c linux/drivers/usb/ibmcam.c --- v2.4.0-test2/linux/drivers/usb/ibmcam.c Mon Jun 19 16:32:00 2000 +++ linux/drivers/usb/ibmcam.c Wed Jul 5 11:16:40 2000 @@ -2933,11 +2933,11 @@ * 1/22/00 Moved camera init code to ibmcam_open() * 1/27/00 Changed to use static structures, added locking. * 5/24/00 Corrected to prevent race condition (MOD_xxx_USE_COUNT). + * 7/3/00 Fixed endianness bug. */ static void *usb_ibmcam_probe(struct usb_device *dev, unsigned int ifnum) { struct usb_ibmcam *ibmcam = NULL; - const unsigned char *p_rev; const struct usb_interface_descriptor *interface; const struct usb_endpoint_descriptor *endpoint; int devnum, model=0; @@ -2955,20 +2955,24 @@ return NULL; /* Check the version/revision */ - p_rev = (const unsigned char *) &dev->descriptor.bcdDevice; - if (p_rev[1] == 0x00 && p_rev[0] == 0x02) { + switch (dev->descriptor.bcdDevice) { + case 0x0002: if (ifnum != 2) return NULL; - printk(KERN_INFO "IBM USB camera found (model 1).\n"); + printk(KERN_INFO "IBM USB camera found (model 1, rev. 0x%04x).\n", + dev->descriptor.bcdDevice); model = IBMCAM_MODEL_1; - } else if (p_rev[1] == 0x03 && p_rev[0] == 0x0A) { + break; + case 0x030A: if (ifnum != 0) return NULL; - printk(KERN_INFO "IBM USB camera found (model 2).\n"); + printk(KERN_INFO "IBM USB camera found (model 2, rev. 0x%04x).\n", + dev->descriptor.bcdDevice); model = IBMCAM_MODEL_2; - } else { - printk(KERN_ERR "IBM camera revision=%02x.%02x not supported\n", - p_rev[1], p_rev[0]); + break; + default: + printk(KERN_ERR "IBM camera with revision 0x%04x is not supported.\n", + dev->descriptor.bcdDevice); return NULL; } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/input.c linux/drivers/usb/input.c --- v2.4.0-test2/linux/drivers/usb/input.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/input.c Thu Jun 29 18:25:51 2000 @@ -401,7 +401,7 @@ printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR); return -EBUSY; } - input_devfs_handle = devfs_mk_dir(NULL, "input", 5, NULL); + input_devfs_handle = devfs_mk_dir(NULL, "input", NULL); return 0; } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/microtek.c linux/drivers/usb/microtek.c --- v2.4.0-test2/linux/drivers/usb/microtek.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/microtek.c Wed Jun 28 19:49:00 2000 @@ -52,11 +52,10 @@ * you want it, just send mail. * * Status: - * - * This driver does not work properly yet. + * * Untested with multiple scanners. * Untested on SMP. - * Untested on UHCI. + * Untested on a bigendian machine. * * History: * @@ -97,6 +96,8 @@ * 20000602 Version 0.2.0 * 20000603 various cosmetic changes * 20000603 Version 0.2.1 + * 20000620 minor cosmetic changes + * 20000620 Version 0.2.2 */ #include @@ -146,7 +147,7 @@ /* Internal driver stuff */ -#define MTS_VERSION "0.2.1" +#define MTS_VERSION "0.2.2" #define MTS_NAME "microtek usb (rev " MTS_VERSION "): " #define MTS_WARNING(x...) \ @@ -409,7 +410,7 @@ MTS_DEBUG_GOT_HERE(); mts_debug_dump(desc); - usb_reset_device(desc->usb_dev); + usb_reset_device(desc->usb_dev); /*FIXME: untested on new reset code */ return 0; /* RANT why here 0 and not SUCCESS */ } @@ -519,7 +520,7 @@ MTS_INT_INIT(); - context->srb->result &= MTS_MAX_CHUNK_MASK; + context->srb->result &= MTS_SCSI_ERR_MASK; context->srb->result |= (unsigned)context->status<<1; mts_transfer_cleanup(transfer); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/microtek.h linux/drivers/usb/microtek.h --- v2.4.0-test2/linux/drivers/usb/microtek.h Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/microtek.h Wed Jun 28 19:49:00 2000 @@ -68,6 +68,5 @@ #define MTS_EP_IMAGE 0x3 #define MTS_EP_TOTAL 0x3 -#define MTS_MAX_CHUNK_MASK ~0x3fu -/*maximum amount the scanner will transmit at once */ +#define MTS_SCSI_ERR_MASK ~0x3fu diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/ov511.c linux/drivers/usb/ov511.c --- v2.4.0-test2/linux/drivers/usb/ov511.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/ov511.c Thu Jun 29 09:53:14 2000 @@ -30,7 +30,7 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static const char version[] = "1.17"; +static const char version[] = "1.18"; #define __NO_VERSION__ @@ -49,10 +49,6 @@ #include #include -#ifdef CONFIG_KMOD -#include -#endif - #include "ov511.h" #undef OV511_GBR422 /* Experimental -- sets the 7610 to GBR422 */ @@ -67,7 +63,7 @@ #define DEFAULT_HEIGHT 480 #define GET_SEGSIZE(p) ((p) == VIDEO_PALETTE_GREY ? 256 : 384) -#define GET_DEPTH(p) ((p) == VIDEO_PALETTE_GREY ? 8 : 24) +#define GET_DEPTH(p) ((p) == VIDEO_PALETTE_GREY ? 8 : ((p) == VIDEO_PALETTE_YUV422 ? 8 : 24)) /* PARAMETER VARIABLES: */ static int autoadjust = 1; /* CCD dynamically changes exposure, etc... */ @@ -626,6 +622,7 @@ ov511_dump_i2c_range(dev, 0x00, 0x38); } +#if 0 static void ov511_dump_reg_range(struct usb_device *dev, int reg1, int regn) { int i; @@ -636,7 +633,6 @@ } } -#if 0 static void ov511_dump_regs(struct usb_device *dev) { PDEBUG(1, "CAMERA INTERFACE REGS"); @@ -1088,7 +1084,7 @@ #ifdef OV511_GBR422 static void ov511_parse_data_rgb24(unsigned char *pIn0, unsigned char *pOut0, - int iOutY, int iOutUV, int iHalf, int iWidth) + int iOutY, int iOutUV, int iHalf, int iWidth) { int k, l, m; unsigned char *pIn; @@ -1138,7 +1134,7 @@ static void ov511_parse_data_rgb24(unsigned char *pIn0, unsigned char *pOut0, - int iOutY, int iOutUV, int iHalf, int iWidth) + int iOutY, int iOutUV, int iHalf, int iWidth) { #ifndef OV511_DUMPPIX int k, l, m; @@ -1231,6 +1227,139 @@ } #endif +static void +ov511_parse_data_yuv422(unsigned char *pIn0, unsigned char *pOut0, + int iOutY, int iOutUV, int iHalf, int iWidth) +{ + int k, l, m; + unsigned char *pIn; + unsigned char *pOut, *pOut1; + + /* Just copy the Y's if in the first stripe */ + if (!iHalf) { + pIn = pIn0 + 128; + pOut = pOut0 + iOutY; + for (k = 0; k < 4; k++) { + pOut1 = pOut; + for (l = 0; l < 8; l++) { + for (m = 0; m < 8; m++) { + *pOut1++ = (*pIn++) & 0xF0; + } + pOut1 += iWidth - 8; + } + pOut += 8; + } + } + + /* Use the first half of VUs to calculate value */ + pIn = pIn0; + pOut = pOut0 + iOutUV; + for (l = 0; l < 4; l++) { + for (m=0; m<8; m++) { + unsigned char *p00 = pOut; + unsigned char *p01 = pOut+1; + unsigned char *p10 = pOut+iWidth; + unsigned char *p11 = pOut+iWidth+1; + int v = *(pIn+64) - 128; + int u = *pIn++ - 128; + int uv = ((u >> 4) & 0x0C) + (v >> 6); + + *p00 |= uv; + *p01 |= uv; + *p10 |= uv; + *p11 |= uv; + + pOut += 2; + } + pOut += (iWidth*2 - 16); + } + + /* Just copy the other UV rows */ + for (l = 0; l < 4; l++) { + for (m = 0; m < 8; m++) { + int v = *(pIn + 64) - 128; + int u = (*pIn++) - 128; + int uv = ((u >> 4) & 0x0C) + (v >> 6); + *(pOut) = uv; + pOut += 2; + } + pOut += (iWidth*2 - 16); + } + + /* Calculate values if it's the second half */ + if (iHalf) { + pIn = pIn0 + 128; + pOut = pOut0 + iOutY; + for (k = 0; k < 4; k++) { + pOut1 = pOut; + for (l=0; l<4; l++) { + for (m=0; m<4; m++) { + int y10 = *(pIn+8); + int y00 = *pIn++; + int y11 = *(pIn+8); + int y01 = *pIn++; + int uv = *pOut1; + + *pOut1 = (y00 & 0xF0) | uv; + *(pOut1+1) = (y01 & 0xF0) | uv; + *(pOut1+iWidth) = (y10 & 0xF0) | uv; + *(pOut1+iWidth+1) = (y11 & 0xF0) | uv; + + pOut1 += 2; + } + pOut1 += (iWidth*2 - 8); + pIn += 8; + } + pOut += 8; + } + } +} + +static void +ov511_parse_data_yuv422p(unsigned char *pIn0, unsigned char *pOut0, + int iOutY, int iOutUV, int iWidth, int iHeight) +{ + int k, l, m; + unsigned char *pIn; + unsigned char *pOut, *pOut1; + unsigned a = iWidth * iHeight; + unsigned w = iWidth / 2; + + pIn = pIn0; + pOut = pOut0 + iOutUV + a; + for (k = 0; k < 8; k++) { + pOut1 = pOut; + for (l = 0; l < 8; l++) { + *pOut1 = *(pOut1 + w) = *pIn++; + pOut1++; + } + pOut += iWidth; + } + + pIn = pIn0 + 64; + pOut = pOut0 + iOutUV + a + a/2; + for (k = 0; k < 8; k++) { + pOut1 = pOut; + for (l = 0; l < 8; l++) { + *pOut1 = *(pOut1 + w) = *pIn++; + pOut1++; + } + pOut += iWidth; + } + + pIn = pIn0 + 128; + pOut = pOut0 + iOutY; + for (k = 0; k < 4; k++) { + pOut1 = pOut; + for (l = 0; l < 8; l++) { + for (m = 0; m < 8; m++) + *pOut1++ =*pIn++; + pOut1 += iWidth - 8; + } + pOut += 8; + } +} + /* * For 640x480 RAW BW images, data shows up in 1200 256 byte segments. * The segments represent 4 squares of 8x8 pixels as follows: @@ -1432,7 +1561,7 @@ frame->segment < frame->width * frame->height / 256) { int iSegY, iSegUV; int iY, jY, iUV, jUV; - int iOutY, iOutUV; + int iOutY, iOutYP, iOutUV, iOutUVP; unsigned char *pOut; iSegY = iSegUV = frame->segment; @@ -1465,10 +1594,12 @@ */ iY = iSegY / (frame->width / WDIV); jY = iSegY - iY * (frame->width / WDIV); - iOutY = (iY*HDIV*frame->width + jY*WDIV) * (frame->depth >> 3); + iOutYP = iY*HDIV*frame->width + jY*WDIV; + iOutY = iOutYP * (frame->depth >> 3); iUV = iSegUV / (frame->width / WDIV * 2); jUV = iSegUV - iUV * (frame->width / WDIV * 2); - iOutUV = (iUV*HDIV*2*frame->width + jUV*WDIV/2) * (frame->depth >> 3); + iOutUVP = iUV*HDIV*2*frame->width + jUV*WDIV/2; + iOutUV = iOutUVP * (frame->depth >> 3); switch (frame->format) { case VIDEO_PALETTE_GREY: @@ -1478,6 +1609,16 @@ ov511_parse_data_rgb24 (pData, pOut, iOutY, iOutUV, iY & 1, frame->width); break; + case VIDEO_PALETTE_YUV422: + ov511_parse_data_yuv422(pData, pOut, iOutY, iOutUV, + iY & 1, frame->width); + break; + case VIDEO_PALETTE_YUV422P: + ov511_parse_data_yuv422p (pData, pOut, iOutYP, iOutUVP/2, + frame->width, frame->height); + break; + default: + err("Unsupported format: %d", frame->format); } pData = &cdata[iPix]; @@ -1995,17 +2136,22 @@ if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm))) return -EFAULT; - PDEBUG(4, "MCAPTURE"); + PDEBUG(4, "CMCAPTURE"); PDEBUG(4, "frame: %d, size: %dx%d, format: %d", vm.frame, vm.width, vm.height, vm.format); if (vm.format != VIDEO_PALETTE_RGB24 && + vm.format != VIDEO_PALETTE_YUV422 && + vm.format != VIDEO_PALETTE_YUV422P && vm.format != VIDEO_PALETTE_GREY) return -EINVAL; if ((vm.frame != 0) && (vm.frame != 1)) return -EINVAL; + if (vm.width > DEFAULT_WIDTH || vm.height > DEFAULT_HEIGHT) + return -EINVAL; + if (ov511->frame[vm.frame].grabstate == FRAME_GRABBING) return -EBUSY; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/printer.c linux/drivers/usb/printer.c --- v2.4.0-test2/linux/drivers/usb/printer.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/printer.c Thu Jul 6 19:38:22 2000 @@ -42,7 +42,7 @@ #include #include #include -#define DEBUG +#undef DEBUG #include #define USBLP_BUF_SIZE 8192 @@ -70,7 +70,7 @@ #define USBLP_MINORS 16 #define USBLP_MINOR_BASE 0 -#define USBLP_WRITE_TIMEOUT (60*HZ) /* 60 seconds */ +#define USBLP_WRITE_TIMEOUT (60*60*HZ) /* 60 minutes */ struct usblp { struct usb_device *dev; /* USB device */ @@ -147,10 +147,8 @@ info("usblp%d: off-line", usblp->minor); return -EIO; } - if (~status & LP_PERRORP) { - info("usblp%d: on fire", usblp->minor); - return -EIO; - } + info("usblp%d: on fire", usblp->minor); + return -EIO; } return 0; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/serial/Makefile linux/drivers/usb/serial/Makefile --- v2.4.0-test2/linux/drivers/usb/serial/Makefile Tue May 23 15:31:35 2000 +++ linux/drivers/usb/serial/Makefile Mon Jul 10 14:33:04 2000 @@ -19,6 +19,9 @@ ifeq ($(CONFIG_USB_SERIAL_KEYSPAN_PDA),y) O_OBJS += keyspan_pda.o endif +ifeq ($(CONFIG_USB_SERIAL_KEYSPAN),y) + O_OBJS += keyspan.o +endif ifeq ($(CONFIG_USB_SERIAL_OMNINET),y) O_OBJS += omninet.o endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/serial/digi_acceleport.c linux/drivers/usb/serial/digi_acceleport.c --- v2.4.0-test2/linux/drivers/usb/serial/digi_acceleport.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/serial/digi_acceleport.c Wed Jun 28 19:49:00 2000 @@ -14,6 +14,25 @@ * Peter Berger (pberger@brimson.com) * Al Borchers (borchers@steinerpoint.com) * +* (6/27/2000) pberger and borchers +* -- Zeroed out sync field in the wakeup_task before first use; +* otherwise the uninitialized value might prevent the task from +* being scheduled. +* -- Initialized ret value to 0 in write_bulk_callback, otherwise +* the uninitialized value could cause a spurious debugging message. +* +* (6/22/2000) pberger and borchers +* -- Made cond_wait_... inline--apparently on SPARC the flags arg +* to spin_lock_irqsave cannot be passed to another function +* to call spin_unlock_irqrestore. Thanks to Pauline Middelink. +* -- In digi_set_modem_signals the inner nested spin locks use just +* spin_lock() rather than spin_lock_irqsave(). The old code +* mistakenly left interrupts off. Thanks to Pauline Middelink. +* -- copy_from_user (which can sleep) is no longer called while a +* spinlock is held. We copy to a local buffer before getting +* the spinlock--don't like the extra copy but the code is simpler. +* -- Printk and dbg are no longer called while a spin lock is held. +* * (6/4/2000) pberger and borchers * -- Replaced separate calls to spin_unlock_irqrestore and * interruptible_sleep_on_interruptible with a new function @@ -119,8 +138,10 @@ * - All sleeps use a timeout of DIGI_RETRY_TIMEOUT before looping to * recheck the condition they are sleeping on. This is defensive, * in case a wake up is lost. +* - Following Documentation/DocBook/kernel-locking.pdf no spin locks +* are held when calling copy_to/from_user or printk. * -* $Id: digi_acceleport.c,v 1.56 2000/06/07 22:47:30 root Exp root $ +* $Id: digi_acceleport.c,v 1.63 2000/06/28 18:28:31 root Exp root $ */ #include @@ -307,7 +328,7 @@ int dp_transmit_idle; int dp_in_close; wait_queue_head_t dp_close_wait; /* wait queue for close */ - struct tq_struct dp_tasks; + struct tq_struct dp_wakeup_task; } digi_private_t; @@ -402,7 +423,7 @@ * wake ups. This is used to implement condition variables. */ -static long cond_wait_interruptible_timeout_irqrestore( +static inline long cond_wait_interruptible_timeout_irqrestore( wait_queue_head_t *q, long timeout, spinlock_t *lock, unsigned long flags ) { @@ -465,6 +486,7 @@ /* wake up other tty processes */ wake_up_interruptible( &tty->write_wait ); + /* For 2.2.16 backport -- wake_up_interruptible( &tty->poll_wait ); */ } @@ -515,17 +537,17 @@ if( (ret=usb_submit_urb(oob_port->write_urb)) == 0 ) { count -= len; buf += len; - } else { - dbg( - "digi_write_oob_command: usb_submit_urb failed, ret=%d", - ret ); - break; } } spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags ); + if( ret ) { + dbg( "digi_write_oob_command: usb_submit_urb failed, ret=%d", + ret ); + } + return( ret ); } @@ -569,8 +591,8 @@ } /* len must be a multiple of 4 and small enough to */ - /* guarantee the write will send all data (or none), */ - /* so commands are not split */ + /* guarantee the write will send buffered data first, */ + /* so commands are in order with data and not split */ len = MIN( count, port->bulk_out_size-2-priv->dp_buf_len ); if( len > 4 ) len &= ~3; @@ -588,35 +610,21 @@ port->write_urb->transfer_buffer_length = len; } -#ifdef DEBUG_DATA - { - int i; - - printk( KERN_DEBUG __FILE__ ": digi_write: port=%d, length=%d, data=", - priv->dp_port_num, port->write_urb->transfer_buffer_length ); - for( i=0; iwrite_urb->transfer_buffer_length; ++i ) { - printk( "%.2x ", - ((unsigned char *)port->write_urb->transfer_buffer)[i] ); - } - printk( "\n" ); - } -#endif - if( (ret=usb_submit_urb(port->write_urb)) == 0 ) { priv->dp_buf_len = 0; count -= len; buf += len; - } else { - dbg( - "digi_write_inb_command: usb_submit_urb failed, ret=%d", - ret ); - break; } } spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + if( ret ) { + dbg( "digi_write_inb_command: usb_submit_urb failed, ret=%d", + ret ); + } + return( ret ); } @@ -647,10 +655,10 @@ port_priv->dp_port_num, modem_signals ); spin_lock_irqsave( &oob_priv->dp_port_lock, flags ); - spin_lock_irqsave( &port_priv->dp_port_lock, flags ); + spin_lock( &port_priv->dp_port_lock ); while( oob_port->write_urb->status == -EINPROGRESS ) { - spin_unlock_irqrestore( &port_priv->dp_port_lock, flags ); + spin_unlock( &port_priv->dp_port_lock ); cond_wait_interruptible_timeout_irqrestore( &oob_port->write_wait, DIGI_RETRY_TIMEOUT, &oob_priv->dp_port_lock, flags ); @@ -658,7 +666,7 @@ return( -EINTR ); } spin_lock_irqsave( &oob_priv->dp_port_lock, flags ); - spin_lock_irqsave( &port_priv->dp_port_lock, flags ); + spin_lock( &port_priv->dp_port_lock ); } data[0] = DIGI_CMD_SET_DTR_SIGNAL; @@ -679,14 +687,16 @@ port_priv->dp_modem_signals = (port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS)) | (modem_signals&(TIOCM_DTR|TIOCM_RTS)); - } else { - dbg( "digi_set_modem_signals: usb_submit_urb failed, ret=%d", - ret ); } - spin_unlock_irqrestore( &port_priv->dp_port_lock, flags ); + spin_unlock( &port_priv->dp_port_lock ); spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags ); + if( ret ) { + dbg( "digi_set_modem_signals: usb_submit_urb failed, ret=%d", + ret ); + } + return( ret ); } @@ -1046,12 +1056,19 @@ int ret,data_len,new_len; digi_private_t *priv = (digi_private_t *)(port->private); unsigned char *data = port->write_urb->transfer_buffer; + unsigned char user_buf[64]; /* 64 bytes is max USB bulk packet */ unsigned long flags = 0; dbg( "digi_write: TOP: port=%d, count=%d, from_user=%d, in_interrupt=%d", priv->dp_port_num, count, from_user, in_interrupt() ); + /* copy user data (which can sleep) before getting spin lock */ + count = MIN( 64, MIN( count, port->bulk_out_size-2 ) ); + if( from_user && copy_from_user( user_buf, buf, count ) ) { + return( -EFAULT ); + } + /* be sure only one write proceeds at a time */ /* there are races on the port private buffer */ /* and races to check write_urb->status */ @@ -1096,40 +1113,19 @@ data += priv->dp_buf_len; /* copy in new data */ - if( from_user ) { - if( copy_from_user( data, buf, new_len ) ) { - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); - return( -EFAULT ); - } - } else { - memcpy( data, buf, new_len ); - } - -#ifdef DEBUG_DATA - { - int i; - - printk( KERN_DEBUG __FILE__ ": digi_write: port=%d, length=%d, data=", - priv->dp_port_num, port->write_urb->transfer_buffer_length ); - for( i=0; iwrite_urb->transfer_buffer_length; ++i ) { - printk( "%.2x ", - ((unsigned char *)port->write_urb->transfer_buffer)[i] ); - } - printk( "\n" ); - } -#endif + memcpy( data, from_user ? user_buf : buf, new_len ); if( (ret=usb_submit_urb(port->write_urb)) == 0 ) { ret = new_len; priv->dp_buf_len = 0; - } else { - dbg( "digi_write: usb_submit_urb failed, ret=%d", - ret ); } /* return length of new data written, or error */ -dbg( "digi_write: returning %d", ret ); spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + if( ret < 0 ) { + dbg( "digi_write: usb_submit_urb failed, ret=%d", ret ); + } +dbg( "digi_write: returning %d", ret ); return( ret ); } @@ -1141,7 +1137,7 @@ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = port->serial; digi_private_t *priv = (digi_private_t *)(port->private); - int ret; + int ret = 0; dbg( "digi_write_bulk_callback: TOP: port=%d", priv->dp_port_num ); @@ -1175,24 +1171,8 @@ memcpy( port->write_urb->transfer_buffer+2, priv->dp_buf, priv->dp_buf_len ); -#ifdef DEBUG_DATA - { - int i; - - printk( KERN_DEBUG __FILE__ ": digi_write_bulk_callback: port=%d, length=%d, data=", - priv->dp_port_num, port->write_urb->transfer_buffer_length ); - for( i=0; iwrite_urb->transfer_buffer_length; ++i ) { - printk( "%.2x ", - ((unsigned char *)port->write_urb->transfer_buffer)[i] ); - } - printk( "\n" ); - } -#endif - if( (ret=usb_submit_urb(port->write_urb)) == 0 ) { priv->dp_buf_len = 0; - } else { - dbg( "digi_write_bulk_callback: usb_submit_urb failed, ret=%d", ret ); } } @@ -1200,13 +1180,16 @@ /* wake up processes sleeping on writes immediately */ digi_wakeup_write( port ); - spin_unlock( &priv->dp_port_lock ); - /* also queue up a wakeup at scheduler time, in case we */ /* lost the race in write_chan(). */ - priv->dp_tasks.routine = (void *)digi_wakeup_write_lock; - priv->dp_tasks.data = (void *)port; - queue_task( &(priv->dp_tasks), &tq_scheduler ); + queue_task( &priv->dp_wakeup_task, &tq_scheduler ); + + spin_unlock( &priv->dp_port_lock ); + + if( ret ) { + dbg( "digi_write_bulk_callback: usb_submit_urb failed, ret=%d", + ret ); + } } @@ -1219,8 +1202,6 @@ unsigned long flags = 0; -dbg( "digi_write_room: TOP: port=%d", priv->dp_port_num ); - spin_lock_irqsave( &priv->dp_port_lock, flags ); if( port->write_urb->status == -EINPROGRESS ) @@ -1242,8 +1223,6 @@ digi_private_t *priv = (digi_private_t *)(port->private); -dbg( "digi_chars_in_buffer: TOP: port=%d", priv->dp_port_num ); - if( port->write_urb->status == -EINPROGRESS ) { dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, port->bulk_out_size - 2 ); /* return( port->bulk_out_size - 2 ); */ @@ -1455,13 +1434,14 @@ int i,ret = 0; - spin_lock( &startup_lock ); - /* be sure this happens exactly once */ + spin_lock( &startup_lock ); if( device_startup ) { spin_unlock( &startup_lock ); return( 0 ); } + device_startup = 1; + spin_unlock( &startup_lock ); /* start reading from each bulk in endpoint for the device */ for( i=0; idp_transmit_idle = 0; priv->dp_in_close = 0; init_waitqueue_head( &priv->dp_close_wait ); - priv->dp_tasks.next = NULL; - priv->dp_tasks.data = NULL; + priv->dp_wakeup_task.next = NULL; + priv->dp_wakeup_task.sync = 0; + priv->dp_wakeup_task.routine = (void *)digi_wakeup_write_lock; + priv->dp_wakeup_task.data = (void *)(&serial->port[i]); spin_lock_init( &priv->dp_port_lock ); /* initialize write wait queue for this port */ @@ -1594,17 +1572,6 @@ return; goto resubmit; } - -#ifdef DEBUG_DATA -if( urb->actual_length ) { - printk( KERN_DEBUG __FILE__ ": digi_read_bulk_callback: port=%d, length=%d, data=", - priv->dp_port_num, urb->actual_length ); - for( i=0; iactual_length; ++i ) { - printk( "%.2x ", ((unsigned char *)urb->transfer_buffer)[i] ); - } - printk( "\n" ); -} -#endif if( urb->actual_length != len + 2 ) err( KERN_INFO "digi_read_bulk_callback: INCOMPLETE PACKET, port=%d, opcode=%d, len=%d, actual_length=%d, status=%d", priv->dp_port_num, opcode, len, urb->actual_length, status ); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/serial/keyspan.c linux/drivers/usb/serial/keyspan.c --- v2.4.0-test2/linux/drivers/usb/serial/keyspan.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/keyspan.c Mon Jul 10 14:33:04 2000 @@ -0,0 +1,512 @@ +/* + Keyspan USB to Serial Converter driver + + (C) Copyright (C) 2000 + Hugh Blemings + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + See http://www.linuxcare.com.au/hugh/keyspan.html for more + information on this driver. + + Code in this driver inspired by and in a number of places taken + from Brian Warner's original Keyspan-PDA driver. + + This driver has been put together with the support of Innosys, Inc. + and Keyspan, Inc the manufacturers of the Keyspan USB-serial products. + Thanks Guys :) + + Tip 'o the hat to Linuxcare for supporting staff in their work on + open source projects. + + Sat Jul 8 11:11:48 EST 2000 Hugh + First public release - nothing works except the firmware upload. + Tested on PPC and x86 architectures, seems to behave... + +*/ + + +#include + +#ifdef CONFIG_USB_SERIAL_KEYSPAN + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_SERIAL_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif +#include + +#include "usb-serial.h" + +struct ezusb_hex_record { + __u16 address; + __u8 data_size; + __u8 data[16]; +}; + + /* Conditionally include firmware images, if they aren't + included create a null pointer instead. Current + firmware images aren't optimised to remove duplicate + addresses. */ +#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA28 + #include "keyspan_usa28_fw.h" +#else + static const struct ezusb_hex_record *keyspan_usa28_firmware = NULL; +#endif + +#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA28X + #include "keyspan_usa28x_fw.h" +#else + static const struct ezusb_hex_record *keyspan_usa28x_firmware = NULL; +#endif + +#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA19 + #include "keyspan_usa19_fw.h" +#else + static const struct ezusb_hex_record *keyspan_usa19_firmware = NULL; +#endif + +#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA18X + #include "keyspan_usa18x_fw.h" +#else + static const struct ezusb_hex_record *keyspan_usa18x_firmware = NULL; +#endif + +#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA19W + #include "keyspan_usa19w_fw.h" +#else + static const struct ezusb_hex_record *keyspan_usa19w_firmware = NULL; +#endif + + /* Include Keyspan message headers (not here yet, need some tweaks + to get clean build) */ +/*#include "keyspan_usa26msg.h"*/ +/*#include "keyspan_usa28msg.h"*/ + + /* If you don't get debugging output, uncomment the following + two lines to enable cheat. */ +#undef dbg +#define dbg printk + + + /* function prototypes for Keyspan serial converter */ +static int keyspan_open (struct usb_serial_port *port, + struct file *filp); +static void keyspan_close (struct usb_serial_port *port, + struct file *filp); +static int keyspan_startup (struct usb_serial *serial); +static void keyspan_shutdown (struct usb_serial *serial); +static void keyspan_rx_interrupt (struct urb *urb); +static void keyspan_rx_throttle (struct usb_serial_port *port); +static void keyspan_rx_unthrottle (struct usb_serial_port *port); +static int keyspan_write_room (struct usb_serial_port *port); +static int keyspan_write (struct usb_serial_port *port, + int from_user, + const unsigned char *buf, + int count); +static void keyspan_write_bulk_callback (struct urb *urb); +static int keyspan_chars_in_buffer (struct usb_serial_port *port); +static int keyspan_ioctl (struct usb_serial_port *port, + struct file *file, + unsigned int cmd, + unsigned long arg); +static void keyspan_set_termios (struct usb_serial_port *port, + struct termios *old); +static void keyspan_break_ctl (struct usb_serial_port *port, + int break_state); +static int keyspan_fake_startup (struct usb_serial *serial); + + + /* Functions - mostly stubs for now */ + +static void keyspan_rx_interrupt (struct urb *urb) +{ + +} + + +static void keyspan_rx_throttle (struct usb_serial_port *port) +{ + dbg("keyspan_rx_throttle port %d", port->number); +} + + +static void keyspan_rx_unthrottle (struct usb_serial_port *port) +{ + dbg("keyspan_rx_unthrottle port %d", port->number); +} + + +static void keyspan_break_ctl (struct usb_serial_port *port, int break_state) +{ + dbg("keyspan_break_ctl"); +} + + +static void keyspan_set_termios (struct usb_serial_port *port, + struct termios *old_termios) +{ + dbg("keyspan_set_termios"); +} + +static int keyspan_ioctl(struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg) +{ + + dbg("keyspan_ioctl_info"); + + return -ENOIOCTLCMD; +} + +static int keyspan_write(struct usb_serial_port *port, int from_user, + const unsigned char *buf, int count) +{ + dbg("keyspan_write called\n"); + return(count); +} + + +static void keyspan_write_bulk_callback (struct urb *urb) +{ + + dbg("keyspan_write_bulk_callback called\n"); +} + + +static int keyspan_write_room (struct usb_serial_port *port) +{ + dbg("keyspan_write_room called\n"); + return (1); + +} + + +static int keyspan_chars_in_buffer (struct usb_serial_port *port) +{ + return (0); +} + + +static int keyspan_open (struct usb_serial_port *port, struct file *filp) +{ + dbg("keyspan_open called\n"); + return (0); +} + + +static void keyspan_close(struct usb_serial_port *port, struct file *filp) +{ + dbg("keyspan_close called\n"); +} + + + /* download the firmware to a pre-renumeration device */ +static int keyspan_fake_startup (struct usb_serial *serial) +{ + int response; + const struct ezusb_hex_record *record; + char *fw_name; + + dbg("Keyspan startup version %04x product %04x\n", serial->dev->descriptor.bcdDevice, + serial->dev->descriptor.idProduct); + + if ((serial->dev->descriptor.bcdDevice & 0x8000) != 0x8000) { + dbg("Firmware already loaded. Quitting.\n"); + return(1); + } + + /* Select firmware image on the basis of idProduct */ + switch (serial->dev->descriptor.idProduct) { + case 0x0101: record = &keyspan_usa28_firmware[0]; + fw_name = "USA28"; + break; + + case 0x0102: record = &keyspan_usa28x_firmware[0]; + fw_name = "USA28X"; + break; + + case 0x0103: record = &keyspan_usa19_firmware[0]; + fw_name = "USA19"; + break; + + case 0x0105: record = &keyspan_usa18x_firmware[0]; + fw_name = "USA18X"; + break; + + case 0x0106: record = &keyspan_usa19w_firmware[0]; + fw_name = "USA19W"; + break; + + default: record = NULL; + fw_name = "Unknown"; + break; + } + + if (record == NULL) { + err("Required keyspan firmware image (%s) unavailable.\n", fw_name); + return(1); + } + + dbg("Uploading Keyspan %s firmware.\n", fw_name); + + /* download the firmware image */ + response = ezusb_set_reset(serial, 1); + + while(record->address != 0xffff) { + response = ezusb_writememory(serial, record->address, + (unsigned char *)record->data, + record->data_size, 0xa0); + if (response < 0) { + err("ezusb_writememory failed for Keyspan" + "firmware (%d %04X %p %d)", + response, + record->address, record->data, record->data_size); + break; + } + record++; + } + /* bring device out of reset. Renumeration will occur in a moment + and the new device will bind to the real driver */ + response = ezusb_set_reset(serial, 0); + + /* we want this device to fail to have a driver assigned to it. */ + return (1); +} + + + /* Gets called by the "real" driver (ie once firmware is loaded + and renumeration has taken place. */ +static int keyspan_startup (struct usb_serial *serial) +{ + dbg("keyspan_startup called.\n"); + + return (0); +} + +static void keyspan_shutdown (struct usb_serial *serial) +{ + dbg("keyspan_shutdown called.\n"); + +} + + /* Miscellaneous defines, datastructures etc. */ + +#define KEYSPAN_VENDOR_ID 0x06cd + + /* Device info needed for the Keyspan serial converter */ +static __u16 keyspan_vendor_id = KEYSPAN_VENDOR_ID; + + /* Product IDs for the five products supported, pre-renumeration */ +static __u16 keyspan_usa18x_pre_product_id = 0x0105; +static __u16 keyspan_usa19_pre_product_id = 0x0103; +static __u16 keyspan_usa19w_pre_product_id = 0x0106; +static __u16 keyspan_usa28_pre_product_id = 0x0101; +static __u16 keyspan_usa28x_pre_product_id = 0x0102; + + /* Product IDs post-renumeration */ +static __u16 keyspan_usa18x_product_id = 0x0112; +static __u16 keyspan_usa19_product_id = 0x0107; +static __u16 keyspan_usa19w_product_id = 0x0108; +static __u16 keyspan_usa28_product_id = 0x010f; +static __u16 keyspan_usa28x_product_id = 0x0110; + + /* Structs for the devices, pre and post renumeration. + These are incomplete at present - HAB 20000708 */ +struct usb_serial_device_type keyspan_usa18x_pre_device = { + name: "Keyspan USA18X - (prerenumeration)", + idVendor: &keyspan_vendor_id, + idProduct: &keyspan_usa18x_pre_product_id, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: DONT_CARE, + needs_bulk_out: DONT_CARE, + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 1, + startup: keyspan_fake_startup +}; + +struct usb_serial_device_type keyspan_usa19_pre_device = { + name: "Keyspan USA19 - (prerenumeration)", + idVendor: &keyspan_vendor_id, + idProduct: &keyspan_usa19_pre_product_id, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: DONT_CARE, + needs_bulk_out: DONT_CARE, + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 1, + startup: keyspan_fake_startup +}; + + +struct usb_serial_device_type keyspan_usa19w_pre_device = { + name: "Keyspan USA19W - (prerenumeration)", + idVendor: &keyspan_vendor_id, + idProduct: &keyspan_usa19w_pre_product_id, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: DONT_CARE, + needs_bulk_out: DONT_CARE, + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 1, + startup: keyspan_fake_startup +}; + + +struct usb_serial_device_type keyspan_usa28_pre_device = { + name: "Keyspan USA28 - (prerenumeration)", + idVendor: &keyspan_vendor_id, + idProduct: &keyspan_usa28_pre_product_id, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: DONT_CARE, + needs_bulk_out: DONT_CARE, + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 2, + startup: keyspan_fake_startup +}; + +struct usb_serial_device_type keyspan_usa28x_pre_device = { + name: "Keyspan USA28X - (prerenumeration)", + idVendor: &keyspan_vendor_id, + idProduct: &keyspan_usa28x_pre_product_id, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: DONT_CARE, + needs_bulk_out: DONT_CARE, + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 2, + startup: keyspan_fake_startup +}; + + +struct usb_serial_device_type keyspan_usa18x_device = { + name: "Keyspan USA18X", + idVendor: &keyspan_vendor_id, + idProduct: &keyspan_usa18x_product_id, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: DONT_CARE, + needs_bulk_out: DONT_CARE, + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 1, + open: keyspan_open, + close: keyspan_close, + throttle: keyspan_rx_throttle, + unthrottle: keyspan_rx_unthrottle, + set_termios: keyspan_set_termios, +}; + +struct usb_serial_device_type keyspan_usa19_device = { + name: "Keyspan USA19", + idVendor: &keyspan_vendor_id, + idProduct: &keyspan_usa19_product_id, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: DONT_CARE, + needs_bulk_out: DONT_CARE, + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 1, + open: keyspan_open, + close: keyspan_close, + write: keyspan_write, + write_room: keyspan_write_room, + write_bulk_callback: keyspan_write_bulk_callback, + read_int_callback: keyspan_rx_interrupt, + chars_in_buffer: keyspan_chars_in_buffer, + throttle: keyspan_rx_throttle, + unthrottle: keyspan_rx_unthrottle, + ioctl: keyspan_ioctl, + set_termios: keyspan_set_termios, + break_ctl: keyspan_break_ctl, + startup: keyspan_startup, + shutdown: keyspan_shutdown, +}; + + +struct usb_serial_device_type keyspan_usa19w_device = { + name: "Keyspan USA19W", + idVendor: &keyspan_vendor_id, + idProduct: &keyspan_usa19w_product_id, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: DONT_CARE, + needs_bulk_out: DONT_CARE, + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 1, + open: keyspan_open, + close: keyspan_close, + throttle: keyspan_rx_throttle, + unthrottle: keyspan_rx_unthrottle, + set_termios: keyspan_set_termios, +}; + + +struct usb_serial_device_type keyspan_usa28_device = { + name: "Keyspan USA28", + idVendor: &keyspan_vendor_id, + idProduct: &keyspan_usa28_product_id, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: DONT_CARE, + needs_bulk_out: DONT_CARE, + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 2, + open: keyspan_open, + close: keyspan_close, + throttle: keyspan_rx_throttle, + unthrottle: keyspan_rx_unthrottle, + set_termios: keyspan_set_termios, +}; + + +struct usb_serial_device_type keyspan_usa28x_device = { + name: "Keyspan USA28X", + idVendor: &keyspan_vendor_id, + idProduct: &keyspan_usa28x_product_id, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: DONT_CARE, + needs_bulk_out: DONT_CARE, + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 2, + open: keyspan_open, + close: keyspan_close, + throttle: keyspan_rx_throttle, + unthrottle: keyspan_rx_unthrottle, + set_termios: keyspan_set_termios, +}; + + + + +#endif /* CONFIG_USB_SERIAL_KEYSPAN */ + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/serial/keyspan_usa18x_fw.h linux/drivers/usb/serial/keyspan_usa18x_fw.h --- v2.4.0-test2/linux/drivers/usb/serial/keyspan_usa18x_fw.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/keyspan_usa18x_fw.h Mon Jul 10 14:33:04 2000 @@ -0,0 +1,406 @@ +/* keyspan_usa18x_fw.h + + Generated from Keyspan firmware image Wed Jul 5 09:18:29 2000 EST + This firmware is for the Keyspan USA-18X Serial Adaptor + + "The firmware contained herein as keyspan_usa18x_fw.h is + Copyright (C) 1999-2000 Keyspan, A division of InnoSys Incorporated + ("Keyspan"), as an unpublished work. This notice does not imply + unrestricted or public access to this firmware which is a trade secret of + Keyspan, and which may not be reproduced, used, sold or transferred to any + third party without Keyspan's prior written consent. All Rights Reserved. + + This firmware may not be modified and may only be used with the Keyspan + USA-18X Serial Adapter. Distribution and/or Modification of the + keyspan.c driver which includes this firmware, in whole or in part, + requires the inclusion of this statement." + +*/ + +static const struct ezusb_hex_record keyspan_usa18x_firmware[] = { +{ 0x0000, 3, {0x02, 0x0e, 0x9b} }, +{ 0x0003, 16, {0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0x30, 0xf0, 0xe4, 0x90, 0x7f, 0x96, 0xf0} }, +{ 0x0013, 16, {0x90, 0x7f, 0x94, 0xf0, 0x90, 0x7f, 0x9d, 0x74, 0xff, 0xf0, 0xe4, 0x90, 0x7f, 0x97, 0xf0, 0x90} }, +{ 0x0023, 15, {0x7f, 0x95, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x07, 0xf0, 0xe4, 0x90, 0x7f, 0x98, 0xf0, 0x22} }, +{ 0x0033, 3, {0x02, 0x13, 0xfc} }, +{ 0x0036, 12, {0x90, 0x7f, 0x98, 0x74, 0x10, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x0043, 3, {0x02, 0x14, 0x00} }, +{ 0x0046, 16, {0x30, 0x08, 0x13, 0x12, 0x13, 0xc0, 0xef, 0xc3, 0x95, 0x3c, 0x50, 0x73, 0x90, 0x7f, 0xbf, 0x74} }, +{ 0x0056, 16, {0x01, 0xf0, 0xc2, 0x08, 0x80, 0x69, 0x30, 0x02, 0x34, 0x90, 0x7f, 0xc6, 0xe0, 0x20, 0xe1, 0x5f} }, +{ 0x0066, 16, {0x12, 0x13, 0xc0, 0xef, 0xc3, 0x94, 0x40, 0x50, 0x56, 0x90, 0x7e, 0x40, 0xe0, 0x13, 0x92, 0x08} }, +{ 0x0076, 16, {0x90, 0x7f, 0xc7, 0xe0, 0x14, 0xf5, 0x08, 0x7e, 0x7e, 0x7f, 0x41, 0x75, 0x0c, 0x7e, 0x75, 0x0d} }, +{ 0x0086, 16, {0x41, 0x12, 0x0d, 0x55, 0xc2, 0x02, 0xe4, 0x90, 0x7f, 0xc7, 0xf0, 0x80, 0x32, 0x90, 0x7f, 0xc8} }, +{ 0x0096, 16, {0xe0, 0x20, 0xe1, 0x2b, 0x12, 0x13, 0xc0, 0xef, 0xc3, 0x94, 0x40, 0x50, 0x22, 0x90, 0x7d, 0xc0} }, +{ 0x00a6, 16, {0xe0, 0x13, 0x92, 0x08, 0x90, 0x7f, 0xc9, 0xe0, 0x14, 0xf5, 0x08, 0x7e, 0x7d, 0x7f, 0xc1, 0x75} }, +{ 0x00b6, 16, {0x0c, 0x7d, 0x75, 0x0d, 0xc1, 0x12, 0x0d, 0x55, 0xd2, 0x02, 0xe4, 0x90, 0x7f, 0xc9, 0xf0, 0x90} }, +{ 0x00c6, 16, {0x7f, 0xb6, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x01, 0x53, 0x53, 0x36, 0x80, 0x12, 0x13, 0xcc, 0xef} }, +{ 0x00d6, 16, {0x42, 0x36, 0x12, 0x12, 0x49, 0x8f, 0x19, 0xef, 0xc3, 0x95, 0x3a, 0x50, 0x0f, 0x12, 0x13, 0xa8} }, +{ 0x00e6, 16, {0xef, 0x30, 0xe0, 0x08, 0xe5, 0x36, 0x20, 0xe7, 0x03, 0x30, 0x0a, 0x61, 0xc2, 0x0a, 0xe5, 0x19} }, +{ 0x00f6, 16, {0x70, 0x04, 0xf5, 0x36, 0x80, 0x57, 0x12, 0x13, 0xcc, 0xef, 0x42, 0x36, 0xe5, 0x36, 0x30, 0xe7} }, +{ 0x0106, 16, {0x26, 0xe5, 0x19, 0xd3, 0x94, 0x20, 0x40, 0x03, 0x75, 0x19, 0x20, 0x85, 0x19, 0x08, 0x7e, 0x7e} }, +{ 0x0116, 16, {0x7f, 0x80, 0x75, 0x0c, 0x7e, 0x75, 0x0d, 0x80, 0xaf, 0x36, 0x12, 0x0f, 0xb7, 0xe5, 0x19, 0x25} }, +{ 0x0126, 16, {0xe0, 0x90, 0x7f, 0xb7, 0xf0, 0x80, 0x26, 0xe5, 0x19, 0xd3, 0x94, 0x3f, 0x40, 0x03, 0x75, 0x19} }, +{ 0x0136, 16, {0x3f, 0x85, 0x19, 0x08, 0xe4, 0x90, 0x7e, 0x80, 0xf0, 0x7e, 0x7e, 0x7f, 0x81, 0x75, 0x0c, 0x7e} }, +{ 0x0146, 16, {0x75, 0x0d, 0x81, 0x12, 0x0d, 0x7a, 0xe5, 0x19, 0x04, 0x90, 0x7f, 0xb7, 0xf0, 0x90, 0x7f, 0xce} }, +{ 0x0156, 16, {0xe0, 0x30, 0xe1, 0x06, 0x20, 0x04, 0x03, 0x02, 0x03, 0xbd, 0xc2, 0x04, 0xe4, 0xf5, 0x18, 0x74} }, +{ 0x0166, 16, {0x40, 0x25, 0x18, 0xf5, 0x82, 0xe4, 0x34, 0x7c, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x18, 0x7c, 0x00} }, +{ 0x0176, 16, {0x7b, 0x01, 0x7a, 0x7e, 0x79, 0x00, 0x24, 0x00, 0xf9, 0xec, 0x34, 0x7e, 0xfa, 0xef, 0x12, 0x0c} }, +{ 0x0186, 16, {0xe5, 0x05, 0x18, 0xe5, 0x18, 0xb4, 0x20, 0xd7, 0x90, 0x7e, 0x00, 0xe0, 0x60, 0x68, 0x90, 0x7e} }, +{ 0x0196, 16, {0x03, 0xe0, 0x60, 0x24, 0x7f, 0x01, 0xe4, 0xfd, 0x12, 0x12, 0x24, 0x7f, 0x03, 0x7d, 0xcd, 0x12} }, +{ 0x01a6, 16, {0x12, 0x24, 0x43, 0x46, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x46} }, +{ 0x01b6, 16, {0xf0, 0xe4, 0x90, 0x7e, 0x13, 0xf0, 0x80, 0x30, 0x90, 0x7e, 0x01, 0xe0, 0xff, 0x12, 0x10, 0xa8} }, +{ 0x01c6, 16, {0x90, 0x7e, 0x02, 0xe0, 0xff, 0x12, 0x10, 0xce, 0x7f, 0x01, 0x90, 0x7e, 0x11, 0xe0, 0xfd, 0x12} }, +{ 0x01d6, 16, {0x12, 0x24, 0x7f, 0x03, 0x7d, 0x07, 0x12, 0x12, 0x24, 0x43, 0x46, 0x80, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x01e6, 16, {0x14, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x46, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x12, 0xf0, 0xe5, 0x40} }, +{ 0x01f6, 16, {0x44, 0x06, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x03, 0xe0, 0x70, 0x06, 0x90, 0x7e, 0x13, 0xe0} }, +{ 0x0206, 16, {0x70, 0x08, 0xe4, 0x90, 0x7e, 0x13, 0xf0, 0x75, 0x25, 0xff, 0x90, 0x7e, 0x05, 0xe0, 0x60, 0x12} }, +{ 0x0216, 16, {0xa3, 0xe0, 0x54, 0x3f, 0xf5, 0x44, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0xe5} }, +{ 0x0226, 16, {0x44, 0xf0, 0x90, 0x7e, 0x07, 0xe0, 0x60, 0x2b, 0xa3, 0xe0, 0x60, 0x05, 0x43, 0x42, 0x80, 0x80} }, +{ 0x0236, 16, {0x03, 0x53, 0x42, 0x7f, 0x53, 0x42, 0xfc, 0x90, 0x7e, 0x09, 0xe0, 0x60, 0x11, 0x43, 0x42, 0x02} }, +{ 0x0246, 16, {0xa3, 0xe0, 0xff, 0x12, 0x11, 0x1a, 0x90, 0x7e, 0x0b, 0xe0, 0xff, 0x12, 0x11, 0x40, 0xaf, 0x42} }, +{ 0x0256, 16, {0x12, 0x10, 0xf4, 0x90, 0x7e, 0x03, 0xe0, 0x60, 0x08, 0x53, 0x42, 0x7f, 0xaf, 0x42, 0x12, 0x10} }, +{ 0x0266, 16, {0xf4, 0x90, 0x7e, 0x0c, 0xe0, 0x60, 0x18, 0xa3, 0xe0, 0x60, 0x05, 0x43, 0x46, 0x02, 0x80, 0x03} }, +{ 0x0276, 16, {0x53, 0x46, 0xfd, 0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x46, 0xf0, 0x90} }, +{ 0x0286, 16, {0x7e, 0x0e, 0xe0, 0x60, 0x18, 0xa3, 0xe0, 0x60, 0x05, 0x43, 0x46, 0x01, 0x80, 0x03, 0x53, 0x46} }, +{ 0x0296, 16, {0xfe, 0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x46, 0xf0, 0x90, 0x7e, 0x12} }, +{ 0x02a6, 16, {0xe0, 0xf5, 0x3a, 0xa3, 0xe0, 0x13, 0x92, 0x0c, 0xa3, 0xe0, 0xf5, 0x3c, 0xa3, 0xe0, 0x60, 0x05} }, +{ 0x02b6, 16, {0x43, 0x46, 0x10, 0x80, 0x03, 0x53, 0x46, 0xef, 0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x90, 0xc0} }, +{ 0x02c6, 16, {0x00, 0xe5, 0x46, 0xf0, 0x90, 0x7e, 0x16, 0xe0, 0x60, 0x32, 0x53, 0x44, 0xbf, 0x90, 0x7f, 0x98} }, +{ 0x02d6, 16, {0x74, 0x13, 0xf0, 0xe5, 0x44, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x11} }, +{ 0x02e6, 16, {0xf0, 0x12, 0x13, 0x9c, 0xef, 0x54, 0xfe, 0x90, 0xc0, 0x00, 0xf0, 0x53, 0x3e, 0xfd, 0xe4, 0xff} }, +{ 0x02f6, 16, {0xad, 0x3e, 0x12, 0x12, 0x24, 0xe4, 0xf5, 0x2a, 0xf5, 0x29, 0xd2, 0x06, 0x90, 0x7e, 0x17, 0xe0} }, +{ 0x0306, 16, {0x60, 0x0f, 0x43, 0x3e, 0x02, 0xe4, 0xff, 0xad, 0x3e, 0x12, 0x12, 0x24, 0x75, 0x29, 0x01, 0xd2} }, +{ 0x0316, 16, {0x06, 0x90, 0x7e, 0x18, 0xe0, 0x60, 0x1b, 0x90, 0x7f, 0x98, 0x74, 0x12, 0xf0, 0xe5, 0x40, 0x44} }, +{ 0x0326, 16, {0x04, 0x90, 0xc0, 0x00, 0xf0, 0xe4, 0x90, 0x7f, 0xc7, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0xd2, 0x02} }, +{ 0x0336, 16, {0xc2, 0x08, 0x90, 0x7e, 0x19, 0xe0, 0x60, 0x11, 0x43, 0x44, 0x40, 0x90, 0x7f, 0x98, 0x74, 0x13} }, +{ 0x0346, 16, {0xf0, 0xe5, 0x44, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x1a, 0xe0, 0x60, 0x0f, 0x53} }, +{ 0x0356, 16, {0x3e, 0xfe, 0xe4, 0xff, 0xad, 0x3e, 0x12, 0x12, 0x24, 0x75, 0x2b, 0x01, 0xd2, 0x06, 0x90, 0x7e} }, +{ 0x0366, 16, {0x1b, 0xe0, 0x60, 0x0f, 0x43, 0x3e, 0x01, 0xe4, 0xff, 0xad, 0x3e, 0x12, 0x12, 0x24, 0xe4, 0xf5} }, +{ 0x0376, 16, {0x2b, 0xd2, 0x06, 0x90, 0x7e, 0x1c, 0xe0, 0x60, 0x0e, 0x90, 0x7f, 0x98, 0x74, 0x12, 0xf0, 0xe5} }, +{ 0x0386, 16, {0x40, 0x44, 0x02, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x1d, 0xe0, 0x60, 0x02, 0xd2, 0x0a, 0x90} }, +{ 0x0396, 16, {0x7e, 0x1e, 0xe0, 0x60, 0x08, 0x75, 0x2c, 0x01, 0xe4, 0xf5, 0x38, 0xd2, 0x06, 0x90, 0x7e, 0x1f} }, +{ 0x03a6, 16, {0xe0, 0x60, 0x0f, 0x90, 0x7f, 0xd7, 0x74, 0x11, 0xf0, 0x74, 0x31, 0xf0, 0x74, 0x15, 0xf0, 0x74} }, +{ 0x03b6, 16, {0x35, 0xf0, 0xe4, 0x90, 0x7f, 0xcf, 0xf0, 0x30, 0x18, 0x52, 0xe5, 0x38, 0x60, 0x02, 0x15, 0x38} }, +{ 0x03c6, 16, {0x20, 0x12, 0x49, 0xe5, 0x13, 0xd3, 0x94, 0x00, 0x40, 0x04, 0x15, 0x13, 0x80, 0x3e, 0x75, 0x13} }, +{ 0x03d6, 16, {0x0a, 0x30, 0x19, 0x02, 0xd2, 0x12, 0x12, 0x13, 0x9c, 0xef, 0x54, 0x01, 0xf5, 0x19, 0x65, 0x2a} }, +{ 0x03e6, 16, {0x60, 0x05, 0x85, 0x19, 0x2a, 0xd2, 0x06, 0x12, 0x13, 0xd8, 0xef, 0x54, 0x80, 0xf5, 0x19, 0x65} }, +{ 0x03f6, 16, {0x26, 0x60, 0x05, 0x85, 0x19, 0x26, 0xd2, 0x06, 0x30, 0x0c, 0x11, 0x12, 0x13, 0xd8, 0xef, 0x54} }, +{ 0x0406, 16, {0x10, 0xf5, 0x19, 0x65, 0x25, 0x60, 0x05, 0x85, 0x19, 0x25, 0xd2, 0x06, 0x20, 0x19, 0x03, 0x02} }, +{ 0x0416, 16, {0x07, 0xe4, 0x30, 0x09, 0x13, 0x12, 0x14, 0x2b, 0xef, 0xc3, 0x95, 0x3d, 0x50, 0x73, 0x90, 0x7f} }, +{ 0x0426, 16, {0xc1, 0x74, 0x01, 0xf0, 0xc2, 0x09, 0x80, 0x69, 0x30, 0x03, 0x34, 0x90, 0x7f, 0xca, 0xe0, 0x20} }, +{ 0x0436, 16, {0xe1, 0x5f, 0x12, 0x14, 0x2b, 0xef, 0xc3, 0x94, 0x40, 0x50, 0x56, 0x90, 0x7d, 0x40, 0xe0, 0x13} }, +{ 0x0446, 16, {0x92, 0x09, 0x90, 0x7f, 0xcb, 0xe0, 0x14, 0xf5, 0x08, 0x7e, 0x7d, 0x7f, 0x41, 0x75, 0x0c, 0x7d} }, +{ 0x0456, 16, {0x75, 0x0d, 0x41, 0x12, 0x0d, 0x9f, 0xc2, 0x03, 0xe4, 0x90, 0x7f, 0xcb, 0xf0, 0x80, 0x32, 0x90} }, +{ 0x0466, 16, {0x7f, 0xcc, 0xe0, 0x20, 0xe1, 0x2b, 0x12, 0x14, 0x2b, 0xef, 0xc3, 0x94, 0x40, 0x50, 0x22, 0x90} }, +{ 0x0476, 16, {0x7c, 0xc0, 0xe0, 0x13, 0x92, 0x09, 0x90, 0x7f, 0xcd, 0xe0, 0x14, 0xf5, 0x08, 0x7e, 0x7c, 0x7f} }, +{ 0x0486, 16, {0xc1, 0x75, 0x0c, 0x7c, 0x75, 0x0d, 0xc1, 0x12, 0x0d, 0x9f, 0xd2, 0x03, 0xe4, 0x90, 0x7f, 0xcd} }, +{ 0x0496, 16, {0xf0, 0x90, 0x7f, 0xba, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x05, 0x25, 0x53, 0x37, 0x80, 0x12, 0x14} }, +{ 0x04a6, 16, {0x37, 0xef, 0x42, 0x37, 0x12, 0x12, 0x93, 0x8f, 0x19, 0xef, 0xc3, 0x95, 0x3b, 0x50, 0x0f, 0x12} }, +{ 0x04b6, 16, {0x14, 0x13, 0xef, 0x30, 0xe0, 0x08, 0xe5, 0x37, 0x20, 0xe7, 0x03, 0x30, 0x0b, 0x61, 0xc2, 0x0b} }, +{ 0x04c6, 16, {0xe5, 0x19, 0x70, 0x04, 0xf5, 0x37, 0x80, 0x57, 0x12, 0x14, 0x37, 0xef, 0x42, 0x37, 0xe5, 0x37} }, +{ 0x04d6, 16, {0x30, 0xe7, 0x26, 0xe5, 0x19, 0xd3, 0x94, 0x20, 0x40, 0x03, 0x75, 0x19, 0x20, 0x85, 0x19, 0x08} }, +{ 0x04e6, 16, {0x7e, 0x7d, 0x7f, 0x80, 0x75, 0x0c, 0x7d, 0x75, 0x0d, 0x80, 0xaf, 0x37, 0x12, 0x0f, 0xf0, 0xe5} }, +{ 0x04f6, 16, {0x19, 0x25, 0xe0, 0x90, 0x7f, 0xbb, 0xf0, 0x80, 0x26, 0xe5, 0x19, 0xd3, 0x94, 0x3f, 0x40, 0x03} }, +{ 0x0506, 16, {0x75, 0x19, 0x3f, 0x85, 0x19, 0x08, 0xe4, 0x90, 0x7d, 0x80, 0xf0, 0x7e, 0x7d, 0x7f, 0x81, 0x75} }, +{ 0x0516, 16, {0x0c, 0x7d, 0x75, 0x0d, 0x81, 0x12, 0x0d, 0xc4, 0xe5, 0x19, 0x04, 0x90, 0x7f, 0xbb, 0xf0, 0x90} }, +{ 0x0526, 16, {0x7f, 0xd0, 0xe0, 0x30, 0xe1, 0x06, 0x20, 0x05, 0x03, 0x02, 0x07, 0x8f, 0xc2, 0x05, 0xe4, 0xf5} }, +{ 0x0536, 16, {0x18, 0x74, 0xc0, 0x25, 0x18, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x18} }, +{ 0x0546, 16, {0x7c, 0x00, 0x7b, 0x01, 0x7a, 0x7e, 0x79, 0x20, 0x24, 0x20, 0xf9, 0xec, 0x34, 0x7e, 0xfa, 0xef} }, +{ 0x0556, 16, {0x12, 0x0c, 0xe5, 0x05, 0x18, 0xe5, 0x18, 0xb4, 0x20, 0xd7, 0x90, 0x7e, 0x20, 0xe0, 0x60, 0x68} }, +{ 0x0566, 16, {0x90, 0x7e, 0x23, 0xe0, 0x60, 0x24, 0x7f, 0x01, 0xe4, 0xfd, 0x12, 0x12, 0x6e, 0x7f, 0x03, 0x7d} }, +{ 0x0576, 16, {0xcd, 0x12, 0x12, 0x6e, 0x43, 0x47, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x0c, 0xf0, 0x90, 0xc0, 0x00} }, +{ 0x0586, 16, {0xe5, 0x47, 0xf0, 0xe4, 0x90, 0x7e, 0x33, 0xf0, 0x80, 0x30, 0x90, 0x7e, 0x21, 0xe0, 0xff, 0x12} }, +{ 0x0596, 16, {0x11, 0x8c, 0x90, 0x7e, 0x22, 0xe0, 0xff, 0x12, 0x11, 0xb2, 0x7f, 0x01, 0x90, 0x7e, 0x31, 0xe0} }, +{ 0x05a6, 16, {0xfd, 0x12, 0x12, 0x6e, 0x7f, 0x03, 0x7d, 0x07, 0x12, 0x12, 0x6e, 0x43, 0x47, 0x80, 0x90, 0x7f} }, +{ 0x05b6, 16, {0x98, 0x74, 0x0c, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x47, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0a, 0xf0} }, +{ 0x05c6, 16, {0xe5, 0x41, 0x44, 0x06, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x23, 0xe0, 0x70, 0x06, 0x90, 0x7e} }, +{ 0x05d6, 16, {0x33, 0xe0, 0x70, 0x08, 0xe4, 0x90, 0x7e, 0x33, 0xf0, 0x75, 0x2e, 0xff, 0x90, 0x7e, 0x25, 0xe0} }, +{ 0x05e6, 16, {0x60, 0x12, 0xa3, 0xe0, 0x54, 0x3f, 0xf5, 0x45, 0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x90, 0xc0} }, +{ 0x05f6, 16, {0x00, 0xe5, 0x45, 0xf0, 0x90, 0x7e, 0x27, 0xe0, 0x60, 0x2b, 0xa3, 0xe0, 0x60, 0x05, 0x43, 0x43} }, +{ 0x0606, 16, {0x80, 0x80, 0x03, 0x53, 0x43, 0x7f, 0x53, 0x43, 0xfc, 0x90, 0x7e, 0x29, 0xe0, 0x60, 0x11, 0x43} }, +{ 0x0616, 16, {0x43, 0x02, 0xa3, 0xe0, 0xff, 0x12, 0x11, 0xd8, 0x90, 0x7e, 0x2b, 0xe0, 0xff, 0x12, 0x11, 0xfe} }, +{ 0x0626, 16, {0xaf, 0x43, 0x12, 0x11, 0x66, 0x90, 0x7e, 0x23, 0xe0, 0x60, 0x08, 0x53, 0x43, 0x7f, 0xaf, 0x43} }, +{ 0x0636, 16, {0x12, 0x11, 0x66, 0x90, 0x7e, 0x2c, 0xe0, 0x60, 0x18, 0xa3, 0xe0, 0x60, 0x05, 0x43, 0x47, 0x02} }, +{ 0x0646, 16, {0x80, 0x03, 0x53, 0x47, 0xfd, 0x90, 0x7f, 0x98, 0x74, 0x0c, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x47} }, +{ 0x0656, 16, {0xf0, 0x90, 0x7e, 0x2e, 0xe0, 0x60, 0x18, 0xa3, 0xe0, 0x60, 0x05, 0x43, 0x47, 0x01, 0x80, 0x03} }, +{ 0x0666, 16, {0x53, 0x47, 0xfe, 0x90, 0x7f, 0x98, 0x74, 0x0c, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x47, 0xf0, 0x90} }, +{ 0x0676, 16, {0x7e, 0x32, 0xe0, 0xf5, 0x3b, 0xa3, 0xe0, 0x13, 0x92, 0x0d, 0xa3, 0xe0, 0xf5, 0x3d, 0xa3, 0xe0} }, +{ 0x0686, 16, {0x60, 0x05, 0x43, 0x47, 0x10, 0x80, 0x03, 0x53, 0x47, 0xef, 0x90, 0x7f, 0x98, 0x74, 0x0c, 0xf0} }, +{ 0x0696, 16, {0x90, 0xc0, 0x00, 0xe5, 0x47, 0xf0, 0x90, 0x7e, 0x36, 0xe0, 0x60, 0x32, 0x53, 0x45, 0xbf, 0x90} }, +{ 0x06a6, 16, {0x7f, 0x98, 0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7f, 0x98} }, +{ 0x06b6, 16, {0x74, 0x09, 0xf0, 0x12, 0x13, 0xf0, 0xef, 0x54, 0xfe, 0x90, 0xc0, 0x00, 0xf0, 0x53, 0x3f, 0xfd} }, +{ 0x06c6, 16, {0xe4, 0xff, 0xad, 0x3f, 0x12, 0x12, 0x6e, 0xe4, 0xf5, 0x33, 0xf5, 0x32, 0xd2, 0x07, 0x90, 0x7e} }, +{ 0x06d6, 16, {0x37, 0xe0, 0x60, 0x0f, 0x43, 0x3f, 0x02, 0xe4, 0xff, 0xad, 0x3f, 0x12, 0x12, 0x6e, 0x75, 0x32} }, +{ 0x06e6, 16, {0x01, 0xd2, 0x07, 0x90, 0x7e, 0x38, 0xe0, 0x60, 0x1b, 0x90, 0x7f, 0x98, 0x74, 0x0a, 0xf0, 0xe5} }, +{ 0x06f6, 16, {0x41, 0x44, 0x04, 0x90, 0xc0, 0x00, 0xf0, 0xe4, 0x90, 0x7f, 0xcb, 0xf0, 0x90, 0x7f, 0xcd, 0xf0} }, +{ 0x0706, 16, {0xd2, 0x03, 0xc2, 0x09, 0x90, 0x7e, 0x39, 0xe0, 0x60, 0x11, 0x43, 0x45, 0x40, 0x90, 0x7f, 0x98} }, +{ 0x0716, 16, {0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x3a, 0xe0, 0x60} }, +{ 0x0726, 16, {0x0f, 0x53, 0x3f, 0xfe, 0xe4, 0xff, 0xad, 0x3f, 0x12, 0x12, 0x6e, 0x75, 0x34, 0x01, 0xd2, 0x07} }, +{ 0x0736, 16, {0x90, 0x7e, 0x3b, 0xe0, 0x60, 0x0f, 0x43, 0x3f, 0x01, 0xe4, 0xff, 0xad, 0x3f, 0x12, 0x12, 0x6e} }, +{ 0x0746, 16, {0xe4, 0xf5, 0x34, 0xd2, 0x07, 0x90, 0x7e, 0x3c, 0xe0, 0x60, 0x0e, 0x90, 0x7f, 0x98, 0x74, 0x0a} }, +{ 0x0756, 16, {0xf0, 0xe5, 0x41, 0x44, 0x02, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x3d, 0xe0, 0x60, 0x02, 0xd2} }, +{ 0x0766, 16, {0x0b, 0x90, 0x7e, 0x3e, 0xe0, 0x60, 0x08, 0x75, 0x35, 0x01, 0xe4, 0xf5, 0x39, 0xd2, 0x07, 0x90} }, +{ 0x0776, 16, {0x7e, 0x3f, 0xe0, 0x60, 0x0f, 0x90, 0x7f, 0xd7, 0x74, 0x13, 0xf0, 0x74, 0x33, 0xf0, 0x74, 0x16} }, +{ 0x0786, 16, {0xf0, 0x74, 0x36, 0xf0, 0xe4, 0x90, 0x7f, 0xd1, 0xf0, 0x30, 0x18, 0x52, 0xe5, 0x39, 0x60, 0x02} }, +{ 0x0796, 16, {0x15, 0x39, 0x30, 0x12, 0x49, 0xe5, 0x13, 0xd3, 0x94, 0x00, 0x40, 0x04, 0x15, 0x13, 0x80, 0x3e} }, +{ 0x07a6, 16, {0x75, 0x13, 0x0a, 0x30, 0x19, 0x02, 0xc2, 0x12, 0x12, 0x13, 0xf0, 0xef, 0x54, 0x01, 0xf5, 0x19} }, +{ 0x07b6, 16, {0x65, 0x33, 0x60, 0x05, 0x85, 0x19, 0x33, 0xd2, 0x07, 0x12, 0x14, 0x43, 0xef, 0x54, 0x80, 0xf5} }, +{ 0x07c6, 16, {0x19, 0x65, 0x2f, 0x60, 0x05, 0x85, 0x19, 0x2f, 0xd2, 0x07, 0x30, 0x0d, 0x11, 0x12, 0x14, 0x43} }, +{ 0x07d6, 16, {0xef, 0x54, 0x10, 0xf5, 0x19, 0x65, 0x2e, 0x60, 0x05, 0x85, 0x19, 0x2e, 0xd2, 0x07, 0x30, 0x18} }, +{ 0x07e6, 16, {0x2a, 0x90, 0x7f, 0xd2, 0xe0, 0x20, 0xe1, 0x23, 0x90, 0x7b, 0x40, 0xe0, 0x60, 0x09, 0xe0, 0xf5} }, +{ 0x07f6, 16, {0x15, 0x90, 0x7b, 0x42, 0xe0, 0xf5, 0x16, 0x90, 0x7b, 0x41, 0xe0, 0x60, 0x09, 0x90, 0x7f, 0xd7} }, +{ 0x0806, 16, {0x74, 0x17, 0xf0, 0x74, 0x37, 0xf0, 0xe4, 0x90, 0x7f, 0xd3, 0xf0, 0x90, 0x7f, 0xc2, 0xe0, 0x30} }, +{ 0x0816, 16, {0xe1, 0x03, 0x02, 0x09, 0x18, 0xe5, 0x0a, 0x70, 0x40, 0x30, 0x06, 0x39, 0xe5, 0x38, 0x70, 0x35} }, +{ 0x0826, 16, {0xc2, 0x06, 0xf5, 0x18, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x24, 0x25, 0x18, 0xf9, 0xee, 0x34, 0x00} }, +{ 0x0836, 16, {0xfa, 0x12, 0x0c, 0x9f, 0xff, 0x74, 0x80, 0x25, 0x18, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83} }, +{ 0x0846, 16, {0xef, 0xf0, 0x05, 0x18, 0xe5, 0x18, 0xb4, 0x09, 0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x09, 0xf0, 0x75} }, +{ 0x0856, 16, {0x38, 0x10, 0xe4, 0xf5, 0x2c, 0x75, 0x0a, 0x01, 0x22, 0xe5, 0x0a, 0x64, 0x01, 0x70, 0x40, 0x30} }, +{ 0x0866, 16, {0x07, 0x39, 0xe5, 0x39, 0x70, 0x35, 0xc2, 0x07, 0xf5, 0x18, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x2d} }, +{ 0x0876, 16, {0x25, 0x18, 0xf9, 0xee, 0x34, 0x00, 0xfa, 0x12, 0x0c, 0x9f, 0xff, 0x74, 0x80, 0x25, 0x18, 0xf5} }, +{ 0x0886, 16, {0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x18, 0xe5, 0x18, 0xb4, 0x09, 0xdb, 0x90} }, +{ 0x0896, 16, {0x7f, 0xc3, 0x74, 0x09, 0xf0, 0x75, 0x39, 0x10, 0xe4, 0xf5, 0x35, 0x75, 0x0a, 0x02, 0x22, 0xe5} }, +{ 0x08a6, 16, {0x0a, 0x64, 0x02, 0x70, 0x36, 0x30, 0x13, 0x2f, 0xc2, 0x13, 0xf5, 0x18, 0x7e, 0x00, 0x7b, 0x00} }, +{ 0x08b6, 16, {0x74, 0x0e, 0x25, 0x18, 0xf9, 0xee, 0x34, 0x00, 0xfa, 0x12, 0x0c, 0x9f, 0xff, 0x74, 0x80, 0x25} }, +{ 0x08c6, 16, {0x18, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x18, 0xe5, 0x18, 0xb4, 0x05} }, +{ 0x08d6, 16, {0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x05, 0xf0, 0x75, 0x0a, 0x03, 0x22, 0xe5, 0x15, 0x60, 0x30, 0x15} }, +{ 0x08e6, 16, {0x15, 0xe4, 0xf5, 0x18, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x14, 0x25, 0x18, 0xf9, 0xee, 0x34, 0x00} }, +{ 0x08f6, 16, {0xfa, 0x12, 0x0c, 0x9f, 0xff, 0x74, 0x80, 0x25, 0x18, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83} }, +{ 0x0906, 16, {0xef, 0xf0, 0x05, 0x18, 0xe5, 0x18, 0xb4, 0x03, 0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x03, 0xf0, 0xe4} }, +{ 0x0916, 2, {0xf5, 0x0a} }, +{ 0x0918, 1, {0x22} }, +{ 0x0919, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x12, 0x0d, 0x2f, 0x09, 0xe9, 0x00, 0x0a, 0x5d, 0x01, 0x0a, 0xc9, 0x03} }, +{ 0x0929, 16, {0x09, 0x3c, 0x06, 0x09, 0xdc, 0x08, 0x09, 0xd6, 0x09, 0x09, 0xbe, 0x0a, 0x09, 0xcd, 0x0b, 0x00} }, +{ 0x0939, 16, {0x00, 0x0b, 0x18, 0x90, 0x7f, 0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x40, 0x24, 0x02} }, +{ 0x0949, 16, {0x70, 0x69, 0x74, 0x19, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x0b} }, +{ 0x0959, 16, {0x1f, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x0f, 0x27, 0x8b, 0x18, 0x8a, 0x19, 0x89, 0x1a, 0xea} }, +{ 0x0969, 16, {0x49, 0x60, 0x11, 0xae, 0x02, 0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5} }, +{ 0x0979, 16, {0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f} }, +{ 0x0989, 16, {0xea, 0xe0, 0xff, 0x12, 0x0f, 0x76, 0x8b, 0x18, 0x8a, 0x19, 0x89, 0x1a, 0xea, 0x49, 0x60, 0x11} }, +{ 0x0999, 16, {0xae, 0x02, 0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x0b} }, +{ 0x09a9, 16, {0x1f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xb4, 0xe0, 0x44} }, +{ 0x09b9, 16, {0x01, 0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0x00, 0xe5, 0x09, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01} }, +{ 0x09c9, 16, {0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x09, 0x02, 0x0b, 0x1f, 0x12, 0x0b, 0x27} }, +{ 0x09d9, 16, {0x02, 0x0b, 0x1f, 0x90, 0x7f, 0x00, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb5, 0xf0, 0x02, 0x0b, 0x1f} }, +{ 0x09e9, 16, {0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b, 0xa2} }, +{ 0x09f9, 16, {0x0f, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x14, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0} }, +{ 0x0a09, 16, {0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x0b, 0x1f, 0xe4, 0x90, 0x7f, 0x00} }, +{ 0x0a19, 16, {0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xec, 0xe0} }, +{ 0x0a29, 16, {0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4} }, +{ 0x0a39, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3} }, +{ 0x0a49, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01} }, +{ 0x0a59, 16, {0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, 0x60, 0x03} }, +{ 0x0a69, 16, {0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x05, 0xc2, 0x0f, 0x02, 0x0b, 0x1f, 0x90} }, +{ 0x0a79, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x38, 0x90} }, +{ 0x0a89, 16, {0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25} }, +{ 0x0a99, 16, {0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0} }, +{ 0x0aa9, 16, {0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7} }, +{ 0x0ab9, 16, {0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x5f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x56} }, +{ 0x0ac9, 16, {0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x4a, 0x90, 0x7f, 0xea, 0xe0} }, +{ 0x0ad9, 16, {0xb4, 0x01, 0x04, 0xd2, 0x0f, 0x80, 0x3f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x36} }, +{ 0x0ae9, 16, {0x90, 0x7f, 0xea, 0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54} }, +{ 0x0af9, 16, {0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5} }, +{ 0x0b09, 16, {0x83, 0x74, 0x01, 0xf0, 0x80, 0x10, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x07, 0x90} }, +{ 0x0b19, 13, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} }, +{ 0x0b26, 1, {0x22} }, +{ 0x0b27, 16, {0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0x18, 0xf0, 0xe4, 0x90, 0x7f, 0x96, 0xf0} }, +{ 0x0b37, 16, {0x90, 0x7f, 0x95, 0x74, 0xc0, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x3f, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x0b47, 16, {0x18, 0xf0, 0xe4, 0xf5, 0x8e, 0x90, 0x7f, 0xdf, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xde, 0xf0, 0xe4} }, +{ 0x0b57, 16, {0xf5, 0x24, 0x75, 0x1b, 0x01, 0x7b, 0x00, 0x74, 0x24, 0x25, 0x1b, 0xf9, 0xe4, 0x34, 0x00, 0xfa} }, +{ 0x0b67, 16, {0xe4, 0x12, 0x0c, 0xe5, 0x05, 0x1b, 0xe5, 0x1b, 0xb4, 0x09, 0xea, 0x75, 0x3a, 0x01, 0xe4, 0xf5} }, +{ 0x0b77, 16, {0x38, 0xf5, 0x13, 0xf5, 0x36, 0xc2, 0x06, 0xc2, 0x0a, 0xc2, 0x04, 0xc2, 0x08, 0xc2, 0x12, 0xd2} }, +{ 0x0b87, 16, {0x02, 0xd2, 0x00, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x75, 0x44, 0x03, 0x90, 0xc0, 0x00, 0x74} }, +{ 0x0b97, 16, {0x03, 0xf0, 0x7f, 0x0c, 0xe4, 0xfd, 0x12, 0x12, 0x24, 0x7f, 0x10, 0x8f, 0x42, 0x12, 0x10, 0xf4} }, +{ 0x0ba7, 16, {0x90, 0x7f, 0x98, 0x74, 0x12, 0xf0, 0x7f, 0x01, 0x8f, 0x40, 0xef, 0x44, 0x06, 0x90, 0xc0, 0x00} }, +{ 0x0bb7, 16, {0xf0, 0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x75, 0x46, 0x80, 0x90, 0xc0, 0x00, 0x74, 0x80, 0xf0} }, +{ 0x0bc7, 16, {0x0f, 0xe4, 0xfd, 0x12, 0x12, 0x24, 0xe4, 0xff, 0x7e, 0xa3, 0xad, 0x06, 0x8d, 0x3e, 0x12, 0x12} }, +{ 0x0bd7, 16, {0x24, 0x90, 0x7f, 0x98, 0x74, 0x11, 0xf0, 0x90, 0xc0, 0x00, 0xe4, 0xf0, 0x7f, 0x05, 0x7d, 0x7f} }, +{ 0x0be7, 16, {0x12, 0x12, 0x24, 0x7f, 0x01, 0x12, 0x13, 0x27, 0x7f, 0x03, 0x7d, 0x07, 0x12, 0x12, 0x24, 0x20} }, +{ 0x0bf7, 16, {0x19, 0x03, 0x02, 0x0c, 0x9c, 0x75, 0x2d, 0x01, 0x75, 0x1b, 0x01, 0x7b, 0x00, 0x74, 0x2d, 0x25} }, +{ 0x0c07, 16, {0x1b, 0xf9, 0xe4, 0x34, 0x00, 0xfa, 0xe4, 0x12, 0x0c, 0xe5, 0x05, 0x1b, 0xe5, 0x1b, 0xb4, 0x09} }, +{ 0x0c17, 16, {0xea, 0x75, 0x3b, 0x01, 0xe4, 0xf5, 0x39, 0xf5, 0x13, 0xf5, 0x37, 0xc2, 0x07, 0xc2, 0x0b, 0xc2} }, +{ 0x0c27, 16, {0x05, 0xc2, 0x09, 0xc2, 0x12, 0xd2, 0x03, 0xd2, 0x01, 0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x75} }, +{ 0x0c37, 16, {0x45, 0x03, 0x90, 0xc0, 0x00, 0x74, 0x03, 0xf0, 0x7f, 0x0c, 0xe4, 0xfd, 0x12, 0x12, 0x6e, 0x7f} }, +{ 0x0c47, 16, {0x10, 0x8f, 0x43, 0x12, 0x11, 0x66, 0x90, 0x7f, 0x98, 0x74, 0x0a, 0xf0, 0x7f, 0x01, 0x8f, 0x41} }, +{ 0x0c57, 16, {0xef, 0x44, 0x06, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0c, 0xf0, 0x75, 0x47, 0x80} }, +{ 0x0c67, 16, {0x90, 0xc0, 0x00, 0x74, 0x80, 0xf0, 0x0f, 0xe4, 0xfd, 0x12, 0x12, 0x6e, 0xe4, 0xff, 0x7e, 0xa3} }, +{ 0x0c77, 16, {0xad, 0x06, 0x8d, 0x3f, 0x12, 0x12, 0x6e, 0x90, 0x7f, 0x98, 0x74, 0x09, 0xf0, 0x90, 0xc0, 0x00} }, +{ 0x0c87, 16, {0xe4, 0xf0, 0x7f, 0x05, 0x7d, 0x7f, 0x12, 0x12, 0x6e, 0x7f, 0x01, 0x12, 0x13, 0x48, 0x7f, 0x03} }, +{ 0x0c97, 7, {0x7d, 0x07, 0x12, 0x12, 0x6e, 0xd2, 0x11} }, +{ 0x0c9e, 1, {0x22} }, +{ 0x0c9f, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} }, +{ 0x0caf, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x0cb8, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} }, +{ 0x0cc8, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} }, +{ 0x0cd8, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x0ce5, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01} }, +{ 0x0cf5, 2, {0xf3, 0x22} }, +{ 0x0cf7, 16, {0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} }, +{ 0x0d07, 16, {0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} }, +{ 0x0d17, 16, {0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} }, +{ 0x0d27, 8, {0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} }, +{ 0x0d2f, 16, {0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3} }, +{ 0x0d3f, 16, {0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60} }, +{ 0x0d4f, 6, {0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf} }, +{ 0x0d55, 16, {0x90, 0x7f, 0x98, 0x74, 0x10, 0xf0, 0xaf, 0x08, 0xe5, 0x0d, 0xf5, 0x82, 0xe5, 0x0c, 0xf5, 0x83} }, +{ 0x0d65, 16, {0xc2, 0xaf, 0x05, 0x86, 0x90, 0xc0, 0x00, 0x05, 0x86, 0xe0, 0xa3, 0x05, 0x86, 0xf0, 0x05, 0x86} }, +{ 0x0d75, 16, {0xdf, 0xf7, 0xd2, 0xaf, 0x22, 0x90, 0x7f, 0x98, 0x74, 0x10, 0xf0, 0xaf, 0x08, 0xe5, 0x0d, 0xf5} }, +{ 0x0d85, 16, {0x82, 0xe5, 0x0c, 0xf5, 0x83, 0xc2, 0xaf, 0x05, 0x86, 0x90, 0xc0, 0x00, 0xe0, 0x05, 0x86, 0xf0} }, +{ 0x0d95, 16, {0xa3, 0x05, 0x86, 0xdf, 0xf7, 0x05, 0x86, 0xd2, 0xaf, 0x22, 0x90, 0x7f, 0x98, 0x74, 0x08, 0xf0} }, +{ 0x0da5, 16, {0xaf, 0x08, 0xe5, 0x0d, 0xf5, 0x82, 0xe5, 0x0c, 0xf5, 0x83, 0xc2, 0xaf, 0x05, 0x86, 0x90, 0xc0} }, +{ 0x0db5, 16, {0x00, 0x05, 0x86, 0xe0, 0xa3, 0x05, 0x86, 0xf0, 0x05, 0x86, 0xdf, 0xf7, 0xd2, 0xaf, 0x22, 0x90} }, +{ 0x0dc5, 16, {0x7f, 0x98, 0x74, 0x08, 0xf0, 0xaf, 0x08, 0xe5, 0x0d, 0xf5, 0x82, 0xe5, 0x0c, 0xf5, 0x83, 0xc2} }, +{ 0x0dd5, 16, {0xaf, 0x05, 0x86, 0x90, 0xc0, 0x00, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xdf, 0xf7, 0x05} }, +{ 0x0de5, 4, {0x86, 0xd2, 0xaf, 0x22} }, +{ 0x0de9, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} }, +{ 0x0df9, 1, {0x22} }, +{ 0x0dfa, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} }, +{ 0x0e0a, 16, {0xd2, 0x17, 0x90, 0x7f, 0x92, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0x7f, 0xae, 0xe0, 0xff, 0xd3, 0x92} }, +{ 0x0e1a, 16, {0x0f, 0xe4, 0x33, 0xfe, 0xef, 0x4e, 0xf0, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xde, 0x74} }, +{ 0x0e2a, 16, {0x01, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9, 0xf0} }, +{ 0x0e3a, 16, {0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f} }, +{ 0x0e4a, 16, {0xae, 0xe0, 0x44, 0x0d, 0xf0, 0xd2, 0xaf, 0xd2, 0x18, 0x12, 0x13, 0x02, 0xc2, 0x10, 0xe4, 0xf5} }, +{ 0x0e5a, 16, {0x0b, 0xf5, 0x13, 0xc2, 0x15, 0xc2, 0x11, 0x90, 0x7f, 0xa1, 0x04, 0xf0, 0x90, 0x7f, 0xd8, 0xe0} }, +{ 0x0e6a, 16, {0x65, 0x17, 0x60, 0x10, 0x30, 0x11, 0x05, 0xd2, 0x18, 0x12, 0x00, 0x46, 0x90, 0x7f, 0xd8, 0xe0} }, +{ 0x0e7a, 16, {0xf5, 0x17, 0x80, 0x08, 0x30, 0x11, 0x05, 0xc2, 0x18, 0x12, 0x00, 0x46, 0x30, 0x10, 0x07, 0xc2} }, +{ 0x0e8a, 16, {0x10, 0x12, 0x09, 0x19, 0x80, 0xd6, 0x30, 0x16, 0xd3, 0xc2, 0x16, 0x12, 0x14, 0x4f, 0x80, 0xcc} }, +{ 0x0e9a, 1, {0x22} }, +{ 0x0e9b, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x47, 0x02, 0x0e, 0xe2} }, +{ 0x0ea7, 16, {0x02, 0x0e, 0x0a, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} }, +{ 0x0eb7, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} }, +{ 0x0ec7, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} }, +{ 0x0ed7, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x13, 0x69, 0xe4, 0x7e} }, +{ 0x0ee7, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} }, +{ 0x0ef7, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} }, +{ 0x0f07, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} }, +{ 0x0f17, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} }, +{ 0x0f27, 16, {0xe4, 0xfe, 0x75, 0x1d, 0xff, 0x75, 0x1e, 0x19, 0x75, 0x1f, 0x12, 0xab, 0x1d, 0xaa, 0x1e, 0xa9} }, +{ 0x0f37, 16, {0x1f, 0x90, 0x00, 0x01, 0x12, 0x0c, 0xb8, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} }, +{ 0x0f47, 16, {0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x0c, 0xf7, 0x85, 0xf0, 0x1b, 0xf5, 0x1c, 0x62, 0x1b} }, +{ 0x0f57, 16, {0xe5, 0x1b, 0x62, 0x1c, 0xe5, 0x1c, 0x62, 0x1b, 0x29, 0xfd, 0xe5, 0x1b, 0x3a, 0xa9, 0x05, 0x75} }, +{ 0x0f67, 14, {0x1d, 0xff, 0xf5, 0x1e, 0x89, 0x1f, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x0f75, 1, {0x22} }, +{ 0x0f76, 2, {0x8f, 0x1b} }, +{ 0x0f78, 16, {0xe4, 0xf5, 0x1c, 0x75, 0x1d, 0xff, 0x75, 0x1e, 0x19, 0x75, 0x1f, 0x86, 0xab, 0x1d, 0xaa, 0x1e} }, +{ 0x0f88, 16, {0xa9, 0x1f, 0x90, 0x00, 0x01, 0x12, 0x0c, 0xb8, 0xb4, 0x03, 0x1d, 0xaf, 0x1c, 0x05, 0x1c, 0xef} }, +{ 0x0f98, 16, {0xb5, 0x1b, 0x01, 0x22, 0x12, 0x0c, 0x9f, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} }, +{ 0x0fa8, 14, {0x1d, 0xff, 0xf5, 0x1e, 0x89, 0x1f, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x0fb6, 1, {0x22} }, +{ 0x0fb7, 16, {0x8f, 0x1a, 0x05, 0x0d, 0xe5, 0x0d, 0xae, 0x0c, 0x70, 0x02, 0x05, 0x0c, 0x14, 0xf5, 0x82, 0x8e} }, +{ 0x0fc7, 16, {0x83, 0xe5, 0x1a, 0xf0, 0x12, 0x00, 0x36, 0x05, 0x0d, 0xe5, 0x0d, 0xac, 0x0c, 0x70, 0x02, 0x05} }, +{ 0x0fd7, 16, {0x0c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x15, 0x08, 0xe5, 0x08, 0x60, 0x0a, 0x12, 0x13} }, +{ 0x0fe7, 9, {0xcc, 0x8f, 0x1a, 0xef, 0x42, 0x36, 0x80, 0xca, 0x22} }, +{ 0x0ff0, 16, {0x8f, 0x1a, 0x05, 0x0d, 0xe5, 0x0d, 0xae, 0x0c, 0x70, 0x02, 0x05, 0x0c, 0x14, 0xf5, 0x82, 0x8e} }, +{ 0x1000, 16, {0x83, 0xe5, 0x1a, 0xf0, 0x12, 0x13, 0xe4, 0x05, 0x0d, 0xe5, 0x0d, 0xac, 0x0c, 0x70, 0x02, 0x05} }, +{ 0x1010, 16, {0x0c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x15, 0x08, 0xe5, 0x08, 0x60, 0x0a, 0x12, 0x14} }, +{ 0x1020, 9, {0x37, 0x8f, 0x1a, 0xef, 0x42, 0x37, 0x80, 0xca, 0x22} }, +{ 0x1029, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x30} }, +{ 0x1039, 16, {0x1a, 0x04, 0xc2, 0x1a, 0x80, 0x02, 0xd2, 0x16, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} }, +{ 0x1049, 14, {0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x1057, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x90} }, +{ 0x1067, 16, {0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x04, 0xf0, 0xd0, 0x86, 0xd0} }, +{ 0x1077, 10, {0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x1081, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xd2} }, +{ 0x1091, 16, {0x10, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85} }, +{ 0x10a1, 7, {0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x10a8, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x10b8, 16, {0x10, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x44, 0x54} }, +{ 0x10c8, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x10ce, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x10de, 16, {0x11, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x44, 0x54} }, +{ 0x10ee, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x10f4, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x1104, 16, {0x12, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x44, 0x54} }, +{ 0x1114, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x111a, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x112a, 16, {0x14, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x44, 0x54} }, +{ 0x113a, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x1140, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x1150, 16, {0x16, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x44, 0x54} }, +{ 0x1160, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x1166, 16, {0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x1176, 16, {0x0a, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54} }, +{ 0x1186, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x118c, 16, {0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x119c, 16, {0x08, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54} }, +{ 0x11ac, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x11b2, 16, {0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x11c2, 16, {0x09, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54} }, +{ 0x11d2, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x11d8, 16, {0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x11e8, 16, {0x0c, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54} }, +{ 0x11f8, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x11fe, 16, {0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x120e, 16, {0x0e, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54} }, +{ 0x121e, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x1224, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x44, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7f} }, +{ 0x1234, 16, {0x98, 0x74, 0x17, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x15, 0xf0, 0x90} }, +{ 0x1244, 5, {0xc0, 0x00, 0xed, 0xf0, 0x22} }, +{ 0x1249, 16, {0x12, 0x13, 0xb4, 0x8f, 0x1a, 0x12, 0x13, 0xb4, 0x8f, 0x1b, 0xe5, 0x1a, 0x65, 0x1b, 0x60, 0x12} }, +{ 0x1259, 16, {0x12, 0x13, 0xb4, 0x8f, 0x1a, 0xe5, 0x1a, 0x65, 0x1b, 0x60, 0x07, 0x12, 0x13, 0xb4, 0x8f, 0x1b} }, +{ 0x1269, 4, {0x80, 0xe8, 0xaf, 0x1a} }, +{ 0x126d, 1, {0x22} }, +{ 0x126e, 16, {0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7f} }, +{ 0x127e, 16, {0x98, 0x74, 0x0f, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0d, 0xf0, 0x90} }, +{ 0x128e, 5, {0xc0, 0x00, 0xed, 0xf0, 0x22} }, +{ 0x1293, 16, {0x12, 0x14, 0x1f, 0x8f, 0x1a, 0x12, 0x14, 0x1f, 0x8f, 0x1b, 0xe5, 0x1a, 0x65, 0x1b, 0x60, 0x12} }, +{ 0x12a3, 16, {0x12, 0x14, 0x1f, 0x8f, 0x1a, 0xe5, 0x1a, 0x65, 0x1b, 0x60, 0x07, 0x12, 0x14, 0x1f, 0x8f, 0x1b} }, +{ 0x12b3, 4, {0x80, 0xe8, 0xaf, 0x1a} }, +{ 0x12b7, 1, {0x22} }, +{ 0x12b8, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} }, +{ 0x12c8, 16, {0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82} }, +{ 0x12d8, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x12dd, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} }, +{ 0x12ed, 16, {0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82} }, +{ 0x12fd, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x1302, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x18, 0x04, 0xe0, 0x44} }, +{ 0x1312, 16, {0x02, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x13, 0x85, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} }, +{ 0x1322, 5, {0xe0, 0x44, 0x04, 0xf0, 0x22} }, +{ 0x1327, 16, {0xae, 0x07, 0xe4, 0xff, 0xe5, 0x3e, 0x54, 0x7f, 0xfd, 0x12, 0x12, 0x24, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x1337, 16, {0x11, 0xf0, 0x90, 0xc0, 0x00, 0xee, 0xf0, 0xe4, 0xe5, 0x3e, 0x44, 0x80, 0xfd, 0x12, 0x12, 0x24} }, +{ 0x1347, 1, {0x22} }, +{ 0x1348, 16, {0xae, 0x07, 0xe4, 0xff, 0xe5, 0x3f, 0x54, 0x7f, 0xfd, 0x12, 0x12, 0x6e, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x1358, 16, {0x09, 0xf0, 0x90, 0xc0, 0x00, 0xee, 0xf0, 0xe4, 0xe5, 0x3f, 0x44, 0x80, 0xfd, 0x12, 0x12, 0x6e} }, +{ 0x1368, 1, {0x22} }, +{ 0x1369, 16, {0x05, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x14, 0x03, 0x00, 0x00, 0xc1, 0x10, 0xc1, 0x16} }, +{ 0x1379, 7, {0xc1, 0x0f, 0xc1, 0x94, 0x01, 0x0a, 0x00} }, +{ 0x1380, 2, {0xc1, 0x19} }, +{ 0x1382, 2, {0xc1, 0x9a} }, +{ 0x1384, 1, {0x00} }, +{ 0x1385, 16, {0x8e, 0x18, 0x8f, 0x19, 0xe5, 0x19, 0x15, 0x19, 0xae, 0x18, 0x70, 0x02, 0x15, 0x18, 0x4e, 0x60} }, +{ 0x1395, 7, {0x05, 0x12, 0x0d, 0xe9, 0x80, 0xee, 0x22} }, +{ 0x139c, 12, {0x90, 0x7f, 0x98, 0x74, 0x11, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13a8, 12, {0x90, 0x7f, 0x98, 0x74, 0x12, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13b4, 12, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13c0, 12, {0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13cc, 12, {0x90, 0x7f, 0x98, 0x74, 0x15, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13d8, 12, {0x90, 0x7f, 0x98, 0x74, 0x16, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13e4, 12, {0x90, 0x7f, 0x98, 0x74, 0x08, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13f0, 12, {0x90, 0x7f, 0x98, 0x74, 0x09, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13fc, 4, {0x53, 0xd8, 0xef, 0x32} }, +{ 0x1400, 16, {0x02, 0x10, 0x81, 0x00, 0x02, 0x12, 0xb8, 0x00, 0x02, 0x10, 0x57, 0x00, 0x02, 0x10, 0x29, 0x00} }, +{ 0x1410, 3, {0x02, 0x12, 0xdd} }, +{ 0x1413, 12, {0x90, 0x7f, 0x98, 0x74, 0x0a, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x141f, 12, {0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x142b, 12, {0x90, 0x7f, 0x98, 0x74, 0x0c, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x1437, 12, {0x90, 0x7f, 0x98, 0x74, 0x0d, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x1443, 12, {0x90, 0x7f, 0x98, 0x74, 0x0e, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x144f, 10, {0x12, 0x00, 0x03, 0x12, 0x0d, 0xfa, 0x12, 0x0b, 0x27, 0x22} }, +{ 0x1900, 16, {0x12, 0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x40, 0xcd, 0x06, 0x12, 0x01, 0x00, 0x00, 0x01, 0x02} }, +{ 0x1910, 16, {0x00, 0x01, 0x09, 0x02, 0x74, 0x00, 0x01, 0x01, 0x00, 0xa0, 0x32, 0x09, 0x04, 0x00, 0x00, 0x0e} }, +{ 0x1920, 16, {0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} }, +{ 0x1930, 16, {0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, 0x00} }, +{ 0x1940, 16, {0x07, 0x05, 0x05, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x06, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05} }, +{ 0x1950, 16, {0x07, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x82, 0x02} }, +{ 0x1960, 16, {0x40, 0x00, 0x00, 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00} }, +{ 0x1970, 16, {0x00, 0x07, 0x05, 0x85, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x86, 0x02, 0x40, 0x00, 0x00, 0x07} }, +{ 0x1980, 16, {0x05, 0x87, 0x02, 0x40, 0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x48, 0x03, 0x4b, 0x00, 0x65, 0x00} }, +{ 0x1990, 16, {0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00} }, +{ 0x19a0, 16, {0x20, 0x00, 0x64, 0x00, 0x69, 0x00, 0x76, 0x00, 0x69, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00} }, +{ 0x19b0, 16, {0x6e, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x6e, 0x00} }, +{ 0x19c0, 16, {0x6f, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00} }, +{ 0x19d0, 16, {0x2e, 0x00, 0x36, 0x03, 0x4b, 0x00, 0x65, 0x00, 0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00} }, +{ 0x19e0, 16, {0x6e, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53, 0x00, 0x42, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00} }, +{ 0x19f0, 16, {0x72, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x41, 0x00, 0x64, 0x00, 0x61, 0x00} }, +{ 0x1a00, 10, {0x70, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00} }, +{ 0xffff, 0, {0x00} } +}; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/serial/keyspan_usa19_fw.h linux/drivers/usb/serial/keyspan_usa19_fw.h --- v2.4.0-test2/linux/drivers/usb/serial/keyspan_usa19_fw.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/keyspan_usa19_fw.h Mon Jul 10 14:33:04 2000 @@ -0,0 +1,299 @@ +/* keyspan_usa19_fw.h + + Generated from Keyspan firmware image Wed Jul 5 09:18:29 2000 EST + This firmware is for the Keyspan USA-19 Serial Adaptor + + "The firmware contained herein as keyspan_usa19_fw.h is + Copyright (C) 1999-2000 Keyspan, A division of InnoSys Incorporated + ("Keyspan"), as an unpublished work. This notice does not imply + unrestricted or public access to this firmware which is a trade secret of + Keyspan, and which may not be reproduced, used, sold or transferred to any + third party without Keyspan's prior written consent. All Rights Reserved. + + This firmware may not be modified and may only be used with the Keyspan + USA-19 Serial Adapter. Distribution and/or Modification of the + keyspan.c driver which includes this firmware, in whole or in part, + requires the inclusion of this statement." + +*/ + +static const struct ezusb_hex_record keyspan_usa19_firmware[] = { +{ 0x0000, 3, {0x02, 0x0b, 0x82} }, +{ 0x0003, 16, {0x8e, 0x13, 0x8f, 0x14, 0xe5, 0x14, 0x15, 0x14, 0xae, 0x13, 0x70, 0x02, 0x15, 0x13, 0x4e, 0x60} }, +{ 0x0013, 7, {0x05, 0x12, 0x0f, 0x38, 0x80, 0xee, 0x22} }, +{ 0x001a, 4, {0x53, 0xd8, 0xef, 0x32} }, +{ 0x0023, 3, {0x02, 0x00, 0x46} }, +{ 0x0026, 10, {0x12, 0x0d, 0xac, 0x12, 0x0f, 0x49, 0x12, 0x0d, 0x08, 0x22} }, +{ 0x0033, 3, {0x02, 0x00, 0x1a} }, +{ 0x0043, 3, {0x02, 0x0f, 0x00} }, +{ 0x0046, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0, 0xd0, 0x75, 0xd0, 0x08} }, +{ 0x0056, 16, {0x30, 0x99, 0x0e, 0x30, 0x06, 0x07, 0xa2, 0x09, 0x92, 0x9b, 0x85, 0x35, 0x99, 0xc2, 0x99, 0xd2} }, +{ 0x0066, 16, {0x0d, 0x20, 0x0d, 0x03, 0x02, 0x04, 0x25, 0xc2, 0x0d, 0x20, 0x01, 0x03, 0x02, 0x02, 0x50, 0x20} }, +{ 0x0076, 16, {0x06, 0x03, 0x02, 0x01, 0x27, 0xe5, 0x37, 0xc3, 0x95, 0x50, 0x50, 0x3e, 0x20, 0x07, 0x36, 0x20} }, +{ 0x0086, 16, {0x04, 0x33, 0x90, 0x7f, 0x9b, 0xe0, 0x30, 0xe3, 0x03, 0x20, 0x0c, 0x29, 0x30, 0x0b, 0x12, 0xaf} }, +{ 0x0096, 16, {0x37, 0x05, 0x37, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0x13, 0x92} }, +{ 0x00a6, 16, {0x09, 0xaf, 0x37, 0x05, 0x37, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0} }, +{ 0x00b6, 16, {0xf5, 0x35, 0x02, 0x04, 0x23, 0xc2, 0x06, 0x02, 0x04, 0x23, 0x90, 0x7f, 0xc7, 0xe4, 0xf0, 0xc2} }, +{ 0x00c6, 16, {0x01, 0x30, 0x08, 0x0c, 0xc2, 0x08, 0x90, 0x7f, 0xbb, 0x04, 0xf0, 0xc2, 0x06, 0x02, 0x04, 0x23} }, +{ 0x00d6, 16, {0x90, 0x7f, 0xc8, 0xe0, 0x30, 0xe1, 0x05, 0xc2, 0x06, 0x02, 0x04, 0x23, 0x90, 0x7f, 0xc9, 0xe0} }, +{ 0x00e6, 16, {0xf5, 0x50, 0x90, 0x7d, 0xc0, 0xe0, 0x13, 0x92, 0x08, 0x20, 0x07, 0x2d, 0x20, 0x04, 0x2a, 0x90} }, +{ 0x00f6, 16, {0x7f, 0x9b, 0xe0, 0x30, 0xe3, 0x03, 0x20, 0x0c, 0x20, 0x30, 0x0b, 0x11, 0x90, 0x7d, 0xc1, 0xe0} }, +{ 0x0106, 16, {0x13, 0x92, 0x09, 0xa3, 0xe0, 0xf5, 0x35, 0x75, 0x37, 0x03, 0x02, 0x04, 0x23, 0x75, 0x37, 0x02} }, +{ 0x0116, 16, {0x90, 0x7d, 0xc1, 0xe0, 0xf5, 0x35, 0x02, 0x04, 0x23, 0x75, 0x37, 0x01, 0xc2, 0x06, 0x02, 0x04} }, +{ 0x0126, 16, {0x23, 0xe5, 0x37, 0xc3, 0x95, 0x50, 0x50, 0x03, 0x02, 0x01, 0xc9, 0x90, 0x7f, 0xc6, 0xe0, 0x30} }, +{ 0x0136, 16, {0xe1, 0x07, 0xc2, 0x0f, 0xd2, 0x0e, 0x02, 0x04, 0x23, 0x90, 0x7f, 0xc7, 0xe0, 0xf5, 0x50, 0x90} }, +{ 0x0146, 16, {0x7e, 0x40, 0xe0, 0x13, 0x92, 0x08, 0x20, 0x07, 0x72, 0x20, 0x04, 0x6f, 0x90, 0x7f, 0x9b, 0xe0} }, +{ 0x0156, 16, {0x30, 0xe3, 0x03, 0x20, 0x0c, 0x65, 0x30, 0x0b, 0x10, 0x90, 0x7e, 0x41, 0xe0, 0x13, 0x92, 0x9b} }, +{ 0x0166, 16, {0xa3, 0xe0, 0xf5, 0x99, 0x75, 0x37, 0x03, 0x80, 0x09, 0x90, 0x7e, 0x41, 0xe0, 0xf5, 0x99, 0x75} }, +{ 0x0176, 16, {0x37, 0x02, 0xe5, 0x37, 0xc3, 0x95, 0x50, 0x40, 0x17, 0x90, 0x7f, 0xc7, 0xe4, 0xf0, 0xc2, 0x01} }, +{ 0x0186, 16, {0x20, 0x08, 0x03, 0x02, 0x04, 0x23, 0xc2, 0x08, 0x90, 0x7f, 0xbb, 0x04, 0xf0, 0x02, 0x04, 0x23} }, +{ 0x0196, 16, {0x30, 0x0b, 0x12, 0xaf, 0x37, 0x05, 0x37, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5} }, +{ 0x01a6, 16, {0x83, 0xe0, 0x13, 0x92, 0x09, 0xaf, 0x37, 0x05, 0x37, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x01b6, 16, {0x7e, 0xf5, 0x83, 0xe0, 0xf5, 0x35, 0xd2, 0x06, 0x02, 0x04, 0x23, 0x75, 0x37, 0x01, 0xc2, 0x0f} }, +{ 0x01c6, 16, {0x02, 0x04, 0x23, 0x30, 0x07, 0x03, 0x02, 0x02, 0x4b, 0x20, 0x04, 0x79, 0x90, 0x7f, 0x9b, 0xe0} }, +{ 0x01d6, 16, {0x30, 0xe3, 0x03, 0x20, 0x0c, 0x6f, 0x30, 0x0b, 0x12, 0xaf, 0x37, 0x05, 0x37, 0x74, 0x40, 0x2f} }, +{ 0x01e6, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x9b, 0xaf, 0x37, 0x05, 0x37, 0x74} }, +{ 0x01f6, 16, {0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0xf5, 0x99, 0xe5, 0x37, 0xc3, 0x95} }, +{ 0x0206, 16, {0x50, 0x40, 0x17, 0x90, 0x7f, 0xc7, 0xe4, 0xf0, 0xc2, 0x01, 0x20, 0x08, 0x03, 0x02, 0x04, 0x23} }, +{ 0x0216, 16, {0xc2, 0x08, 0x90, 0x7f, 0xbb, 0x04, 0xf0, 0x02, 0x04, 0x23, 0x30, 0x0b, 0x12, 0xaf, 0x37, 0x05} }, +{ 0x0226, 16, {0x37, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x09, 0xaf} }, +{ 0x0236, 16, {0x37, 0x05, 0x37, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0xf5, 0x35} }, +{ 0x0246, 16, {0xd2, 0x06, 0x02, 0x04, 0x23, 0xc2, 0x0f, 0x02, 0x04, 0x23, 0x20, 0x06, 0x03, 0x02, 0x03, 0x02} }, +{ 0x0256, 16, {0xe5, 0x37, 0xc3, 0x95, 0x50, 0x50, 0x3e, 0x20, 0x07, 0x36, 0x20, 0x04, 0x33, 0x90, 0x7f, 0x9b} }, +{ 0x0266, 16, {0xe0, 0x30, 0xe3, 0x03, 0x20, 0x0c, 0x29, 0x30, 0x0b, 0x12, 0xaf, 0x37, 0x05, 0x37, 0x74, 0xc0} }, +{ 0x0276, 16, {0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x09, 0xaf, 0x37, 0x05, 0x37} }, +{ 0x0286, 16, {0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xf5, 0x35, 0x02, 0x04, 0x23} }, +{ 0x0296, 16, {0xc2, 0x06, 0x02, 0x04, 0x23, 0x90, 0x7f, 0xc9, 0xe4, 0xf0, 0xd2, 0x01, 0x30, 0x08, 0x0c, 0xc2} }, +{ 0x02a6, 16, {0x08, 0x90, 0x7f, 0xbb, 0x04, 0xf0, 0xc2, 0x06, 0x02, 0x04, 0x23, 0x90, 0x7f, 0xc6, 0xe0, 0x30} }, +{ 0x02b6, 16, {0xe1, 0x05, 0xc2, 0x06, 0x02, 0x04, 0x23, 0x90, 0x7f, 0xc7, 0xe0, 0xf5, 0x50, 0x90, 0x7e, 0x40} }, +{ 0x02c6, 16, {0xe0, 0x13, 0x92, 0x08, 0x20, 0x07, 0x2d, 0x20, 0x04, 0x2a, 0x90, 0x7f, 0x9b, 0xe0, 0x30, 0xe3} }, +{ 0x02d6, 16, {0x03, 0x20, 0x0c, 0x20, 0x30, 0x0b, 0x11, 0x90, 0x7e, 0x41, 0xe0, 0x13, 0x92, 0x09, 0xa3, 0xe0} }, +{ 0x02e6, 16, {0xf5, 0x35, 0x75, 0x37, 0x03, 0x02, 0x04, 0x23, 0x75, 0x37, 0x02, 0x90, 0x7e, 0x41, 0xe0, 0xf5} }, +{ 0x02f6, 16, {0x35, 0x02, 0x04, 0x23, 0x75, 0x37, 0x01, 0xc2, 0x06, 0x02, 0x04, 0x23, 0xe5, 0x37, 0xc3, 0x95} }, +{ 0x0306, 16, {0x50, 0x50, 0x03, 0x02, 0x03, 0xa4, 0x90, 0x7f, 0xc8, 0xe0, 0x30, 0xe1, 0x07, 0xc2, 0x0f, 0xd2} }, +{ 0x0316, 16, {0x0e, 0x02, 0x04, 0x23, 0x90, 0x7f, 0xc9, 0xe0, 0xf5, 0x50, 0x90, 0x7d, 0xc0, 0xe0, 0x13, 0x92} }, +{ 0x0326, 16, {0x08, 0x20, 0x07, 0x72, 0x20, 0x04, 0x6f, 0x90, 0x7f, 0x9b, 0xe0, 0x30, 0xe3, 0x03, 0x20, 0x0c} }, +{ 0x0336, 16, {0x65, 0x30, 0x0b, 0x10, 0x90, 0x7d, 0xc1, 0xe0, 0x13, 0x92, 0x9b, 0xa3, 0xe0, 0xf5, 0x99, 0x75} }, +{ 0x0346, 16, {0x37, 0x03, 0x80, 0x09, 0x90, 0x7d, 0xc1, 0xe0, 0xf5, 0x99, 0x75, 0x37, 0x02, 0xe5, 0x37, 0xc3} }, +{ 0x0356, 16, {0x95, 0x50, 0x40, 0x17, 0x90, 0x7f, 0xc9, 0xe4, 0xf0, 0xd2, 0x01, 0x20, 0x08, 0x03, 0x02, 0x04} }, +{ 0x0366, 16, {0x23, 0xc2, 0x08, 0x90, 0x7f, 0xbb, 0x04, 0xf0, 0x02, 0x04, 0x23, 0x30, 0x0b, 0x12, 0xaf, 0x37} }, +{ 0x0376, 16, {0x05, 0x37, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x09} }, +{ 0x0386, 16, {0xaf, 0x37, 0x05, 0x37, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xf5} }, +{ 0x0396, 16, {0x35, 0xd2, 0x06, 0x02, 0x04, 0x23, 0x75, 0x37, 0x01, 0xc2, 0x0f, 0x02, 0x04, 0x23, 0x30, 0x07} }, +{ 0x03a6, 16, {0x03, 0x02, 0x04, 0x21, 0x20, 0x04, 0x74, 0x90, 0x7f, 0x9b, 0xe0, 0x30, 0xe3, 0x03, 0x20, 0x0c} }, +{ 0x03b6, 16, {0x6a, 0x30, 0x0b, 0x12, 0xaf, 0x37, 0x05, 0x37, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7d} }, +{ 0x03c6, 16, {0xf5, 0x83, 0xe0, 0x13, 0x92, 0x9b, 0xaf, 0x37, 0x05, 0x37, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4} }, +{ 0x03d6, 16, {0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xf5, 0x99, 0xe5, 0x37, 0xc3, 0x95, 0x50, 0x40, 0x13, 0x90, 0x7f} }, +{ 0x03e6, 16, {0xc9, 0xe4, 0xf0, 0xd2, 0x01, 0x30, 0x08, 0x35, 0xc2, 0x08, 0x90, 0x7f, 0xbb, 0x04, 0xf0, 0x80} }, +{ 0x03f6, 16, {0x2c, 0x30, 0x0b, 0x12, 0xaf, 0x37, 0x05, 0x37, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7d} }, +{ 0x0406, 16, {0xf5, 0x83, 0xe0, 0x13, 0x92, 0x09, 0xaf, 0x37, 0x05, 0x37, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4} }, +{ 0x0416, 16, {0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xf5, 0x35, 0xd2, 0x06, 0x80, 0x02, 0xc2, 0x0f, 0xd2, 0x11, 0x20} }, +{ 0x0426, 5, {0x98, 0x03, 0x02, 0x05, 0x61} }, +{ 0x042b, 16, {0xc2, 0x98, 0x20, 0x00, 0x03, 0x02, 0x04, 0xce, 0x20, 0x10, 0x27, 0xaf, 0x36, 0x05, 0x36, 0x74} }, +{ 0x043b, 16, {0x80, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x99, 0xf0, 0x30, 0x0b, 0x4d, 0xaf} }, +{ 0x044b, 16, {0x36, 0x05, 0x36, 0x74, 0x80, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x98, 0xf0} }, +{ 0x045b, 16, {0x80, 0x3a, 0x85, 0x99, 0x10, 0xe5, 0x10, 0xb5, 0x44, 0x04, 0xd2, 0x04, 0x80, 0x2e, 0xe5, 0x10} }, +{ 0x046b, 16, {0xb5, 0x43, 0x04, 0xc2, 0x04, 0x80, 0x25, 0xaf, 0x36, 0x05, 0x36, 0x74, 0x80, 0x2f, 0xf5, 0x82} }, +{ 0x047b, 16, {0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x10, 0xf0, 0x30, 0x0b, 0x11, 0xaf, 0x36, 0x05, 0x36, 0x74} }, +{ 0x048b, 16, {0x80, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x98, 0xf0, 0xd2, 0x0a, 0xe5, 0x36} }, +{ 0x049b, 16, {0xc3, 0x95, 0x40, 0x50, 0x03, 0x02, 0x05, 0x5f, 0x90, 0x7f, 0xb8, 0xe0, 0x30, 0xe1, 0x16, 0xe5} }, +{ 0x04ab, 16, {0x36, 0xc3, 0x94, 0x40, 0x50, 0x03, 0x02, 0x05, 0x5f, 0x15, 0x36, 0x15, 0x36, 0x05, 0x2b, 0x43} }, +{ 0x04bb, 16, {0x33, 0x01, 0x02, 0x05, 0x5f, 0x90, 0x7f, 0xb7, 0xe5, 0x36, 0xf0, 0x75, 0x36, 0x00, 0xc2, 0x00} }, +{ 0x04cb, 16, {0x02, 0x05, 0x5f, 0x20, 0x10, 0x27, 0xaf, 0x36, 0x05, 0x36, 0x74, 0x00, 0x2f, 0xf5, 0x82, 0xe4} }, +{ 0x04db, 16, {0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x99, 0xf0, 0x30, 0x0b, 0x4d, 0xaf, 0x36, 0x05, 0x36, 0x74, 0x00} }, +{ 0x04eb, 16, {0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x98, 0xf0, 0x80, 0x3a, 0x85, 0x99, 0x10} }, +{ 0x04fb, 16, {0xe5, 0x10, 0xb5, 0x44, 0x04, 0xd2, 0x04, 0x80, 0x2e, 0xe5, 0x10, 0xb5, 0x43, 0x04, 0xc2, 0x04} }, +{ 0x050b, 16, {0x80, 0x25, 0xaf, 0x36, 0x05, 0x36, 0x74, 0x00, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83} }, +{ 0x051b, 16, {0xe5, 0x10, 0xf0, 0x30, 0x0b, 0x11, 0xaf, 0x36, 0x05, 0x36, 0x74, 0x00, 0x2f, 0xf5, 0x82, 0xe4} }, +{ 0x052b, 16, {0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x98, 0xf0, 0xd2, 0x0a, 0xe5, 0x36, 0xc3, 0x95, 0x40, 0x40, 0x24} }, +{ 0x053b, 16, {0x90, 0x7f, 0xb6, 0xe0, 0x30, 0xe1, 0x12, 0xe5, 0x36, 0xc3, 0x94, 0x40, 0x40, 0x16, 0x15, 0x36} }, +{ 0x054b, 16, {0x15, 0x36, 0x05, 0x2b, 0x43, 0x33, 0x01, 0x80, 0x0b, 0x90, 0x7f, 0xb9, 0xe5, 0x36, 0xf0, 0x75} }, +{ 0x055b, 6, {0x36, 0x00, 0xd2, 0x00, 0xd2, 0x11} }, +{ 0x0561, 16, {0x30, 0x11, 0x05, 0xc2, 0x11, 0x02, 0x00, 0x56, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x82, 0xd0, 0x83} }, +{ 0x0571, 3, {0xd0, 0xe0, 0x32} }, +{ 0x0574, 16, {0x90, 0x7f, 0xca, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x06, 0xa5, 0xe4, 0xf5, 0x13, 0x74, 0x40, 0x25} }, +{ 0x0584, 16, {0x13, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x13, 0x7c, 0x00, 0x7b, 0x00} }, +{ 0x0594, 16, {0x24, 0x38, 0xf9, 0xec, 0x34, 0x00, 0xfa, 0xef, 0x12, 0x0c, 0x54, 0x05, 0x13, 0xe5, 0x13, 0xb4} }, +{ 0x05a4, 16, {0x18, 0xdb, 0xe5, 0x38, 0x60, 0x0c, 0x75, 0xc9, 0x20, 0x75, 0xc8, 0x34, 0x85, 0x39, 0xca, 0x85} }, +{ 0x05b4, 16, {0x3a, 0xcb, 0xe5, 0x3b, 0x13, 0x92, 0x0b, 0x92, 0x9f, 0xe5, 0x3c, 0x13, 0x92, 0x0c, 0xe5, 0x3d} }, +{ 0x05c4, 16, {0x13, 0x92, 0x10, 0xe5, 0x3e, 0x60, 0x09, 0x90, 0x7f, 0x98, 0xe0, 0x54, 0xfb, 0xf0, 0x80, 0x07} }, +{ 0x05d4, 16, {0x90, 0x7f, 0x98, 0xe0, 0x44, 0x04, 0xf0, 0xe5, 0x3f, 0x60, 0x09, 0x90, 0x7f, 0x98, 0xe0, 0x54} }, +{ 0x05e4, 16, {0x7f, 0xf0, 0x80, 0x07, 0x90, 0x7f, 0x98, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x45, 0x60, 0x0b, 0xc2} }, +{ 0x05f4, 16, {0x07, 0xc2, 0x04, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x46, 0x60, 0x0c, 0xd2, 0x04} }, +{ 0x0604, 16, {0x43, 0x33, 0x01, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x47, 0x60, 0x17, 0xc2, 0xaf} }, +{ 0x0614, 16, {0xe4, 0x90, 0x7f, 0xc7, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0xc2, 0x06, 0xd2, 0x01, 0xc2, 0x08, 0xf5} }, +{ 0x0624, 16, {0x50, 0xf5, 0x37, 0xd2, 0xaf, 0xe5, 0x48, 0x60, 0x05, 0x30, 0x10, 0x02, 0xd2, 0x04, 0xe5, 0x49} }, +{ 0x0634, 16, {0x60, 0x15, 0x90, 0x7f, 0x95, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0x9e, 0xe0, 0x44, 0x02, 0xf0} }, +{ 0x0644, 16, {0x90, 0x7f, 0x98, 0xe0, 0x54, 0xfd, 0xf0, 0xe5, 0x4a, 0x60, 0x0a, 0xd2, 0x9c, 0xc2, 0x98, 0x75} }, +{ 0x0654, 16, {0x2c, 0x01, 0x75, 0x31, 0x1e, 0xe5, 0x4b, 0x60, 0x07, 0xc2, 0x9c, 0xe4, 0xf5, 0x36, 0xf5, 0x2c} }, +{ 0x0664, 16, {0xe5, 0x4c, 0x60, 0x03, 0xe4, 0xf5, 0x36, 0xe5, 0x4d, 0x60, 0x02, 0xd2, 0x02, 0xe5, 0x4e, 0x60} }, +{ 0x0674, 16, {0x0a, 0xe5, 0x4a, 0x70, 0x02, 0xf5, 0x31, 0xe5, 0x4e, 0x42, 0x33, 0xe5, 0x4f, 0x60, 0x1b, 0x90} }, +{ 0x0684, 16, {0x7f, 0xd7, 0x74, 0x11, 0xf0, 0x74, 0x31, 0xf0, 0x74, 0x12, 0xf0, 0x74, 0x32, 0xf0, 0x74, 0x13} }, +{ 0x0694, 16, {0xf0, 0x74, 0x33, 0xf0, 0x74, 0x14, 0xf0, 0x74, 0x34, 0xf0, 0xd2, 0x03, 0xe4, 0x90, 0x7f, 0xcb} }, +{ 0x06a4, 16, {0xf0, 0xa2, 0x07, 0xe4, 0x33, 0xff, 0x65, 0x29, 0x60, 0x05, 0x8f, 0x29, 0x43, 0x33, 0x01, 0xa2} }, +{ 0x06b4, 16, {0x04, 0xe4, 0x33, 0xff, 0x65, 0x2a, 0x60, 0x05, 0x8f, 0x2a, 0x43, 0x33, 0x01, 0x90, 0x7f, 0x9b} }, +{ 0x06c4, 16, {0xe0, 0x54, 0x08, 0xb5, 0x25, 0x0a, 0xe0, 0x54, 0x08, 0x64, 0x08, 0xf5, 0x25, 0x43, 0x33, 0x01} }, +{ 0x06d4, 16, {0x90, 0x7f, 0x9b, 0xe0, 0x54, 0x10, 0xb5, 0x26, 0x0a, 0xe0, 0x54, 0x10, 0x64, 0x10, 0xf5, 0x26} }, +{ 0x06e4, 16, {0x43, 0x33, 0x01, 0x90, 0x7f, 0x9b, 0xe0, 0x54, 0x40, 0xb5, 0x27, 0x0a, 0xe0, 0x54, 0x40, 0x64} }, +{ 0x06f4, 16, {0x40, 0xf5, 0x27, 0x43, 0x33, 0x01, 0x90, 0x7f, 0x9b, 0xe0, 0x54, 0x20, 0xb5, 0x28, 0x0a, 0xe0} }, +{ 0x0704, 16, {0x54, 0x20, 0x64, 0x20, 0xf5, 0x28, 0x43, 0x33, 0x01, 0x30, 0x02, 0x35, 0xc2, 0xaf, 0x30, 0x00} }, +{ 0x0714, 16, {0x18, 0x90, 0x7f, 0xb8, 0xe0, 0x20, 0xe1, 0x27, 0xe5, 0x36, 0x60, 0x09, 0x90, 0x7f, 0xb7, 0xf0} }, +{ 0x0724, 16, {0xe4, 0xf5, 0x36, 0xc2, 0x00, 0xc2, 0x02, 0x80, 0x16, 0x90, 0x7f, 0xb6, 0xe0, 0x20, 0xe1, 0x0f} }, +{ 0x0734, 16, {0xe5, 0x36, 0x60, 0x09, 0x90, 0x7f, 0xb9, 0xf0, 0xe4, 0xf5, 0x36, 0xd2, 0x00, 0xc2, 0x02, 0xd2} }, +{ 0x0744, 16, {0xaf, 0x30, 0x0e, 0x37, 0x30, 0x01, 0x1b, 0x90, 0x7f, 0xc6, 0xe0, 0x20, 0xe1, 0x2d, 0x90, 0x7e} }, +{ 0x0754, 16, {0x40, 0xe0, 0x13, 0x92, 0x08, 0x75, 0x37, 0x01, 0x90, 0x7f, 0xc7, 0xe0, 0xf5, 0x50, 0xc2, 0x0e} }, +{ 0x0764, 16, {0x80, 0x19, 0x90, 0x7f, 0xc8, 0xe0, 0x20, 0xe1, 0x12, 0x90, 0x7d, 0xc0, 0xe0, 0x13, 0x92, 0x08} }, +{ 0x0774, 16, {0x75, 0x37, 0x01, 0x90, 0x7f, 0xc9, 0xe0, 0xf5, 0x50, 0xc2, 0x0e, 0x30, 0x0f, 0x03, 0x02, 0x08} }, +{ 0x0784, 16, {0x87, 0x30, 0x0e, 0x03, 0x02, 0x08, 0x87, 0x30, 0x0c, 0x0a, 0x90, 0x7f, 0x9b, 0xe0, 0x30, 0xe3} }, +{ 0x0794, 16, {0x03, 0x02, 0x08, 0x87, 0x30, 0x04, 0x03, 0x02, 0x08, 0x87, 0x30, 0x07, 0x03, 0x02, 0x08, 0x87} }, +{ 0x07a4, 16, {0x30, 0x01, 0x62, 0x30, 0x0b, 0x12, 0xaf, 0x37, 0x05, 0x37, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4} }, +{ 0x07b4, 16, {0x34, 0x7e, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x18, 0xaf, 0x37, 0x05, 0x37, 0x74, 0x40, 0x2f, 0xf5} }, +{ 0x07c4, 16, {0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0xf5, 0x14, 0xe5, 0x37, 0xc3, 0x95, 0x50, 0x50, 0x2a} }, +{ 0x07d4, 16, {0x30, 0x0b, 0x12, 0xaf, 0x37, 0x05, 0x37, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5} }, +{ 0x07e4, 16, {0x83, 0xe0, 0x13, 0x92, 0x09, 0xaf, 0x37, 0x05, 0x37, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x07f4, 16, {0x7e, 0xf5, 0x83, 0xe0, 0xf5, 0x35, 0xd2, 0x06, 0x80, 0x6b, 0xc2, 0x06, 0xe4, 0x90, 0x7f, 0xc7} }, +{ 0x0804, 16, {0xf0, 0xc2, 0x01, 0x80, 0x60, 0x30, 0x0b, 0x12, 0xaf, 0x37, 0x05, 0x37, 0x74, 0xc0, 0x2f, 0xf5} }, +{ 0x0814, 16, {0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x18, 0xaf, 0x37, 0x05, 0x37, 0x74, 0xc0} }, +{ 0x0824, 16, {0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xf5, 0x14, 0xe5, 0x37, 0xc3, 0x95, 0x50} }, +{ 0x0834, 16, {0x50, 0x2a, 0x30, 0x0b, 0x12, 0xaf, 0x37, 0x05, 0x37, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x0844, 16, {0x7d, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x09, 0xaf, 0x37, 0x05, 0x37, 0x74, 0xc0, 0x2f, 0xf5, 0x82} }, +{ 0x0854, 16, {0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xf5, 0x35, 0xd2, 0x06, 0x80, 0x09, 0xc2, 0x06, 0xe4, 0x90} }, +{ 0x0864, 16, {0x7f, 0xc9, 0xf0, 0xd2, 0x01, 0x30, 0x0b, 0x04, 0xa2, 0x18, 0x92, 0x9b, 0xd2, 0x0f, 0xc2, 0xaf} }, +{ 0x0874, 16, {0x85, 0x14, 0x99, 0x20, 0x06, 0x0b, 0x30, 0x08, 0x08, 0xc2, 0x08, 0x90, 0x7f, 0xbb, 0x74, 0x01} }, +{ 0x0884, 16, {0xf0, 0xd2, 0xaf, 0x90, 0x7f, 0xbc, 0xe0, 0x20, 0xe1, 0x51, 0xe5, 0x33, 0x60, 0x4d, 0xe5, 0x31} }, +{ 0x0894, 16, {0x70, 0x49, 0xe5, 0x33, 0x30, 0xe1, 0x08, 0xe4, 0xf5, 0x2f, 0x75, 0x33, 0x01, 0x80, 0x0b, 0xa2} }, +{ 0x08a4, 16, {0x03, 0xe4, 0x33, 0xf5, 0x2f, 0xc2, 0x03, 0xe4, 0xf5, 0x33, 0xe4, 0xf5, 0x13, 0x7e, 0x00, 0x7b} }, +{ 0x08b4, 16, {0x00, 0x74, 0x24, 0x25, 0x13, 0xf9, 0xee, 0x34, 0x00, 0xfa, 0x12, 0x0c, 0x0e, 0xff, 0x74, 0x00} }, +{ 0x08c4, 16, {0x25, 0x13, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x13, 0xe5, 0x13, 0xb4} }, +{ 0x08d4, 11, {0x0c, 0xdb, 0x90, 0x7f, 0xbd, 0x74, 0x0c, 0xf0, 0x75, 0x31, 0x10} }, +{ 0x08df, 1, {0x22} }, +{ 0x08e0, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x12, 0x0c, 0x66, 0x09, 0xb1, 0x00, 0x0a, 0x25, 0x01, 0x0a, 0x91, 0x03} }, +{ 0x08f0, 16, {0x09, 0x03, 0x06, 0x09, 0xa4, 0x08, 0x09, 0x9e, 0x09, 0x09, 0x86, 0x0a, 0x09, 0x95, 0x0b, 0x00} }, +{ 0x0900, 16, {0x00, 0x0a, 0xe0, 0x90, 0x7f, 0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x4b, 0x24, 0x02} }, +{ 0x0910, 16, {0x70, 0x6a, 0x74, 0x0f, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x64, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x0a} }, +{ 0x0920, 16, {0xe7, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x04, 0x7f, 0x02, 0x80, 0x02, 0x7f, 0x03, 0x75, 0x82, 0xb5} }, +{ 0x0930, 16, {0x75, 0x83, 0x0f, 0xef, 0xf0, 0x75, 0x82, 0xae, 0x75, 0x83, 0x0f, 0xf0, 0x75, 0x82, 0xa7, 0x75} }, +{ 0x0940, 16, {0x83, 0x0f, 0xf0, 0x75, 0x82, 0xa0, 0x75, 0x83, 0x0f, 0xf0, 0x74, 0x0f, 0x90, 0x7f, 0xd4, 0xf0} }, +{ 0x0950, 16, {0x74, 0x76, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x0a, 0xe7, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x0d} }, +{ 0x0960, 16, {0xf1, 0xea, 0x49, 0x60, 0x0d, 0xea, 0x90, 0x7f, 0xd4, 0xf0, 0xe9, 0x90, 0x7f, 0xd5, 0xf0, 0x02} }, +{ 0x0970, 16, {0x0a, 0xe7, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x0a, 0xe7, 0x90, 0x7f, 0xb4, 0xe0} }, +{ 0x0980, 16, {0x44, 0x01, 0xf0, 0x02, 0x0a, 0xe7, 0x90, 0x7f, 0x00, 0xe5, 0x18, 0xf0, 0x90, 0x7f, 0xb5, 0x74} }, +{ 0x0990, 16, {0x01, 0xf0, 0x02, 0x0a, 0xe7, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x18, 0x02, 0x0a, 0xe7, 0x12, 0x0d} }, +{ 0x09a0, 16, {0x08, 0x02, 0x0a, 0xe7, 0x90, 0x7f, 0x00, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb5, 0xf0, 0x02, 0x0a} }, +{ 0x09b0, 16, {0xe7, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b} }, +{ 0x09c0, 16, {0xa2, 0x12, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x15, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00} }, +{ 0x09d0, 16, {0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x0a, 0xe7, 0xe4, 0x90, 0x7f} }, +{ 0x09e0, 16, {0x00, 0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x0a, 0xe7, 0x90, 0x7f, 0xec} }, +{ 0x09f0, 16, {0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24} }, +{ 0x0a00, 16, {0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4} }, +{ 0x0a10, 16, {0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x0a, 0xe7, 0x90, 0x7f, 0xb4, 0xe0, 0x44} }, +{ 0x0a20, 16, {0x01, 0xf0, 0x02, 0x0a, 0xe7, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, 0x60} }, +{ 0x0a30, 16, {0x03, 0x02, 0x0a, 0xe7, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x05, 0xc2, 0x12, 0x02, 0x0a, 0xe7} }, +{ 0x0a40, 16, {0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x0a, 0xe7, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x38} }, +{ 0x0a50, 16, {0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f} }, +{ 0x0a60, 16, {0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec} }, +{ 0x0a70, 16, {0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f} }, +{ 0x0a80, 16, {0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x5f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80} }, +{ 0x0a90, 16, {0x56, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x4a, 0x90, 0x7f, 0xea} }, +{ 0x0aa0, 16, {0xe0, 0xb4, 0x01, 0x04, 0xd2, 0x12, 0x80, 0x3f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80} }, +{ 0x0ab0, 16, {0x36, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4} }, +{ 0x0ac0, 16, {0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f} }, +{ 0x0ad0, 16, {0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x10, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x07} }, +{ 0x0ae0, 14, {0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} }, +{ 0x0aee, 1, {0x22} }, +{ 0x0aef, 16, {0x20, 0x14, 0x03, 0x02, 0x0b, 0x81, 0xe5, 0x31, 0x60, 0x02, 0x15, 0x31, 0xe5, 0x36, 0x60, 0x4f} }, +{ 0x0aff, 16, {0x65, 0x34, 0x70, 0x45, 0xe5, 0x32, 0xf4, 0x60, 0x02, 0x05, 0x32, 0xe5, 0x32, 0xc3, 0x95, 0x41} }, +{ 0x0b0f, 16, {0x40, 0x3d, 0xc2, 0xaf, 0x30, 0x00, 0x18, 0x90, 0x7f, 0xb8, 0xe0, 0x20, 0xe1, 0x27, 0x90, 0x7f} }, +{ 0x0b1f, 16, {0xb7, 0xe5, 0x36, 0xf0, 0xc2, 0x00, 0xe4, 0xf5, 0x36, 0xf5, 0x32, 0xf5, 0x34, 0x80, 0x16, 0x90} }, +{ 0x0b2f, 16, {0x7f, 0xb6, 0xe0, 0x20, 0xe1, 0x0f, 0x90, 0x7f, 0xb9, 0xe5, 0x36, 0xf0, 0xd2, 0x00, 0xe4, 0xf5} }, +{ 0x0b3f, 16, {0x36, 0xf5, 0x32, 0xf5, 0x34, 0xd2, 0xaf, 0x80, 0x06, 0x85, 0x36, 0x34, 0xe4, 0xf5, 0x32, 0xe5} }, +{ 0x0b4f, 16, {0x2c, 0x60, 0x2f, 0x20, 0x0a, 0x07, 0x90, 0x7f, 0x9b, 0xe0, 0x30, 0xe0, 0x0f, 0xe5, 0x2d, 0x60} }, +{ 0x0b5f, 16, {0x06, 0xe4, 0xf5, 0x2d, 0x43, 0x33, 0x01, 0xe4, 0xf5, 0x30, 0x80, 0x14, 0xe5, 0x30, 0xd3, 0x95} }, +{ 0x0b6f, 16, {0x42, 0x50, 0x0d, 0xe5, 0x30, 0xb5, 0x42, 0x06, 0x75, 0x2d, 0x01, 0x43, 0x33, 0x01, 0x05, 0x30} }, +{ 0x0b7f, 3, {0xc2, 0x0a, 0x22} }, +{ 0x0b82, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x50, 0x02, 0x0b, 0xc9} }, +{ 0x0b8e, 16, {0x02, 0x0c, 0x8c, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} }, +{ 0x0b9e, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} }, +{ 0x0bae, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} }, +{ 0x0bbe, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x0d, 0x5c, 0xe4, 0x7e} }, +{ 0x0bce, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} }, +{ 0x0bde, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} }, +{ 0x0bee, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} }, +{ 0x0bfe, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} }, +{ 0x0c0e, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} }, +{ 0x0c1e, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x0c27, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} }, +{ 0x0c37, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} }, +{ 0x0c47, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x0c54, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01} }, +{ 0x0c64, 2, {0xf3, 0x22} }, +{ 0x0c66, 16, {0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3} }, +{ 0x0c76, 16, {0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60} }, +{ 0x0c86, 6, {0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf} }, +{ 0x0c8c, 16, {0x75, 0x12, 0x01, 0x90, 0x7f, 0x92, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xae, 0xe0, 0xff, 0xd3} }, +{ 0x0c9c, 16, {0x92, 0x12, 0xe4, 0x33, 0xfe, 0xef, 0x4e, 0xf0, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xde} }, +{ 0x0cac, 16, {0x74, 0x01, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9} }, +{ 0x0cbc, 16, {0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90} }, +{ 0x0ccc, 16, {0x7f, 0xae, 0xe0, 0x44, 0x0d, 0xf0, 0xd2, 0xaf, 0xd2, 0xbc, 0xd2, 0x18, 0x12, 0x0f, 0x13, 0xc2} }, +{ 0x0cdc, 16, {0x13, 0x30, 0x14, 0x03, 0x12, 0x05, 0x74, 0x90, 0x7f, 0xd8, 0xe0, 0x65, 0x11, 0x60, 0x08, 0xe0} }, +{ 0x0cec, 16, {0xf5, 0x11, 0x12, 0x0a, 0xef, 0x80, 0xea, 0x30, 0x13, 0x07, 0xc2, 0x13, 0x12, 0x08, 0xe0, 0x80} }, +{ 0x0cfc, 11, {0xe0, 0x30, 0x16, 0xdd, 0xc2, 0x16, 0x12, 0x00, 0x26, 0x80, 0xd6} }, +{ 0x0d07, 1, {0x22} }, +{ 0x0d08, 16, {0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0x30, 0xf0, 0x90, 0x7f, 0x96, 0x74, 0x10} }, +{ 0x0d18, 16, {0xf0, 0x90, 0x7f, 0x94, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0x9d, 0x04, 0xf0, 0x90, 0x7f, 0x97, 0x74} }, +{ 0x0d28, 16, {0x20, 0xf0, 0x90, 0x7f, 0x95, 0x74, 0x03, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x84, 0xf0, 0xe4, 0x90} }, +{ 0x0d38, 16, {0x7f, 0x98, 0xf0, 0x90, 0x7f, 0xc7, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0x90, 0x7f, 0xcb, 0xf0, 0x75} }, +{ 0x0d48, 16, {0x98, 0x40, 0x43, 0xa8, 0x10, 0x90, 0x7f, 0xde, 0x74, 0x1f, 0xf0, 0x90, 0x7f, 0xdf, 0x74, 0x0f} }, +{ 0x0d58, 4, {0xf0, 0xd2, 0x14, 0x22} }, +{ 0x0d5c, 12, {0xc1, 0x13, 0xc1, 0x16, 0xc1, 0x12, 0xc1, 0x95, 0xc1, 0x14, 0xc1, 0x11} }, +{ 0x0d68, 16, {0x0c, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30} }, +{ 0x0d78, 16, {0x00, 0x01, 0x33, 0x01, 0x01, 0x32, 0x00, 0x01, 0x37, 0x00, 0x01, 0x50, 0x00, 0x01, 0x36, 0x00} }, +{ 0x0d88, 16, {0x01, 0x34, 0x00, 0xc1, 0x03, 0xc1, 0x0a, 0xc1, 0x8e, 0xc1, 0x0d, 0xc1, 0x02, 0xc1, 0x0c, 0xc1} }, +{ 0x0d98, 16, {0x10, 0xc1, 0x08, 0xc1, 0x0f, 0xc1, 0x06, 0xc1, 0x07, 0xc1, 0x04, 0xc1, 0x0b, 0xc1, 0x80, 0xc1} }, +{ 0x0da8, 1, {0x81} }, +{ 0x0da9, 2, {0xc1, 0x97} }, +{ 0x0dab, 1, {0x00} }, +{ 0x0dac, 16, {0xe4, 0x90, 0x7f, 0x95, 0xf0, 0x90, 0x7f, 0x94, 0xf0, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9d} }, +{ 0x0dbc, 16, {0xe0, 0x44, 0x02, 0xf0, 0x90, 0x7f, 0x97, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0x7f, 0x9d, 0xe0, 0x54} }, +{ 0x0dcc, 16, {0xfd, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0x20, 0xf0, 0xe4, 0x90, 0x7f, 0x96, 0xf0, 0x90, 0x7f, 0x9d} }, +{ 0x0ddc, 16, {0xe0, 0x44, 0xfd, 0xf0, 0xe4, 0x90, 0x7f, 0x97, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0xff, 0xf0, 0xe4} }, +{ 0x0dec, 5, {0x90, 0x7f, 0x98, 0xf0, 0x22} }, +{ 0x0df1, 2, {0x8f, 0x13} }, +{ 0x0df3, 16, {0xe4, 0xf5, 0x14, 0x75, 0x15, 0xff, 0x75, 0x16, 0x0f, 0x75, 0x17, 0xb9, 0xab, 0x15, 0xaa, 0x16} }, +{ 0x0e03, 16, {0xa9, 0x17, 0x90, 0x00, 0x01, 0x12, 0x0c, 0x27, 0xb4, 0x03, 0x1d, 0xaf, 0x14, 0x05, 0x14, 0xef} }, +{ 0x0e13, 16, {0xb5, 0x13, 0x01, 0x22, 0x12, 0x0c, 0x0e, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} }, +{ 0x0e23, 14, {0x15, 0xff, 0xf5, 0x16, 0x89, 0x17, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x0e31, 1, {0x22} }, +{ 0x0e32, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x30} }, +{ 0x0e42, 16, {0x17, 0x04, 0xc2, 0x17, 0x80, 0x02, 0xd2, 0x16, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} }, +{ 0x0e52, 14, {0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0e60, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x90} }, +{ 0x0e70, 16, {0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x04, 0xf0, 0xd0, 0x86, 0xd0} }, +{ 0x0e80, 10, {0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0e8a, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xd2} }, +{ 0x0e9a, 16, {0x13, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85} }, +{ 0x0eaa, 7, {0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0eb1, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} }, +{ 0x0ec1, 16, {0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82} }, +{ 0x0ed1, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0ed6, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} }, +{ 0x0ee6, 16, {0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82} }, +{ 0x0ef6, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0f00, 16, {0x02, 0x0e, 0x8a, 0x00, 0x02, 0x0e, 0xb1, 0x00, 0x02, 0x0e, 0x60, 0x00, 0x02, 0x0e, 0x32, 0x00} }, +{ 0x0f10, 3, {0x02, 0x0e, 0xd6} }, +{ 0x0f13, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x18, 0x04, 0xe0, 0x44} }, +{ 0x0f23, 16, {0x02, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x00, 0x03, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} }, +{ 0x0f33, 5, {0xe0, 0x44, 0x04, 0xf0, 0x22} }, +{ 0x0f38, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} }, +{ 0x0f48, 1, {0x22} }, +{ 0x0f49, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} }, +{ 0x0f64, 16, {0x12, 0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x40, 0xcd, 0x06, 0x07, 0x01, 0x01, 0x00, 0x01, 0x02} }, +{ 0x0f74, 16, {0x00, 0x01, 0x09, 0x02, 0x43, 0x00, 0x01, 0x01, 0x00, 0xa0, 0x32, 0x09, 0x04, 0x00, 0x00, 0x07} }, +{ 0x0f84, 16, {0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} }, +{ 0x0f94, 16, {0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00} }, +{ 0x0fa4, 16, {0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05} }, +{ 0x0fb4, 16, {0x84, 0x02, 0x40, 0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x10, 0x03, 0x4b, 0x00, 0x65, 0x00, 0x79} }, +{ 0x0fc4, 16, {0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x0e, 0x03, 0x53, 0x00, 0x65, 0x00, 0x72} }, +{ 0x0fd4, 9, {0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x00, 0x00} }, +{ 0xffff, 0, {0x00} } +}; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/serial/keyspan_usa19w_fw.h linux/drivers/usb/serial/keyspan_usa19w_fw.h --- v2.4.0-test2/linux/drivers/usb/serial/keyspan_usa19w_fw.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/keyspan_usa19w_fw.h Mon Jul 10 14:33:04 2000 @@ -0,0 +1,304 @@ +/* keyspan_usa19w_fw.h + + Generated from Keyspan firmware image Wed Jul 5 09:18:29 2000 EST + This firmware is for the Keyspan USA-19W Serial Adaptor + + "The firmware contained herein as keyspan_usa19w_fw.h is + Copyright (C) 1999-2000 Keyspan, A division of InnoSys Incorporated + ("Keyspan"), as an unpublished work. This notice does not imply + unrestricted or public access to this firmware which is a trade secret of + Keyspan, and which may not be reproduced, used, sold or transferred to any + third party without Keyspan's prior written consent. All Rights Reserved. + + This firmware may not be modified and may only be used with the Keyspan + USA-19W Serial Adapter. Distribution and/or Modification of the + keyspan.c driver which includes this firmware, in whole or in part, + requires the inclusion of this statement." + +*/ + +static const struct ezusb_hex_record keyspan_usa19w_firmware[] = { +{ 0x0000, 3, {0x02, 0x09, 0x60} }, +{ 0x0003, 16, {0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0x30, 0xf0, 0xe4, 0x90, 0x7f, 0x96, 0xf0} }, +{ 0x0013, 16, {0x90, 0x7f, 0x94, 0xf0, 0x90, 0x7f, 0x9d, 0x74, 0xff, 0xf0, 0xe4, 0x90, 0x7f, 0x97, 0xf0, 0x90} }, +{ 0x0023, 15, {0x7f, 0x95, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x17, 0xf0, 0xe4, 0x90, 0x7f, 0x98, 0xf0, 0x22} }, +{ 0x0033, 3, {0x02, 0x0e, 0x43} }, +{ 0x0036, 12, {0x90, 0x7f, 0x98, 0x74, 0x10, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x0043, 3, {0x02, 0x0e, 0x00} }, +{ 0x0046, 16, {0x30, 0x0d, 0x13, 0x12, 0x0e, 0x1f, 0xef, 0xc3, 0x95, 0x14, 0x50, 0x73, 0x90, 0x7f, 0xbf, 0x74} }, +{ 0x0056, 16, {0x01, 0xf0, 0xc2, 0x0d, 0x80, 0x69, 0x30, 0x0a, 0x34, 0x90, 0x7f, 0xc6, 0xe0, 0x20, 0xe1, 0x5f} }, +{ 0x0066, 16, {0x12, 0x0e, 0x1f, 0xef, 0xc3, 0x94, 0x40, 0x50, 0x56, 0x90, 0x7e, 0x40, 0xe0, 0x13, 0x92, 0x0d} }, +{ 0x0076, 16, {0x90, 0x7f, 0xc7, 0xe0, 0x14, 0xf5, 0x23, 0x7e, 0x7e, 0x7f, 0x41, 0x75, 0x27, 0x7e, 0x75, 0x28} }, +{ 0x0086, 16, {0x41, 0x12, 0x08, 0xab, 0xc2, 0x0a, 0xe4, 0x90, 0x7f, 0xc7, 0xf0, 0x80, 0x32, 0x90, 0x7f, 0xc8} }, +{ 0x0096, 16, {0xe0, 0x20, 0xe1, 0x2b, 0x12, 0x0e, 0x1f, 0xef, 0xc3, 0x94, 0x40, 0x50, 0x22, 0x90, 0x7d, 0xc0} }, +{ 0x00a6, 16, {0xe0, 0x13, 0x92, 0x0d, 0x90, 0x7f, 0xc9, 0xe0, 0x14, 0xf5, 0x23, 0x7e, 0x7d, 0x7f, 0xc1, 0x75} }, +{ 0x00b6, 16, {0x27, 0x7d, 0x75, 0x28, 0xc1, 0x12, 0x08, 0xab, 0xd2, 0x0a, 0xe4, 0x90, 0x7f, 0xc9, 0xf0, 0x90} }, +{ 0x00c6, 16, {0x7f, 0xb6, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x01, 0x4d, 0x53, 0x11, 0x80, 0x12, 0x0e, 0x2b, 0xef} }, +{ 0x00d6, 16, {0x42, 0x11, 0x12, 0x0c, 0xc8, 0x8f, 0x34, 0xef, 0xc3, 0x95, 0x13, 0x50, 0x0f, 0x12, 0x0d, 0xf1} }, +{ 0x00e6, 16, {0xef, 0x30, 0xe0, 0x08, 0xe5, 0x11, 0x20, 0xe7, 0x03, 0x30, 0x10, 0x5b, 0xc2, 0x10, 0xe5, 0x34} }, +{ 0x00f6, 16, {0x70, 0x04, 0xf5, 0x11, 0x80, 0x51, 0xe5, 0x11, 0x30, 0xe7, 0x26, 0xe5, 0x34, 0xd3, 0x94, 0x20} }, +{ 0x0106, 16, {0x40, 0x03, 0x75, 0x34, 0x20, 0x85, 0x34, 0x23, 0x7e, 0x7e, 0x7f, 0x80, 0x75, 0x27, 0x7e, 0x75} }, +{ 0x0116, 16, {0x28, 0x80, 0xaf, 0x11, 0x12, 0x0b, 0x01, 0xe5, 0x34, 0x25, 0xe0, 0x90, 0x7f, 0xb7, 0xf0, 0x80} }, +{ 0x0126, 16, {0x26, 0xe5, 0x34, 0xd3, 0x94, 0x3f, 0x40, 0x03, 0x75, 0x34, 0x3f, 0x85, 0x34, 0x23, 0xe4, 0x90} }, +{ 0x0136, 16, {0x7e, 0x80, 0xf0, 0x7e, 0x7e, 0x7f, 0x81, 0x75, 0x27, 0x7e, 0x75, 0x28, 0x81, 0x12, 0x08, 0xd0} }, +{ 0x0146, 16, {0xe5, 0x34, 0x04, 0x90, 0x7f, 0xb7, 0xf0, 0x90, 0x7f, 0xce, 0xe0, 0x30, 0xe1, 0x06, 0x20, 0x0b} }, +{ 0x0156, 16, {0x03, 0x02, 0x03, 0xb2, 0xe4, 0xf5, 0x33, 0x74, 0x40, 0x25, 0x33, 0xf5, 0x82, 0xe4, 0x34, 0x7c} }, +{ 0x0166, 16, {0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x33, 0x7c, 0x00, 0x7b, 0x01, 0x7a, 0x7e, 0x79, 0x00, 0x24, 0x00} }, +{ 0x0176, 16, {0xf9, 0xec, 0x34, 0x7e, 0xfa, 0xef, 0x12, 0x08, 0x3b, 0x05, 0x33, 0xe5, 0x33, 0xb4, 0x20, 0xd7} }, +{ 0x0186, 16, {0x90, 0x7e, 0x00, 0xe0, 0x60, 0x6e, 0x7f, 0x01, 0x90, 0x7e, 0x11, 0xe0, 0xfd, 0x12, 0x0c, 0xa3} }, +{ 0x0196, 16, {0x90, 0x7e, 0x01, 0xe0, 0xff, 0x12, 0x0b, 0xe5, 0x90, 0x7e, 0x02, 0xe0, 0xff, 0x12, 0x0c, 0x0b} }, +{ 0x01a6, 16, {0xd2, 0x0e, 0xd2, 0x0f, 0x75, 0x34, 0x04, 0x90, 0x7e, 0x03, 0xe0, 0x60, 0x05, 0xc2, 0x0f, 0x43} }, +{ 0x01b6, 16, {0x34, 0xc0, 0x90, 0x7e, 0x04, 0xe0, 0xb4, 0x01, 0x07, 0xc2, 0x0f, 0x43, 0x34, 0x0b, 0x80, 0x10} }, +{ 0x01c6, 16, {0x90, 0x7e, 0x04, 0xe0, 0x60, 0x07, 0xc2, 0x0e, 0x43, 0x34, 0x09, 0x80, 0x03, 0x43, 0x34, 0x02} }, +{ 0x01d6, 16, {0x7f, 0x03, 0xad, 0x34, 0x12, 0x0c, 0xa3, 0x43, 0x19, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0} }, +{ 0x01e6, 16, {0x90, 0xc0, 0x00, 0xe5, 0x19, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x12, 0xf0, 0xe5, 0x16, 0x44, 0x06} }, +{ 0x01f6, 16, {0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x05, 0xe0, 0x60, 0x12, 0xa3, 0xe0, 0x54, 0x3f, 0xf5, 0x18} }, +{ 0x0206, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x18, 0xf0, 0x90, 0x7e, 0x07, 0xe0} }, +{ 0x0216, 16, {0x60, 0x42, 0x90, 0x7e, 0x13, 0xe0, 0x60, 0x05, 0x43, 0x15, 0x04, 0x80, 0x03, 0x53, 0x15, 0xfb} }, +{ 0x0226, 16, {0xe4, 0xff, 0xad, 0x15, 0x12, 0x0c, 0xa3, 0x90, 0x7e, 0x08, 0xe0, 0x60, 0x05, 0x43, 0x17, 0x80} }, +{ 0x0236, 16, {0x80, 0x03, 0x53, 0x17, 0x7f, 0x53, 0x17, 0xfc, 0x90, 0x7e, 0x09, 0xe0, 0x60, 0x11, 0x43, 0x17} }, +{ 0x0246, 16, {0x02, 0xa3, 0xe0, 0xff, 0x12, 0x0c, 0x57, 0x90, 0x7e, 0x0b, 0xe0, 0xff, 0x12, 0x0c, 0x7d, 0xaf} }, +{ 0x0256, 16, {0x17, 0x12, 0x0c, 0x31, 0x90, 0x7e, 0x0e, 0xe0, 0x60, 0x18, 0xa3, 0xe0, 0x60, 0x05, 0x43, 0x19} }, +{ 0x0266, 16, {0x01, 0x80, 0x03, 0x53, 0x19, 0xfe, 0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x90, 0xc0, 0x00, 0xe5} }, +{ 0x0276, 16, {0x19, 0xf0, 0x90, 0x7e, 0x0c, 0xe0, 0x60, 0x18, 0xa3, 0xe0, 0x60, 0x05, 0x43, 0x19, 0x02, 0x80} }, +{ 0x0286, 16, {0x03, 0x53, 0x19, 0xfd, 0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x19, 0xf0} }, +{ 0x0296, 16, {0x90, 0x7e, 0x12, 0xe0, 0xf5, 0x13, 0xa3, 0xe0, 0x13, 0x92, 0x11, 0xa3, 0xe0, 0xf5, 0x14, 0xa3} }, +{ 0x02a6, 16, {0xe0, 0x60, 0x05, 0x43, 0x19, 0x10, 0x80, 0x03, 0x53, 0x19, 0xef, 0x90, 0x7f, 0x98, 0x74, 0x14} }, +{ 0x02b6, 16, {0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x19, 0xf0, 0x90, 0x7e, 0x16, 0xe0, 0x60, 0x32, 0x53, 0x18, 0xbf} }, +{ 0x02c6, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x18, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7f} }, +{ 0x02d6, 16, {0x98, 0x74, 0x11, 0xf0, 0x12, 0x0d, 0xe5, 0xef, 0x54, 0xfe, 0x90, 0xc0, 0x00, 0xf0, 0x53, 0x15} }, +{ 0x02e6, 16, {0xfd, 0xe4, 0xff, 0xad, 0x15, 0x12, 0x0c, 0xa3, 0xe4, 0xf5, 0x0e, 0xf5, 0x0d, 0xd2, 0x0c, 0x90} }, +{ 0x02f6, 16, {0x7e, 0x17, 0xe0, 0x60, 0x0f, 0x43, 0x15, 0x02, 0xe4, 0xff, 0xad, 0x15, 0x12, 0x0c, 0xa3, 0x75} }, +{ 0x0306, 16, {0x0d, 0x01, 0xd2, 0x0c, 0x90, 0x7e, 0x18, 0xe0, 0x60, 0x1b, 0x90, 0x7f, 0x98, 0x74, 0x12, 0xf0} }, +{ 0x0316, 16, {0xe5, 0x16, 0x44, 0x04, 0x90, 0xc0, 0x00, 0xf0, 0xe4, 0x90, 0x7f, 0xc7, 0xf0, 0x90, 0x7f, 0xc9} }, +{ 0x0326, 16, {0xf0, 0xd2, 0x0a, 0xc2, 0x0d, 0x90, 0x7e, 0x19, 0xe0, 0x60, 0x11, 0x43, 0x18, 0x40, 0x90, 0x7f} }, +{ 0x0336, 16, {0x98, 0x74, 0x13, 0xf0, 0xe5, 0x18, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x1a, 0xe0} }, +{ 0x0346, 16, {0x60, 0x0f, 0x53, 0x15, 0xfe, 0xe4, 0xff, 0xad, 0x15, 0x12, 0x0c, 0xa3, 0x75, 0x0f, 0x01, 0xd2} }, +{ 0x0356, 16, {0x0c, 0x90, 0x7e, 0x1b, 0xe0, 0x60, 0x0f, 0x43, 0x15, 0x01, 0xe4, 0xff, 0xad, 0x15, 0x12, 0x0c} }, +{ 0x0366, 16, {0xa3, 0xe4, 0xf5, 0x0f, 0xd2, 0x0c, 0x90, 0x7e, 0x1c, 0xe0, 0x60, 0x0e, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x0376, 16, {0x12, 0xf0, 0xe5, 0x16, 0x44, 0x02, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x1d, 0xe0, 0x60, 0x02} }, +{ 0x0386, 16, {0xd2, 0x10, 0x90, 0x7e, 0x1e, 0xe0, 0x60, 0x08, 0x75, 0x10, 0x01, 0xe4, 0xf5, 0x12, 0xd2, 0x0c} }, +{ 0x0396, 16, {0x90, 0x7e, 0x1f, 0xe0, 0x60, 0x0f, 0x90, 0x7f, 0xd7, 0x74, 0x11, 0xf0, 0x74, 0x31, 0xf0, 0x74} }, +{ 0x03a6, 16, {0x15, 0xf0, 0x74, 0x35, 0xf0, 0xc2, 0x0b, 0xe4, 0x90, 0x7f, 0xcf, 0xf0, 0x30, 0x13, 0x71, 0xe5} }, +{ 0x03b6, 16, {0x12, 0x60, 0x02, 0x15, 0x12, 0xe5, 0x2e, 0xd3, 0x94, 0x00, 0x40, 0x04, 0x15, 0x2e, 0x80, 0x60} }, +{ 0x03c6, 16, {0x75, 0x2e, 0x0a, 0x12, 0x0d, 0xe5, 0xef, 0x54, 0x01, 0xf5, 0x34, 0x65, 0x0e, 0x60, 0x07, 0x85} }, +{ 0x03d6, 16, {0x34, 0x0e, 0xd2, 0x0c, 0x80, 0x11, 0x12, 0x0e, 0x37, 0xef, 0x54, 0x10, 0xf5, 0x34, 0x65, 0x09} }, +{ 0x03e6, 16, {0x60, 0x05, 0x85, 0x34, 0x09, 0xd2, 0x0c, 0x12, 0x0e, 0x37, 0xef, 0x54, 0x80, 0xf5, 0x34, 0x65} }, +{ 0x03f6, 16, {0x0a, 0x60, 0x05, 0x85, 0x34, 0x0a, 0xd2, 0x0c, 0x12, 0x0e, 0x37, 0xef, 0x54, 0x20, 0xf5, 0x34} }, +{ 0x0406, 16, {0x65, 0x0b, 0x60, 0x08, 0x85, 0x34, 0x0b, 0x30, 0x0e, 0x02, 0xd2, 0x0c, 0x12, 0x0e, 0x37, 0xef} }, +{ 0x0416, 16, {0x54, 0x40, 0xf5, 0x34, 0x65, 0x0c, 0x60, 0x08, 0x85, 0x34, 0x0c, 0x30, 0x0f, 0x02, 0xd2, 0x0c} }, +{ 0x0426, 16, {0x30, 0x13, 0x2a, 0x90, 0x7f, 0xd2, 0xe0, 0x20, 0xe1, 0x23, 0x90, 0x7b, 0x40, 0xe0, 0x60, 0x09} }, +{ 0x0436, 16, {0xe0, 0xf5, 0x30, 0x90, 0x7b, 0x42, 0xe0, 0xf5, 0x31, 0x90, 0x7b, 0x41, 0xe0, 0x60, 0x09, 0x90} }, +{ 0x0446, 16, {0x7f, 0xd7, 0x74, 0x17, 0xf0, 0x74, 0x37, 0xf0, 0xe4, 0x90, 0x7f, 0xd3, 0xf0, 0x90, 0x7f, 0xc2} }, +{ 0x0456, 16, {0xe0, 0x30, 0xe1, 0x03, 0x02, 0x05, 0x17, 0xe5, 0x25, 0x70, 0x40, 0x30, 0x0c, 0x39, 0xe5, 0x12} }, +{ 0x0466, 16, {0x70, 0x35, 0xc2, 0x0c, 0xf5, 0x33, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x08, 0x25, 0x33, 0xf9, 0xee} }, +{ 0x0476, 16, {0x34, 0x00, 0xfa, 0x12, 0x07, 0xf5, 0xff, 0x74, 0x80, 0x25, 0x33, 0xf5, 0x82, 0xe4, 0x34, 0x7b} }, +{ 0x0486, 16, {0xf5, 0x83, 0xef, 0xf0, 0x05, 0x33, 0xe5, 0x33, 0xb4, 0x09, 0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x09} }, +{ 0x0496, 16, {0xf0, 0x75, 0x12, 0x10, 0xe4, 0xf5, 0x10, 0x75, 0x25, 0x02, 0x22, 0xe5, 0x25, 0x64, 0x02, 0x70} }, +{ 0x04a6, 16, {0x36, 0x30, 0x05, 0x2f, 0xc2, 0x05, 0xf5, 0x33, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x29, 0x25, 0x33} }, +{ 0x04b6, 16, {0xf9, 0xee, 0x34, 0x00, 0xfa, 0x12, 0x07, 0xf5, 0xff, 0x74, 0x80, 0x25, 0x33, 0xf5, 0x82, 0xe4} }, +{ 0x04c6, 16, {0x34, 0x7b, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x33, 0xe5, 0x33, 0xb4, 0x05, 0xdb, 0x90, 0x7f, 0xc3} }, +{ 0x04d6, 16, {0x74, 0x05, 0xf0, 0x75, 0x25, 0x03, 0x22, 0xe5, 0x30, 0x60, 0x33, 0x75, 0x2f, 0x03, 0x15, 0x30} }, +{ 0x04e6, 16, {0xe4, 0xf5, 0x33, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x2f, 0x25, 0x33, 0xf9, 0xee, 0x34, 0x00, 0xfa} }, +{ 0x04f6, 16, {0x12, 0x07, 0xf5, 0xff, 0x74, 0x80, 0x25, 0x33, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xef} }, +{ 0x0506, 16, {0xf0, 0x05, 0x33, 0xe5, 0x33, 0xb4, 0x03, 0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x03, 0xf0, 0xe4, 0xf5} }, +{ 0x0516, 1, {0x25} }, +{ 0x0517, 1, {0x22} }, +{ 0x0518, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x12, 0x08, 0x85, 0x05, 0xe8, 0x00, 0x06, 0x5c, 0x01, 0x06, 0xc9, 0x03} }, +{ 0x0528, 16, {0x05, 0x3b, 0x06, 0x05, 0xdb, 0x08, 0x05, 0xd5, 0x09, 0x05, 0xbd, 0x0a, 0x05, 0xcc, 0x0b, 0x00} }, +{ 0x0538, 16, {0x00, 0x07, 0x19, 0x90, 0x7f, 0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x40, 0x24, 0x02} }, +{ 0x0548, 16, {0x70, 0x69, 0x74, 0x19, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x07} }, +{ 0x0558, 16, {0x20, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x0a, 0x71, 0x8b, 0x33, 0x8a, 0x34, 0x89, 0x35, 0xea} }, +{ 0x0568, 16, {0x49, 0x60, 0x11, 0xae, 0x02, 0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5} }, +{ 0x0578, 16, {0xf0, 0x02, 0x07, 0x20, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x07, 0x20, 0x90, 0x7f} }, +{ 0x0588, 16, {0xea, 0xe0, 0xff, 0x12, 0x0a, 0xc0, 0x8b, 0x33, 0x8a, 0x34, 0x89, 0x35, 0xea, 0x49, 0x60, 0x11} }, +{ 0x0598, 16, {0xae, 0x02, 0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x07} }, +{ 0x05a8, 16, {0x20, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x07, 0x20, 0x90, 0x7f, 0xb4, 0xe0, 0x44} }, +{ 0x05b8, 16, {0x01, 0xf0, 0x02, 0x07, 0x20, 0x90, 0x7f, 0x00, 0xe5, 0x24, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01} }, +{ 0x05c8, 16, {0xf0, 0x02, 0x07, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x24, 0x02, 0x07, 0x20, 0x12, 0x07, 0x28} }, +{ 0x05d8, 16, {0x02, 0x07, 0x20, 0x90, 0x7f, 0x00, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb5, 0xf0, 0x02, 0x07, 0x20} }, +{ 0x05e8, 16, {0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b, 0xa2} }, +{ 0x05f8, 16, {0x01, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x06, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0} }, +{ 0x0608, 16, {0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x07, 0x20, 0xe4, 0x90, 0x7f, 0x00} }, +{ 0x0618, 16, {0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x07, 0x20, 0x90, 0x7f, 0xec, 0xe0} }, +{ 0x0628, 16, {0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4} }, +{ 0x0638, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3} }, +{ 0x0648, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x07, 0x20, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01} }, +{ 0x0658, 16, {0xf0, 0x02, 0x07, 0x20, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x1e, 0x24, 0x02, 0x60, 0x03} }, +{ 0x0668, 16, {0x02, 0x07, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x06, 0x12, 0x0e, 0x47, 0x02, 0x07, 0x20} }, +{ 0x0678, 16, {0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x07, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x38} }, +{ 0x0688, 16, {0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f} }, +{ 0x0698, 16, {0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec} }, +{ 0x06a8, 16, {0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f} }, +{ 0x06b8, 16, {0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x60, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80} }, +{ 0x06c8, 16, {0x57, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x19, 0x24, 0x02, 0x70, 0x4b, 0x90, 0x7f, 0xea} }, +{ 0x06d8, 16, {0xe0, 0xb4, 0x01, 0x05, 0x12, 0x0d, 0xfd, 0x80, 0x3f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0} }, +{ 0x06e8, 16, {0x80, 0x36, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff} }, +{ 0x06f8, 16, {0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x0708, 16, {0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x10, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80} }, +{ 0x0718, 15, {0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} }, +{ 0x0727, 1, {0x22} }, +{ 0x0728, 16, {0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0x30, 0xf0, 0xe4, 0x90, 0x7f, 0x96, 0xf0} }, +{ 0x0738, 16, {0x90, 0x7f, 0x95, 0x74, 0xc0, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x3f, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x0748, 16, {0x18, 0xf0, 0xe4, 0xf5, 0x8e, 0x90, 0x7f, 0xdf, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xde, 0xf0, 0xe4} }, +{ 0x0758, 16, {0xf5, 0x08, 0x7f, 0x01, 0x7b, 0x00, 0x74, 0x08, 0x2f, 0xf9, 0xe4, 0x34, 0x00, 0xfa, 0xe4, 0x12} }, +{ 0x0768, 16, {0x08, 0x3b, 0x0f, 0xbf, 0x09, 0xee, 0x75, 0x13, 0x01, 0xe4, 0xf5, 0x12, 0xf5, 0x2e, 0xf5, 0x11} }, +{ 0x0778, 16, {0xc2, 0x0c, 0xc2, 0x10, 0xc2, 0x0b, 0xc2, 0x0d, 0xc2, 0x04, 0xd2, 0x0a, 0xd2, 0x09, 0x90, 0x7f} }, +{ 0x0788, 16, {0x98, 0x74, 0x13, 0xf0, 0x75, 0x18, 0x03, 0x90, 0xc0, 0x00, 0x74, 0x03, 0xf0, 0x7f, 0x0c, 0xe4} }, +{ 0x0798, 16, {0xfd, 0x12, 0x0c, 0xa3, 0x7f, 0x10, 0x8f, 0x17, 0x12, 0x0c, 0x31, 0x90, 0x7f, 0x98, 0x74, 0x12} }, +{ 0x07a8, 16, {0xf0, 0x7f, 0x01, 0x8f, 0x16, 0xef, 0x44, 0x06, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x07b8, 16, {0x14, 0xf0, 0x75, 0x19, 0x80, 0x90, 0xc0, 0x00, 0x74, 0x80, 0xf0, 0x0f, 0xe4, 0xfd, 0x12, 0x0c} }, +{ 0x07c8, 16, {0xa3, 0xe4, 0xff, 0x7e, 0xa3, 0xad, 0x06, 0x8d, 0x15, 0x12, 0x0c, 0xa3, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x07d8, 16, {0x11, 0xf0, 0x90, 0xc0, 0x00, 0xe4, 0xf0, 0x7f, 0x05, 0x7d, 0x7f, 0x12, 0x0c, 0xa3, 0x7f, 0x01} }, +{ 0x07e8, 12, {0x12, 0x0d, 0x7d, 0x7f, 0x03, 0x7d, 0x07, 0x12, 0x0c, 0xa3, 0xd2, 0x03} }, +{ 0x07f4, 1, {0x22} }, +{ 0x07f5, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} }, +{ 0x0805, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x080e, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} }, +{ 0x081e, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} }, +{ 0x082e, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x083b, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01} }, +{ 0x084b, 2, {0xf3, 0x22} }, +{ 0x084d, 16, {0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} }, +{ 0x085d, 16, {0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} }, +{ 0x086d, 16, {0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} }, +{ 0x087d, 8, {0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} }, +{ 0x0885, 16, {0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3} }, +{ 0x0895, 16, {0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60} }, +{ 0x08a5, 6, {0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf} }, +{ 0x08ab, 16, {0x90, 0x7f, 0x98, 0x74, 0x10, 0xf0, 0xaf, 0x23, 0xe5, 0x28, 0xf5, 0x82, 0xe5, 0x27, 0xf5, 0x83} }, +{ 0x08bb, 16, {0xc2, 0xaf, 0x05, 0x86, 0x90, 0xc0, 0x00, 0x05, 0x86, 0xe0, 0xa3, 0x05, 0x86, 0xf0, 0x05, 0x86} }, +{ 0x08cb, 16, {0xdf, 0xf7, 0xd2, 0xaf, 0x22, 0x90, 0x7f, 0x98, 0x74, 0x10, 0xf0, 0xaf, 0x23, 0xe5, 0x28, 0xf5} }, +{ 0x08db, 16, {0x82, 0xe5, 0x27, 0xf5, 0x83, 0xc2, 0xaf, 0x05, 0x86, 0x90, 0xc0, 0x00, 0xe0, 0x05, 0x86, 0xf0} }, +{ 0x08eb, 16, {0xa3, 0x05, 0x86, 0xdf, 0xf7, 0x05, 0x86, 0xd2, 0xaf, 0x22, 0x90, 0x7f, 0x98, 0x74, 0x08, 0xf0} }, +{ 0x08fb, 16, {0xaf, 0x23, 0xe5, 0x28, 0xf5, 0x82, 0xe5, 0x27, 0xf5, 0x83, 0xc2, 0xaf, 0x05, 0x86, 0x90, 0xc0} }, +{ 0x090b, 16, {0x00, 0x05, 0x86, 0xe0, 0xa3, 0x05, 0x86, 0xf0, 0x05, 0x86, 0xdf, 0xf7, 0xd2, 0xaf, 0x22, 0x90} }, +{ 0x091b, 16, {0x7f, 0x98, 0x74, 0x08, 0xf0, 0xaf, 0x23, 0xe5, 0x28, 0xf5, 0x82, 0xe5, 0x27, 0xf5, 0x83, 0xc2} }, +{ 0x092b, 16, {0xaf, 0x05, 0x86, 0x90, 0xc0, 0x00, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xdf, 0xf7, 0x05} }, +{ 0x093b, 4, {0x86, 0xd2, 0xaf, 0x22} }, +{ 0x093f, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} }, +{ 0x094f, 1, {0x22} }, +{ 0x0950, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} }, +{ 0x0960, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x3a, 0x02, 0x09, 0xa7} }, +{ 0x096c, 16, {0x02, 0x09, 0xec, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} }, +{ 0x097c, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} }, +{ 0x098c, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} }, +{ 0x099c, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x0d, 0x9e, 0xe4, 0x7e} }, +{ 0x09ac, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} }, +{ 0x09bc, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} }, +{ 0x09cc, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} }, +{ 0x09dc, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} }, +{ 0x09ec, 16, {0xd2, 0x12, 0x90, 0x7f, 0x92, 0xe0, 0x44, 0x02, 0xf0, 0x12, 0x0e, 0x47, 0xd2, 0xe8, 0x43, 0xd8} }, +{ 0x09fc, 16, {0x20, 0x90, 0x7f, 0xde, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xab, 0x74, 0xff} }, +{ 0x0a0c, 16, {0xf0, 0x90, 0x7f, 0xa9, 0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaf, 0xe0} }, +{ 0x0a1c, 16, {0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae, 0x74, 0x0d, 0xf0, 0xd2, 0xaf, 0xd2, 0x13, 0x12, 0x0d, 0x37} }, +{ 0x0a2c, 16, {0xc2, 0x02, 0xe4, 0xf5, 0x26, 0xf5, 0x2e, 0xc2, 0x07, 0xc2, 0x03, 0x90, 0x7f, 0xa1, 0x04, 0xf0} }, +{ 0x0a3c, 16, {0x90, 0x7f, 0xd8, 0xe0, 0x65, 0x32, 0x60, 0x10, 0x30, 0x03, 0x05, 0xd2, 0x13, 0x12, 0x00, 0x46} }, +{ 0x0a4c, 16, {0x90, 0x7f, 0xd8, 0xe0, 0xf5, 0x32, 0x80, 0x08, 0x30, 0x03, 0x05, 0xc2, 0x13, 0x12, 0x00, 0x46} }, +{ 0x0a5c, 16, {0x30, 0x02, 0x07, 0xc2, 0x02, 0x12, 0x05, 0x18, 0x80, 0xd6, 0x30, 0x08, 0xd3, 0xc2, 0x08, 0x12} }, +{ 0x0a6c, 4, {0x0b, 0x68, 0x80, 0xcc} }, +{ 0x0a70, 1, {0x22} }, +{ 0x0a71, 16, {0xe4, 0xfe, 0x75, 0x38, 0xff, 0x75, 0x39, 0x19, 0x75, 0x3a, 0x12, 0xab, 0x38, 0xaa, 0x39, 0xa9} }, +{ 0x0a81, 16, {0x3a, 0x90, 0x00, 0x01, 0x12, 0x08, 0x0e, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} }, +{ 0x0a91, 16, {0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x08, 0x4d, 0x85, 0xf0, 0x36, 0xf5, 0x37, 0x62, 0x36} }, +{ 0x0aa1, 16, {0xe5, 0x36, 0x62, 0x37, 0xe5, 0x37, 0x62, 0x36, 0x29, 0xfd, 0xe5, 0x36, 0x3a, 0xa9, 0x05, 0x75} }, +{ 0x0ab1, 14, {0x38, 0xff, 0xf5, 0x39, 0x89, 0x3a, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x0abf, 1, {0x22} }, +{ 0x0ac0, 2, {0x8f, 0x36} }, +{ 0x0ac2, 16, {0xe4, 0xf5, 0x37, 0x75, 0x38, 0xff, 0x75, 0x39, 0x19, 0x75, 0x3a, 0x86, 0xab, 0x38, 0xaa, 0x39} }, +{ 0x0ad2, 16, {0xa9, 0x3a, 0x90, 0x00, 0x01, 0x12, 0x08, 0x0e, 0xb4, 0x03, 0x1d, 0xaf, 0x37, 0x05, 0x37, 0xef} }, +{ 0x0ae2, 16, {0xb5, 0x36, 0x01, 0x22, 0x12, 0x07, 0xf5, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} }, +{ 0x0af2, 14, {0x38, 0xff, 0xf5, 0x39, 0x89, 0x3a, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x0b00, 1, {0x22} }, +{ 0x0b01, 16, {0x8f, 0x35, 0x05, 0x28, 0xe5, 0x28, 0xae, 0x27, 0x70, 0x02, 0x05, 0x27, 0x14, 0xf5, 0x82, 0x8e} }, +{ 0x0b11, 16, {0x83, 0xe5, 0x35, 0xf0, 0x12, 0x00, 0x36, 0x05, 0x28, 0xe5, 0x28, 0xac, 0x27, 0x70, 0x02, 0x05} }, +{ 0x0b21, 16, {0x27, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x15, 0x23, 0xe5, 0x23, 0x60, 0x0a, 0x12, 0x0e} }, +{ 0x0b31, 9, {0x2b, 0x8f, 0x35, 0xef, 0x42, 0x11, 0x80, 0xca, 0x22} }, +{ 0x0b3a, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x30} }, +{ 0x0b4a, 16, {0x14, 0x04, 0xc2, 0x14, 0x80, 0x02, 0xd2, 0x08, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} }, +{ 0x0b5a, 14, {0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0b68, 16, {0x90, 0x7f, 0xd8, 0xe0, 0xf5, 0x33, 0x12, 0x00, 0x03, 0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0} }, +{ 0x0b78, 16, {0x12, 0x09, 0x50, 0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0x0e, 0x30, 0x01, 0x05, 0x12, 0x0d, 0xcf} }, +{ 0x0b88, 11, {0x80, 0x06, 0x12, 0x0d, 0x5c, 0xef, 0x60, 0xe1, 0x12, 0x07, 0x28} }, +{ 0x0b93, 1, {0x22} }, +{ 0x0b94, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x90} }, +{ 0x0ba4, 16, {0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x04, 0xf0, 0xd0, 0x86, 0xd0} }, +{ 0x0bb4, 10, {0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0bbe, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xd2} }, +{ 0x0bce, 16, {0x02, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85} }, +{ 0x0bde, 7, {0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0be5, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x0bf5, 16, {0x10, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x18, 0x54} }, +{ 0x0c05, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x0c0b, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x0c1b, 16, {0x11, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x18, 0x54} }, +{ 0x0c2b, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x0c31, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x0c41, 16, {0x12, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x18, 0x54} }, +{ 0x0c51, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x0c57, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x0c67, 16, {0x14, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x18, 0x54} }, +{ 0x0c77, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x0c7d, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x0c8d, 16, {0x16, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x18, 0x54} }, +{ 0x0c9d, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x0ca3, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x18, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7f} }, +{ 0x0cb3, 16, {0x98, 0x74, 0x17, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x15, 0xf0, 0x90} }, +{ 0x0cc3, 5, {0xc0, 0x00, 0xed, 0xf0, 0x22} }, +{ 0x0cc8, 16, {0x12, 0x0e, 0x13, 0x8f, 0x35, 0x12, 0x0e, 0x13, 0x8f, 0x36, 0xe5, 0x35, 0x65, 0x36, 0x60, 0x12} }, +{ 0x0cd8, 16, {0x12, 0x0e, 0x13, 0x8f, 0x35, 0xe5, 0x35, 0x65, 0x36, 0x60, 0x07, 0x12, 0x0e, 0x13, 0x8f, 0x36} }, +{ 0x0ce8, 4, {0x80, 0xe8, 0xaf, 0x35} }, +{ 0x0cec, 1, {0x22} }, +{ 0x0ced, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} }, +{ 0x0cfd, 16, {0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82} }, +{ 0x0d0d, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0d12, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} }, +{ 0x0d22, 16, {0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82} }, +{ 0x0d32, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0d37, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x13, 0x04, 0xe0, 0x44} }, +{ 0x0d47, 16, {0x02, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x0d, 0xb8, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} }, +{ 0x0d57, 5, {0xe0, 0x44, 0x04, 0xf0, 0x22} }, +{ 0x0d5c, 16, {0x90, 0x7f, 0xd8, 0xe0, 0xf5, 0x34, 0x12, 0x07, 0x28, 0x12, 0x0e, 0x37, 0xef, 0x30, 0xe6, 0x0b} }, +{ 0x0d6c, 16, {0x90, 0x7f, 0xd8, 0xe0, 0x65, 0x34, 0x60, 0xf1, 0x7f, 0x01, 0x22, 0x12, 0x00, 0x03, 0x7f, 0x00} }, +{ 0x0d7c, 1, {0x22} }, +{ 0x0d7d, 16, {0xae, 0x07, 0xe4, 0xff, 0xe5, 0x15, 0x54, 0x7f, 0xfd, 0x12, 0x0c, 0xa3, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x0d8d, 16, {0x11, 0xf0, 0x90, 0xc0, 0x00, 0xee, 0xf0, 0xe4, 0xe5, 0x15, 0x44, 0x80, 0xfd, 0x12, 0x0c, 0xa3} }, +{ 0x0d9d, 1, {0x22} }, +{ 0x0d9e, 16, {0x05, 0x29, 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x2f, 0x03, 0x00, 0x00, 0xc1, 0x02, 0xc1, 0x08} }, +{ 0x0dae, 7, {0xc1, 0x01, 0xc1, 0x86, 0x01, 0x25, 0x00} }, +{ 0x0db5, 2, {0xc1, 0x94} }, +{ 0x0db7, 1, {0x00} }, +{ 0x0db8, 16, {0x8e, 0x34, 0x8f, 0x35, 0xe5, 0x35, 0x15, 0x35, 0xae, 0x34, 0x70, 0x02, 0x15, 0x34, 0x4e, 0x60} }, +{ 0x0dc8, 7, {0x05, 0x12, 0x09, 0x3f, 0x80, 0xee, 0x22} }, +{ 0x0dcf, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x0d, 0x7e, 0x00, 0x12, 0x0d, 0xb8, 0x90, 0x7f} }, +{ 0x0ddf, 6, {0xd6, 0xe0, 0x54, 0xfe, 0xf0, 0x22} }, +{ 0x0de5, 12, {0x90, 0x7f, 0x98, 0x74, 0x11, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x0df1, 12, {0x90, 0x7f, 0x98, 0x74, 0x12, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x0dfd, 3, {0xd2, 0x01, 0x22} }, +{ 0x0e00, 16, {0x02, 0x0b, 0xbe, 0x00, 0x02, 0x0c, 0xed, 0x00, 0x02, 0x0b, 0x94, 0x00, 0x02, 0x0b, 0x3a, 0x00} }, +{ 0x0e10, 3, {0x02, 0x0d, 0x12} }, +{ 0x0e13, 12, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x0e1f, 12, {0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x0e2b, 12, {0x90, 0x7f, 0x98, 0x74, 0x15, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x0e37, 12, {0x90, 0x7f, 0x98, 0x74, 0x16, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x0e43, 4, {0x53, 0xd8, 0xef, 0x32} }, +{ 0x0e47, 3, {0xc2, 0x01, 0x22} }, +{ 0x1900, 16, {0x12, 0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x40, 0xcd, 0x06, 0x08, 0x01, 0x00, 0x00, 0x01, 0x02} }, +{ 0x1910, 16, {0x00, 0x01, 0x09, 0x02, 0x74, 0x00, 0x01, 0x01, 0x00, 0xa0, 0x32, 0x09, 0x04, 0x00, 0x00, 0x0e} }, +{ 0x1920, 16, {0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} }, +{ 0x1930, 16, {0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, 0x00} }, +{ 0x1940, 16, {0x07, 0x05, 0x05, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x06, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05} }, +{ 0x1950, 16, {0x07, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x82, 0x02} }, +{ 0x1960, 16, {0x40, 0x00, 0x00, 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00} }, +{ 0x1970, 16, {0x00, 0x07, 0x05, 0x85, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x86, 0x02, 0x40, 0x00, 0x00, 0x07} }, +{ 0x1980, 16, {0x05, 0x87, 0x02, 0x40, 0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x48, 0x03, 0x4b, 0x00, 0x65, 0x00} }, +{ 0x1990, 16, {0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00} }, +{ 0x19a0, 16, {0x20, 0x00, 0x64, 0x00, 0x69, 0x00, 0x76, 0x00, 0x69, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00} }, +{ 0x19b0, 16, {0x6e, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x6e, 0x00} }, +{ 0x19c0, 16, {0x6f, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00} }, +{ 0x19d0, 16, {0x2e, 0x00, 0x36, 0x03, 0x4b, 0x00, 0x65, 0x00, 0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00} }, +{ 0x19e0, 16, {0x6e, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53, 0x00, 0x42, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00} }, +{ 0x19f0, 16, {0x72, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x41, 0x00, 0x64, 0x00, 0x61, 0x00} }, +{ 0x1a00, 10, {0x70, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00} }, +{ 0xffff, 0, {0x00} } +}; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/serial/keyspan_usa26msg.h linux/drivers/usb/serial/keyspan_usa26msg.h --- v2.4.0-test2/linux/drivers/usb/serial/keyspan_usa26msg.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/keyspan_usa26msg.h Mon Jul 10 14:33:04 2000 @@ -0,0 +1,248 @@ +/* + usa26msg.h + + Copyright (c) 1998-2000 InnoSys Incorporated. All Rights Reserved + This file is available under a BSD-style copyright + + Keyspan USB Async Firmware to run on Anchor EZ-USB + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain this licence text + without modification, this list of conditions, and the following + disclaimer. The following copyright notice must appear immediately at + the beginning of all source files: + + Copyright (c) 1998-2000 InnoSys Incorporated. All Rights Reserved + + This file is available under a BSD-style copyright + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of InnoSys Incorprated may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY INNOSYS CORP. ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + Third revision: USA28X version (aka USA26) + + Buffer formats for RX/TX data messages are not defined by + a structure, but are described here: + + USB OUT (host -> USA26, transmit) messages contain a + REQUEST_ACK indicator (set to 0xff to request an ACK at the + completion of transmit; 0x00 otherwise), followed by data: + + RQSTACK DAT DAT DAT ... + + with a total data length of 63. + + USB IN (USA26 -> host, receive) messages contain either a zero + flag (indicating no error in any data bytes): + + 00 DAT DAT DAT ... + + for a total of 63 data bytes, or a non-zero status flag (indicating + that all data bytes will be preceded by status flag): + + STAT DAT STAT DAT STAT DAT ... + + for a total of 32 data bytes. The valid bits in the STAT bytes are: + + OVERRUN 0x02 + PARITY 0x04 + FRAMING 0x08 + BREAK 0x10 + + Note: a "no status" RX data message (first byte zero) can serve as + a "break off" indicator. + + revision history: + + 1999feb10 add reportHskiaChanges to allow us to ignore them + 1999feb10 add txAckThreshold for fast+loose throughput enhancement + 1999mar30 beef up support for RX error reporting + 1999apr14 add resetDataToggle to control message + 2000jan04 merge with usa17msg.h + 2000jun01 add extended BSD-style copyright text + + Note on shared names: + + In the case of fields which have been merged between the USA17 + and USA26 definitions, the USA26 definition is the first part + of the name and the USA17 definition is the second part of the + name; both meanings are described below. +*/ + +#ifndef __USA26MSG__ +#define __USA26MSG__ + +#ifndef __stubs__ +#include "datadefs.h" +#endif + +typedef struct txAckMessage +{ + u8 dummy; +} txAckMessage; + +typedef struct portControlMessage +{ + /* + there are three types of "commands" sent in the control message: + + 1. configuration changes which must be requested by setting + the corresponding "set" flag (and should only be requested + when necessary, to reduce overhead on the USA26): + */ + u8 setClocking, // BOTH: host requests baud rate be set + baudLo, // BOTH: host does baud divisor calculation + baudHi, // BOTH: baudHi is only used for first port (gives lower rates) + externalClock_txClocking, + // USA26: 0=internal, other=external + // USA17: 0=internal, other=external/RI + rxClocking, // USA17: 0=internal, 1=external/RI, other=external/DSR + + + setLcr, // BOTH: host requests lcr be set + lcr, // BOTH: use PARITY, STOPBITS, DATABITS below + + setFlowControl, // BOTH: host requests flow control be set + ctsFlowControl, // BOTH: 1=use CTS flow control, 0=don't + xonFlowControl, // BOTH: 1=use XON/XOFF flow control, 0=don't + xonChar, // BOTH: specified in current character format + xoffChar, // BOTH: specified in current character format + + setTxTriState_setRts, + // USA26: host requests TX tri-state be set + // USA17: host requests RTS output be set + txTriState_rts, // BOTH: 1=active (normal), 0=tristate (off) + + setHskoa_setDtr, + // USA26: host requests HSKOA output be set + // USA17: host requests DTR output be set + hskoa_dtr, // BOTH: 1=on, 0=off + + setPrescaler, // USA26: host requests prescalar be set (default: 13) + prescaler; // BOTH: specified as N/8; values 8-ff are valid + // must be set any time internal baud rate is set; + // must not be set when external clocking is used + // note: in USA17, prescaler is applied whenever + // setClocking is requested + + /* + 3. configuration data which is simply used as is (no overhead, + but must be specified correctly in every host message). + */ + u8 forwardingLength, // BOTH: forward when this number of chars available + reportHskiaChanges_dsrFlowControl, + // USA26: 1=normal; 0=ignore external clock + // USA17: 1=use DSR flow control, 0=don't + txAckThreshold, // BOTH: 0=not allowed, 1=normal, 2-255 deliver ACK faster + loopbackMode; // BOTH: 0=no loopback, 1=loopback enabled + + /* + 4. commands which are flags only; these are processed in order + (so that, e.g., if both _txOn and _txOff flags are set, the + port ends in a TX_OFF state); any non-zero value is respected + */ + u8 _txOn, // BOTH: enable transmitting (and continue if there's data) + _txOff, // BOTH: stop transmitting + txFlush, // BOTH: toss outbound data + txBreak, // BOTH: turn on break (cleared by _txOn) + rxOn, // BOTH: turn on receiver + rxOff, // BOTH: turn off receiver + rxFlush, // BOTH: toss inbound data + rxForward, // BOTH: forward all inbound data, NOW (as if fwdLen==1) + returnStatus, // BOTH: return current status (even if it hasn't changed) + resetDataToggle;// BOTH: reset data toggle state to DATA0 + +} portControlMessage; + +// defines for bits in lcr +#define USA_DATABITS_5 0x00 +#define USA_DATABITS_6 0x01 +#define USA_DATABITS_7 0x02 +#define USA_DATABITS_8 0x03 +#define STOPBITS_5678_1 0x00 // 1 stop bit for all byte sizes +#define STOPBITS_5_1p5 0x04 // 1.5 stop bits for 5-bit byte +#define STOPBITS_678_2 0x04 // 2 stop bits for 6/7/8-bit byte +#define USA_PARITY_NONE 0x00 +#define USA_PARITY_ODD 0x08 +#define USA_PARITY_EVEN 0x18 +#define PARITY_1 0x28 +#define PARITY_0 0x38 + +// all things called "StatusMessage" are sent on the status endpoint + +typedef struct portStatusMessage // one for each port +{ + u8 port, // BOTH: 0=first, 1=second, other=see below + hskia_cts, // USA26: reports HSKIA pin + // USA17: reports CTS pin + gpia_dcd, // USA26: reports GPIA pin + // USA17: reports DCD pin + dsr, // USA17: reports DSR pin + ri, // USA17: reports RI pin + _txOff, // port has been disabled (by host) + _txXoff, // port is in XOFF state (either host or RX XOFF) + rxEnabled, // as configured by rxOn/rxOff 1=on, 0=off + controlResponse;// 1=a control message has been processed +} portStatusMessage; + +// bits in RX data message when STAT byte is included +#define RXERROR_OVERRUN 0x02 +#define RXERROR_PARITY 0x04 +#define RXERROR_FRAMING 0x08 +#define RXERROR_BREAK 0x10 + +typedef struct globalControlMessage +{ + u8 sendGlobalStatus, // 2=request for two status responses + resetStatusToggle, // 1=reset global status toggle + resetStatusCount; // a cycling value +} globalControlMessage; + +typedef struct globalStatusMessage +{ + u8 port, // 3 + sendGlobalStatus, // from request, decremented + resetStatusCount; // as in request +} globalStatusMessage; + +typedef struct globalDebugMessage +{ + u8 port, // 2 + a, + b, + c, + d; +} globalDebugMessage; + +// ie: the maximum length of an EZUSB endpoint buffer +#define MAX_DATA_LEN 64 + +// update status approx. 60 times a second (16.6666 ms) +#define STATUS_UPDATE_INTERVAL 16 + +// status rationing tuning value (each port gets checked each n ms) +#define STATUS_RATION 10 + +#endif + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/serial/keyspan_usa28_fw.h linux/drivers/usb/serial/keyspan_usa28_fw.h --- v2.4.0-test2/linux/drivers/usb/serial/keyspan_usa28_fw.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/keyspan_usa28_fw.h Mon Jul 10 14:33:04 2000 @@ -0,0 +1,462 @@ +/* keyspan_usa28_fw.h + + Generated from Keyspan firmware image Wed Jul 5 09:18:29 2000 EST + This firmware is for the Keyspan USA-28 Serial Adaptor + + "The firmware contained herein as keyspan_usa28_fw.h is + Copyright (C) 1999-2000 Keyspan, A division of InnoSys Incorporated + ("Keyspan"), as an unpublished work. This notice does not imply + unrestricted or public access to this firmware which is a trade secret of + Keyspan, and which may not be reproduced, used, sold or transferred to any + third party without Keyspan's prior written consent. All Rights Reserved. + + This firmware may not be modified and may only be used with the Keyspan + USA-28 Serial Adapter. Distribution and/or Modification of the + keyspan.c driver which includes this firmware, in whole or in part, + requires the inclusion of this statement." + +*/ + +static const struct ezusb_hex_record keyspan_usa28_firmware[] = { +{ 0x0000, 3, {0x02, 0x15, 0xc5} }, +{ 0x0003, 3, {0x02, 0x00, 0x46} }, +{ 0x0006, 16, {0x8e, 0x12, 0x8f, 0x13, 0xe5, 0x13, 0x15, 0x13, 0xae, 0x12, 0x70, 0x02, 0x15, 0x12, 0x4e, 0x60} }, +{ 0x0016, 7, {0x05, 0x12, 0x18, 0x7d, 0x80, 0xee, 0x22} }, +{ 0x001d, 4, {0x53, 0xd8, 0xef, 0x32} }, +{ 0x0023, 3, {0x02, 0x00, 0x46} }, +{ 0x0026, 10, {0x12, 0x17, 0x91, 0x12, 0x18, 0x8e, 0x12, 0x14, 0x47, 0x22} }, +{ 0x0033, 3, {0x02, 0x00, 0x1d} }, +{ 0x003b, 3, {0x02, 0x00, 0x46} }, +{ 0x0043, 3, {0x02, 0x1b, 0x00} }, +{ 0x0046, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0, 0xd0, 0x75, 0xd0, 0x08} }, +{ 0x0056, 16, {0x30, 0x99, 0x0e, 0x30, 0x0e, 0x07, 0xa2, 0x14, 0x92, 0x9b, 0x85, 0x46, 0x99, 0xc2, 0x99, 0xd2} }, +{ 0x0066, 16, {0x1c, 0x30, 0xc1, 0x0e, 0x30, 0x0f, 0x07, 0xa2, 0x15, 0x92, 0xc3, 0x85, 0x47, 0xc1, 0xc2, 0xc1} }, +{ 0x0076, 16, {0xd2, 0x1d, 0x20, 0x1c, 0x03, 0x02, 0x04, 0x36, 0xc2, 0x1c, 0x20, 0x02, 0x03, 0x02, 0x02, 0x61} }, +{ 0x0086, 16, {0x20, 0x0e, 0x03, 0x02, 0x01, 0x38, 0xe5, 0x4a, 0xc3, 0x95, 0x7c, 0x50, 0x3e, 0x20, 0x10, 0x36} }, +{ 0x0096, 16, {0x20, 0x08, 0x33, 0x90, 0x7f, 0x9b, 0xe0, 0x20, 0xe3, 0x03, 0x20, 0x19, 0x29, 0x30, 0x18, 0x12} }, +{ 0x00a6, 16, {0xae, 0x4a, 0x05, 0x4a, 0x74, 0x40, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0x13} }, +{ 0x00b6, 16, {0x92, 0x14, 0xae, 0x4a, 0x05, 0x4a, 0x74, 0x40, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83} }, +{ 0x00c6, 16, {0xe0, 0xf5, 0x46, 0x02, 0x04, 0x34, 0xc2, 0x0e, 0x02, 0x04, 0x34, 0x90, 0x7f, 0xc7, 0xe4, 0xf0} }, +{ 0x00d6, 16, {0xc2, 0x02, 0x30, 0x12, 0x0c, 0xc2, 0x12, 0x90, 0x7f, 0xbf, 0x04, 0xf0, 0xc2, 0x0e, 0x02, 0x04} }, +{ 0x00e6, 16, {0x34, 0x90, 0x7f, 0xc8, 0xe0, 0x30, 0xe1, 0x05, 0xc2, 0x0e, 0x02, 0x04, 0x34, 0x90, 0x7f, 0xc9} }, +{ 0x00f6, 16, {0xe0, 0xf5, 0x7c, 0x90, 0x7d, 0xc0, 0xe0, 0x13, 0x92, 0x12, 0x20, 0x10, 0x2d, 0x20, 0x08, 0x2a} }, +{ 0x0106, 16, {0x90, 0x7f, 0x9b, 0xe0, 0x20, 0xe3, 0x03, 0x20, 0x19, 0x20, 0x30, 0x18, 0x11, 0x90, 0x7d, 0xc1} }, +{ 0x0116, 16, {0xe0, 0x13, 0x92, 0x14, 0xa3, 0xe0, 0xf5, 0x46, 0x75, 0x4a, 0x03, 0x02, 0x04, 0x34, 0x75, 0x4a} }, +{ 0x0126, 16, {0x02, 0x90, 0x7d, 0xc1, 0xe0, 0xf5, 0x46, 0x02, 0x04, 0x34, 0x75, 0x4a, 0x01, 0xc2, 0x0e, 0x02} }, +{ 0x0136, 16, {0x04, 0x34, 0xe5, 0x4a, 0xc3, 0x95, 0x7c, 0x50, 0x03, 0x02, 0x01, 0xda, 0x90, 0x7f, 0xc6, 0xe0} }, +{ 0x0146, 16, {0x30, 0xe1, 0x07, 0xc2, 0x20, 0xd2, 0x1e, 0x02, 0x04, 0x34, 0x90, 0x7f, 0xc7, 0xe0, 0xf5, 0x7c} }, +{ 0x0156, 16, {0x90, 0x7e, 0x40, 0xe0, 0x13, 0x92, 0x12, 0x20, 0x10, 0x72, 0x20, 0x08, 0x6f, 0x90, 0x7f, 0x9b} }, +{ 0x0166, 16, {0xe0, 0x20, 0xe3, 0x03, 0x20, 0x19, 0x65, 0x30, 0x18, 0x10, 0x90, 0x7e, 0x41, 0xe0, 0x13, 0x92} }, +{ 0x0176, 16, {0x9b, 0xa3, 0xe0, 0xf5, 0x99, 0x75, 0x4a, 0x03, 0x80, 0x09, 0x90, 0x7e, 0x41, 0xe0, 0xf5, 0x99} }, +{ 0x0186, 16, {0x75, 0x4a, 0x02, 0xe5, 0x4a, 0xc3, 0x95, 0x7c, 0x40, 0x17, 0x90, 0x7f, 0xc7, 0xe4, 0xf0, 0xc2} }, +{ 0x0196, 16, {0x02, 0x20, 0x12, 0x03, 0x02, 0x04, 0x34, 0xc2, 0x12, 0x90, 0x7f, 0xbf, 0x04, 0xf0, 0x02, 0x04} }, +{ 0x01a6, 16, {0x34, 0x30, 0x18, 0x12, 0xae, 0x4a, 0x05, 0x4a, 0x74, 0x40, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7e} }, +{ 0x01b6, 16, {0xf5, 0x83, 0xe0, 0x13, 0x92, 0x14, 0xae, 0x4a, 0x05, 0x4a, 0x74, 0x40, 0x2e, 0xf5, 0x82, 0xe4} }, +{ 0x01c6, 16, {0x34, 0x7e, 0xf5, 0x83, 0xe0, 0xf5, 0x46, 0xd2, 0x0e, 0x02, 0x04, 0x34, 0x75, 0x4a, 0x01, 0xc2} }, +{ 0x01d6, 16, {0x20, 0x02, 0x04, 0x34, 0x30, 0x10, 0x03, 0x02, 0x02, 0x5c, 0x20, 0x08, 0x79, 0x90, 0x7f, 0x9b} }, +{ 0x01e6, 16, {0xe0, 0x20, 0xe3, 0x03, 0x20, 0x19, 0x6f, 0x30, 0x18, 0x12, 0xae, 0x4a, 0x05, 0x4a, 0x74, 0x40} }, +{ 0x01f6, 16, {0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x9b, 0xae, 0x4a, 0x05, 0x4a} }, +{ 0x0206, 16, {0x74, 0x40, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0xf5, 0x99, 0xe5, 0x4a, 0xc3} }, +{ 0x0216, 16, {0x95, 0x7c, 0x40, 0x17, 0x90, 0x7f, 0xc7, 0xe4, 0xf0, 0xc2, 0x02, 0x20, 0x12, 0x03, 0x02, 0x04} }, +{ 0x0226, 16, {0x34, 0xc2, 0x12, 0x90, 0x7f, 0xbf, 0x04, 0xf0, 0x02, 0x04, 0x34, 0x30, 0x18, 0x12, 0xae, 0x4a} }, +{ 0x0236, 16, {0x05, 0x4a, 0x74, 0x40, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x14} }, +{ 0x0246, 16, {0xae, 0x4a, 0x05, 0x4a, 0x74, 0x40, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0xf5} }, +{ 0x0256, 16, {0x46, 0xd2, 0x0e, 0x02, 0x04, 0x34, 0xc2, 0x20, 0x02, 0x04, 0x34, 0x20, 0x0e, 0x03, 0x02, 0x03} }, +{ 0x0266, 16, {0x13, 0xe5, 0x4a, 0xc3, 0x95, 0x7c, 0x50, 0x3e, 0x20, 0x10, 0x36, 0x20, 0x08, 0x33, 0x90, 0x7f} }, +{ 0x0276, 16, {0x9b, 0xe0, 0x20, 0xe3, 0x03, 0x20, 0x19, 0x29, 0x30, 0x18, 0x12, 0xae, 0x4a, 0x05, 0x4a, 0x74} }, +{ 0x0286, 16, {0xc0, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x14, 0xae, 0x4a, 0x05} }, +{ 0x0296, 16, {0x4a, 0x74, 0xc0, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xf5, 0x46, 0x02, 0x04} }, +{ 0x02a6, 16, {0x34, 0xc2, 0x0e, 0x02, 0x04, 0x34, 0x90, 0x7f, 0xc9, 0xe4, 0xf0, 0xd2, 0x02, 0x30, 0x12, 0x0c} }, +{ 0x02b6, 16, {0xc2, 0x12, 0x90, 0x7f, 0xbf, 0x04, 0xf0, 0xc2, 0x0e, 0x02, 0x04, 0x34, 0x90, 0x7f, 0xc6, 0xe0} }, +{ 0x02c6, 16, {0x30, 0xe1, 0x05, 0xc2, 0x0e, 0x02, 0x04, 0x34, 0x90, 0x7f, 0xc7, 0xe0, 0xf5, 0x7c, 0x90, 0x7e} }, +{ 0x02d6, 16, {0x40, 0xe0, 0x13, 0x92, 0x12, 0x20, 0x10, 0x2d, 0x20, 0x08, 0x2a, 0x90, 0x7f, 0x9b, 0xe0, 0x20} }, +{ 0x02e6, 16, {0xe3, 0x03, 0x20, 0x19, 0x20, 0x30, 0x18, 0x11, 0x90, 0x7e, 0x41, 0xe0, 0x13, 0x92, 0x14, 0xa3} }, +{ 0x02f6, 16, {0xe0, 0xf5, 0x46, 0x75, 0x4a, 0x03, 0x02, 0x04, 0x34, 0x75, 0x4a, 0x02, 0x90, 0x7e, 0x41, 0xe0} }, +{ 0x0306, 16, {0xf5, 0x46, 0x02, 0x04, 0x34, 0x75, 0x4a, 0x01, 0xc2, 0x0e, 0x02, 0x04, 0x34, 0xe5, 0x4a, 0xc3} }, +{ 0x0316, 16, {0x95, 0x7c, 0x50, 0x03, 0x02, 0x03, 0xb5, 0x90, 0x7f, 0xc8, 0xe0, 0x30, 0xe1, 0x07, 0xc2, 0x20} }, +{ 0x0326, 16, {0xd2, 0x1e, 0x02, 0x04, 0x34, 0x90, 0x7f, 0xc9, 0xe0, 0xf5, 0x7c, 0x90, 0x7d, 0xc0, 0xe0, 0x13} }, +{ 0x0336, 16, {0x92, 0x12, 0x20, 0x10, 0x72, 0x20, 0x08, 0x6f, 0x90, 0x7f, 0x9b, 0xe0, 0x20, 0xe3, 0x03, 0x20} }, +{ 0x0346, 16, {0x19, 0x65, 0x30, 0x18, 0x10, 0x90, 0x7d, 0xc1, 0xe0, 0x13, 0x92, 0x9b, 0xa3, 0xe0, 0xf5, 0x99} }, +{ 0x0356, 16, {0x75, 0x4a, 0x03, 0x80, 0x09, 0x90, 0x7d, 0xc1, 0xe0, 0xf5, 0x99, 0x75, 0x4a, 0x02, 0xe5, 0x4a} }, +{ 0x0366, 16, {0xc3, 0x95, 0x7c, 0x40, 0x17, 0x90, 0x7f, 0xc9, 0xe4, 0xf0, 0xd2, 0x02, 0x20, 0x12, 0x03, 0x02} }, +{ 0x0376, 16, {0x04, 0x34, 0xc2, 0x12, 0x90, 0x7f, 0xbf, 0x04, 0xf0, 0x02, 0x04, 0x34, 0x30, 0x18, 0x12, 0xae} }, +{ 0x0386, 16, {0x4a, 0x05, 0x4a, 0x74, 0xc0, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0x13, 0x92} }, +{ 0x0396, 16, {0x14, 0xae, 0x4a, 0x05, 0x4a, 0x74, 0xc0, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0} }, +{ 0x03a6, 16, {0xf5, 0x46, 0xd2, 0x0e, 0x02, 0x04, 0x34, 0x75, 0x4a, 0x01, 0xc2, 0x20, 0x02, 0x04, 0x34, 0x30} }, +{ 0x03b6, 16, {0x10, 0x03, 0x02, 0x04, 0x32, 0x20, 0x08, 0x74, 0x90, 0x7f, 0x9b, 0xe0, 0x20, 0xe3, 0x03, 0x20} }, +{ 0x03c6, 16, {0x19, 0x6a, 0x30, 0x18, 0x12, 0xae, 0x4a, 0x05, 0x4a, 0x74, 0xc0, 0x2e, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x03d6, 16, {0x7d, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x9b, 0xae, 0x4a, 0x05, 0x4a, 0x74, 0xc0, 0x2e, 0xf5, 0x82} }, +{ 0x03e6, 16, {0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xf5, 0x99, 0xe5, 0x4a, 0xc3, 0x95, 0x7c, 0x40, 0x13, 0x90} }, +{ 0x03f6, 16, {0x7f, 0xc9, 0xe4, 0xf0, 0xd2, 0x02, 0x30, 0x12, 0x35, 0xc2, 0x12, 0x90, 0x7f, 0xbf, 0x04, 0xf0} }, +{ 0x0406, 16, {0x80, 0x2c, 0x30, 0x18, 0x12, 0xae, 0x4a, 0x05, 0x4a, 0x74, 0xc0, 0x2e, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x0416, 16, {0x7d, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x14, 0xae, 0x4a, 0x05, 0x4a, 0x74, 0xc0, 0x2e, 0xf5, 0x82} }, +{ 0x0426, 16, {0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xf5, 0x46, 0xd2, 0x0e, 0x80, 0x02, 0xc2, 0x20, 0xd2, 0x24} }, +{ 0x0436, 16, {0x20, 0x1d, 0x03, 0x02, 0x07, 0xf4, 0xc2, 0x1d, 0x20, 0x03, 0x03, 0x02, 0x06, 0x1f, 0x20, 0x0f} }, +{ 0x0446, 16, {0x03, 0x02, 0x04, 0xf6, 0xe5, 0x4b, 0xc3, 0x95, 0x7d, 0x50, 0x3e, 0x20, 0x11, 0x36, 0x20, 0x0a} }, +{ 0x0456, 16, {0x33, 0x90, 0x7f, 0x9a, 0xe0, 0x20, 0xe5, 0x03, 0x20, 0x1b, 0x29, 0x30, 0x1a, 0x12, 0xae, 0x4b} }, +{ 0x0466, 16, {0x05, 0x4b, 0x74, 0x40, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x15} }, +{ 0x0476, 16, {0xae, 0x4b, 0x05, 0x4b, 0x74, 0x40, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xf5} }, +{ 0x0486, 16, {0x47, 0x02, 0x07, 0xf2, 0xc2, 0x0f, 0x02, 0x07, 0xf2, 0x90, 0x7f, 0xcb, 0xe4, 0xf0, 0xc2, 0x03} }, +{ 0x0496, 16, {0x30, 0x13, 0x0c, 0xc2, 0x13, 0x90, 0x7f, 0xc1, 0x04, 0xf0, 0xc2, 0x0f, 0x02, 0x07, 0xf2, 0x90} }, +{ 0x04a6, 16, {0x7f, 0xcc, 0xe0, 0x30, 0xe1, 0x05, 0xc2, 0x0f, 0x02, 0x07, 0xf2, 0x90, 0x7f, 0xcd, 0xe0, 0xf5} }, +{ 0x04b6, 16, {0x7d, 0x90, 0x7c, 0xc0, 0xe0, 0x13, 0x92, 0x13, 0x20, 0x11, 0x2d, 0x20, 0x0a, 0x2a, 0x90, 0x7f} }, +{ 0x04c6, 16, {0x9a, 0xe0, 0x20, 0xe5, 0x03, 0x20, 0x1b, 0x20, 0x30, 0x1a, 0x11, 0x90, 0x7c, 0xc1, 0xe0, 0x13} }, +{ 0x04d6, 16, {0x92, 0x15, 0xa3, 0xe0, 0xf5, 0x47, 0x75, 0x4b, 0x03, 0x02, 0x07, 0xf2, 0x75, 0x4b, 0x02, 0x90} }, +{ 0x04e6, 16, {0x7c, 0xc1, 0xe0, 0xf5, 0x47, 0x02, 0x07, 0xf2, 0x75, 0x4b, 0x01, 0xc2, 0x0f, 0x02, 0x07, 0xf2} }, +{ 0x04f6, 16, {0xe5, 0x4b, 0xc3, 0x95, 0x7d, 0x50, 0x03, 0x02, 0x05, 0x98, 0x90, 0x7f, 0xca, 0xe0, 0x30, 0xe1} }, +{ 0x0506, 16, {0x07, 0xc2, 0x21, 0xd2, 0x1f, 0x02, 0x07, 0xf2, 0x90, 0x7f, 0xcb, 0xe0, 0xf5, 0x7d, 0x90, 0x7d} }, +{ 0x0516, 16, {0x40, 0xe0, 0x13, 0x92, 0x13, 0x20, 0x11, 0x72, 0x20, 0x0a, 0x6f, 0x90, 0x7f, 0x9a, 0xe0, 0x20} }, +{ 0x0526, 16, {0xe5, 0x03, 0x20, 0x1b, 0x65, 0x30, 0x1a, 0x10, 0x90, 0x7d, 0x41, 0xe0, 0x13, 0x92, 0xc3, 0xa3} }, +{ 0x0536, 16, {0xe0, 0xf5, 0xc1, 0x75, 0x4b, 0x03, 0x80, 0x09, 0x90, 0x7d, 0x41, 0xe0, 0xf5, 0xc1, 0x75, 0x4b} }, +{ 0x0546, 16, {0x02, 0xe5, 0x4b, 0xc3, 0x95, 0x7d, 0x40, 0x17, 0x90, 0x7f, 0xcb, 0xe4, 0xf0, 0xc2, 0x03, 0x20} }, +{ 0x0556, 16, {0x13, 0x03, 0x02, 0x07, 0xf2, 0xc2, 0x13, 0x90, 0x7f, 0xc1, 0x04, 0xf0, 0x02, 0x07, 0xf2, 0x30} }, +{ 0x0566, 16, {0x1a, 0x12, 0xae, 0x4b, 0x05, 0x4b, 0x74, 0x40, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83} }, +{ 0x0576, 16, {0xe0, 0x13, 0x92, 0x15, 0xae, 0x4b, 0x05, 0x4b, 0x74, 0x40, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d} }, +{ 0x0586, 16, {0xf5, 0x83, 0xe0, 0xf5, 0x47, 0xd2, 0x0f, 0x02, 0x07, 0xf2, 0x75, 0x4b, 0x01, 0xc2, 0x21, 0x02} }, +{ 0x0596, 16, {0x07, 0xf2, 0x30, 0x11, 0x03, 0x02, 0x06, 0x1a, 0x20, 0x0a, 0x79, 0x90, 0x7f, 0x9a, 0xe0, 0x20} }, +{ 0x05a6, 16, {0xe5, 0x03, 0x20, 0x1b, 0x6f, 0x30, 0x1a, 0x12, 0xae, 0x4b, 0x05, 0x4b, 0x74, 0x40, 0x2e, 0xf5} }, +{ 0x05b6, 16, {0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0xc3, 0xae, 0x4b, 0x05, 0x4b, 0x74, 0x40} }, +{ 0x05c6, 16, {0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xf5, 0xc1, 0xe5, 0x4b, 0xc3, 0x95, 0x7d} }, +{ 0x05d6, 16, {0x40, 0x17, 0x90, 0x7f, 0xcb, 0xe4, 0xf0, 0xc2, 0x03, 0x20, 0x13, 0x03, 0x02, 0x07, 0xf2, 0xc2} }, +{ 0x05e6, 16, {0x13, 0x90, 0x7f, 0xc1, 0x04, 0xf0, 0x02, 0x07, 0xf2, 0x30, 0x1a, 0x12, 0xae, 0x4b, 0x05, 0x4b} }, +{ 0x05f6, 16, {0x74, 0x40, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x15, 0xae, 0x4b} }, +{ 0x0606, 16, {0x05, 0x4b, 0x74, 0x40, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xf5, 0x47, 0xd2} }, +{ 0x0616, 16, {0x0f, 0x02, 0x07, 0xf2, 0xc2, 0x21, 0x02, 0x07, 0xf2, 0x20, 0x0f, 0x03, 0x02, 0x06, 0xd1, 0xe5} }, +{ 0x0626, 16, {0x4b, 0xc3, 0x95, 0x7d, 0x50, 0x3e, 0x20, 0x11, 0x36, 0x20, 0x0a, 0x33, 0x90, 0x7f, 0x9a, 0xe0} }, +{ 0x0636, 16, {0x20, 0xe5, 0x03, 0x20, 0x1b, 0x29, 0x30, 0x1a, 0x12, 0xae, 0x4b, 0x05, 0x4b, 0x74, 0xc0, 0x2e} }, +{ 0x0646, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7c, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x15, 0xae, 0x4b, 0x05, 0x4b, 0x74} }, +{ 0x0656, 16, {0xc0, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7c, 0xf5, 0x83, 0xe0, 0xf5, 0x47, 0x02, 0x07, 0xf2, 0xc2} }, +{ 0x0666, 16, {0x0f, 0x02, 0x07, 0xf2, 0x90, 0x7f, 0xcd, 0xe4, 0xf0, 0xd2, 0x03, 0x30, 0x13, 0x0c, 0xc2, 0x13} }, +{ 0x0676, 16, {0x90, 0x7f, 0xc1, 0x04, 0xf0, 0xc2, 0x0f, 0x02, 0x07, 0xf2, 0x90, 0x7f, 0xca, 0xe0, 0x30, 0xe1} }, +{ 0x0686, 16, {0x05, 0xc2, 0x0f, 0x02, 0x07, 0xf2, 0x90, 0x7f, 0xcb, 0xe0, 0xf5, 0x7d, 0x90, 0x7d, 0x40, 0xe0} }, +{ 0x0696, 16, {0x13, 0x92, 0x13, 0x20, 0x11, 0x2d, 0x20, 0x0a, 0x2a, 0x90, 0x7f, 0x9a, 0xe0, 0x20, 0xe5, 0x03} }, +{ 0x06a6, 16, {0x20, 0x1b, 0x20, 0x30, 0x1a, 0x11, 0x90, 0x7d, 0x41, 0xe0, 0x13, 0x92, 0x15, 0xa3, 0xe0, 0xf5} }, +{ 0x06b6, 16, {0x47, 0x75, 0x4b, 0x03, 0x02, 0x07, 0xf2, 0x75, 0x4b, 0x02, 0x90, 0x7d, 0x41, 0xe0, 0xf5, 0x47} }, +{ 0x06c6, 16, {0x02, 0x07, 0xf2, 0x75, 0x4b, 0x01, 0xc2, 0x0f, 0x02, 0x07, 0xf2, 0xe5, 0x4b, 0xc3, 0x95, 0x7d} }, +{ 0x06d6, 16, {0x50, 0x03, 0x02, 0x07, 0x73, 0x90, 0x7f, 0xcc, 0xe0, 0x30, 0xe1, 0x07, 0xc2, 0x21, 0xd2, 0x1f} }, +{ 0x06e6, 16, {0x02, 0x07, 0xf2, 0x90, 0x7f, 0xcd, 0xe0, 0xf5, 0x7d, 0x90, 0x7c, 0xc0, 0xe0, 0x13, 0x92, 0x13} }, +{ 0x06f6, 16, {0x20, 0x11, 0x72, 0x20, 0x0a, 0x6f, 0x90, 0x7f, 0x9a, 0xe0, 0x20, 0xe5, 0x03, 0x20, 0x1b, 0x65} }, +{ 0x0706, 16, {0x30, 0x1a, 0x10, 0x90, 0x7c, 0xc1, 0xe0, 0x13, 0x92, 0xc3, 0xa3, 0xe0, 0xf5, 0xc1, 0x75, 0x4b} }, +{ 0x0716, 16, {0x03, 0x80, 0x09, 0x90, 0x7c, 0xc1, 0xe0, 0xf5, 0xc1, 0x75, 0x4b, 0x02, 0xe5, 0x4b, 0xc3, 0x95} }, +{ 0x0726, 16, {0x7d, 0x40, 0x17, 0x90, 0x7f, 0xcd, 0xe4, 0xf0, 0xd2, 0x03, 0x20, 0x13, 0x03, 0x02, 0x07, 0xf2} }, +{ 0x0736, 16, {0xc2, 0x13, 0x90, 0x7f, 0xc1, 0x04, 0xf0, 0x02, 0x07, 0xf2, 0x30, 0x1a, 0x12, 0xae, 0x4b, 0x05} }, +{ 0x0746, 16, {0x4b, 0x74, 0xc0, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7c, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x15, 0xae} }, +{ 0x0756, 16, {0x4b, 0x05, 0x4b, 0x74, 0xc0, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7c, 0xf5, 0x83, 0xe0, 0xf5, 0x47} }, +{ 0x0766, 16, {0xd2, 0x0f, 0x02, 0x07, 0xf2, 0x75, 0x4b, 0x01, 0xc2, 0x21, 0x02, 0x07, 0xf2, 0x30, 0x11, 0x03} }, +{ 0x0776, 16, {0x02, 0x07, 0xf0, 0x20, 0x0a, 0x74, 0x90, 0x7f, 0x9a, 0xe0, 0x20, 0xe5, 0x03, 0x20, 0x1b, 0x6a} }, +{ 0x0786, 16, {0x30, 0x1a, 0x12, 0xae, 0x4b, 0x05, 0x4b, 0x74, 0xc0, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7c, 0xf5} }, +{ 0x0796, 16, {0x83, 0xe0, 0x13, 0x92, 0xc3, 0xae, 0x4b, 0x05, 0x4b, 0x74, 0xc0, 0x2e, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x07a6, 16, {0x7c, 0xf5, 0x83, 0xe0, 0xf5, 0xc1, 0xe5, 0x4b, 0xc3, 0x95, 0x7d, 0x40, 0x13, 0x90, 0x7f, 0xcd} }, +{ 0x07b6, 16, {0xe4, 0xf0, 0xd2, 0x03, 0x30, 0x13, 0x35, 0xc2, 0x13, 0x90, 0x7f, 0xc1, 0x04, 0xf0, 0x80, 0x2c} }, +{ 0x07c6, 16, {0x30, 0x1a, 0x12, 0xae, 0x4b, 0x05, 0x4b, 0x74, 0xc0, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7c, 0xf5} }, +{ 0x07d6, 16, {0x83, 0xe0, 0x13, 0x92, 0x15, 0xae, 0x4b, 0x05, 0x4b, 0x74, 0xc0, 0x2e, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x07e6, 16, {0x7c, 0xf5, 0x83, 0xe0, 0xf5, 0x47, 0xd2, 0x0f, 0x80, 0x02, 0xc2, 0x21, 0xd2, 0x24, 0x20, 0x98} }, +{ 0x07f6, 16, {0x03, 0x02, 0x09, 0x26, 0xc2, 0x98, 0x20, 0x00, 0x03, 0x02, 0x08, 0x98, 0x20, 0x22, 0x27, 0xae} }, +{ 0x0806, 16, {0x48, 0x05, 0x48, 0x74, 0x80, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x99, 0xf0} }, +{ 0x0816, 16, {0x30, 0x18, 0x49, 0xae, 0x48, 0x05, 0x48, 0x74, 0x80, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5} }, +{ 0x0826, 16, {0x83, 0xe5, 0x98, 0xf0, 0x80, 0x36, 0xaf, 0x99, 0xef, 0xb5, 0x58, 0x04, 0xd2, 0x08, 0x80, 0x2c} }, +{ 0x0836, 3, {0xef, 0xb5, 0x57} }, +{ 0x0839, 16, {0x04, 0xc2, 0x08, 0x80, 0x24, 0xae, 0x48, 0x05, 0x48, 0x74, 0x80, 0x2e, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x0849, 16, {0x7e, 0xf5, 0x83, 0xef, 0xf0, 0x30, 0x18, 0x11, 0xae, 0x48, 0x05, 0x48, 0x74, 0x80, 0x2e, 0xf5} }, +{ 0x0859, 16, {0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x98, 0xf0, 0xd2, 0x16, 0xe5, 0x48, 0xc3, 0x95, 0x54} }, +{ 0x0869, 16, {0x50, 0x03, 0x02, 0x09, 0x24, 0x90, 0x7f, 0xb8, 0xe0, 0x30, 0xe1, 0x15, 0xe5, 0x48, 0xc3, 0x94} }, +{ 0x0879, 16, {0x40, 0x50, 0x03, 0x02, 0x09, 0x24, 0x15, 0x48, 0x15, 0x48, 0x05, 0x2d, 0xd2, 0x09, 0x02, 0x09} }, +{ 0x0889, 16, {0x24, 0x90, 0x7f, 0xb7, 0xe5, 0x48, 0xf0, 0x75, 0x48, 0x00, 0xc2, 0x00, 0x02, 0x09, 0x24, 0x20} }, +{ 0x0899, 16, {0x22, 0x27, 0xae, 0x48, 0x05, 0x48, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83} }, +{ 0x08a9, 16, {0xe5, 0x99, 0xf0, 0x30, 0x18, 0x49, 0xae, 0x48, 0x05, 0x48, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4} }, +{ 0x08b9, 16, {0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x98, 0xf0, 0x80, 0x36, 0xaf, 0x99, 0xef, 0xb5, 0x58, 0x04, 0xd2} }, +{ 0x08c9, 16, {0x08, 0x80, 0x2c, 0xef, 0xb5, 0x57, 0x04, 0xc2, 0x08, 0x80, 0x24, 0xae, 0x48, 0x05, 0x48, 0x74} }, +{ 0x08d9, 16, {0x00, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xef, 0xf0, 0x30, 0x18, 0x11, 0xae, 0x48} }, +{ 0x08e9, 16, {0x05, 0x48, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x98, 0xf0, 0xd2} }, +{ 0x08f9, 16, {0x16, 0xe5, 0x48, 0xc3, 0x95, 0x54, 0x40, 0x23, 0x90, 0x7f, 0xb6, 0xe0, 0x30, 0xe1, 0x11, 0xe5} }, +{ 0x0909, 16, {0x48, 0xc3, 0x94, 0x40, 0x40, 0x15, 0x15, 0x48, 0x15, 0x48, 0x05, 0x2d, 0xd2, 0x09, 0x80, 0x0b} }, +{ 0x0919, 16, {0x90, 0x7f, 0xb9, 0xe5, 0x48, 0xf0, 0x75, 0x48, 0x00, 0xd2, 0x00, 0xd2, 0x24, 0x20, 0xc0, 0x03} }, +{ 0x0929, 16, {0x02, 0x0a, 0x58, 0xc2, 0xc0, 0x20, 0x01, 0x03, 0x02, 0x09, 0xca, 0x20, 0x23, 0x27, 0xae, 0x49} }, +{ 0x0939, 16, {0x05, 0x49, 0x74, 0x80, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe5, 0xc1, 0xf0, 0x30} }, +{ 0x0949, 16, {0x1a, 0x49, 0xae, 0x49, 0x05, 0x49, 0x74, 0x80, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83} }, +{ 0x0959, 16, {0xe5, 0xc0, 0xf0, 0x80, 0x36, 0xaf, 0xc1, 0xef, 0xb5, 0x70, 0x04, 0xd2, 0x0a, 0x80, 0x2c, 0xef} }, +{ 0x0969, 16, {0xb5, 0x6f, 0x04, 0xc2, 0x0a, 0x80, 0x24, 0xae, 0x49, 0x05, 0x49, 0x74, 0x80, 0x2e, 0xf5, 0x82} }, +{ 0x0979, 16, {0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xef, 0xf0, 0x30, 0x1a, 0x11, 0xae, 0x49, 0x05, 0x49, 0x74, 0x80} }, +{ 0x0989, 16, {0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe5, 0xc0, 0xf0, 0xd2, 0x17, 0xe5, 0x49, 0xc3} }, +{ 0x0999, 16, {0x95, 0x6c, 0x50, 0x03, 0x02, 0x0a, 0x56, 0x90, 0x7f, 0xbc, 0xe0, 0x30, 0xe1, 0x15, 0xe5, 0x49} }, +{ 0x09a9, 16, {0xc3, 0x94, 0x40, 0x50, 0x03, 0x02, 0x0a, 0x56, 0x15, 0x49, 0x15, 0x49, 0x05, 0x39, 0xd2, 0x0b} }, +{ 0x09b9, 16, {0x02, 0x0a, 0x56, 0x90, 0x7f, 0xbb, 0xe5, 0x49, 0xf0, 0x75, 0x49, 0x00, 0xc2, 0x01, 0x02, 0x0a} }, +{ 0x09c9, 16, {0x56, 0x20, 0x23, 0x27, 0xae, 0x49, 0x05, 0x49, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d} }, +{ 0x09d9, 16, {0xf5, 0x83, 0xe5, 0xc1, 0xf0, 0x30, 0x1a, 0x49, 0xae, 0x49, 0x05, 0x49, 0x74, 0x00, 0x2e, 0xf5} }, +{ 0x09e9, 16, {0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe5, 0xc0, 0xf0, 0x80, 0x36, 0xaf, 0xc1, 0xef, 0xb5, 0x70} }, +{ 0x09f9, 16, {0x04, 0xd2, 0x0a, 0x80, 0x2c, 0xef, 0xb5, 0x6f, 0x04, 0xc2, 0x0a, 0x80, 0x24, 0xae, 0x49, 0x05} }, +{ 0x0a09, 16, {0x49, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xef, 0xf0, 0x30, 0x1a, 0x11} }, +{ 0x0a19, 16, {0xae, 0x49, 0x05, 0x49, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe5, 0xc0} }, +{ 0x0a29, 16, {0xf0, 0xd2, 0x17, 0xe5, 0x49, 0xc3, 0x95, 0x6c, 0x40, 0x23, 0x90, 0x7f, 0xba, 0xe0, 0x30, 0xe1} }, +{ 0x0a39, 16, {0x11, 0xe5, 0x49, 0xc3, 0x94, 0x40, 0x40, 0x15, 0x15, 0x49, 0x15, 0x49, 0x05, 0x39, 0xd2, 0x0b} }, +{ 0x0a49, 16, {0x80, 0x0b, 0x90, 0x7f, 0xbd, 0xe5, 0x49, 0xf0, 0x75, 0x49, 0x00, 0xd2, 0x01, 0xd2, 0x24, 0x30} }, +{ 0x0a59, 7, {0x24, 0x05, 0xc2, 0x24, 0x02, 0x00, 0x56} }, +{ 0x0a60, 11, {0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0a6b, 16, {0x90, 0x7f, 0xce, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x0b, 0x93, 0xe4, 0xf5, 0x12, 0x74, 0x40, 0x25} }, +{ 0x0a7b, 16, {0x12, 0xf5, 0x82, 0xe4, 0x34, 0x7c, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x12, 0x7c, 0x00, 0x7b, 0x00} }, +{ 0x0a8b, 16, {0x24, 0x4c, 0xf9, 0xec, 0x34, 0x00, 0xfa, 0xef, 0x12, 0x15, 0x55, 0x05, 0x12, 0xe5, 0x12, 0xb4} }, +{ 0x0a9b, 16, {0x18, 0xdb, 0xe5, 0x4c, 0x60, 0x0c, 0x75, 0xc9, 0x20, 0x75, 0xc8, 0x36, 0x85, 0x4d, 0xca, 0x85} }, +{ 0x0aab, 16, {0x4e, 0xcb, 0xe5, 0x4f, 0x13, 0x92, 0x18, 0x92, 0x9f, 0xe5, 0x50, 0x13, 0x92, 0x19, 0xe5, 0x51} }, +{ 0x0abb, 16, {0x13, 0x92, 0x22, 0xe5, 0x52, 0x60, 0x09, 0x90, 0x7f, 0x98, 0xe0, 0x54, 0xfb, 0xf0, 0x80, 0x07} }, +{ 0x0acb, 16, {0x90, 0x7f, 0x98, 0xe0, 0x44, 0x04, 0xf0, 0xe5, 0x53, 0x60, 0x09, 0x90, 0x7f, 0x98, 0xe0, 0x54} }, +{ 0x0adb, 16, {0x7f, 0xf0, 0x80, 0x07, 0x90, 0x7f, 0x98, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x59, 0x60, 0x0b, 0xc2} }, +{ 0x0aeb, 16, {0x10, 0xc2, 0x08, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x5a, 0x60, 0x0b, 0xd2, 0x08} }, +{ 0x0afb, 16, {0xd2, 0x09, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x5b, 0x60, 0x17, 0xc2, 0xaf, 0xe4} }, +{ 0x0b0b, 16, {0x90, 0x7f, 0xc7, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0xc2, 0x0e, 0xd2, 0x02, 0xc2, 0x12, 0xf5, 0x7c} }, +{ 0x0b1b, 16, {0xf5, 0x4a, 0xd2, 0xaf, 0xe5, 0x5c, 0x60, 0x05, 0x30, 0x22, 0x02, 0xd2, 0x08, 0xe5, 0x5d, 0x60} }, +{ 0x0b2b, 16, {0x15, 0x90, 0x7f, 0x95, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0x9e, 0xe0, 0x44, 0x02, 0xf0, 0x90} }, +{ 0x0b3b, 16, {0x7f, 0x98, 0xe0, 0x54, 0xfd, 0xf0, 0xe5, 0x5e, 0x60, 0x0a, 0xd2, 0x9c, 0xc2, 0x98, 0x75, 0x2e} }, +{ 0x0b4b, 16, {0x01, 0x75, 0x40, 0x28, 0xe5, 0x5f, 0x60, 0x07, 0xc2, 0x9c, 0xe4, 0xf5, 0x48, 0xf5, 0x2e, 0xe5} }, +{ 0x0b5b, 16, {0x60, 0x60, 0x03, 0xe4, 0xf5, 0x48, 0xe5, 0x61, 0x60, 0x02, 0xd2, 0x04, 0xe5, 0x62, 0x60, 0x08} }, +{ 0x0b6b, 16, {0xe5, 0x5e, 0x70, 0x02, 0xf5, 0x40, 0xd2, 0x09, 0xe5, 0x63, 0x60, 0x15, 0x90, 0x7f, 0xd7, 0x74} }, +{ 0x0b7b, 16, {0x11, 0xf0, 0x74, 0x31, 0xf0, 0x74, 0x12, 0xf0, 0x74, 0x32, 0xf0, 0x74, 0x15, 0xf0, 0x74, 0x35} }, +{ 0x0b8b, 16, {0xf0, 0xd2, 0x06, 0xe4, 0x90, 0x7f, 0xcf, 0xf0, 0xa2, 0x10, 0xe4, 0x33, 0xff, 0x65, 0x2b, 0x60} }, +{ 0x0b9b, 16, {0x04, 0x8f, 0x2b, 0xd2, 0x09, 0xa2, 0x08, 0xe4, 0x33, 0xff, 0x65, 0x2c, 0x60, 0x04, 0x8f, 0x2c} }, +{ 0x0bab, 16, {0xd2, 0x09, 0x90, 0x7f, 0x9b, 0xe0, 0x54, 0x08, 0x65, 0x27, 0x60, 0x07, 0xe0, 0x54, 0x08, 0xf5} }, +{ 0x0bbb, 16, {0x27, 0xd2, 0x09, 0x90, 0x7f, 0x9b, 0xe0, 0x54, 0x40, 0xb5, 0x29, 0x09, 0xe0, 0x54, 0x40, 0x64} }, +{ 0x0bcb, 16, {0x40, 0xf5, 0x29, 0xd2, 0x09, 0x30, 0x04, 0x35, 0xc2, 0xaf, 0x30, 0x00, 0x18, 0x90, 0x7f, 0xb8} }, +{ 0x0bdb, 16, {0xe0, 0x20, 0xe1, 0x27, 0xe5, 0x48, 0x60, 0x09, 0x90, 0x7f, 0xb7, 0xf0, 0xe4, 0xf5, 0x48, 0xc2} }, +{ 0x0beb, 16, {0x00, 0xc2, 0x04, 0x80, 0x16, 0x90, 0x7f, 0xb6, 0xe0, 0x20, 0xe1, 0x0f, 0xe5, 0x48, 0x60, 0x09} }, +{ 0x0bfb, 16, {0x90, 0x7f, 0xb9, 0xf0, 0xe4, 0xf5, 0x48, 0xd2, 0x00, 0xc2, 0x04, 0xd2, 0xaf, 0x30, 0x1e, 0x37} }, +{ 0x0c0b, 16, {0x30, 0x02, 0x1b, 0x90, 0x7f, 0xc6, 0xe0, 0x20, 0xe1, 0x2d, 0x90, 0x7e, 0x40, 0xe0, 0x13, 0x92} }, +{ 0x0c1b, 16, {0x12, 0x75, 0x4a, 0x01, 0x90, 0x7f, 0xc7, 0xe0, 0xf5, 0x7c, 0xc2, 0x1e, 0x80, 0x19, 0x90, 0x7f} }, +{ 0x0c2b, 16, {0xc8, 0xe0, 0x20, 0xe1, 0x12, 0x90, 0x7d, 0xc0, 0xe0, 0x13, 0x92, 0x12, 0x75, 0x4a, 0x01, 0x90} }, +{ 0x0c3b, 16, {0x7f, 0xc9, 0xe0, 0xf5, 0x7c, 0xc2, 0x1e, 0x30, 0x20, 0x03, 0x02, 0x0d, 0x4a, 0x30, 0x1e, 0x03} }, +{ 0x0c4b, 16, {0x02, 0x0d, 0x4a, 0x30, 0x19, 0x0a, 0x90, 0x7f, 0x9b, 0xe0, 0x20, 0xe3, 0x03, 0x02, 0x0d, 0x4a} }, +{ 0x0c5b, 16, {0x30, 0x08, 0x03, 0x02, 0x0d, 0x4a, 0x30, 0x10, 0x03, 0x02, 0x0d, 0x4a, 0x30, 0x02, 0x62, 0x30} }, +{ 0x0c6b, 16, {0x18, 0x12, 0xaf, 0x4a, 0x05, 0x4a, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83} }, +{ 0x0c7b, 16, {0xe0, 0x13, 0x92, 0x2c, 0xaf, 0x4a, 0x05, 0x4a, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e} }, +{ 0x0c8b, 16, {0xf5, 0x83, 0xe0, 0xf5, 0x13, 0xe5, 0x4a, 0xc3, 0x95, 0x7c, 0x50, 0x2a, 0x30, 0x18, 0x12, 0xaf} }, +{ 0x0c9b, 16, {0x4a, 0x05, 0x4a, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0x13, 0x92} }, +{ 0x0cab, 16, {0x14, 0xaf, 0x4a, 0x05, 0x4a, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0} }, +{ 0x0cbb, 16, {0xf5, 0x46, 0xd2, 0x0e, 0x80, 0x6b, 0xc2, 0x0e, 0xe4, 0x90, 0x7f, 0xc7, 0xf0, 0xc2, 0x02, 0x80} }, +{ 0x0ccb, 16, {0x60, 0x30, 0x18, 0x12, 0xaf, 0x4a, 0x05, 0x4a, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7d} }, +{ 0x0cdb, 16, {0xf5, 0x83, 0xe0, 0x13, 0x92, 0x2c, 0xaf, 0x4a, 0x05, 0x4a, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4} }, +{ 0x0ceb, 16, {0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xf5, 0x13, 0xe5, 0x4a, 0xc3, 0x95, 0x7c, 0x50, 0x2a, 0x30, 0x18} }, +{ 0x0cfb, 16, {0x12, 0xaf, 0x4a, 0x05, 0x4a, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0} }, +{ 0x0d0b, 16, {0x13, 0x92, 0x14, 0xaf, 0x4a, 0x05, 0x4a, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5} }, +{ 0x0d1b, 16, {0x83, 0xe0, 0xf5, 0x46, 0xd2, 0x0e, 0x80, 0x09, 0xc2, 0x0e, 0xe4, 0x90, 0x7f, 0xc9, 0xf0, 0xd2} }, +{ 0x0d2b, 16, {0x02, 0x30, 0x18, 0x04, 0xa2, 0x2c, 0x92, 0x9b, 0xd2, 0x20, 0xc2, 0xaf, 0x85, 0x13, 0x99, 0x20} }, +{ 0x0d3b, 16, {0x0e, 0x0b, 0x30, 0x12, 0x08, 0xc2, 0x12, 0x90, 0x7f, 0xbf, 0x74, 0x01, 0xf0, 0xd2, 0xaf, 0x90} }, +{ 0x0d4b, 16, {0x7f, 0xd0, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x0e, 0x71, 0xe4, 0xf5, 0x12, 0x74, 0xc0, 0x25, 0x12} }, +{ 0x0d5b, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x12, 0x7c, 0x00, 0x7b, 0x00, 0x24} }, +{ 0x0d6b, 16, {0x64, 0xf9, 0xec, 0x34, 0x00, 0xfa, 0xef, 0x12, 0x15, 0x55, 0x05, 0x12, 0xe5, 0x12, 0xb4, 0x18} }, +{ 0x0d7b, 16, {0xdb, 0xe5, 0x64, 0x60, 0x0b, 0x75, 0x89, 0x60, 0x75, 0x88, 0x40, 0xd2, 0xdf, 0x85, 0x65, 0x8d} }, +{ 0x0d8b, 16, {0xe5, 0x67, 0x13, 0x92, 0x1a, 0x92, 0xc7, 0xe5, 0x68, 0x13, 0x92, 0x1b, 0xe5, 0x69, 0x13, 0x92} }, +{ 0x0d9b, 16, {0x23, 0xe5, 0x6a, 0x60, 0x09, 0x90, 0x7f, 0x97, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0x7f} }, +{ 0x0dab, 16, {0x97, 0xe0, 0x44, 0x10, 0xf0, 0xe5, 0x6b, 0x60, 0x09, 0x90, 0x7f, 0x97, 0xe0, 0x54, 0x7f, 0xf0} }, +{ 0x0dbb, 16, {0x80, 0x07, 0x90, 0x7f, 0x97, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x71, 0x60, 0x0b, 0xc2, 0x11, 0xc2} }, +{ 0x0dcb, 16, {0x0a, 0x90, 0x7f, 0x94, 0xe0, 0x44, 0x08, 0xf0, 0xe5, 0x72, 0x60, 0x0b, 0xd2, 0x0a, 0xd2, 0x0b} }, +{ 0x0ddb, 16, {0x90, 0x7f, 0x94, 0xe0, 0x44, 0x08, 0xf0, 0xe5, 0x73, 0x60, 0x17, 0xc2, 0xaf, 0xe4, 0x90, 0x7f} }, +{ 0x0deb, 16, {0xcb, 0xf0, 0x90, 0x7f, 0xcd, 0xf0, 0xc2, 0x0f, 0xd2, 0x03, 0xc2, 0x13, 0xf5, 0x7d, 0xf5, 0x4b} }, +{ 0x0dfb, 16, {0xd2, 0xaf, 0xe5, 0x74, 0x60, 0x05, 0x30, 0x23, 0x02, 0xd2, 0x0a, 0xe5, 0x75, 0x60, 0x15, 0x90} }, +{ 0x0e0b, 16, {0x7f, 0x94, 0xe0, 0x54, 0xf7, 0xf0, 0x90, 0x7f, 0x9d, 0xe0, 0x44, 0x08, 0xf0, 0x90, 0x7f, 0x97} }, +{ 0x0e1b, 16, {0xe0, 0x54, 0xf7, 0xf0, 0xe5, 0x76, 0x60, 0x0a, 0xd2, 0xc4, 0xc2, 0xc0, 0x75, 0x3a, 0x01, 0x75} }, +{ 0x0e2b, 16, {0x41, 0x28, 0xe5, 0x77, 0x60, 0x07, 0xc2, 0xc4, 0xe4, 0xf5, 0x49, 0xf5, 0x3a, 0xe5, 0x78, 0x60} }, +{ 0x0e3b, 16, {0x03, 0xe4, 0xf5, 0x49, 0xe5, 0x79, 0x60, 0x02, 0xd2, 0x05, 0xe5, 0x7a, 0x60, 0x08, 0xe5, 0x76} }, +{ 0x0e4b, 16, {0x70, 0x02, 0xf5, 0x41, 0xd2, 0x0b, 0xe5, 0x7b, 0x60, 0x15, 0x90, 0x7f, 0xd7, 0x74, 0x13, 0xf0} }, +{ 0x0e5b, 16, {0x74, 0x33, 0xf0, 0x74, 0x14, 0xf0, 0x74, 0x34, 0xf0, 0x74, 0x16, 0xf0, 0x74, 0x36, 0xf0, 0xd2} }, +{ 0x0e6b, 16, {0x07, 0xe4, 0x90, 0x7f, 0xd1, 0xf0, 0xa2, 0x11, 0xe4, 0x33, 0xff, 0x65, 0x37, 0x60, 0x04, 0x8f} }, +{ 0x0e7b, 16, {0x37, 0xd2, 0x0b, 0xa2, 0x0a, 0xe4, 0x33, 0xff, 0x65, 0x38, 0x60, 0x04, 0x8f, 0x38, 0xd2, 0x0b} }, +{ 0x0e8b, 16, {0x90, 0x7f, 0x9a, 0xe0, 0x54, 0x20, 0x65, 0x33, 0x60, 0x07, 0xe0, 0x54, 0x20, 0xf5, 0x33, 0xd2} }, +{ 0x0e9b, 16, {0x0b, 0x90, 0x7f, 0x9a, 0xe0, 0x54, 0x40, 0xb5, 0x35, 0x09, 0xe0, 0x54, 0x40, 0x64, 0x40, 0xf5} }, +{ 0x0eab, 16, {0x35, 0xd2, 0x0b, 0x30, 0x05, 0x35, 0xc2, 0xaf, 0x30, 0x01, 0x18, 0x90, 0x7f, 0xbc, 0xe0, 0x20} }, +{ 0x0ebb, 16, {0xe1, 0x27, 0xe5, 0x49, 0x60, 0x09, 0x90, 0x7f, 0xbb, 0xf0, 0xe4, 0xf5, 0x49, 0xc2, 0x01, 0xc2} }, +{ 0x0ecb, 16, {0x05, 0x80, 0x16, 0x90, 0x7f, 0xba, 0xe0, 0x20, 0xe1, 0x0f, 0xe5, 0x49, 0x60, 0x09, 0x90, 0x7f} }, +{ 0x0edb, 16, {0xbd, 0xf0, 0xe4, 0xf5, 0x49, 0xd2, 0x01, 0xc2, 0x05, 0xd2, 0xaf, 0x30, 0x1f, 0x37, 0x30, 0x03} }, +{ 0x0eeb, 16, {0x1b, 0x90, 0x7f, 0xca, 0xe0, 0x20, 0xe1, 0x2d, 0x90, 0x7d, 0x40, 0xe0, 0x13, 0x92, 0x13, 0x75} }, +{ 0x0efb, 16, {0x4b, 0x01, 0x90, 0x7f, 0xcb, 0xe0, 0xf5, 0x7d, 0xc2, 0x1f, 0x80, 0x19, 0x90, 0x7f, 0xcc, 0xe0} }, +{ 0x0f0b, 16, {0x20, 0xe1, 0x12, 0x90, 0x7c, 0xc0, 0xe0, 0x13, 0x92, 0x13, 0x75, 0x4b, 0x01, 0x90, 0x7f, 0xcd} }, +{ 0x0f1b, 16, {0xe0, 0xf5, 0x7d, 0xc2, 0x1f, 0x30, 0x21, 0x03, 0x02, 0x10, 0x28, 0x30, 0x1f, 0x03, 0x02, 0x10} }, +{ 0x0f2b, 16, {0x28, 0x30, 0x1b, 0x0a, 0x90, 0x7f, 0x9a, 0xe0, 0x20, 0xe5, 0x03, 0x02, 0x10, 0x28, 0x30, 0x0a} }, +{ 0x0f3b, 16, {0x03, 0x02, 0x10, 0x28, 0x30, 0x11, 0x03, 0x02, 0x10, 0x28, 0x30, 0x03, 0x62, 0x30, 0x1a, 0x12} }, +{ 0x0f4b, 16, {0xaf, 0x4b, 0x05, 0x4b, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0x13} }, +{ 0x0f5b, 16, {0x92, 0x2c, 0xaf, 0x4b, 0x05, 0x4b, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83} }, +{ 0x0f6b, 16, {0xe0, 0xf5, 0x13, 0xe5, 0x4b, 0xc3, 0x95, 0x7d, 0x50, 0x2a, 0x30, 0x1a, 0x12, 0xaf, 0x4b, 0x05} }, +{ 0x0f7b, 16, {0x4b, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x15, 0xaf} }, +{ 0x0f8b, 16, {0x4b, 0x05, 0x4b, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xf5, 0x47} }, +{ 0x0f9b, 16, {0xd2, 0x0f, 0x80, 0x6b, 0xc2, 0x0f, 0xe4, 0x90, 0x7f, 0xcb, 0xf0, 0xc2, 0x03, 0x80, 0x60, 0x30} }, +{ 0x0fab, 16, {0x1a, 0x12, 0xaf, 0x4b, 0x05, 0x4b, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7c, 0xf5, 0x83} }, +{ 0x0fbb, 16, {0xe0, 0x13, 0x92, 0x2c, 0xaf, 0x4b, 0x05, 0x4b, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7c} }, +{ 0x0fcb, 16, {0xf5, 0x83, 0xe0, 0xf5, 0x13, 0xe5, 0x4b, 0xc3, 0x95, 0x7d, 0x50, 0x2a, 0x30, 0x1a, 0x12, 0xaf} }, +{ 0x0fdb, 16, {0x4b, 0x05, 0x4b, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7c, 0xf5, 0x83, 0xe0, 0x13, 0x92} }, +{ 0x0feb, 16, {0x15, 0xaf, 0x4b, 0x05, 0x4b, 0x74, 0xc0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7c, 0xf5, 0x83, 0xe0} }, +{ 0x0ffb, 16, {0xf5, 0x47, 0xd2, 0x0f, 0x80, 0x09, 0xc2, 0x0f, 0xe4, 0x90, 0x7f, 0xcd, 0xf0, 0xd2, 0x03, 0x30} }, +{ 0x100b, 16, {0x1a, 0x04, 0xa2, 0x2c, 0x92, 0xc3, 0xd2, 0x21, 0xc2, 0xaf, 0x85, 0x13, 0xc1, 0x20, 0x0f, 0x0b} }, +{ 0x101b, 16, {0x30, 0x13, 0x08, 0xc2, 0x13, 0x90, 0x7f, 0xc1, 0x74, 0x01, 0xf0, 0xd2, 0xaf, 0x90, 0x7f, 0xc2} }, +{ 0x102b, 16, {0xe0, 0x30, 0xe1, 0x03, 0x02, 0x10, 0xfe, 0xe5, 0x1a, 0x70, 0x46, 0x30, 0x09, 0x3f, 0xe5, 0x40} }, +{ 0x103b, 16, {0x70, 0x3b, 0xa2, 0x06, 0x33, 0xf5, 0x31, 0xc2, 0x06, 0xc2, 0x09, 0xe4, 0xf5, 0x12, 0x7e, 0x00} }, +{ 0x104b, 16, {0x7b, 0x00, 0x74, 0x26, 0x25, 0x12, 0xf9, 0xee, 0x34, 0x00, 0xfa, 0x12, 0x15, 0x0f, 0xff, 0x74} }, +{ 0x105b, 16, {0x80, 0x25, 0x12, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x12, 0xe5, 0x12} }, +{ 0x106b, 16, {0xb4, 0x0c, 0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x0c, 0xf0, 0x75, 0x40, 0x10, 0x22, 0x75, 0x1a, 0x01} }, +{ 0x107b, 16, {0x22, 0xe5, 0x1a, 0x64, 0x01, 0x70, 0x45, 0x30, 0x0b, 0x3e, 0xe5, 0x41, 0x70, 0x3a, 0xa2, 0x07} }, +{ 0x108b, 16, {0x33, 0xf5, 0x3d, 0xc2, 0x07, 0xc2, 0x0b, 0xe4, 0xf5, 0x12, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x32} }, +{ 0x109b, 16, {0x25, 0x12, 0xf9, 0xee, 0x34, 0x00, 0xfa, 0x12, 0x15, 0x0f, 0xff, 0x74, 0x80, 0x25, 0x12, 0xf5} }, +{ 0x10ab, 16, {0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x12, 0xe5, 0x12, 0xb4, 0x0c, 0xdb, 0x90} }, +{ 0x10bb, 16, {0x7f, 0xc3, 0x74, 0x0c, 0xf0, 0x75, 0x41, 0x10, 0x75, 0x1a, 0x02, 0x22, 0xe5, 0x1c, 0x60, 0x30} }, +{ 0x10cb, 16, {0x15, 0x1c, 0xe4, 0xf5, 0x12, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x1b, 0x25, 0x12, 0xf9, 0xee, 0x34} }, +{ 0x10db, 16, {0x00, 0xfa, 0x12, 0x15, 0x0f, 0xff, 0x74, 0x80, 0x25, 0x12, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5} }, +{ 0x10eb, 16, {0x83, 0xef, 0xf0, 0x05, 0x12, 0xe5, 0x12, 0xb4, 0x03, 0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x03, 0xf0} }, +{ 0x10fb, 3, {0xe4, 0xf5, 0x1a} }, +{ 0x10fe, 1, {0x22} }, +{ 0x10ff, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x12, 0x15, 0x9f, 0x11, 0xc4, 0x00, 0x12, 0x38, 0x01, 0x12, 0xa4, 0x03} }, +{ 0x110f, 16, {0x11, 0x22, 0x06, 0x11, 0xb7, 0x08, 0x11, 0xb1, 0x09, 0x11, 0xa4, 0x0a, 0x12, 0xfa, 0x0b, 0x00} }, +{ 0x111f, 16, {0x00, 0x12, 0xf3, 0x90, 0x7f, 0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x40, 0x24, 0x02} }, +{ 0x112f, 16, {0x70, 0x69, 0x74, 0x19, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x12} }, +{ 0x113f, 16, {0xfa, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x16, 0xd3, 0x8b, 0x12, 0x8a, 0x13, 0x89, 0x14, 0xea} }, +{ 0x114f, 16, {0x49, 0x60, 0x11, 0xae, 0x02, 0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5} }, +{ 0x115f, 16, {0xf0, 0x02, 0x12, 0xfa, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x12, 0xfa, 0x90, 0x7f} }, +{ 0x116f, 16, {0xea, 0xe0, 0xff, 0x12, 0x17, 0x22, 0x8b, 0x12, 0x8a, 0x13, 0x89, 0x14, 0xea, 0x49, 0x60, 0x11} }, +{ 0x117f, 16, {0xae, 0x02, 0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x12} }, +{ 0x118f, 16, {0xfa, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x12, 0xfa, 0x90, 0x7f, 0xb4, 0xe0, 0x44} }, +{ 0x119f, 16, {0x01, 0xf0, 0x02, 0x12, 0xfa, 0x90, 0x7f, 0x00, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb5, 0xf0, 0x02} }, +{ 0x11af, 16, {0x12, 0xfa, 0x12, 0x14, 0x47, 0x02, 0x12, 0xfa, 0x90, 0x7f, 0x00, 0x74, 0x01, 0xf0, 0x90, 0x7f} }, +{ 0x11bf, 16, {0xb5, 0xf0, 0x02, 0x12, 0xfa, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31} }, +{ 0x11cf, 16, {0x24, 0x02, 0x70, 0x5b, 0xa2, 0x25, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x29, 0xe4, 0x33} }, +{ 0x11df, 16, {0x4f, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x12} }, +{ 0x11ef, 16, {0xfa, 0xe4, 0x90, 0x7f, 0x00, 0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x12} }, +{ 0x11ff, 16, {0xfa, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07} }, +{ 0x120f, 16, {0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90} }, +{ 0x121f, 16, {0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x12, 0xfa, 0x90} }, +{ 0x122f, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x12, 0xfa, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60} }, +{ 0x123f, 16, {0x1d, 0x24, 0x02, 0x60, 0x03, 0x02, 0x12, 0xfa, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x05, 0xc2} }, +{ 0x124f, 16, {0x25, 0x02, 0x12, 0xfa, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x12, 0xfa, 0x90, 0x7f} }, +{ 0x125f, 16, {0xea, 0xe0, 0x70, 0x38, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff} }, +{ 0x126f, 16, {0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4} }, +{ 0x127f, 16, {0xf0, 0x90, 0x7f, 0xec, 0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f, 0xff, 0xe0, 0x54} }, +{ 0x128f, 16, {0x07, 0x2f, 0x90, 0x7f, 0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x5f, 0x90, 0x7f, 0xb4, 0xe0} }, +{ 0x129f, 16, {0x44, 0x01, 0xf0, 0x80, 0x56, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70} }, +{ 0x12af, 16, {0x4a, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04, 0xd2, 0x25, 0x80, 0x3f, 0x90, 0x7f, 0xb4, 0xe0} }, +{ 0x12bf, 16, {0x44, 0x01, 0xf0, 0x80, 0x36, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4} }, +{ 0x12cf, 16, {0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5} }, +{ 0x12df, 16, {0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x10, 0x90, 0x7f, 0xb4, 0xe0, 0x44} }, +{ 0x12ef, 16, {0x01, 0xf0, 0x80, 0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44} }, +{ 0x12ff, 2, {0x02, 0xf0} }, +{ 0x1301, 1, {0x22} }, +{ 0x1302, 16, {0x20, 0x27, 0x03, 0x02, 0x14, 0x46, 0xe5, 0x40, 0x60, 0x02, 0x15, 0x40, 0xe5, 0x48, 0x60, 0x4f} }, +{ 0x1312, 16, {0x65, 0x44, 0x70, 0x45, 0xe5, 0x42, 0xf4, 0x60, 0x02, 0x05, 0x42, 0xe5, 0x42, 0xc3, 0x95, 0x55} }, +{ 0x1322, 16, {0x40, 0x3d, 0xc2, 0xaf, 0x30, 0x00, 0x18, 0x90, 0x7f, 0xb8, 0xe0, 0x20, 0xe1, 0x27, 0x90, 0x7f} }, +{ 0x1332, 16, {0xb7, 0xe5, 0x48, 0xf0, 0xc2, 0x00, 0xe4, 0xf5, 0x48, 0xf5, 0x42, 0xf5, 0x44, 0x80, 0x16, 0x90} }, +{ 0x1342, 16, {0x7f, 0xb6, 0xe0, 0x20, 0xe1, 0x0f, 0x90, 0x7f, 0xb9, 0xe5, 0x48, 0xf0, 0xd2, 0x00, 0xe4, 0xf5} }, +{ 0x1352, 16, {0x48, 0xf5, 0x42, 0xf5, 0x44, 0xd2, 0xaf, 0x80, 0x06, 0x85, 0x48, 0x44, 0xe4, 0xf5, 0x42, 0xe5} }, +{ 0x1362, 16, {0x2e, 0x60, 0x2d, 0x20, 0x16, 0x07, 0x90, 0x7f, 0x9b, 0xe0, 0x30, 0xe0, 0x0e, 0xe5, 0x2f, 0x60} }, +{ 0x1372, 16, {0x05, 0xe4, 0xf5, 0x2f, 0xd2, 0x09, 0xe4, 0xf5, 0x3e, 0x80, 0x13, 0xe5, 0x3e, 0xd3, 0x95, 0x56} }, +{ 0x1382, 16, {0x50, 0x0c, 0xe5, 0x3e, 0xb5, 0x56, 0x05, 0x75, 0x2f, 0x01, 0xd2, 0x09, 0x05, 0x3e, 0xc2, 0x16} }, +{ 0x1392, 16, {0xe5, 0x41, 0x60, 0x02, 0x15, 0x41, 0xe5, 0x49, 0x60, 0x4f, 0x65, 0x45, 0x70, 0x45, 0xe5, 0x43} }, +{ 0x13a2, 16, {0xf4, 0x60, 0x02, 0x05, 0x43, 0xe5, 0x43, 0xc3, 0x95, 0x6d, 0x40, 0x3d, 0xc2, 0xaf, 0x30, 0x01} }, +{ 0x13b2, 16, {0x18, 0x90, 0x7f, 0xbc, 0xe0, 0x20, 0xe1, 0x27, 0x90, 0x7f, 0xbb, 0xe5, 0x49, 0xf0, 0xc2, 0x01} }, +{ 0x13c2, 16, {0xe4, 0xf5, 0x49, 0xf5, 0x43, 0xf5, 0x45, 0x80, 0x16, 0x90, 0x7f, 0xba, 0xe0, 0x20, 0xe1, 0x0f} }, +{ 0x13d2, 16, {0x90, 0x7f, 0xbd, 0xe5, 0x49, 0xf0, 0xd2, 0x01, 0xe4, 0xf5, 0x49, 0xf5, 0x43, 0xf5, 0x45, 0xd2} }, +{ 0x13e2, 16, {0xaf, 0x80, 0x06, 0x85, 0x49, 0x45, 0xe4, 0xf5, 0x43, 0xe5, 0x3a, 0x60, 0x2d, 0x20, 0x17, 0x07} }, +{ 0x13f2, 16, {0x90, 0x7f, 0x9a, 0xe0, 0x30, 0xe2, 0x0e, 0xe5, 0x3b, 0x60, 0x05, 0xe4, 0xf5, 0x3b, 0xd2, 0x0b} }, +{ 0x1402, 16, {0xe4, 0xf5, 0x3f, 0x80, 0x13, 0xe5, 0x3f, 0xd3, 0x95, 0x6e, 0x50, 0x0c, 0xe5, 0x3f, 0xb5, 0x6e} }, +{ 0x1412, 16, {0x05, 0x75, 0x3b, 0x01, 0xd2, 0x0b, 0x05, 0x3f, 0xc2, 0x17, 0x90, 0x7f, 0xd2, 0xe0, 0x20, 0xe1} }, +{ 0x1422, 16, {0x23, 0x90, 0x7b, 0x40, 0xe0, 0x60, 0x09, 0xe0, 0xf5, 0x1c, 0x90, 0x7b, 0x42, 0xe0, 0xf5, 0x1d} }, +{ 0x1432, 16, {0x90, 0x7b, 0x41, 0xe0, 0x60, 0x09, 0x90, 0x7f, 0xd7, 0x74, 0x17, 0xf0, 0x74, 0x37, 0xf0, 0xe4} }, +{ 0x1442, 5, {0x90, 0x7f, 0xd3, 0xf0, 0x22} }, +{ 0x1447, 16, {0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0x30, 0xf0, 0x90, 0x7f, 0x96, 0xe0, 0x44} }, +{ 0x1457, 16, {0x10, 0xf0, 0x90, 0x7f, 0x94, 0x74, 0x0d, 0xf0, 0x90, 0x7f, 0x9d, 0x74, 0x9a, 0xf0, 0x90, 0x7f} }, +{ 0x1467, 16, {0x97, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0x95, 0x74, 0x23, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x84} }, +{ 0x1477, 16, {0xf0, 0xe4, 0x90, 0x7f, 0xc7, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0x90, 0x7f, 0xcf, 0xf0, 0x75, 0x98} }, +{ 0x1487, 16, {0x40, 0x43, 0xa8, 0x10, 0xc2, 0x18, 0xc2, 0x20, 0xc2, 0x08, 0xc2, 0x10, 0xf5, 0x7c, 0xf5, 0x4a} }, +{ 0x1497, 16, {0xc2, 0x0e, 0xc2, 0x12, 0xf5, 0x42, 0xc2, 0x16, 0xf5, 0x44, 0xf5, 0x48, 0xc2, 0x22, 0xc2, 0x19} }, +{ 0x14a7, 16, {0xf5, 0x2d, 0xf5, 0x2f, 0xc2, 0x04, 0xc2, 0x1c, 0xf5, 0x3e, 0xc2, 0x06, 0xd2, 0x00, 0xd2, 0x02} }, +{ 0x14b7, 16, {0xd2, 0x09, 0xd2, 0x1e, 0xf5, 0x26, 0x90, 0x7f, 0xcb, 0xf0, 0x90, 0x7f, 0xcd, 0xf0, 0x90, 0x7f} }, +{ 0x14c7, 16, {0xd1, 0xf0, 0x75, 0xc0, 0x40, 0x43, 0xa8, 0x40, 0xc2, 0x1a, 0xc2, 0x21, 0xc2, 0x0a, 0xc2, 0x11} }, +{ 0x14d7, 16, {0xf5, 0x7d, 0xf5, 0x4b, 0xc2, 0x0f, 0xc2, 0x13, 0xf5, 0x43, 0xc2, 0x17, 0xf5, 0x45, 0xf5, 0x49} }, +{ 0x14e7, 16, {0xc2, 0x23, 0xc2, 0x1b, 0xf5, 0x39, 0xf5, 0x3b, 0xc2, 0x05, 0xc2, 0x1d, 0xf5, 0x3f, 0xc2, 0x07} }, +{ 0x14f7, 16, {0xd2, 0x01, 0xd2, 0x03, 0xd2, 0x0b, 0xd2, 0x1f, 0x75, 0x32, 0x01, 0x90, 0x7f, 0xdf, 0x74, 0xff} }, +{ 0x1507, 8, {0xf0, 0x90, 0x7f, 0xde, 0xf0, 0xd2, 0x27, 0x22} }, +{ 0x150f, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} }, +{ 0x151f, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x1528, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} }, +{ 0x1538, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} }, +{ 0x1548, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x1555, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01} }, +{ 0x1565, 2, {0xf3, 0x22} }, +{ 0x1567, 16, {0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} }, +{ 0x1577, 16, {0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} }, +{ 0x1587, 16, {0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} }, +{ 0x1597, 8, {0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} }, +{ 0x159f, 16, {0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3} }, +{ 0x15af, 16, {0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60} }, +{ 0x15bf, 6, {0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf} }, +{ 0x15c5, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x7d, 0x02, 0x16, 0x0c} }, +{ 0x15d1, 16, {0x02, 0x16, 0x51, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} }, +{ 0x15e1, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} }, +{ 0x15f1, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} }, +{ 0x1601, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x18, 0x9e, 0xe4, 0x7e} }, +{ 0x1611, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} }, +{ 0x1621, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} }, +{ 0x1631, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} }, +{ 0x1641, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} }, +{ 0x1651, 16, {0x75, 0x11, 0x01, 0x90, 0x7f, 0x92, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xae, 0xe0, 0xff, 0xd3} }, +{ 0x1661, 16, {0x92, 0x25, 0xe4, 0x33, 0xfe, 0xef, 0x4e, 0xf0, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xde} }, +{ 0x1671, 16, {0x74, 0x01, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9} }, +{ 0x1681, 16, {0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90} }, +{ 0x1691, 16, {0x7f, 0xae, 0xe0, 0x44, 0x0d, 0xf0, 0xd2, 0xaf, 0xd2, 0xbc, 0xd2, 0xbe, 0xd2, 0x2c, 0x12, 0x18} }, +{ 0x16a1, 16, {0x58, 0xc2, 0x26, 0xc2, 0x24, 0xc2, 0x27, 0x30, 0x27, 0x03, 0x12, 0x0a, 0x6b, 0x90, 0x7f, 0xd8} }, +{ 0x16b1, 16, {0xe0, 0x65, 0x10, 0x60, 0x08, 0xe0, 0xf5, 0x10, 0x12, 0x13, 0x02, 0x80, 0xea, 0x30, 0x26, 0x07} }, +{ 0x16c1, 16, {0xc2, 0x26, 0x12, 0x10, 0xff, 0x80, 0xe0, 0x30, 0x2a, 0xdd, 0xc2, 0x2a, 0x12, 0x00, 0x26, 0x80} }, +{ 0x16d1, 1, {0xd6} }, +{ 0x16d2, 1, {0x22} }, +{ 0x16d3, 16, {0xe4, 0xfe, 0x75, 0x17, 0xff, 0x75, 0x18, 0x19, 0x75, 0x19, 0x12, 0xab, 0x17, 0xaa, 0x18, 0xa9} }, +{ 0x16e3, 16, {0x19, 0x90, 0x00, 0x01, 0x12, 0x15, 0x28, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} }, +{ 0x16f3, 16, {0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x15, 0x67, 0x85, 0xf0, 0x15, 0xf5, 0x16, 0x62, 0x15} }, +{ 0x1703, 16, {0xe5, 0x15, 0x62, 0x16, 0xe5, 0x16, 0x62, 0x15, 0x29, 0xfd, 0xe5, 0x15, 0x3a, 0xa9, 0x05, 0x75} }, +{ 0x1713, 14, {0x17, 0xff, 0xf5, 0x18, 0x89, 0x19, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x1721, 1, {0x22} }, +{ 0x1722, 2, {0x8f, 0x15} }, +{ 0x1724, 16, {0xe4, 0xf5, 0x16, 0x75, 0x17, 0xff, 0x75, 0x18, 0x19, 0x75, 0x19, 0x86, 0xab, 0x17, 0xaa, 0x18} }, +{ 0x1734, 16, {0xa9, 0x19, 0x90, 0x00, 0x01, 0x12, 0x15, 0x28, 0xb4, 0x03, 0x1d, 0xaf, 0x16, 0x05, 0x16, 0xef} }, +{ 0x1744, 16, {0xb5, 0x15, 0x01, 0x22, 0x12, 0x15, 0x0f, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} }, +{ 0x1754, 14, {0x17, 0xff, 0xf5, 0x18, 0x89, 0x19, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x1762, 1, {0x22} }, +{ 0x1763, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x30} }, +{ 0x1773, 16, {0x2b, 0x04, 0xc2, 0x2b, 0x80, 0x02, 0xd2, 0x2a, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} }, +{ 0x1783, 14, {0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x1791, 16, {0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0xf0, 0x90, 0x7f, 0x94, 0xf0, 0x90, 0x7f, 0x9d} }, +{ 0x17a1, 16, {0x74, 0x02, 0xf0, 0x90, 0x7f, 0x97, 0xf0, 0xe4, 0x90, 0x7f, 0x95, 0xf0, 0x90, 0x7f, 0x9e, 0x74} }, +{ 0x17b1, 12, {0xff, 0xf0, 0xe4, 0x90, 0x7f, 0x98, 0xf0, 0x90, 0x7f, 0x9d, 0xf0, 0x22} }, +{ 0x17bd, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x90} }, +{ 0x17cd, 16, {0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x04, 0xf0, 0xd0, 0x86, 0xd0} }, +{ 0x17dd, 10, {0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x17e7, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xd2} }, +{ 0x17f7, 16, {0x26, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85} }, +{ 0x1807, 7, {0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x180e, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} }, +{ 0x181e, 16, {0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82} }, +{ 0x182e, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x1833, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} }, +{ 0x1843, 16, {0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82} }, +{ 0x1853, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x1858, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x2c, 0x04, 0xe0, 0x44} }, +{ 0x1868, 16, {0x02, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x00, 0x06, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} }, +{ 0x1878, 5, {0xe0, 0x44, 0x04, 0xf0, 0x22} }, +{ 0x187d, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} }, +{ 0x188d, 1, {0x22} }, +{ 0x188e, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} }, +{ 0x189e, 16, {0x01, 0x1a, 0x00, 0x03, 0x1b, 0x03, 0x00, 0x00, 0xc1, 0x26, 0xc1, 0x2a, 0xc1, 0x25, 0xc1, 0xa9} }, +{ 0x18ae, 2, {0xc1, 0xab} }, +{ 0x18b0, 1, {0x00} }, +{ 0x1900, 16, {0x12, 0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x40, 0xcd, 0x06, 0x0f, 0x01, 0x00, 0x00, 0x01, 0x02} }, +{ 0x1910, 16, {0x00, 0x01, 0x09, 0x02, 0x74, 0x00, 0x01, 0x01, 0x00, 0xa0, 0x32, 0x09, 0x04, 0x00, 0x00, 0x0e} }, +{ 0x1920, 16, {0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} }, +{ 0x1930, 16, {0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, 0x00} }, +{ 0x1940, 16, {0x07, 0x05, 0x05, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x06, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05} }, +{ 0x1950, 16, {0x07, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x82, 0x02} }, +{ 0x1960, 16, {0x40, 0x00, 0x00, 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00} }, +{ 0x1970, 16, {0x00, 0x07, 0x05, 0x85, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x86, 0x02, 0x40, 0x00, 0x00, 0x07} }, +{ 0x1980, 16, {0x05, 0x87, 0x02, 0x40, 0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x48, 0x03, 0x4b, 0x00, 0x65, 0x00} }, +{ 0x1990, 16, {0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00} }, +{ 0x19a0, 16, {0x20, 0x00, 0x64, 0x00, 0x69, 0x00, 0x76, 0x00, 0x69, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00} }, +{ 0x19b0, 16, {0x6e, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x6e, 0x00} }, +{ 0x19c0, 16, {0x6f, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00} }, +{ 0x19d0, 16, {0x2e, 0x00, 0x36, 0x03, 0x4b, 0x00, 0x65, 0x00, 0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00} }, +{ 0x19e0, 16, {0x6e, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53, 0x00, 0x42, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00} }, +{ 0x19f0, 16, {0x72, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x41, 0x00, 0x64, 0x00, 0x61, 0x00} }, +{ 0x1a00, 10, {0x70, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00} }, +{ 0x1b00, 16, {0x02, 0x17, 0xe7, 0x00, 0x02, 0x18, 0x0e, 0x00, 0x02, 0x17, 0xbd, 0x00, 0x02, 0x17, 0x63, 0x00} }, +{ 0x1b10, 3, {0x02, 0x18, 0x33} }, +{ 0xffff, 0, {0x00} } +}; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/serial/keyspan_usa28msg.h linux/drivers/usb/serial/keyspan_usa28msg.h --- v2.4.0-test2/linux/drivers/usb/serial/keyspan_usa28msg.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/keyspan_usa28msg.h Mon Jul 10 14:33:04 2000 @@ -0,0 +1,212 @@ +/* + usa28msg.h + + Copyright (c) 1998-2000 InnoSys Incorporated. All Rights Reserved + This file is available under a BSD-style copyright + + Keyspan USB Async Firmware to run on Anchor EZ-USB + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain this licence text + without modification, this list of conditions, and the following + disclaimer. The following copyright notice must appear immediately at + the beginning of all source files: + + Copyright (c) 1998-2000 InnoSys Incorporated. All Rights Reserved + + This file is available under a BSD-style copyright + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of InnoSys Incorprated may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY INNOSYS CORP. ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + Note: these message formats are common to USA18, USA19, and USA28; + (for USA28X, see usa26msg.h) + + Buffer formats for RX/TX data messages are not defined by + a structure, but are described here: + + USB OUT (host -> USA28, transmit) messages contain a + REQUEST_ACK indicator (set to 0xff to request an ACK at the + completion of transmit; 0x00 otherwise), followed by data. + If the port is configured for parity, the data will be an + alternating string of parity and data bytes, so the message + format will be: + + RQSTACK PAR DAT PAR DAT ... + + so the maximum length is 63 bytes (1 + 62, or 31 data bytes); + always an odd number for the total message length. + + If there is no parity, the format is simply: + + RQSTACK DAT DAT DAT ... + + with a total data length of 63. + + USB IN (USA28 -> host, receive) messages contain data and parity + if parity is configred, thusly: + + DAT PAR DAT PAR DAT PAR ... + + for a total of 32 data bytes; + + If parity is not configured, the format is: + + DAT DAT DAT ... + + for a total of 64 data bytes. + + In the TX messages (USB OUT), the 0x01 bit of the PARity byte is + the parity bit. In the RX messages (USB IN), the PARity byte is + the content of the 8051's status register; the parity bit + (RX_PARITY_BIT) is the 0x04 bit. + + revision history: + + 1999may06 add resetDataToggle to control message + 2000mar21 add rs232invalid to status response message + 2000apr04 add 230.4Kb definition to setBaudRate + 2000apr13 add/remove loopbackMode switch + 2000apr13 change definition of setBaudRate to cover 115.2Kb, too + 2000jun01 add extended BSD-style copyright text +*/ + +#ifndef __USA28MSG__ +#define __USA28MSG__ + +#ifndef STUBS +#include "datadefs.h" +#endif + +typedef struct txAckMessage +{ + u8 dummy; +} txAckMessage; + +typedef struct portControlMessage +{ + /* + there are four types of "commands" sent in the control message: + + 1. configuration changes which must be requested by setting + the corresponding "set" flag (and should only be requested + when necessary, to reduce overhead on the USA28): + */ + u8 setBaudRate, // 0=don't set, 1=baudLo/Hi, 2=115.2K, 3=230.4K + baudLo, // host does baud divisor calculation + baudHi; // baudHi is only used for first port (gives lower rates) + + /* + 2. configuration changes which are done every time (because it's + hardly more trouble to do them than to check whether to do them): + */ + u8 parity, // 1=use parity, 0=don't + ctsFlowControl, // 1=use CTS flow control, 0=don't + xonFlowControl, // 1=use XON/XOFF flow control, 0=don't + rts, // 1=on, 0=off + dtr; // 1=on, 0=off + + /* + 3. configuration data which is simply used as is (no overhead, + but must be correct in every host message). + */ + u8 forwardingLength, // forward when this number of chars available + forwardMs, // forward this many ms after last rx data + breakThreshold, // specified in ms, 1-255 (see note below) + xonChar, // specified in current character format + xoffChar; // specified in current character format + + /* + 4. commands which are flags only; these are processed in order + (so that, e.g., if both _txOn and _txOff flags are set, the + port ends in a TX_OFF state); any non-zero value is respected + */ + u8 _txOn, // enable transmitting (and continue if there's data) + _txOff, // stop transmitting + txFlush, // toss outbound data + txForceXoff, // pretend we've received XOFF + txBreak, // turn on break (leave on until txOn clears it) + rxOn, // turn on receiver + rxOff, // turn off receiver + rxFlush, // toss inbound data + rxForward, // forward all inbound data, NOW + returnStatus, // return current status n times (1 or 2) + resetDataToggle;// reset data toggle state to DATA0 + +} portControlMessage; + +typedef struct portStatusMessage +{ + u8 port, // 0=first, 1=second, 2=global (see below) + cts, + dsr, // (not used in all products) + dcd, + + ri, // (not used in all products) + _txOff, // port has been disabled (by host) + _txXoff, // port is in XOFF state (either host or RX XOFF) + dataLost, // count of lost chars; wraps; not guaranteed exact + + rxEnabled, // as configured by rxOn/rxOff 1=on, 0=off + rxBreak, // 1=we're in break state + rs232invalid, // 1=no valid signals on rs-232 inputs + controlResponse;// 1=a control messages has been processed +} portStatusMessage; + +// bit defines in txState +#define TX_OFF 0x01 // requested by host txOff command +#define TX_XOFF 0x02 // either real, or simulated by host + +typedef struct globalControlMessage +{ + u8 sendGlobalStatus, // 2=request for two status responses + resetStatusToggle, // 1=reset global status toggle + resetStatusCount; // a cycling value +} globalControlMessage; + +typedef struct globalStatusMessage +{ + u8 port, // 3 + sendGlobalStatus, // from request, decremented + resetStatusCount; // as in request +} globalStatusMessage; + +typedef struct globalDebugMessage +{ + u8 port, // 2 + n, // typically a count/status byte + b; // typically a data byte +} globalDebugMessage; + +// ie: the maximum length of an EZUSB endpoint buffer +#define MAX_DATA_LEN 64 + +// the parity bytes have only one significant bit +#define RX_PARITY_BIT 0x04 +#define TX_PARITY_BIT 0x01 + +// update status approx. 60 times a second (16.6666 ms) +#define STATUS_UPDATE_INTERVAL 16 + +#endif + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/serial/keyspan_usa28x_fw.h linux/drivers/usb/serial/keyspan_usa28x_fw.h --- v2.4.0-test2/linux/drivers/usb/serial/keyspan_usa28x_fw.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/keyspan_usa28x_fw.h Mon Jul 10 14:33:04 2000 @@ -0,0 +1,406 @@ +/* keyspan_usa28x_fw.h + + Generated from Keyspan firmware image Wed Jul 5 09:18:29 2000 EST + This firmware is for the Keyspan USA-28X Serial Adaptor + + "The firmware contained herein as keyspan_usa28x_fw.h is + Copyright (C) 1999-2000 Keyspan, A division of InnoSys Incorporated + ("Keyspan"), as an unpublished work. This notice does not imply + unrestricted or public access to this firmware which is a trade secret of + Keyspan, and which may not be reproduced, used, sold or transferred to any + third party without Keyspan's prior written consent. All Rights Reserved. + + This firmware may not be modified and may only be used with the Keyspan + USA-28X Serial Adapter. Distribution and/or Modification of the + keyspan.c driver which includes this firmware, in whole or in part, + requires the inclusion of this statement." + +*/ + +static const struct ezusb_hex_record keyspan_usa28x_firmware[] = { +{ 0x0000, 3, {0x02, 0x0e, 0x9b} }, +{ 0x0003, 16, {0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0x30, 0xf0, 0xe4, 0x90, 0x7f, 0x96, 0xf0} }, +{ 0x0013, 16, {0x90, 0x7f, 0x94, 0xf0, 0x90, 0x7f, 0x9d, 0x74, 0xff, 0xf0, 0xe4, 0x90, 0x7f, 0x97, 0xf0, 0x90} }, +{ 0x0023, 15, {0x7f, 0x95, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x07, 0xf0, 0xe4, 0x90, 0x7f, 0x98, 0xf0, 0x22} }, +{ 0x0033, 3, {0x02, 0x13, 0xfc} }, +{ 0x0036, 12, {0x90, 0x7f, 0x98, 0x74, 0x10, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x0043, 3, {0x02, 0x14, 0x00} }, +{ 0x0046, 16, {0x30, 0x08, 0x13, 0x12, 0x13, 0xc0, 0xef, 0xc3, 0x95, 0x3c, 0x50, 0x73, 0x90, 0x7f, 0xbf, 0x74} }, +{ 0x0056, 16, {0x01, 0xf0, 0xc2, 0x08, 0x80, 0x69, 0x30, 0x02, 0x34, 0x90, 0x7f, 0xc6, 0xe0, 0x20, 0xe1, 0x5f} }, +{ 0x0066, 16, {0x12, 0x13, 0xc0, 0xef, 0xc3, 0x94, 0x40, 0x50, 0x56, 0x90, 0x7e, 0x40, 0xe0, 0x13, 0x92, 0x08} }, +{ 0x0076, 16, {0x90, 0x7f, 0xc7, 0xe0, 0x14, 0xf5, 0x08, 0x7e, 0x7e, 0x7f, 0x41, 0x75, 0x0c, 0x7e, 0x75, 0x0d} }, +{ 0x0086, 16, {0x41, 0x12, 0x0d, 0x55, 0xc2, 0x02, 0xe4, 0x90, 0x7f, 0xc7, 0xf0, 0x80, 0x32, 0x90, 0x7f, 0xc8} }, +{ 0x0096, 16, {0xe0, 0x20, 0xe1, 0x2b, 0x12, 0x13, 0xc0, 0xef, 0xc3, 0x94, 0x40, 0x50, 0x22, 0x90, 0x7d, 0xc0} }, +{ 0x00a6, 16, {0xe0, 0x13, 0x92, 0x08, 0x90, 0x7f, 0xc9, 0xe0, 0x14, 0xf5, 0x08, 0x7e, 0x7d, 0x7f, 0xc1, 0x75} }, +{ 0x00b6, 16, {0x0c, 0x7d, 0x75, 0x0d, 0xc1, 0x12, 0x0d, 0x55, 0xd2, 0x02, 0xe4, 0x90, 0x7f, 0xc9, 0xf0, 0x90} }, +{ 0x00c6, 16, {0x7f, 0xb6, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x01, 0x53, 0x53, 0x36, 0x80, 0x12, 0x13, 0xcc, 0xef} }, +{ 0x00d6, 16, {0x42, 0x36, 0x12, 0x12, 0x49, 0x8f, 0x19, 0xef, 0xc3, 0x95, 0x3a, 0x50, 0x0f, 0x12, 0x13, 0xa8} }, +{ 0x00e6, 16, {0xef, 0x30, 0xe0, 0x08, 0xe5, 0x36, 0x20, 0xe7, 0x03, 0x30, 0x0a, 0x61, 0xc2, 0x0a, 0xe5, 0x19} }, +{ 0x00f6, 16, {0x70, 0x04, 0xf5, 0x36, 0x80, 0x57, 0x12, 0x13, 0xcc, 0xef, 0x42, 0x36, 0xe5, 0x36, 0x30, 0xe7} }, +{ 0x0106, 16, {0x26, 0xe5, 0x19, 0xd3, 0x94, 0x20, 0x40, 0x03, 0x75, 0x19, 0x20, 0x85, 0x19, 0x08, 0x7e, 0x7e} }, +{ 0x0116, 16, {0x7f, 0x80, 0x75, 0x0c, 0x7e, 0x75, 0x0d, 0x80, 0xaf, 0x36, 0x12, 0x0f, 0xb7, 0xe5, 0x19, 0x25} }, +{ 0x0126, 16, {0xe0, 0x90, 0x7f, 0xb7, 0xf0, 0x80, 0x26, 0xe5, 0x19, 0xd3, 0x94, 0x3f, 0x40, 0x03, 0x75, 0x19} }, +{ 0x0136, 16, {0x3f, 0x85, 0x19, 0x08, 0xe4, 0x90, 0x7e, 0x80, 0xf0, 0x7e, 0x7e, 0x7f, 0x81, 0x75, 0x0c, 0x7e} }, +{ 0x0146, 16, {0x75, 0x0d, 0x81, 0x12, 0x0d, 0x7a, 0xe5, 0x19, 0x04, 0x90, 0x7f, 0xb7, 0xf0, 0x90, 0x7f, 0xce} }, +{ 0x0156, 16, {0xe0, 0x30, 0xe1, 0x06, 0x20, 0x04, 0x03, 0x02, 0x03, 0xbd, 0xc2, 0x04, 0xe4, 0xf5, 0x18, 0x74} }, +{ 0x0166, 16, {0x40, 0x25, 0x18, 0xf5, 0x82, 0xe4, 0x34, 0x7c, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x18, 0x7c, 0x00} }, +{ 0x0176, 16, {0x7b, 0x01, 0x7a, 0x7e, 0x79, 0x00, 0x24, 0x00, 0xf9, 0xec, 0x34, 0x7e, 0xfa, 0xef, 0x12, 0x0c} }, +{ 0x0186, 16, {0xe5, 0x05, 0x18, 0xe5, 0x18, 0xb4, 0x20, 0xd7, 0x90, 0x7e, 0x00, 0xe0, 0x60, 0x68, 0x90, 0x7e} }, +{ 0x0196, 16, {0x03, 0xe0, 0x60, 0x24, 0x7f, 0x01, 0xe4, 0xfd, 0x12, 0x12, 0x24, 0x7f, 0x03, 0x7d, 0xcd, 0x12} }, +{ 0x01a6, 16, {0x12, 0x24, 0x43, 0x46, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x46} }, +{ 0x01b6, 16, {0xf0, 0xe4, 0x90, 0x7e, 0x13, 0xf0, 0x80, 0x30, 0x90, 0x7e, 0x01, 0xe0, 0xff, 0x12, 0x10, 0xa8} }, +{ 0x01c6, 16, {0x90, 0x7e, 0x02, 0xe0, 0xff, 0x12, 0x10, 0xce, 0x7f, 0x01, 0x90, 0x7e, 0x11, 0xe0, 0xfd, 0x12} }, +{ 0x01d6, 16, {0x12, 0x24, 0x7f, 0x03, 0x7d, 0x07, 0x12, 0x12, 0x24, 0x43, 0x46, 0x80, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x01e6, 16, {0x14, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x46, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x12, 0xf0, 0xe5, 0x40} }, +{ 0x01f6, 16, {0x44, 0x06, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x03, 0xe0, 0x70, 0x06, 0x90, 0x7e, 0x13, 0xe0} }, +{ 0x0206, 16, {0x70, 0x08, 0xe4, 0x90, 0x7e, 0x13, 0xf0, 0x75, 0x25, 0xff, 0x90, 0x7e, 0x05, 0xe0, 0x60, 0x12} }, +{ 0x0216, 16, {0xa3, 0xe0, 0x54, 0x3f, 0xf5, 0x44, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0xe5} }, +{ 0x0226, 16, {0x44, 0xf0, 0x90, 0x7e, 0x07, 0xe0, 0x60, 0x2b, 0xa3, 0xe0, 0x60, 0x05, 0x43, 0x42, 0x80, 0x80} }, +{ 0x0236, 16, {0x03, 0x53, 0x42, 0x7f, 0x53, 0x42, 0xfc, 0x90, 0x7e, 0x09, 0xe0, 0x60, 0x11, 0x43, 0x42, 0x02} }, +{ 0x0246, 16, {0xa3, 0xe0, 0xff, 0x12, 0x11, 0x1a, 0x90, 0x7e, 0x0b, 0xe0, 0xff, 0x12, 0x11, 0x40, 0xaf, 0x42} }, +{ 0x0256, 16, {0x12, 0x10, 0xf4, 0x90, 0x7e, 0x03, 0xe0, 0x60, 0x08, 0x53, 0x42, 0x7f, 0xaf, 0x42, 0x12, 0x10} }, +{ 0x0266, 16, {0xf4, 0x90, 0x7e, 0x0c, 0xe0, 0x60, 0x18, 0xa3, 0xe0, 0x60, 0x05, 0x43, 0x46, 0x02, 0x80, 0x03} }, +{ 0x0276, 16, {0x53, 0x46, 0xfd, 0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x46, 0xf0, 0x90} }, +{ 0x0286, 16, {0x7e, 0x0e, 0xe0, 0x60, 0x18, 0xa3, 0xe0, 0x60, 0x05, 0x43, 0x46, 0x01, 0x80, 0x03, 0x53, 0x46} }, +{ 0x0296, 16, {0xfe, 0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x46, 0xf0, 0x90, 0x7e, 0x12} }, +{ 0x02a6, 16, {0xe0, 0xf5, 0x3a, 0xa3, 0xe0, 0x13, 0x92, 0x0c, 0xa3, 0xe0, 0xf5, 0x3c, 0xa3, 0xe0, 0x60, 0x05} }, +{ 0x02b6, 16, {0x43, 0x46, 0x10, 0x80, 0x03, 0x53, 0x46, 0xef, 0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x90, 0xc0} }, +{ 0x02c6, 16, {0x00, 0xe5, 0x46, 0xf0, 0x90, 0x7e, 0x16, 0xe0, 0x60, 0x32, 0x53, 0x44, 0xbf, 0x90, 0x7f, 0x98} }, +{ 0x02d6, 16, {0x74, 0x13, 0xf0, 0xe5, 0x44, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x11} }, +{ 0x02e6, 16, {0xf0, 0x12, 0x13, 0x9c, 0xef, 0x54, 0xfe, 0x90, 0xc0, 0x00, 0xf0, 0x53, 0x3e, 0xfd, 0xe4, 0xff} }, +{ 0x02f6, 16, {0xad, 0x3e, 0x12, 0x12, 0x24, 0xe4, 0xf5, 0x2a, 0xf5, 0x29, 0xd2, 0x06, 0x90, 0x7e, 0x17, 0xe0} }, +{ 0x0306, 16, {0x60, 0x0f, 0x43, 0x3e, 0x02, 0xe4, 0xff, 0xad, 0x3e, 0x12, 0x12, 0x24, 0x75, 0x29, 0x01, 0xd2} }, +{ 0x0316, 16, {0x06, 0x90, 0x7e, 0x18, 0xe0, 0x60, 0x1b, 0x90, 0x7f, 0x98, 0x74, 0x12, 0xf0, 0xe5, 0x40, 0x44} }, +{ 0x0326, 16, {0x04, 0x90, 0xc0, 0x00, 0xf0, 0xe4, 0x90, 0x7f, 0xc7, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0xd2, 0x02} }, +{ 0x0336, 16, {0xc2, 0x08, 0x90, 0x7e, 0x19, 0xe0, 0x60, 0x11, 0x43, 0x44, 0x40, 0x90, 0x7f, 0x98, 0x74, 0x13} }, +{ 0x0346, 16, {0xf0, 0xe5, 0x44, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x1a, 0xe0, 0x60, 0x0f, 0x53} }, +{ 0x0356, 16, {0x3e, 0xfe, 0xe4, 0xff, 0xad, 0x3e, 0x12, 0x12, 0x24, 0x75, 0x2b, 0x01, 0xd2, 0x06, 0x90, 0x7e} }, +{ 0x0366, 16, {0x1b, 0xe0, 0x60, 0x0f, 0x43, 0x3e, 0x01, 0xe4, 0xff, 0xad, 0x3e, 0x12, 0x12, 0x24, 0xe4, 0xf5} }, +{ 0x0376, 16, {0x2b, 0xd2, 0x06, 0x90, 0x7e, 0x1c, 0xe0, 0x60, 0x0e, 0x90, 0x7f, 0x98, 0x74, 0x12, 0xf0, 0xe5} }, +{ 0x0386, 16, {0x40, 0x44, 0x02, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x1d, 0xe0, 0x60, 0x02, 0xd2, 0x0a, 0x90} }, +{ 0x0396, 16, {0x7e, 0x1e, 0xe0, 0x60, 0x08, 0x75, 0x2c, 0x01, 0xe4, 0xf5, 0x38, 0xd2, 0x06, 0x90, 0x7e, 0x1f} }, +{ 0x03a6, 16, {0xe0, 0x60, 0x0f, 0x90, 0x7f, 0xd7, 0x74, 0x11, 0xf0, 0x74, 0x31, 0xf0, 0x74, 0x15, 0xf0, 0x74} }, +{ 0x03b6, 16, {0x35, 0xf0, 0xe4, 0x90, 0x7f, 0xcf, 0xf0, 0x30, 0x18, 0x52, 0xe5, 0x38, 0x60, 0x02, 0x15, 0x38} }, +{ 0x03c6, 16, {0x20, 0x12, 0x49, 0xe5, 0x13, 0xd3, 0x94, 0x00, 0x40, 0x04, 0x15, 0x13, 0x80, 0x3e, 0x75, 0x13} }, +{ 0x03d6, 16, {0x0a, 0x30, 0x19, 0x02, 0xd2, 0x12, 0x12, 0x13, 0x9c, 0xef, 0x54, 0x01, 0xf5, 0x19, 0x65, 0x2a} }, +{ 0x03e6, 16, {0x60, 0x05, 0x85, 0x19, 0x2a, 0xd2, 0x06, 0x12, 0x13, 0xd8, 0xef, 0x54, 0x80, 0xf5, 0x19, 0x65} }, +{ 0x03f6, 16, {0x26, 0x60, 0x05, 0x85, 0x19, 0x26, 0xd2, 0x06, 0x30, 0x0c, 0x11, 0x12, 0x13, 0xd8, 0xef, 0x54} }, +{ 0x0406, 16, {0x10, 0xf5, 0x19, 0x65, 0x25, 0x60, 0x05, 0x85, 0x19, 0x25, 0xd2, 0x06, 0x20, 0x19, 0x03, 0x02} }, +{ 0x0416, 16, {0x07, 0xe4, 0x30, 0x09, 0x13, 0x12, 0x14, 0x2b, 0xef, 0xc3, 0x95, 0x3d, 0x50, 0x73, 0x90, 0x7f} }, +{ 0x0426, 16, {0xc1, 0x74, 0x01, 0xf0, 0xc2, 0x09, 0x80, 0x69, 0x30, 0x03, 0x34, 0x90, 0x7f, 0xca, 0xe0, 0x20} }, +{ 0x0436, 16, {0xe1, 0x5f, 0x12, 0x14, 0x2b, 0xef, 0xc3, 0x94, 0x40, 0x50, 0x56, 0x90, 0x7d, 0x40, 0xe0, 0x13} }, +{ 0x0446, 16, {0x92, 0x09, 0x90, 0x7f, 0xcb, 0xe0, 0x14, 0xf5, 0x08, 0x7e, 0x7d, 0x7f, 0x41, 0x75, 0x0c, 0x7d} }, +{ 0x0456, 16, {0x75, 0x0d, 0x41, 0x12, 0x0d, 0x9f, 0xc2, 0x03, 0xe4, 0x90, 0x7f, 0xcb, 0xf0, 0x80, 0x32, 0x90} }, +{ 0x0466, 16, {0x7f, 0xcc, 0xe0, 0x20, 0xe1, 0x2b, 0x12, 0x14, 0x2b, 0xef, 0xc3, 0x94, 0x40, 0x50, 0x22, 0x90} }, +{ 0x0476, 16, {0x7c, 0xc0, 0xe0, 0x13, 0x92, 0x09, 0x90, 0x7f, 0xcd, 0xe0, 0x14, 0xf5, 0x08, 0x7e, 0x7c, 0x7f} }, +{ 0x0486, 16, {0xc1, 0x75, 0x0c, 0x7c, 0x75, 0x0d, 0xc1, 0x12, 0x0d, 0x9f, 0xd2, 0x03, 0xe4, 0x90, 0x7f, 0xcd} }, +{ 0x0496, 16, {0xf0, 0x90, 0x7f, 0xba, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x05, 0x25, 0x53, 0x37, 0x80, 0x12, 0x14} }, +{ 0x04a6, 16, {0x37, 0xef, 0x42, 0x37, 0x12, 0x12, 0x93, 0x8f, 0x19, 0xef, 0xc3, 0x95, 0x3b, 0x50, 0x0f, 0x12} }, +{ 0x04b6, 16, {0x14, 0x13, 0xef, 0x30, 0xe0, 0x08, 0xe5, 0x37, 0x20, 0xe7, 0x03, 0x30, 0x0b, 0x61, 0xc2, 0x0b} }, +{ 0x04c6, 16, {0xe5, 0x19, 0x70, 0x04, 0xf5, 0x37, 0x80, 0x57, 0x12, 0x14, 0x37, 0xef, 0x42, 0x37, 0xe5, 0x37} }, +{ 0x04d6, 16, {0x30, 0xe7, 0x26, 0xe5, 0x19, 0xd3, 0x94, 0x20, 0x40, 0x03, 0x75, 0x19, 0x20, 0x85, 0x19, 0x08} }, +{ 0x04e6, 16, {0x7e, 0x7d, 0x7f, 0x80, 0x75, 0x0c, 0x7d, 0x75, 0x0d, 0x80, 0xaf, 0x37, 0x12, 0x0f, 0xf0, 0xe5} }, +{ 0x04f6, 16, {0x19, 0x25, 0xe0, 0x90, 0x7f, 0xbb, 0xf0, 0x80, 0x26, 0xe5, 0x19, 0xd3, 0x94, 0x3f, 0x40, 0x03} }, +{ 0x0506, 16, {0x75, 0x19, 0x3f, 0x85, 0x19, 0x08, 0xe4, 0x90, 0x7d, 0x80, 0xf0, 0x7e, 0x7d, 0x7f, 0x81, 0x75} }, +{ 0x0516, 16, {0x0c, 0x7d, 0x75, 0x0d, 0x81, 0x12, 0x0d, 0xc4, 0xe5, 0x19, 0x04, 0x90, 0x7f, 0xbb, 0xf0, 0x90} }, +{ 0x0526, 16, {0x7f, 0xd0, 0xe0, 0x30, 0xe1, 0x06, 0x20, 0x05, 0x03, 0x02, 0x07, 0x8f, 0xc2, 0x05, 0xe4, 0xf5} }, +{ 0x0536, 16, {0x18, 0x74, 0xc0, 0x25, 0x18, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x18} }, +{ 0x0546, 16, {0x7c, 0x00, 0x7b, 0x01, 0x7a, 0x7e, 0x79, 0x20, 0x24, 0x20, 0xf9, 0xec, 0x34, 0x7e, 0xfa, 0xef} }, +{ 0x0556, 16, {0x12, 0x0c, 0xe5, 0x05, 0x18, 0xe5, 0x18, 0xb4, 0x20, 0xd7, 0x90, 0x7e, 0x20, 0xe0, 0x60, 0x68} }, +{ 0x0566, 16, {0x90, 0x7e, 0x23, 0xe0, 0x60, 0x24, 0x7f, 0x01, 0xe4, 0xfd, 0x12, 0x12, 0x6e, 0x7f, 0x03, 0x7d} }, +{ 0x0576, 16, {0xcd, 0x12, 0x12, 0x6e, 0x43, 0x47, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x0c, 0xf0, 0x90, 0xc0, 0x00} }, +{ 0x0586, 16, {0xe5, 0x47, 0xf0, 0xe4, 0x90, 0x7e, 0x33, 0xf0, 0x80, 0x30, 0x90, 0x7e, 0x21, 0xe0, 0xff, 0x12} }, +{ 0x0596, 16, {0x11, 0x8c, 0x90, 0x7e, 0x22, 0xe0, 0xff, 0x12, 0x11, 0xb2, 0x7f, 0x01, 0x90, 0x7e, 0x31, 0xe0} }, +{ 0x05a6, 16, {0xfd, 0x12, 0x12, 0x6e, 0x7f, 0x03, 0x7d, 0x07, 0x12, 0x12, 0x6e, 0x43, 0x47, 0x80, 0x90, 0x7f} }, +{ 0x05b6, 16, {0x98, 0x74, 0x0c, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x47, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0a, 0xf0} }, +{ 0x05c6, 16, {0xe5, 0x41, 0x44, 0x06, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x23, 0xe0, 0x70, 0x06, 0x90, 0x7e} }, +{ 0x05d6, 16, {0x33, 0xe0, 0x70, 0x08, 0xe4, 0x90, 0x7e, 0x33, 0xf0, 0x75, 0x2e, 0xff, 0x90, 0x7e, 0x25, 0xe0} }, +{ 0x05e6, 16, {0x60, 0x12, 0xa3, 0xe0, 0x54, 0x3f, 0xf5, 0x45, 0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x90, 0xc0} }, +{ 0x05f6, 16, {0x00, 0xe5, 0x45, 0xf0, 0x90, 0x7e, 0x27, 0xe0, 0x60, 0x2b, 0xa3, 0xe0, 0x60, 0x05, 0x43, 0x43} }, +{ 0x0606, 16, {0x80, 0x80, 0x03, 0x53, 0x43, 0x7f, 0x53, 0x43, 0xfc, 0x90, 0x7e, 0x29, 0xe0, 0x60, 0x11, 0x43} }, +{ 0x0616, 16, {0x43, 0x02, 0xa3, 0xe0, 0xff, 0x12, 0x11, 0xd8, 0x90, 0x7e, 0x2b, 0xe0, 0xff, 0x12, 0x11, 0xfe} }, +{ 0x0626, 16, {0xaf, 0x43, 0x12, 0x11, 0x66, 0x90, 0x7e, 0x23, 0xe0, 0x60, 0x08, 0x53, 0x43, 0x7f, 0xaf, 0x43} }, +{ 0x0636, 16, {0x12, 0x11, 0x66, 0x90, 0x7e, 0x2c, 0xe0, 0x60, 0x18, 0xa3, 0xe0, 0x60, 0x05, 0x43, 0x47, 0x02} }, +{ 0x0646, 16, {0x80, 0x03, 0x53, 0x47, 0xfd, 0x90, 0x7f, 0x98, 0x74, 0x0c, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x47} }, +{ 0x0656, 16, {0xf0, 0x90, 0x7e, 0x2e, 0xe0, 0x60, 0x18, 0xa3, 0xe0, 0x60, 0x05, 0x43, 0x47, 0x01, 0x80, 0x03} }, +{ 0x0666, 16, {0x53, 0x47, 0xfe, 0x90, 0x7f, 0x98, 0x74, 0x0c, 0xf0, 0x90, 0xc0, 0x00, 0xe5, 0x47, 0xf0, 0x90} }, +{ 0x0676, 16, {0x7e, 0x32, 0xe0, 0xf5, 0x3b, 0xa3, 0xe0, 0x13, 0x92, 0x0d, 0xa3, 0xe0, 0xf5, 0x3d, 0xa3, 0xe0} }, +{ 0x0686, 16, {0x60, 0x05, 0x43, 0x47, 0x10, 0x80, 0x03, 0x53, 0x47, 0xef, 0x90, 0x7f, 0x98, 0x74, 0x0c, 0xf0} }, +{ 0x0696, 16, {0x90, 0xc0, 0x00, 0xe5, 0x47, 0xf0, 0x90, 0x7e, 0x36, 0xe0, 0x60, 0x32, 0x53, 0x45, 0xbf, 0x90} }, +{ 0x06a6, 16, {0x7f, 0x98, 0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7f, 0x98} }, +{ 0x06b6, 16, {0x74, 0x09, 0xf0, 0x12, 0x13, 0xf0, 0xef, 0x54, 0xfe, 0x90, 0xc0, 0x00, 0xf0, 0x53, 0x3f, 0xfd} }, +{ 0x06c6, 16, {0xe4, 0xff, 0xad, 0x3f, 0x12, 0x12, 0x6e, 0xe4, 0xf5, 0x33, 0xf5, 0x32, 0xd2, 0x07, 0x90, 0x7e} }, +{ 0x06d6, 16, {0x37, 0xe0, 0x60, 0x0f, 0x43, 0x3f, 0x02, 0xe4, 0xff, 0xad, 0x3f, 0x12, 0x12, 0x6e, 0x75, 0x32} }, +{ 0x06e6, 16, {0x01, 0xd2, 0x07, 0x90, 0x7e, 0x38, 0xe0, 0x60, 0x1b, 0x90, 0x7f, 0x98, 0x74, 0x0a, 0xf0, 0xe5} }, +{ 0x06f6, 16, {0x41, 0x44, 0x04, 0x90, 0xc0, 0x00, 0xf0, 0xe4, 0x90, 0x7f, 0xcb, 0xf0, 0x90, 0x7f, 0xcd, 0xf0} }, +{ 0x0706, 16, {0xd2, 0x03, 0xc2, 0x09, 0x90, 0x7e, 0x39, 0xe0, 0x60, 0x11, 0x43, 0x45, 0x40, 0x90, 0x7f, 0x98} }, +{ 0x0716, 16, {0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x3a, 0xe0, 0x60} }, +{ 0x0726, 16, {0x0f, 0x53, 0x3f, 0xfe, 0xe4, 0xff, 0xad, 0x3f, 0x12, 0x12, 0x6e, 0x75, 0x34, 0x01, 0xd2, 0x07} }, +{ 0x0736, 16, {0x90, 0x7e, 0x3b, 0xe0, 0x60, 0x0f, 0x43, 0x3f, 0x01, 0xe4, 0xff, 0xad, 0x3f, 0x12, 0x12, 0x6e} }, +{ 0x0746, 16, {0xe4, 0xf5, 0x34, 0xd2, 0x07, 0x90, 0x7e, 0x3c, 0xe0, 0x60, 0x0e, 0x90, 0x7f, 0x98, 0x74, 0x0a} }, +{ 0x0756, 16, {0xf0, 0xe5, 0x41, 0x44, 0x02, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7e, 0x3d, 0xe0, 0x60, 0x02, 0xd2} }, +{ 0x0766, 16, {0x0b, 0x90, 0x7e, 0x3e, 0xe0, 0x60, 0x08, 0x75, 0x35, 0x01, 0xe4, 0xf5, 0x39, 0xd2, 0x07, 0x90} }, +{ 0x0776, 16, {0x7e, 0x3f, 0xe0, 0x60, 0x0f, 0x90, 0x7f, 0xd7, 0x74, 0x13, 0xf0, 0x74, 0x33, 0xf0, 0x74, 0x16} }, +{ 0x0786, 16, {0xf0, 0x74, 0x36, 0xf0, 0xe4, 0x90, 0x7f, 0xd1, 0xf0, 0x30, 0x18, 0x52, 0xe5, 0x39, 0x60, 0x02} }, +{ 0x0796, 16, {0x15, 0x39, 0x30, 0x12, 0x49, 0xe5, 0x13, 0xd3, 0x94, 0x00, 0x40, 0x04, 0x15, 0x13, 0x80, 0x3e} }, +{ 0x07a6, 16, {0x75, 0x13, 0x0a, 0x30, 0x19, 0x02, 0xc2, 0x12, 0x12, 0x13, 0xf0, 0xef, 0x54, 0x01, 0xf5, 0x19} }, +{ 0x07b6, 16, {0x65, 0x33, 0x60, 0x05, 0x85, 0x19, 0x33, 0xd2, 0x07, 0x12, 0x14, 0x43, 0xef, 0x54, 0x80, 0xf5} }, +{ 0x07c6, 16, {0x19, 0x65, 0x2f, 0x60, 0x05, 0x85, 0x19, 0x2f, 0xd2, 0x07, 0x30, 0x0d, 0x11, 0x12, 0x14, 0x43} }, +{ 0x07d6, 16, {0xef, 0x54, 0x10, 0xf5, 0x19, 0x65, 0x2e, 0x60, 0x05, 0x85, 0x19, 0x2e, 0xd2, 0x07, 0x30, 0x18} }, +{ 0x07e6, 16, {0x2a, 0x90, 0x7f, 0xd2, 0xe0, 0x20, 0xe1, 0x23, 0x90, 0x7b, 0x40, 0xe0, 0x60, 0x09, 0xe0, 0xf5} }, +{ 0x07f6, 16, {0x15, 0x90, 0x7b, 0x42, 0xe0, 0xf5, 0x16, 0x90, 0x7b, 0x41, 0xe0, 0x60, 0x09, 0x90, 0x7f, 0xd7} }, +{ 0x0806, 16, {0x74, 0x17, 0xf0, 0x74, 0x37, 0xf0, 0xe4, 0x90, 0x7f, 0xd3, 0xf0, 0x90, 0x7f, 0xc2, 0xe0, 0x30} }, +{ 0x0816, 16, {0xe1, 0x03, 0x02, 0x09, 0x18, 0xe5, 0x0a, 0x70, 0x40, 0x30, 0x06, 0x39, 0xe5, 0x38, 0x70, 0x35} }, +{ 0x0826, 16, {0xc2, 0x06, 0xf5, 0x18, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x24, 0x25, 0x18, 0xf9, 0xee, 0x34, 0x00} }, +{ 0x0836, 16, {0xfa, 0x12, 0x0c, 0x9f, 0xff, 0x74, 0x80, 0x25, 0x18, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83} }, +{ 0x0846, 16, {0xef, 0xf0, 0x05, 0x18, 0xe5, 0x18, 0xb4, 0x09, 0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x09, 0xf0, 0x75} }, +{ 0x0856, 16, {0x38, 0x10, 0xe4, 0xf5, 0x2c, 0x75, 0x0a, 0x01, 0x22, 0xe5, 0x0a, 0x64, 0x01, 0x70, 0x40, 0x30} }, +{ 0x0866, 16, {0x07, 0x39, 0xe5, 0x39, 0x70, 0x35, 0xc2, 0x07, 0xf5, 0x18, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x2d} }, +{ 0x0876, 16, {0x25, 0x18, 0xf9, 0xee, 0x34, 0x00, 0xfa, 0x12, 0x0c, 0x9f, 0xff, 0x74, 0x80, 0x25, 0x18, 0xf5} }, +{ 0x0886, 16, {0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x18, 0xe5, 0x18, 0xb4, 0x09, 0xdb, 0x90} }, +{ 0x0896, 16, {0x7f, 0xc3, 0x74, 0x09, 0xf0, 0x75, 0x39, 0x10, 0xe4, 0xf5, 0x35, 0x75, 0x0a, 0x02, 0x22, 0xe5} }, +{ 0x08a6, 16, {0x0a, 0x64, 0x02, 0x70, 0x36, 0x30, 0x13, 0x2f, 0xc2, 0x13, 0xf5, 0x18, 0x7e, 0x00, 0x7b, 0x00} }, +{ 0x08b6, 16, {0x74, 0x0e, 0x25, 0x18, 0xf9, 0xee, 0x34, 0x00, 0xfa, 0x12, 0x0c, 0x9f, 0xff, 0x74, 0x80, 0x25} }, +{ 0x08c6, 16, {0x18, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x18, 0xe5, 0x18, 0xb4, 0x05} }, +{ 0x08d6, 16, {0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x05, 0xf0, 0x75, 0x0a, 0x03, 0x22, 0xe5, 0x15, 0x60, 0x30, 0x15} }, +{ 0x08e6, 16, {0x15, 0xe4, 0xf5, 0x18, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x14, 0x25, 0x18, 0xf9, 0xee, 0x34, 0x00} }, +{ 0x08f6, 16, {0xfa, 0x12, 0x0c, 0x9f, 0xff, 0x74, 0x80, 0x25, 0x18, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83} }, +{ 0x0906, 16, {0xef, 0xf0, 0x05, 0x18, 0xe5, 0x18, 0xb4, 0x03, 0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x03, 0xf0, 0xe4} }, +{ 0x0916, 2, {0xf5, 0x0a} }, +{ 0x0918, 1, {0x22} }, +{ 0x0919, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x12, 0x0d, 0x2f, 0x09, 0xe9, 0x00, 0x0a, 0x5d, 0x01, 0x0a, 0xc9, 0x03} }, +{ 0x0929, 16, {0x09, 0x3c, 0x06, 0x09, 0xdc, 0x08, 0x09, 0xd6, 0x09, 0x09, 0xbe, 0x0a, 0x09, 0xcd, 0x0b, 0x00} }, +{ 0x0939, 16, {0x00, 0x0b, 0x18, 0x90, 0x7f, 0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x40, 0x24, 0x02} }, +{ 0x0949, 16, {0x70, 0x69, 0x74, 0x19, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x0b} }, +{ 0x0959, 16, {0x1f, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x0f, 0x27, 0x8b, 0x18, 0x8a, 0x19, 0x89, 0x1a, 0xea} }, +{ 0x0969, 16, {0x49, 0x60, 0x11, 0xae, 0x02, 0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5} }, +{ 0x0979, 16, {0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f} }, +{ 0x0989, 16, {0xea, 0xe0, 0xff, 0x12, 0x0f, 0x76, 0x8b, 0x18, 0x8a, 0x19, 0x89, 0x1a, 0xea, 0x49, 0x60, 0x11} }, +{ 0x0999, 16, {0xae, 0x02, 0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x0b} }, +{ 0x09a9, 16, {0x1f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xb4, 0xe0, 0x44} }, +{ 0x09b9, 16, {0x01, 0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0x00, 0xe5, 0x09, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01} }, +{ 0x09c9, 16, {0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x09, 0x02, 0x0b, 0x1f, 0x12, 0x0b, 0x27} }, +{ 0x09d9, 16, {0x02, 0x0b, 0x1f, 0x90, 0x7f, 0x00, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb5, 0xf0, 0x02, 0x0b, 0x1f} }, +{ 0x09e9, 16, {0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b, 0xa2} }, +{ 0x09f9, 16, {0x0f, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x14, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0} }, +{ 0x0a09, 16, {0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x0b, 0x1f, 0xe4, 0x90, 0x7f, 0x00} }, +{ 0x0a19, 16, {0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xec, 0xe0} }, +{ 0x0a29, 16, {0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4} }, +{ 0x0a39, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3} }, +{ 0x0a49, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01} }, +{ 0x0a59, 16, {0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, 0x60, 0x03} }, +{ 0x0a69, 16, {0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x05, 0xc2, 0x0f, 0x02, 0x0b, 0x1f, 0x90} }, +{ 0x0a79, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x0b, 0x1f, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x38, 0x90} }, +{ 0x0a89, 16, {0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25} }, +{ 0x0a99, 16, {0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0} }, +{ 0x0aa9, 16, {0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7} }, +{ 0x0ab9, 16, {0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x5f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x56} }, +{ 0x0ac9, 16, {0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x4a, 0x90, 0x7f, 0xea, 0xe0} }, +{ 0x0ad9, 16, {0xb4, 0x01, 0x04, 0xd2, 0x0f, 0x80, 0x3f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x36} }, +{ 0x0ae9, 16, {0x90, 0x7f, 0xea, 0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54} }, +{ 0x0af9, 16, {0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5} }, +{ 0x0b09, 16, {0x83, 0x74, 0x01, 0xf0, 0x80, 0x10, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x07, 0x90} }, +{ 0x0b19, 13, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} }, +{ 0x0b26, 1, {0x22} }, +{ 0x0b27, 16, {0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0x18, 0xf0, 0xe4, 0x90, 0x7f, 0x96, 0xf0} }, +{ 0x0b37, 16, {0x90, 0x7f, 0x95, 0x74, 0xc0, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x3f, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x0b47, 16, {0x18, 0xf0, 0xe4, 0xf5, 0x8e, 0x90, 0x7f, 0xdf, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xde, 0xf0, 0xe4} }, +{ 0x0b57, 16, {0xf5, 0x24, 0x75, 0x1b, 0x01, 0x7b, 0x00, 0x74, 0x24, 0x25, 0x1b, 0xf9, 0xe4, 0x34, 0x00, 0xfa} }, +{ 0x0b67, 16, {0xe4, 0x12, 0x0c, 0xe5, 0x05, 0x1b, 0xe5, 0x1b, 0xb4, 0x09, 0xea, 0x75, 0x3a, 0x01, 0xe4, 0xf5} }, +{ 0x0b77, 16, {0x38, 0xf5, 0x13, 0xf5, 0x36, 0xc2, 0x06, 0xc2, 0x0a, 0xc2, 0x04, 0xc2, 0x08, 0xc2, 0x12, 0xd2} }, +{ 0x0b87, 16, {0x02, 0xd2, 0x00, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x75, 0x44, 0x03, 0x90, 0xc0, 0x00, 0x74} }, +{ 0x0b97, 16, {0x03, 0xf0, 0x7f, 0x0c, 0xe4, 0xfd, 0x12, 0x12, 0x24, 0x7f, 0x10, 0x8f, 0x42, 0x12, 0x10, 0xf4} }, +{ 0x0ba7, 16, {0x90, 0x7f, 0x98, 0x74, 0x12, 0xf0, 0x7f, 0x01, 0x8f, 0x40, 0xef, 0x44, 0x06, 0x90, 0xc0, 0x00} }, +{ 0x0bb7, 16, {0xf0, 0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x75, 0x46, 0x80, 0x90, 0xc0, 0x00, 0x74, 0x80, 0xf0} }, +{ 0x0bc7, 16, {0x0f, 0xe4, 0xfd, 0x12, 0x12, 0x24, 0xe4, 0xff, 0x7e, 0xa3, 0xad, 0x06, 0x8d, 0x3e, 0x12, 0x12} }, +{ 0x0bd7, 16, {0x24, 0x90, 0x7f, 0x98, 0x74, 0x11, 0xf0, 0x90, 0xc0, 0x00, 0xe4, 0xf0, 0x7f, 0x05, 0x7d, 0x7f} }, +{ 0x0be7, 16, {0x12, 0x12, 0x24, 0x7f, 0x01, 0x12, 0x13, 0x27, 0x7f, 0x03, 0x7d, 0x07, 0x12, 0x12, 0x24, 0x20} }, +{ 0x0bf7, 16, {0x19, 0x03, 0x02, 0x0c, 0x9c, 0x75, 0x2d, 0x01, 0x75, 0x1b, 0x01, 0x7b, 0x00, 0x74, 0x2d, 0x25} }, +{ 0x0c07, 16, {0x1b, 0xf9, 0xe4, 0x34, 0x00, 0xfa, 0xe4, 0x12, 0x0c, 0xe5, 0x05, 0x1b, 0xe5, 0x1b, 0xb4, 0x09} }, +{ 0x0c17, 16, {0xea, 0x75, 0x3b, 0x01, 0xe4, 0xf5, 0x39, 0xf5, 0x13, 0xf5, 0x37, 0xc2, 0x07, 0xc2, 0x0b, 0xc2} }, +{ 0x0c27, 16, {0x05, 0xc2, 0x09, 0xc2, 0x12, 0xd2, 0x03, 0xd2, 0x01, 0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x75} }, +{ 0x0c37, 16, {0x45, 0x03, 0x90, 0xc0, 0x00, 0x74, 0x03, 0xf0, 0x7f, 0x0c, 0xe4, 0xfd, 0x12, 0x12, 0x6e, 0x7f} }, +{ 0x0c47, 16, {0x10, 0x8f, 0x43, 0x12, 0x11, 0x66, 0x90, 0x7f, 0x98, 0x74, 0x0a, 0xf0, 0x7f, 0x01, 0x8f, 0x41} }, +{ 0x0c57, 16, {0xef, 0x44, 0x06, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0c, 0xf0, 0x75, 0x47, 0x80} }, +{ 0x0c67, 16, {0x90, 0xc0, 0x00, 0x74, 0x80, 0xf0, 0x0f, 0xe4, 0xfd, 0x12, 0x12, 0x6e, 0xe4, 0xff, 0x7e, 0xa3} }, +{ 0x0c77, 16, {0xad, 0x06, 0x8d, 0x3f, 0x12, 0x12, 0x6e, 0x90, 0x7f, 0x98, 0x74, 0x09, 0xf0, 0x90, 0xc0, 0x00} }, +{ 0x0c87, 16, {0xe4, 0xf0, 0x7f, 0x05, 0x7d, 0x7f, 0x12, 0x12, 0x6e, 0x7f, 0x01, 0x12, 0x13, 0x48, 0x7f, 0x03} }, +{ 0x0c97, 7, {0x7d, 0x07, 0x12, 0x12, 0x6e, 0xd2, 0x11} }, +{ 0x0c9e, 1, {0x22} }, +{ 0x0c9f, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} }, +{ 0x0caf, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x0cb8, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} }, +{ 0x0cc8, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} }, +{ 0x0cd8, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x0ce5, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01} }, +{ 0x0cf5, 2, {0xf3, 0x22} }, +{ 0x0cf7, 16, {0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} }, +{ 0x0d07, 16, {0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} }, +{ 0x0d17, 16, {0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} }, +{ 0x0d27, 8, {0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} }, +{ 0x0d2f, 16, {0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3} }, +{ 0x0d3f, 16, {0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60} }, +{ 0x0d4f, 6, {0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf} }, +{ 0x0d55, 16, {0x90, 0x7f, 0x98, 0x74, 0x10, 0xf0, 0xaf, 0x08, 0xe5, 0x0d, 0xf5, 0x82, 0xe5, 0x0c, 0xf5, 0x83} }, +{ 0x0d65, 16, {0xc2, 0xaf, 0x05, 0x86, 0x90, 0xc0, 0x00, 0x05, 0x86, 0xe0, 0xa3, 0x05, 0x86, 0xf0, 0x05, 0x86} }, +{ 0x0d75, 16, {0xdf, 0xf7, 0xd2, 0xaf, 0x22, 0x90, 0x7f, 0x98, 0x74, 0x10, 0xf0, 0xaf, 0x08, 0xe5, 0x0d, 0xf5} }, +{ 0x0d85, 16, {0x82, 0xe5, 0x0c, 0xf5, 0x83, 0xc2, 0xaf, 0x05, 0x86, 0x90, 0xc0, 0x00, 0xe0, 0x05, 0x86, 0xf0} }, +{ 0x0d95, 16, {0xa3, 0x05, 0x86, 0xdf, 0xf7, 0x05, 0x86, 0xd2, 0xaf, 0x22, 0x90, 0x7f, 0x98, 0x74, 0x08, 0xf0} }, +{ 0x0da5, 16, {0xaf, 0x08, 0xe5, 0x0d, 0xf5, 0x82, 0xe5, 0x0c, 0xf5, 0x83, 0xc2, 0xaf, 0x05, 0x86, 0x90, 0xc0} }, +{ 0x0db5, 16, {0x00, 0x05, 0x86, 0xe0, 0xa3, 0x05, 0x86, 0xf0, 0x05, 0x86, 0xdf, 0xf7, 0xd2, 0xaf, 0x22, 0x90} }, +{ 0x0dc5, 16, {0x7f, 0x98, 0x74, 0x08, 0xf0, 0xaf, 0x08, 0xe5, 0x0d, 0xf5, 0x82, 0xe5, 0x0c, 0xf5, 0x83, 0xc2} }, +{ 0x0dd5, 16, {0xaf, 0x05, 0x86, 0x90, 0xc0, 0x00, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xdf, 0xf7, 0x05} }, +{ 0x0de5, 4, {0x86, 0xd2, 0xaf, 0x22} }, +{ 0x0de9, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} }, +{ 0x0df9, 1, {0x22} }, +{ 0x0dfa, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} }, +{ 0x0e0a, 16, {0xd2, 0x17, 0x90, 0x7f, 0x92, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0x7f, 0xae, 0xe0, 0xff, 0xd3, 0x92} }, +{ 0x0e1a, 16, {0x0f, 0xe4, 0x33, 0xfe, 0xef, 0x4e, 0xf0, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xde, 0x74} }, +{ 0x0e2a, 16, {0x01, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9, 0xf0} }, +{ 0x0e3a, 16, {0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f} }, +{ 0x0e4a, 16, {0xae, 0xe0, 0x44, 0x0d, 0xf0, 0xd2, 0xaf, 0xd2, 0x18, 0x12, 0x13, 0x02, 0xc2, 0x10, 0xe4, 0xf5} }, +{ 0x0e5a, 16, {0x0b, 0xf5, 0x13, 0xc2, 0x15, 0xc2, 0x11, 0x90, 0x7f, 0xa1, 0x04, 0xf0, 0x90, 0x7f, 0xd8, 0xe0} }, +{ 0x0e6a, 16, {0x65, 0x17, 0x60, 0x10, 0x30, 0x11, 0x05, 0xd2, 0x18, 0x12, 0x00, 0x46, 0x90, 0x7f, 0xd8, 0xe0} }, +{ 0x0e7a, 16, {0xf5, 0x17, 0x80, 0x08, 0x30, 0x11, 0x05, 0xc2, 0x18, 0x12, 0x00, 0x46, 0x30, 0x10, 0x07, 0xc2} }, +{ 0x0e8a, 16, {0x10, 0x12, 0x09, 0x19, 0x80, 0xd6, 0x30, 0x16, 0xd3, 0xc2, 0x16, 0x12, 0x14, 0x4f, 0x80, 0xcc} }, +{ 0x0e9a, 1, {0x22} }, +{ 0x0e9b, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x47, 0x02, 0x0e, 0xe2} }, +{ 0x0ea7, 16, {0x02, 0x0e, 0x0a, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} }, +{ 0x0eb7, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} }, +{ 0x0ec7, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} }, +{ 0x0ed7, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x13, 0x69, 0xe4, 0x7e} }, +{ 0x0ee7, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} }, +{ 0x0ef7, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} }, +{ 0x0f07, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} }, +{ 0x0f17, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} }, +{ 0x0f27, 16, {0xe4, 0xfe, 0x75, 0x1d, 0xff, 0x75, 0x1e, 0x19, 0x75, 0x1f, 0x12, 0xab, 0x1d, 0xaa, 0x1e, 0xa9} }, +{ 0x0f37, 16, {0x1f, 0x90, 0x00, 0x01, 0x12, 0x0c, 0xb8, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} }, +{ 0x0f47, 16, {0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x0c, 0xf7, 0x85, 0xf0, 0x1b, 0xf5, 0x1c, 0x62, 0x1b} }, +{ 0x0f57, 16, {0xe5, 0x1b, 0x62, 0x1c, 0xe5, 0x1c, 0x62, 0x1b, 0x29, 0xfd, 0xe5, 0x1b, 0x3a, 0xa9, 0x05, 0x75} }, +{ 0x0f67, 14, {0x1d, 0xff, 0xf5, 0x1e, 0x89, 0x1f, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x0f75, 1, {0x22} }, +{ 0x0f76, 2, {0x8f, 0x1b} }, +{ 0x0f78, 16, {0xe4, 0xf5, 0x1c, 0x75, 0x1d, 0xff, 0x75, 0x1e, 0x19, 0x75, 0x1f, 0x86, 0xab, 0x1d, 0xaa, 0x1e} }, +{ 0x0f88, 16, {0xa9, 0x1f, 0x90, 0x00, 0x01, 0x12, 0x0c, 0xb8, 0xb4, 0x03, 0x1d, 0xaf, 0x1c, 0x05, 0x1c, 0xef} }, +{ 0x0f98, 16, {0xb5, 0x1b, 0x01, 0x22, 0x12, 0x0c, 0x9f, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} }, +{ 0x0fa8, 14, {0x1d, 0xff, 0xf5, 0x1e, 0x89, 0x1f, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x0fb6, 1, {0x22} }, +{ 0x0fb7, 16, {0x8f, 0x1a, 0x05, 0x0d, 0xe5, 0x0d, 0xae, 0x0c, 0x70, 0x02, 0x05, 0x0c, 0x14, 0xf5, 0x82, 0x8e} }, +{ 0x0fc7, 16, {0x83, 0xe5, 0x1a, 0xf0, 0x12, 0x00, 0x36, 0x05, 0x0d, 0xe5, 0x0d, 0xac, 0x0c, 0x70, 0x02, 0x05} }, +{ 0x0fd7, 16, {0x0c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x15, 0x08, 0xe5, 0x08, 0x60, 0x0a, 0x12, 0x13} }, +{ 0x0fe7, 9, {0xcc, 0x8f, 0x1a, 0xef, 0x42, 0x36, 0x80, 0xca, 0x22} }, +{ 0x0ff0, 16, {0x8f, 0x1a, 0x05, 0x0d, 0xe5, 0x0d, 0xae, 0x0c, 0x70, 0x02, 0x05, 0x0c, 0x14, 0xf5, 0x82, 0x8e} }, +{ 0x1000, 16, {0x83, 0xe5, 0x1a, 0xf0, 0x12, 0x13, 0xe4, 0x05, 0x0d, 0xe5, 0x0d, 0xac, 0x0c, 0x70, 0x02, 0x05} }, +{ 0x1010, 16, {0x0c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x15, 0x08, 0xe5, 0x08, 0x60, 0x0a, 0x12, 0x14} }, +{ 0x1020, 9, {0x37, 0x8f, 0x1a, 0xef, 0x42, 0x37, 0x80, 0xca, 0x22} }, +{ 0x1029, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x30} }, +{ 0x1039, 16, {0x1a, 0x04, 0xc2, 0x1a, 0x80, 0x02, 0xd2, 0x16, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} }, +{ 0x1049, 14, {0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x1057, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x90} }, +{ 0x1067, 16, {0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x04, 0xf0, 0xd0, 0x86, 0xd0} }, +{ 0x1077, 10, {0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x1081, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xd2} }, +{ 0x1091, 16, {0x10, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85} }, +{ 0x10a1, 7, {0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x10a8, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x10b8, 16, {0x10, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x44, 0x54} }, +{ 0x10c8, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x10ce, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x10de, 16, {0x11, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x44, 0x54} }, +{ 0x10ee, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x10f4, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x1104, 16, {0x12, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x44, 0x54} }, +{ 0x1114, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x111a, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x112a, 16, {0x14, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x44, 0x54} }, +{ 0x113a, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x1140, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x1150, 16, {0x16, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x44, 0x54} }, +{ 0x1160, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x1166, 16, {0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x1176, 16, {0x0a, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54} }, +{ 0x1186, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x118c, 16, {0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x119c, 16, {0x08, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54} }, +{ 0x11ac, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x11b2, 16, {0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x11c2, 16, {0x09, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54} }, +{ 0x11d2, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x11d8, 16, {0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x11e8, 16, {0x0c, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54} }, +{ 0x11f8, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x11fe, 16, {0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x120e, 16, {0x0e, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54} }, +{ 0x121e, 6, {0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x1224, 16, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0xe5, 0x44, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7f} }, +{ 0x1234, 16, {0x98, 0x74, 0x17, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x15, 0xf0, 0x90} }, +{ 0x1244, 5, {0xc0, 0x00, 0xed, 0xf0, 0x22} }, +{ 0x1249, 16, {0x12, 0x13, 0xb4, 0x8f, 0x1a, 0x12, 0x13, 0xb4, 0x8f, 0x1b, 0xe5, 0x1a, 0x65, 0x1b, 0x60, 0x12} }, +{ 0x1259, 16, {0x12, 0x13, 0xb4, 0x8f, 0x1a, 0xe5, 0x1a, 0x65, 0x1b, 0x60, 0x07, 0x12, 0x13, 0xb4, 0x8f, 0x1b} }, +{ 0x1269, 4, {0x80, 0xe8, 0xaf, 0x1a} }, +{ 0x126d, 1, {0x22} }, +{ 0x126e, 16, {0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0xe5, 0x45, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x7f} }, +{ 0x127e, 16, {0x98, 0x74, 0x0f, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x0d, 0xf0, 0x90} }, +{ 0x128e, 5, {0xc0, 0x00, 0xed, 0xf0, 0x22} }, +{ 0x1293, 16, {0x12, 0x14, 0x1f, 0x8f, 0x1a, 0x12, 0x14, 0x1f, 0x8f, 0x1b, 0xe5, 0x1a, 0x65, 0x1b, 0x60, 0x12} }, +{ 0x12a3, 16, {0x12, 0x14, 0x1f, 0x8f, 0x1a, 0xe5, 0x1a, 0x65, 0x1b, 0x60, 0x07, 0x12, 0x14, 0x1f, 0x8f, 0x1b} }, +{ 0x12b3, 4, {0x80, 0xe8, 0xaf, 0x1a} }, +{ 0x12b7, 1, {0x22} }, +{ 0x12b8, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} }, +{ 0x12c8, 16, {0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82} }, +{ 0x12d8, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x12dd, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} }, +{ 0x12ed, 16, {0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82} }, +{ 0x12fd, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x1302, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x18, 0x04, 0xe0, 0x44} }, +{ 0x1312, 16, {0x02, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x13, 0x85, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} }, +{ 0x1322, 5, {0xe0, 0x44, 0x04, 0xf0, 0x22} }, +{ 0x1327, 16, {0xae, 0x07, 0xe4, 0xff, 0xe5, 0x3e, 0x54, 0x7f, 0xfd, 0x12, 0x12, 0x24, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x1337, 16, {0x11, 0xf0, 0x90, 0xc0, 0x00, 0xee, 0xf0, 0xe4, 0xe5, 0x3e, 0x44, 0x80, 0xfd, 0x12, 0x12, 0x24} }, +{ 0x1347, 1, {0x22} }, +{ 0x1348, 16, {0xae, 0x07, 0xe4, 0xff, 0xe5, 0x3f, 0x54, 0x7f, 0xfd, 0x12, 0x12, 0x6e, 0x90, 0x7f, 0x98, 0x74} }, +{ 0x1358, 16, {0x09, 0xf0, 0x90, 0xc0, 0x00, 0xee, 0xf0, 0xe4, 0xe5, 0x3f, 0x44, 0x80, 0xfd, 0x12, 0x12, 0x6e} }, +{ 0x1368, 1, {0x22} }, +{ 0x1369, 16, {0x05, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x14, 0x03, 0x00, 0x00, 0xc1, 0x10, 0xc1, 0x16} }, +{ 0x1379, 7, {0xc1, 0x0f, 0xc1, 0x94, 0x01, 0x0a, 0x00} }, +{ 0x1380, 2, {0xc1, 0x99} }, +{ 0x1382, 2, {0xc1, 0x9a} }, +{ 0x1384, 1, {0x00} }, +{ 0x1385, 16, {0x8e, 0x18, 0x8f, 0x19, 0xe5, 0x19, 0x15, 0x19, 0xae, 0x18, 0x70, 0x02, 0x15, 0x18, 0x4e, 0x60} }, +{ 0x1395, 7, {0x05, 0x12, 0x0d, 0xe9, 0x80, 0xee, 0x22} }, +{ 0x139c, 12, {0x90, 0x7f, 0x98, 0x74, 0x11, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13a8, 12, {0x90, 0x7f, 0x98, 0x74, 0x12, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13b4, 12, {0x90, 0x7f, 0x98, 0x74, 0x13, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13c0, 12, {0x90, 0x7f, 0x98, 0x74, 0x14, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13cc, 12, {0x90, 0x7f, 0x98, 0x74, 0x15, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13d8, 12, {0x90, 0x7f, 0x98, 0x74, 0x16, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13e4, 12, {0x90, 0x7f, 0x98, 0x74, 0x08, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13f0, 12, {0x90, 0x7f, 0x98, 0x74, 0x09, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x13fc, 4, {0x53, 0xd8, 0xef, 0x32} }, +{ 0x1400, 16, {0x02, 0x10, 0x81, 0x00, 0x02, 0x12, 0xb8, 0x00, 0x02, 0x10, 0x57, 0x00, 0x02, 0x10, 0x29, 0x00} }, +{ 0x1410, 3, {0x02, 0x12, 0xdd} }, +{ 0x1413, 12, {0x90, 0x7f, 0x98, 0x74, 0x0a, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x141f, 12, {0x90, 0x7f, 0x98, 0x74, 0x0b, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x142b, 12, {0x90, 0x7f, 0x98, 0x74, 0x0c, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x1437, 12, {0x90, 0x7f, 0x98, 0x74, 0x0d, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x1443, 12, {0x90, 0x7f, 0x98, 0x74, 0x0e, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x144f, 10, {0x12, 0x00, 0x03, 0x12, 0x0d, 0xfa, 0x12, 0x0b, 0x27, 0x22} }, +{ 0x1900, 16, {0x12, 0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x40, 0xcd, 0x06, 0x10, 0x01, 0x00, 0x00, 0x01, 0x02} }, +{ 0x1910, 16, {0x00, 0x01, 0x09, 0x02, 0x74, 0x00, 0x01, 0x01, 0x00, 0xa0, 0x32, 0x09, 0x04, 0x00, 0x00, 0x0e} }, +{ 0x1920, 16, {0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} }, +{ 0x1930, 16, {0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, 0x00} }, +{ 0x1940, 16, {0x07, 0x05, 0x05, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x06, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05} }, +{ 0x1950, 16, {0x07, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x82, 0x02} }, +{ 0x1960, 16, {0x40, 0x00, 0x00, 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00} }, +{ 0x1970, 16, {0x00, 0x07, 0x05, 0x85, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x86, 0x02, 0x40, 0x00, 0x00, 0x07} }, +{ 0x1980, 16, {0x05, 0x87, 0x02, 0x40, 0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x48, 0x03, 0x4b, 0x00, 0x65, 0x00} }, +{ 0x1990, 16, {0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00} }, +{ 0x19a0, 16, {0x20, 0x00, 0x64, 0x00, 0x69, 0x00, 0x76, 0x00, 0x69, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00} }, +{ 0x19b0, 16, {0x6e, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x6e, 0x00} }, +{ 0x19c0, 16, {0x6f, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00} }, +{ 0x19d0, 16, {0x2e, 0x00, 0x36, 0x03, 0x4b, 0x00, 0x65, 0x00, 0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00} }, +{ 0x19e0, 16, {0x6e, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53, 0x00, 0x42, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00} }, +{ 0x19f0, 16, {0x72, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x41, 0x00, 0x64, 0x00, 0x61, 0x00} }, +{ 0x1a00, 10, {0x70, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00} }, +{ 0xffff, 0, {0x00} } +}; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/serial/usb-serial.h linux/drivers/usb/serial/usb-serial.h --- v2.4.0-test2/linux/drivers/usb/serial/usb-serial.h Thu May 11 15:30:08 2000 +++ linux/drivers/usb/serial/usb-serial.h Mon Jul 10 14:33:04 2000 @@ -51,6 +51,8 @@ wait_queue_head_t write_wait; + struct tq_struct tqueue; /* task queue for line discipline waking up */ + void * private; /* data private to the specific port */ }; @@ -122,12 +124,22 @@ extern struct usb_serial_device_type ftdi_sio_device; extern struct usb_serial_device_type keyspan_pda_fake_device; extern struct usb_serial_device_type keyspan_pda_device; +extern struct usb_serial_device_type keyspan_usa18x_pre_device; +extern struct usb_serial_device_type keyspan_usa19_pre_device; +extern struct usb_serial_device_type keyspan_usa19w_pre_device; +extern struct usb_serial_device_type keyspan_usa28_pre_device; +extern struct usb_serial_device_type keyspan_usa28x_pre_device; +extern struct usb_serial_device_type keyspan_usa18x_device; +extern struct usb_serial_device_type keyspan_usa19_device; +extern struct usb_serial_device_type keyspan_usa19w_device; +extern struct usb_serial_device_type keyspan_usa28_device; +extern struct usb_serial_device_type keyspan_usa28x_device; extern struct usb_serial_device_type zyxel_omninet_device; extern struct usb_serial_device_type digi_acceleport_device; /* determine if we should include the EzUSB loader functions */ -#if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_WHITEHEAT) +#if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_WHITEHEAT) || defined(CONFIG_USB_SERIAL_KEYSPAN) #define USES_EZUSB_FUNCTIONS extern int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest); extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit); @@ -177,7 +189,6 @@ return 0; } - #endif /* ifdef __LINUX_USB_SERIAL_H */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c --- v2.4.0-test2/linux/drivers/usb/serial/usbserial.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/serial/usbserial.c Mon Jul 10 14:33:04 2000 @@ -14,6 +14,13 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (07/03/2000) gkh + * Added more debugging to serial_ioctl call + * + * (06/25/2000) gkh + * Changed generic_write_bulk_callback to not call wake_up_interruptible + * directly, but to have port_softint do it at a safer time. + * * (06/23/2000) gkh * Cleaned up debugging statements in a quest to find UHCI timeout bug. * @@ -222,6 +229,8 @@ #include #include #include +#include +#include #ifdef CONFIG_USB_SERIAL_DEBUG #define DEBUG @@ -302,6 +311,18 @@ #ifdef CONFIG_USB_SERIAL_DIGI_ACCELEPORT &digi_acceleport_device, #endif +#ifdef CONFIG_USB_SERIAL_KEYSPAN + &keyspan_usa18x_pre_device, + &keyspan_usa19_pre_device, + &keyspan_usa19w_pre_device, + &keyspan_usa28_pre_device, + &keyspan_usa28x_pre_device, + &keyspan_usa18x_device, + &keyspan_usa19_device, + &keyspan_usa19w_device, + &keyspan_usa28_device, + &keyspan_usa28x_device, +#endif NULL }; @@ -638,7 +659,7 @@ return -ENODEV; } - dbg(__FUNCTION__ " - port %d", port->number); + dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd); if (!port->active) { dbg (__FUNCTION__ " - port not open"); @@ -803,36 +824,32 @@ static int generic_write_room (struct usb_serial_port *port) { struct usb_serial *serial = port->serial; - int room; + int room = 0; dbg(__FUNCTION__ " - port %d", port->number); - if (serial->num_bulk_out) { - if (port->write_urb->status == -EINPROGRESS) - room = 0; - else + if (serial->num_bulk_out) + if (port->write_urb->status != -EINPROGRESS) room = port->bulk_out_size; - dbg(__FUNCTION__ " returns %d", room); - return (room); - } - return (0); + dbg(__FUNCTION__ " - returns %d", room); + return (room); } static int generic_chars_in_buffer (struct usb_serial_port *port) { struct usb_serial *serial = port->serial; + int chars = 0; dbg(__FUNCTION__ " - port %d", port->number); - if (serial->num_bulk_out) { - if (port->write_urb->status == -EINPROGRESS) { - return (port->bulk_out_size); - } - } + if (serial->num_bulk_out) + if (port->write_urb->status == -EINPROGRESS) + chars = port->write_urb->transfer_buffer_length; - return (0); + dbg (__FUNCTION__ " - returns %d", chars); + return (chars); } @@ -844,9 +861,10 @@ unsigned char *data = urb->transfer_buffer; int i; - dbg (__FUNCTION__ " - enter"); + dbg(__FUNCTION__ " - port %d", port->number); if (!serial) { + dbg(__FUNCTION__ " - bad serial pointer, exiting"); return; } @@ -877,8 +895,6 @@ if (usb_submit_urb(urb)) dbg(__FUNCTION__ " - failed resubmitting read urb"); - dbg (__FUNCTION__ " - exit"); - return; } @@ -887,11 +903,11 @@ { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); - struct tty_struct *tty; - dbg (__FUNCTION__ " - enter"); + dbg(__FUNCTION__ " - port %d", port->number); if (!serial) { + dbg(__FUNCTION__ " - bad serial pointer, exiting"); return; } @@ -900,18 +916,36 @@ return; } + queue_task(&port->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); + + return; +} + + +static void port_softint(void *private) +{ + struct usb_serial_port *port = (struct usb_serial_port *)private; + struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); + struct tty_struct *tty; + + dbg(__FUNCTION__ " - port %d", port->number); + + if (!serial) { + return; + } + tty = port->tty; - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { + dbg(__FUNCTION__ " - write wakeup call."); (tty->ldisc.write_wakeup)(tty); + } wake_up_interruptible(&tty->write_wait); - - dbg (__FUNCTION__ " - exit"); - - return; } + static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) { struct usb_serial *serial = NULL; @@ -1117,6 +1151,8 @@ port->number = i + serial->minor; port->serial = serial; port->magic = USB_SERIAL_PORT_MAGIC; + port->tqueue.routine = port_softint; + port->tqueue.data = port; } /* initialize the devfs nodes for this device and let the user know what ports we are bound to */ diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c --- v2.4.0-test2/linux/drivers/usb/serial/visor.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/serial/visor.c Wed Jul 5 11:16:41 2000 @@ -11,6 +11,14 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (07/03/2000) gkh + * Added visor_set_ioctl and visor_set_termios functions (they don't do much + * of anything, but are good for debugging.) + * + * (06/25/2000) gkh + * Fixed bug in visor_unthrottle that should help with the disconnect in PPP + * bug that people have been reporting. + * * (06/23/2000) gkh * Cleaned up debugging statements in a quest to find UHCI timeout bug. * @@ -55,6 +63,8 @@ static void visor_throttle (struct usb_serial_port *port); static void visor_unthrottle (struct usb_serial_port *port); static int visor_startup (struct usb_serial *serial); +static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); +static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios); /* All of the device info needed for the Handspring Visor */ static __u16 handspring_vendor_id = HANDSPRING_VENDOR_ID; @@ -75,6 +85,8 @@ throttle: visor_throttle, unthrottle: visor_unthrottle, startup: visor_startup, + ioctl: visor_ioctl, + set_termios: visor_set_termios, }; @@ -137,7 +149,7 @@ { dbg(__FUNCTION__ " - port %d", port->number); - if (usb_unlink_urb (port->read_urb)) + if (usb_submit_urb (port->read_urb)) dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed"); return; @@ -206,4 +218,79 @@ /* continue on with initialization */ return (0); } + + +static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) +{ + dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd); + + return -ENOIOCTLCMD; +} + + +/* This function is all nice and good, but we don't change anything based on it :) */ +static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios) +{ + unsigned int cflag = port->tty->termios->c_cflag; + + dbg(__FUNCTION__ " - port %d", port->number); + + /* check that they really want us to change something */ + if (old_termios) { + if ((cflag == old_termios->c_cflag) && + (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { + dbg(__FUNCTION__ " - nothing to change..."); + return; + } + } + + if ((!port->tty) || (!port->tty->termios)) { + dbg(__FUNCTION__" - no tty structures"); + return; + } + + /* get the byte size */ + switch (cflag & CSIZE) { + case CS5: dbg(__FUNCTION__ " - data bits = 5"); break; + case CS6: dbg(__FUNCTION__ " - data bits = 6"); break; + case CS7: dbg(__FUNCTION__ " - data bits = 7"); break; + default: + case CS8: dbg(__FUNCTION__ " - data bits = 8"); break; + } + + /* determine the parity */ + if (cflag & PARENB) + if (cflag & PARODD) + dbg(__FUNCTION__ " - parity = odd"); + else + dbg(__FUNCTION__ " - parity = even"); + else + dbg(__FUNCTION__ " - parity = none"); + + /* figure out the stop bits requested */ + if (cflag & CSTOPB) + dbg(__FUNCTION__ " - stop bits = 2"); + else + dbg(__FUNCTION__ " - stop bits = 1"); + + + /* figure out the flow control settings */ + if (cflag & CRTSCTS) + dbg(__FUNCTION__ " - RTS/CTS is enabled"); + else + dbg(__FUNCTION__ " - RTS/CTS is disabled"); + + /* determine software flow control */ + if (I_IXOFF(port->tty)) + dbg(__FUNCTION__ " - XON/XOFF is enabled, XON = %2x, XOFF = %2x", START_CHAR(port->tty), STOP_CHAR(port->tty)); + else + dbg(__FUNCTION__ " - XON/XOFF is disabled"); + + /* get the baud rate wanted */ + dbg(__FUNCTION__ " - baud rate = %d", tty_get_baud_rate(port->tty)); + + return; +} + + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/serial/whiteheat.c linux/drivers/usb/serial/whiteheat.c --- v2.4.0-test2/linux/drivers/usb/serial/whiteheat.c Tue May 23 15:31:35 2000 +++ linux/drivers/usb/serial/whiteheat.c Wed Jul 5 11:16:41 2000 @@ -11,6 +11,11 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (07/04/2000) gkh + * Added support for port settings. Baud rate can now be changed. Line signals + * are not transferred to and from the tty layer yet, but things seem to be + * working well now. + * * (05/04/2000) gkh * First cut at open and close commands. Data can flow through the ports at * default speeds now. @@ -55,6 +60,7 @@ /* function prototypes for the Connect Tech WhiteHEAT serial converter */ static int whiteheat_open (struct usb_serial_port *port, struct file *filp); static void whiteheat_close (struct usb_serial_port *port, struct file *filp); +static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); static void whiteheat_set_termios (struct usb_serial_port *port, struct termios * old); static void whiteheat_throttle (struct usb_serial_port *port); static void whiteheat_unthrottle (struct usb_serial_port *port); @@ -93,6 +99,7 @@ close: whiteheat_close, throttle: whiteheat_throttle, unthrottle: whiteheat_unthrottle, + ioctl: whiteheat_ioctl, set_termios: whiteheat_set_termios, shutdown: whiteheat_shutdown, }; @@ -103,6 +110,13 @@ }; +/* local function prototypes */ +static inline void set_rts (struct usb_serial_port *port, unsigned char rts); +static inline void set_dtr (struct usb_serial_port *port, unsigned char dtr); +static inline void set_break (struct usb_serial_port *port, unsigned char brk); + + + #define COMMAND_PORT 4 #define COMMAND_TIMEOUT (2*HZ) /* 2 second timeout for a command */ @@ -116,7 +130,7 @@ int i; #endif - dbg ("command_port_write_callback"); + dbg (__FUNCTION__); if (urb->status) { dbg ("nonzero urb status: %d", urb->status); @@ -125,7 +139,7 @@ #ifdef DEBUG if (urb->actual_length) { - printk (KERN_DEBUG __FILE__ ": data read - length = %d, data = ", urb->actual_length); + printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", urb->actual_length); for (i = 0; i < urb->actual_length; ++i) { printk ("%.2x ", data[i]); } @@ -145,16 +159,16 @@ int i; #endif - dbg ("command_port_write_callback"); + dbg (__FUNCTION__); if (urb->status) { - dbg ("nonzero urb status: %d", urb->status); + dbg (__FUNCTION__ " - nonzero urb status: %d", urb->status); return; } #ifdef DEBUG if (urb->actual_length) { - printk (KERN_DEBUG __FILE__ ": data read - length = %d, data = ", urb->actual_length); + printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", urb->actual_length); for (i = 0; i < urb->actual_length; ++i) { printk ("%.2x ", data[i]); } @@ -179,7 +193,7 @@ int timeout; __u8 *transfer_buffer; - dbg("whiteheat_send_cmd: %d", command); + dbg(__FUNCTION__" - command %d", command); port = &serial->port[COMMAND_PORT]; info = (struct whiteheat_private *)port->private; @@ -189,8 +203,10 @@ transfer_buffer[0] = command; memcpy (&transfer_buffer[1], data, datasize); port->write_urb->transfer_buffer_length = datasize + 1; - if (usb_submit_urb (port->write_urb)) - dbg ("submit urb failed"); + if (usb_submit_urb (port->write_urb)) { + dbg (__FUNCTION__" - submit urb failed"); + return -1; + } /* wait for the command to complete */ timeout = COMMAND_TIMEOUT; @@ -199,6 +215,7 @@ } if (info->command_finished == FALSE) { + dbg (__FUNCTION__ " - command timed out."); return -1; } @@ -212,10 +229,10 @@ struct usb_serial_port *command_port; struct whiteheat_private *info; - dbg("whiteheat_open port %d", port->number); + dbg(__FUNCTION__" - port %d", port->number); if (port->active) { - dbg ("device already open"); + dbg (__FUNCTION__ " - device already open"); return -EINVAL; } port->active = 1; @@ -225,7 +242,7 @@ if (command_port->private == NULL) { info = (struct whiteheat_private *)kmalloc (sizeof(struct whiteheat_private), GFP_KERNEL); if (info == NULL) { - err("out of memory"); + err(__FUNCTION__ " - out of memory"); return -ENOMEM; } @@ -238,7 +255,7 @@ /* Start reading from the device */ if (usb_submit_urb(port->read_urb)) - dbg("usb_submit_urb(read bulk) failed"); + dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed"); /* send an open port command */ open_command.port = port->number - port->minor; @@ -247,9 +264,9 @@ /* Need to do device specific setup here (control lines, baud rate, etc.) */ /* FIXME!!! */ - dbg("whiteheat_open exit"); + dbg(__FUNCTION__ " - exit"); - return (0); + return 0; } @@ -257,7 +274,7 @@ { struct whiteheat_min_set close_command; - dbg("whiteheat_close port %d", port->number); + dbg(__FUNCTION__ " - port %d", port->number); /* send a close command to the port */ close_command.port = port->number - port->minor; @@ -273,30 +290,102 @@ } +static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) +{ + dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd); + + return -ENOIOCTLCMD; +} + + static void whiteheat_set_termios (struct usb_serial_port *port, struct termios *old_termios) { unsigned int cflag = port->tty->termios->c_cflag; + struct whiteheat_port_settings port_settings; - dbg("whiteheat_set_termios port %d", port->number); + dbg(__FUNCTION__ " -port %d", port->number); /* check that they really want us to change something */ if (old_termios) { if ((cflag == old_termios->c_cflag) && (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { - dbg("nothing to change..."); + dbg(__FUNCTION__ " - nothing to change..."); return; } } - /* do the parsing of the cflag to see what to set the line to */ - /* FIXME!! */ + if ((!port->tty) || (!port->tty->termios)) { + dbg(__FUNCTION__" - no tty structures"); + return; + } + + /* get the byte size */ + switch (cflag & CSIZE) { + case CS5: port_settings.bits = 5; break; + case CS6: port_settings.bits = 6; break; + case CS7: port_settings.bits = 7; break; + default: + case CS8: port_settings.bits = 8; break; + } + dbg(__FUNCTION__ " - data bits = %d", port_settings.bits); + + /* determine the parity */ + if (cflag & PARENB) + if (cflag & PARODD) + port_settings.parity = 'o'; + else + port_settings.parity = 'e'; + else + port_settings.parity = 'n'; + dbg(__FUNCTION__ " - parity = %c", port_settings.parity); + + /* figure out the stop bits requested */ + if (cflag & CSTOPB) + port_settings.stop = 2; + else + port_settings.stop = 1; + dbg(__FUNCTION__ " - stop bits = %d", port_settings.stop); + + /* figure out the flow control settings */ + if (cflag & CRTSCTS) + port_settings.hflow = (WHITEHEAT_CTS_FLOW | WHITEHEAT_RTS_FLOW); + else + port_settings.hflow = 0; + dbg(__FUNCTION__ " - hardware flow control = %s %s %s %s", + (port_settings.hflow | WHITEHEAT_CTS_FLOW) ? "CTS" : "", + (port_settings.hflow | WHITEHEAT_RTS_FLOW) ? "RTS" : "", + (port_settings.hflow | WHITEHEAT_DSR_FLOW) ? "DSR" : "", + (port_settings.hflow | WHITEHEAT_DTR_FLOW) ? "DTR" : ""); + + /* determine software flow control */ + if (I_IXOFF(port->tty)) + port_settings.sflow = 'b'; + else + port_settings.sflow = 'n'; + dbg(__FUNCTION__ " - software flow control = %c", port_settings.sflow); + + port_settings.xon = START_CHAR(port->tty); + port_settings.xoff = STOP_CHAR(port->tty); + dbg(__FUNCTION__ " - XON = %2x, XOFF = %2x", port_settings.xon, port_settings.xoff); + + /* get the baud rate wanted */ + port_settings.baud = tty_get_baud_rate(port->tty); + dbg(__FUNCTION__ " - baud rate = %d", port_settings.baud); + + /* handle any settings that aren't specified in the tty structure */ + port_settings.lloop = 0; + + /* now send the message to the device */ + whiteheat_send_cmd (port->serial, WHITEHEAT_SETUP_PORT, (__u8 *)&port_settings, sizeof(port_settings)); + return; } + static void whiteheat_throttle (struct usb_serial_port *port) { - dbg("whiteheat_throttle port %d", port->number); + dbg(__FUNCTION__" - port %d", port->number); /* Change the control signals */ /* FIXME!!! */ @@ -307,7 +396,7 @@ static void whiteheat_unthrottle (struct usb_serial_port *port) { - dbg("whiteheat_unthrottle port %d", port->number); + dbg(__FUNCTION__" - port %d", port->number); /* Change the control signals */ /* FIXME!!! */ @@ -334,7 +423,7 @@ int response; const struct whiteheat_hex_record *record; - dbg("whiteheat_startup"); + dbg(__FUNCTION__); response = ezusb_set_reset (serial, 1); @@ -343,7 +432,7 @@ response = ezusb_writememory (serial, record->address, (unsigned char *)record->data, record->data_size, 0xa0); if (response < 0) { - err("ezusb_writememory failed for loader (%d %04X %p %d)", + err(__FUNCTION__ " - ezusb_writememory failed for loader (%d %04X %p %d)", response, record->address, record->data, record->data_size); break; } @@ -360,7 +449,7 @@ response = ezusb_writememory (serial, record->address, (unsigned char *)record->data, record->data_size, 0xa3); if (response < 0) { - err("ezusb_writememory failed for first firmware step (%d %04X %p %d)", + err(__FUNCTION__ " - ezusb_writememory failed for first firmware step (%d %04X %p %d)", response, record->address, record->data, record->data_size); break; } @@ -374,7 +463,7 @@ response = ezusb_writememory (serial, record->address, (unsigned char *)record->data, record->data_size, 0xa0); if (response < 0) { - err("ezusb_writememory failed for second firmware step (%d %04X %p %d)", + err(__FUNCTION__" - ezusb_writememory failed for second firmware step (%d %04X %p %d)", response, record->address, record->data, record->data_size); break; } @@ -392,9 +481,9 @@ { struct usb_serial_port *command_port; - dbg("whiteheat_shutdown"); + dbg(__FUNCTION__); - /* set up some stuff for our command port */ + /* free up our private data for our command port */ command_port = &serial->port[COMMAND_PORT]; if (command_port->private != NULL) { kfree (command_port->private); @@ -402,5 +491,37 @@ } return; +} + + + + +static void set_command (struct usb_serial_port *port, unsigned char state, unsigned char command) +{ + struct whiteheat_rdb_set rdb_command; + + /* send a set rts command to the port */ + rdb_command.port = port->number - port->minor; + rdb_command.state = state; + + whiteheat_send_cmd (port->serial, command, (__u8 *)&rdb_command, sizeof(rdb_command)); +} + + +static inline void set_rts (struct usb_serial_port *port, unsigned char rts) +{ + set_command (port, rts, WHITEHEAT_SET_RTS); +} + + +static inline void set_dtr (struct usb_serial_port *port, unsigned char dtr) +{ + set_command (port, dtr, WHITEHEAT_SET_DTR); +} + + +static inline void set_break (struct usb_serial_port *port, unsigned char brk) +{ + set_command (port, brk, WHITEHEAT_SET_BREAK); } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/storage/Makefile linux/drivers/usb/storage/Makefile --- v2.4.0-test2/linux/drivers/usb/storage/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/Makefile Wed Jun 28 19:46:22 2000 @@ -0,0 +1,32 @@ +# +# Makefile for the USB Mass Storage device drivers. +# + +O_TARGET := usb-storage.o +M_OBJS := usb-storage.o +O_OBJS := scsiglue.o protocol.o transport.o debug.o usb.o +MOD_LIST_NAME := USB_STORAGE_MODULES + +CFLAGS_scsiglue.o:= -I../../scsi/ +CFLAGS_protocol.o:= -I../../scsi/ +CFLAGS_transport.o:= -I../../scsi/ +CFLAGS_debug.o:= -I../../scsi/ +CFLAGS_usb.o:= -I../../scsi/ + +ifeq ($(CONFIG_USB_STORAGE_DEBUG),y) + O_OBJS += debug.o +endif + +ifeq ($(CONFIG_USB_STORAGE_FREECOM),y) + O_OBJS += freecom.o +endif + +ifeq ($(CONFIG_USB_STORAGE_SHUTTLE_SMARTMEDIA),y) + O_OBJS += shuttle_sm.o +endif + +ifeq ($(CONFIG_USB_STORAGE_SHUTTLE_COMPACTFLASH),y) + O_OBJS += shuttle_cf.o +endif + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/storage/debug.c linux/drivers/usb/storage/debug.c --- v2.4.0-test2/linux/drivers/usb/storage/debug.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/debug.c Wed Jun 28 19:46:22 2000 @@ -0,0 +1,185 @@ +/* Driver for USB Mass Storage compliant devices + * Debugging Functions Source Code File + * + * $Id: debug.c,v 1.1 2000/06/27 01:25:28 mdharm Exp $ + * + * Current development and maintainance by: + * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * + * Initial work by: + * (c) 1999 Michael Gee (michael@linuxspecific.com) + * + * This driver is based on the 'USB Mass Storage Class' document. This + * describes in detail the protocol used to communicate with such + * devices. Clearly, the designers had SCSI and ATAPI commands in + * mind when they created this document. The commands are all very + * similar to commands in the SCSI-II and ATAPI specifications. + * + * It is important to note that in a number of cases this class + * exhibits class-specific exemptions from the USB specification. + * Notably the usage of NAK, STALL and ACK differs from the norm, in + * that they are used to communicate wait, failed and OK on commands. + * + * Also, for certain devices, the interrupt endpoint is used to convey + * status of a command. + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "debug.h" + +void usb_stor_show_command(Scsi_Cmnd *srb) +{ + char *what = NULL; + + switch (srb->cmnd[0]) { + case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break; + case REZERO_UNIT: what = "REZERO_UNIT"; break; + case REQUEST_SENSE: what = "REQUEST_SENSE"; break; + case FORMAT_UNIT: what = "FORMAT_UNIT"; break; + case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break; + case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break; + case READ_6: what = "READ_6"; break; + case WRITE_6: what = "WRITE_6"; break; + case SEEK_6: what = "SEEK_6"; break; + case READ_REVERSE: what = "READ_REVERSE"; break; + case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break; + case SPACE: what = "SPACE"; break; + case INQUIRY: what = "INQUIRY"; break; + case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break; + case MODE_SELECT: what = "MODE_SELECT"; break; + case RESERVE: what = "RESERVE"; break; + case RELEASE: what = "RELEASE"; break; + case COPY: what = "COPY"; break; + case ERASE: what = "ERASE"; break; + case MODE_SENSE: what = "MODE_SENSE"; break; + case START_STOP: what = "START_STOP"; break; + case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break; + case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break; + case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break; + case SET_WINDOW: what = "SET_WINDOW"; break; + case READ_CAPACITY: what = "READ_CAPACITY"; break; + case READ_10: what = "READ_10"; break; + case WRITE_10: what = "WRITE_10"; break; + case SEEK_10: what = "SEEK_10"; break; + case WRITE_VERIFY: what = "WRITE_VERIFY"; break; + case VERIFY: what = "VERIFY"; break; + case SEARCH_HIGH: what = "SEARCH_HIGH"; break; + case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break; + case SEARCH_LOW: what = "SEARCH_LOW"; break; + case SET_LIMITS: what = "SET_LIMITS"; break; + case READ_POSITION: what = "READ_POSITION"; break; + case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break; + case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break; + case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break; + case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break; + case COMPARE: what = "COMPARE"; break; + case COPY_VERIFY: what = "COPY_VERIFY"; break; + case WRITE_BUFFER: what = "WRITE_BUFFER"; break; + case READ_BUFFER: what = "READ_BUFFER"; break; + case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break; + case READ_LONG: what = "READ_LONG"; break; + case WRITE_LONG: what = "WRITE_LONG"; break; + case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break; + case WRITE_SAME: what = "WRITE_SAME"; break; + case READ_TOC: what = "READ_TOC"; break; + case LOG_SELECT: what = "LOG_SELECT"; break; + case LOG_SENSE: what = "LOG_SENSE"; break; + case MODE_SELECT_10: what = "MODE_SELECT_10"; break; + case MODE_SENSE_10: what = "MODE_SENSE_10"; break; + case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break; + case READ_12: what = "READ_12"; break; + case WRITE_12: what = "WRITE_12"; break; + case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break; + case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break; + case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break; + case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break; + case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break; + case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break; + case WRITE_LONG_2: what = "WRITE_LONG_2"; break; + default: break; + } + US_DEBUGP("Command %s (%d bytes)\n", what, srb->cmd_len); + US_DEBUGP("%02x %02x %02x %02x " + "%02x %02x %02x %02x " + "%02x %02x %02x %02x\n", + srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], + srb->cmnd[4], srb->cmnd[5], srb->cmnd[6], srb->cmnd[7], + srb->cmnd[8], srb->cmnd[9], srb->cmnd[10], + srb->cmnd[11]); +} + +void usb_stor_print_Scsi_Cmnd( Scsi_Cmnd* cmd ) +{ + int i=0, bufferSize = cmd->request_bufflen; + u8* buffer = cmd->request_buffer; + struct scatterlist* sg = (struct scatterlist*)cmd->request_buffer; + + US_DEBUGP("Dumping information about %p.\n", cmd ); + US_DEBUGP("cmd->cmnd[0] value is %d.\n", cmd->cmnd[0] ); + US_DEBUGP("(MODE_SENSE is %d and MODE_SENSE_10 is %d)\n", + MODE_SENSE, MODE_SENSE_10 ); + + US_DEBUGP("buffer is %p with length %d.\n", buffer, bufferSize ); + for ( i=0; iuse_sg ); + for ( i=0; iuse_sg; i++ ) + { + US_DEBUGP("Length of scatterlist %d is %d.\n",i,sg[i].length); + US_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x\n" + "%02x %02x %02x %02x %02x %02x %02x %02x\n", + sg[i].address[0], + sg[i].address[1], + sg[i].address[2], + sg[i].address[3], + sg[i].address[4], + sg[i].address[5], + sg[i].address[6], + sg[i].address[7], + sg[i].address[8], + sg[i].address[9], + sg[i].address[10], + sg[i].address[11], + sg[i].address[12], + sg[i].address[13], + sg[i].address[14], + sg[i].address[15]); + } +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/storage/debug.h linux/drivers/usb/storage/debug.h --- v2.4.0-test2/linux/drivers/usb/storage/debug.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/debug.h Wed Jun 28 19:46:22 2000 @@ -0,0 +1,66 @@ +/* Driver for USB Mass Storage compliant devices + * Debugging Functions Header File + * + * $Id: debug.h,v 1.1 2000/06/27 01:25:28 mdharm Exp $ + * + * Current development and maintainance by: + * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * + * Initial work by: + * (c) 1999 Michael Gee (michael@linuxspecific.com) + * + * This driver is based on the 'USB Mass Storage Class' document. This + * describes in detail the protocol used to communicate with such + * devices. Clearly, the designers had SCSI and ATAPI commands in + * mind when they created this document. The commands are all very + * similar to commands in the SCSI-II and ATAPI specifications. + * + * It is important to note that in a number of cases this class + * exhibits class-specific exemptions from the USB specification. + * Notably the usage of NAK, STALL and ACK differs from the norm, in + * that they are used to communicate wait, failed and OK on commands. + * + * Also, for certain devices, the interrupt endpoint is used to convey + * status of a command. + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include +#include +#include +#include "scsi.h" + +#define USB_STORAGE "usb-storage: " + +#ifdef CONFIG_USB_STORAGE_DEBUG +void usb_stor_show_command(Scsi_Cmnd *srb); +void usb_stor_print_Scsi_Cmnd( Scsi_Cmnd* cmd ); +#define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE ## x ) +#define US_DEBUGPX(x...) printk( ## x ) +#define US_DEBUG(x) x +#else +#define US_DEBUGP(x...) +#define US_DEBUGPX(x...) +#define US_DEBUG(x) +#endif + +#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/storage/protocol.c linux/drivers/usb/storage/protocol.c --- v2.4.0-test2/linux/drivers/usb/storage/protocol.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/protocol.c Wed Jun 28 19:46:22 2000 @@ -0,0 +1,304 @@ +/* Driver for USB Mass Storage compliant devices + * + * $Id: protocol.c,v 1.1 2000/06/27 01:25:28 mdharm Exp $ + * + * Current development and maintainance by: + * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * + * Developed with the assistance of: + * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) + * + * Initial work by: + * (c) 1999 Michael Gee (michael@linuxspecific.com) + * + * This driver is based on the 'USB Mass Storage Class' document. This + * describes in detail the protocol used to communicate with such + * devices. Clearly, the designers had SCSI and ATAPI commands in + * mind when they created this document. The commands are all very + * similar to commands in the SCSI-II and ATAPI specifications. + * + * It is important to note that in a number of cases this class + * exhibits class-specific exemptions from the USB specification. + * Notably the usage of NAK, STALL and ACK differs from the norm, in + * that they are used to communicate wait, failed and OK on commands. + * + * Also, for certain devices, the interrupt endpoint is used to convey + * status of a command. + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "protocol.h" +#include "usb.h" +#include "debug.h" +#include "scsiglue.h" +#include "transport.h" + +/*********************************************************************** + * Protocol routines + ***********************************************************************/ + +void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) +{ + int old_cmnd = 0; + + /* Fix some commands -- this is a form of mode translation + * ATAPI devices only accept 12 byte long commands + * + * NOTE: This only works because a Scsi_Cmnd struct field contains + * a unsigned char cmnd[12], so we know we have storage available + */ + + /* set command length to 12 bytes */ + srb->cmd_len = 12; + + /* determine the correct (or minimum) data length for these commands */ + switch (srb->cmnd[0]) { + + /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ + case MODE_SENSE: + case MODE_SELECT: + /* save the command so we can tell what it was */ + old_cmnd = srb->cmnd[0]; + + srb->cmnd[11] = 0; + srb->cmnd[10] = 0; + srb->cmnd[9] = 0; + srb->cmnd[8] = srb->cmnd[4]; + srb->cmnd[7] = 0; + srb->cmnd[6] = 0; + srb->cmnd[5] = 0; + srb->cmnd[4] = 0; + srb->cmnd[3] = 0; + srb->cmnd[2] = srb->cmnd[2]; + srb->cmnd[1] = srb->cmnd[1]; + srb->cmnd[0] = srb->cmnd[0] | 0x40; + break; + + /* change READ_6/WRITE_6 to READ_10/WRITE_10, which + * are ATAPI commands */ + case WRITE_6: + case READ_6: + srb->cmnd[11] = 0; + srb->cmnd[10] = 0; + srb->cmnd[9] = 0; + srb->cmnd[8] = srb->cmnd[4]; + srb->cmnd[7] = 0; + srb->cmnd[6] = 0; + srb->cmnd[5] = srb->cmnd[3]; + srb->cmnd[4] = srb->cmnd[2]; + srb->cmnd[3] = srb->cmnd[1] & 0x1F; + srb->cmnd[2] = 0; + srb->cmnd[1] = srb->cmnd[1] & 0xE0; + srb->cmnd[0] = srb->cmnd[0] | 0x20; + break; + } /* end switch on cmnd[0] */ + + /* convert MODE_SELECT data here */ + if (old_cmnd == MODE_SELECT) + usb_stor_scsiSense6to10(srb); + + /* send the command to the transport layer */ + usb_stor_invoke_transport(srb, us); + + /* Fix the MODE_SENSE data if we translated the command */ + if ((old_cmnd == MODE_SENSE) && (srb->result == GOOD)) + usb_stor_scsiSense10to6(srb); + + /* Fix-up the return data from an INQUIRY command to show + * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us + */ + if (srb->cmnd[0] == INQUIRY) { + ((unsigned char *)us->srb->request_buffer)[2] |= 0x2; + } +} + + +void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us) +{ + int old_cmnd = 0; + + /* fix some commands -- this is a form of mode translation + * UFI devices only accept 12 byte long commands + * + * NOTE: This only works because a Scsi_Cmnd struct field contains + * a unsigned char cmnd[12], so we know we have storage available + */ + + /* set command length to 12 bytes (this affects the transport layer) */ + srb->cmd_len = 12; + + /* determine the correct (or minimum) data length for these commands */ + switch (srb->cmnd[0]) { + + /* for INQUIRY, UFI devices only ever return 36 bytes */ + case INQUIRY: + srb->cmnd[4] = 36; + break; + + /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ + case MODE_SENSE: + case MODE_SELECT: + /* save the command so we can tell what it was */ + old_cmnd = srb->cmnd[0]; + + srb->cmnd[11] = 0; + srb->cmnd[10] = 0; + srb->cmnd[9] = 0; + + /* if we're sending data, we send all. If getting data, + * get the minimum */ + if (srb->cmnd[0] == MODE_SELECT) + srb->cmnd[8] = srb->cmnd[4]; + else + srb->cmnd[8] = 8; + + srb->cmnd[7] = 0; + srb->cmnd[6] = 0; + srb->cmnd[5] = 0; + srb->cmnd[4] = 0; + srb->cmnd[3] = 0; + srb->cmnd[2] = srb->cmnd[2]; + srb->cmnd[1] = srb->cmnd[1]; + srb->cmnd[0] = srb->cmnd[0] | 0x40; + break; + + /* again, for MODE_SENSE_10, we get the minimum (8) */ + case MODE_SENSE_10: + srb->cmnd[7] = 0; + srb->cmnd[8] = 8; + break; + + /* for REQUEST_SENSE, UFI devices only ever return 18 bytes */ + case REQUEST_SENSE: + srb->cmnd[4] = 18; + break; + + /* change READ_6/WRITE_6 to READ_10/WRITE_10, which + * are UFI commands */ + case WRITE_6: + case READ_6: + srb->cmnd[11] = 0; + srb->cmnd[10] = 0; + srb->cmnd[9] = 0; + srb->cmnd[8] = srb->cmnd[4]; + srb->cmnd[7] = 0; + srb->cmnd[6] = 0; + srb->cmnd[5] = srb->cmnd[3]; + srb->cmnd[4] = srb->cmnd[2]; + srb->cmnd[3] = srb->cmnd[1] & 0x1F; + srb->cmnd[2] = 0; + srb->cmnd[1] = srb->cmnd[1] & 0xE0; + srb->cmnd[0] = srb->cmnd[0] | 0x20; + break; + } /* end switch on cmnd[0] */ + + /* convert MODE_SELECT data here */ + if (old_cmnd == MODE_SELECT) + usb_stor_scsiSense6to10(srb); + + /* send the command to the transport layer */ + usb_stor_invoke_transport(srb, us); + + /* Fix the MODE_SENSE data if we translated the command */ + if ((old_cmnd == MODE_SENSE) && (srb->result == GOOD)) + usb_stor_scsiSense10to6(srb); + + /* Fix-up the return data from an INQUIRY command to show + * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us + */ + if (srb->cmnd[0] == INQUIRY) { + ((unsigned char *)us->srb->request_buffer)[2] |= 0x2; + } +} + +void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us) +{ + /* This code supports devices which do not support {READ|WRITE}_6 + * Apparently, neither Windows or MacOS will use these commands, + * so some devices do not support them + */ + if (us->flags & US_FL_MODE_XLATE) { + + /* translate READ_6 to READ_10 */ + if (srb->cmnd[0] == 0x08) { + + /* get the control */ + srb->cmnd[9] = us->srb->cmnd[5]; + + /* get the length */ + srb->cmnd[8] = us->srb->cmnd[6]; + srb->cmnd[7] = 0; + + /* set the reserved area to 0 */ + srb->cmnd[6] = 0; + + /* get LBA */ + srb->cmnd[5] = us->srb->cmnd[3]; + srb->cmnd[4] = us->srb->cmnd[2]; + srb->cmnd[3] = 0; + srb->cmnd[2] = 0; + + /* LUN and other info in cmnd[1] can stay */ + + /* fix command code */ + srb->cmnd[0] = 0x28; + + US_DEBUGP("Changing READ_6 to READ_10\n"); + US_DEBUG(usb_stor_show_command(srb)); + } + + /* translate WRITE_6 to WRITE_10 */ + if (srb->cmnd[0] == 0x0A) { + + /* get the control */ + srb->cmnd[9] = us->srb->cmnd[5]; + + /* get the length */ + srb->cmnd[8] = us->srb->cmnd[4]; + srb->cmnd[7] = 0; + + /* set the reserved area to 0 */ + srb->cmnd[6] = 0; + + /* get LBA */ + srb->cmnd[5] = us->srb->cmnd[3]; + srb->cmnd[4] = us->srb->cmnd[2]; + srb->cmnd[3] = 0; + srb->cmnd[2] = 0; + + /* LUN and other info in cmnd[1] can stay */ + + /* fix command code */ + srb->cmnd[0] = 0x2A; + + US_DEBUGP("Changing WRITE_6 to WRITE_10\n"); + US_DEBUG(usb_stor_show_command(us->srb)); + } + } /* if (us->flags & US_FL_MODE_XLATE) */ + + /* send the command to the transport layer */ + usb_stor_invoke_transport(srb, us); + + /* fix the results of an INQUIRY */ + if (srb->cmnd[0] == INQUIRY) { + US_DEBUGP("Fixing INQUIRY data, setting SCSI rev to 2\n"); + ((unsigned char*)us->srb->request_buffer)[2] |= 2; + } +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/storage/protocol.h linux/drivers/usb/storage/protocol.h --- v2.4.0-test2/linux/drivers/usb/storage/protocol.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/protocol.h Wed Jun 28 19:46:22 2000 @@ -0,0 +1,63 @@ +/* Driver for USB Mass Storage compliant devices + * Protocol Functions Header File + * + * $Id: protocol.h,v 1.1 2000/06/27 01:25:28 mdharm Exp $ + * + * Current development and maintainance by: + * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * + * This driver is based on the 'USB Mass Storage Class' document. This + * describes in detail the protocol used to communicate with such + * devices. Clearly, the designers had SCSI and ATAPI commands in + * mind when they created this document. The commands are all very + * similar to commands in the SCSI-II and ATAPI specifications. + * + * It is important to note that in a number of cases this class + * exhibits class-specific exemptions from the USB specification. + * Notably the usage of NAK, STALL and ACK differs from the norm, in + * that they are used to communicate wait, failed and OK on commands. + * + * Also, for certain devices, the interrupt endpoint is used to convey + * status of a command. + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _PROTOCOL_H_ +#define _PROTOCOL_H_ + +#include +#include "scsi.h" +#include "usb.h" + +/* Sub Classes */ + +#define US_SC_RBC 0x01 /* Typically, flash devices */ +#define US_SC_8020 0x02 /* CD-ROM */ +#define US_SC_QIC 0x03 /* QIC-157 Tapes */ +#define US_SC_UFI 0x04 /* Floppy */ +#define US_SC_8070 0x05 /* Removable media */ +#define US_SC_SCSI 0x06 /* Transparent */ +#define US_SC_MIN US_SC_RBC +#define US_SC_MAX US_SC_SCSI + +extern void usb_stor_ATAPI_command(Scsi_Cmnd*, struct us_data*); +extern void usb_stor_ufi_command(Scsi_Cmnd*, struct us_data*); +extern void usb_stor_transparent_scsi_command(Scsi_Cmnd*, struct us_data*); + +#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/storage/scsiglue.c linux/drivers/usb/storage/scsiglue.c --- v2.4.0-test2/linux/drivers/usb/storage/scsiglue.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/scsiglue.c Wed Jun 28 19:47:53 2000 @@ -0,0 +1,824 @@ +/* Driver for USB Mass Storage compliant devices + * SCSI layer glue code + * + * $Id: scsiglue.c,v 1.2 2000/06/27 10:20:39 mdharm Exp $ + * + * Current development and maintainance by: + * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * + * Developed with the assistance of: + * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) + * + * Initial work by: + * (c) 1999 Michael Gee (michael@linuxspecific.com) + * + * This driver is based on the 'USB Mass Storage Class' document. This + * describes in detail the protocol used to communicate with such + * devices. Clearly, the designers had SCSI and ATAPI commands in + * mind when they created this document. The commands are all very + * similar to commands in the SCSI-II and ATAPI specifications. + * + * It is important to note that in a number of cases this class + * exhibits class-specific exemptions from the USB specification. + * Notably the usage of NAK, STALL and ACK differs from the norm, in + * that they are used to communicate wait, failed and OK on commands. + * + * Also, for certain devices, the interrupt endpoint is used to convey + * status of a command. + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "scsiglue.h" +#include "usb.h" +#include "debug.h" + +#include + +/* direction table -- this indicates the direction of the data + * transfer for each command code -- a 1 indicates input + */ +/* FIXME: we need to use the new direction indicators in the Scsi_Cmnd + * structure, not this table. First we need to evaluate if it's being set + * correctly for us, though + */ +unsigned char us_direction[256/8] = { + 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, + 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + + +/* + * kernel thread actions + */ + +#define US_ACT_COMMAND 1 +#define US_ACT_DEVICE_RESET 2 +#define US_ACT_BUS_RESET 3 +#define US_ACT_HOST_RESET 4 +#define US_ACT_EXIT 5 + +/*********************************************************************** + * Host functions + ***********************************************************************/ + +static const char* host_info(struct Scsi_Host *host) +{ + return "SCSI emulation for USB Mass Storage devices"; +} + +/* detect a virtual adapter (always works) */ +static int detect(struct SHT *sht) +{ + struct us_data *us; + char local_name[32]; + + /* This is not nice at all, but how else are we to get the + * data here? */ + us = (struct us_data *)sht->proc_dir; + + /* set up the name of our subdirectory under /proc/scsi/ */ + sprintf(local_name, "usb-storage-%d", us->host_number); + sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL); + if (!sht->proc_name) + return 0; + strcpy(sht->proc_name, local_name); + + /* we start with no /proc directory entry */ + sht->proc_dir = NULL; + + /* register the host */ + us->host = scsi_register(sht, sizeof(us)); + if (us->host) { + us->host->hostdata[0] = (unsigned long)us; + us->host_no = us->host->host_no; + return 1; + } + + /* odd... didn't register properly. Abort and free pointers */ + kfree(sht->proc_name); + sht->proc_name = NULL; + return 0; +} + +/* Release all resources used by the virtual host + * + * NOTE: There is no contention here, because we're allready deregistered + * the driver and we're doing each virtual host in turn, not in parallel + */ +static int release(struct Scsi_Host *psh) +{ + struct us_data *us = (struct us_data *)psh->hostdata[0]; + + US_DEBUGP("us_release() called for host %s\n", us->htmplt.name); + + /* Kill the control threads + * + * Enqueue the command, wake up the thread, and wait for + * notification that it's exited. + */ + US_DEBUGP("-- sending US_ACT_EXIT command to thread\n"); + us->action = US_ACT_EXIT; + up(&(us->sleeper)); + down(&(us->notify)); + + /* free the data structure we were using */ + US_DEBUGP("-- freeing URB\n"); + kfree(us->current_urb); + (struct us_data*)psh->hostdata[0] = NULL; + + /* we always have a successful release */ + return 0; +} + +/* run command */ +static int command( Scsi_Cmnd *srb ) +{ + US_DEBUGP("Bad use of us_command\n"); + + return DID_BAD_TARGET << 16; +} + +/* run command */ +static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *)) +{ + struct us_data *us = (struct us_data *)srb->host->hostdata[0]; + + US_DEBUGP("queuecommand() called\n"); + srb->host_scribble = (unsigned char *)us; + + /* get exclusive access to the structures we want */ + down(&(us->queue_exclusion)); + + /* enqueue the command */ + us->queue_srb = srb; + srb->scsi_done = done; + us->action = US_ACT_COMMAND; + + /* wake up the process task */ + up(&(us->queue_exclusion)); + up(&(us->sleeper)); + + return 0; +} + +/*********************************************************************** + * Error handling functions + ***********************************************************************/ + +/* Command abort + * + * Note that this is really only meaningful right now for CBI transport + * devices which have failed to give us the command completion interrupt + */ +static int command_abort( Scsi_Cmnd *srb ) +{ + struct us_data *us = (struct us_data *)srb->host->hostdata[0]; + api_wrapper_data *awd = (api_wrapper_data *)us->current_urb->context; + + US_DEBUGP("command_abort() called\n"); + + /* if we're stuck waiting for an IRQ, simulate it */ + if (us->ip_wanted) { + US_DEBUGP("-- simulating missing IRQ\n"); + up(&(us->ip_waitq)); + return SUCCESS; + } + + /* if we have an urb pending, let's wake the control thread up */ + if (us->current_urb->status == -EINPROGRESS) { + /* cancel the URB */ + usb_unlink_urb(us->current_urb); + + /* wake the control thread up */ + if (waitqueue_active(awd->wakeup)) + wake_up(awd->wakeup); + + /* wait for us to be done */ + down(&(us->notify)); + return SUCCESS; + } + + US_DEBUGP ("-- nothing to abort\n"); + return FAILED; +} + +/* FIXME: this doesn't do anything right now */ +static int bus_reset( Scsi_Cmnd *srb ) +{ + // struct us_data *us = (struct us_data *)srb->host->hostdata[0]; + + printk(KERN_CRIT "usb-storage: bus_reset() requested but not implemented\n" ); + US_DEBUGP("Bus reset requested\n"); + // us->transport_reset(us); + return FAILED; +} + +/* FIXME: This doesn't actually reset anything */ +static int host_reset( Scsi_Cmnd *srb ) +{ + printk(KERN_CRIT "usb-storage: host_reset() requested but not implemented\n" ); + return FAILED; +} + +/*********************************************************************** + * /proc/scsi/ functions + ***********************************************************************/ + +/* we use this macro to help us write into the buffer */ +#undef SPRINTF +#define SPRINTF(args...) \ + do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0) + +static int proc_info (char *buffer, char **start, off_t offset, int length, + int hostno, int inout) +{ + struct us_data *us; + char *pos = buffer; + + /* if someone is sending us data, just throw it away */ + if (inout) + return length; + + /* lock the data structures */ + down(&us_list_semaphore); + + /* find our data from hostno */ + us = us_list; + while (us) { + if (us->host_no == hostno) + break; + us = us->next; + } + + /* if we couldn't find it, we return an error */ + if (!us) { + up(&us_list_semaphore); + return -ESRCH; + } + + /* print the controler name */ + SPRINTF(" Host scsi%d: usb-storage\n", hostno); + + /* print product, vendor, and serial number strings */ + SPRINTF(" Vendor: %s\n", us->vendor); + SPRINTF(" Product: %s\n", us->product); + SPRINTF("Serial Number: %s\n", us->serial); + + /* show the protocol and transport */ + SPRINTF(" Protocol: %s\n", us->protocol_name); + SPRINTF(" Transport: %s\n", us->transport_name); + + /* show the GUID of the device */ + SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid)); + + /* release our lock on the data structures */ + up(&us_list_semaphore); + + /* + * Calculate start of next buffer, and return value. + */ + *start = buffer + offset; + + if ((pos - buffer) < offset) + return (0); + else if ((pos - buffer - offset) < length) + return (pos - buffer - offset); + else + return (length); +} + +/* + * this defines our 'host' + */ + +Scsi_Host_Template usb_stor_host_template = { + name: "usb-storage", + proc_info: proc_info, + info: host_info, + + detect: detect, + release: release, + command: command, + queuecommand: queuecommand, + + eh_abort_handler: command_abort, + eh_device_reset_handler:bus_reset, + eh_bus_reset_handler: bus_reset, + eh_host_reset_handler: host_reset, + + can_queue: 1, + this_id: -1, + + sg_tablesize: SG_ALL, + cmd_per_lun: 1, + present: 0, + unchecked_isa_dma: FALSE, + use_clustering: TRUE, + use_new_eh_code: TRUE, + emulated: TRUE +}; + +unsigned char usb_stor_sense_notready[12] = { + [0] = 0x70, /* current error */ + [2] = 0x02, /* not ready */ + [5] = 0x0a, /* additional length */ + [10] = 0x04, /* not ready */ + [11] = 0x03 /* manual intervention */ +}; + +#define USB_STOR_SCSI_SENSE_HDRSZ 4 +#define USB_STOR_SCSI_SENSE_10_HDRSZ 8 + +struct usb_stor_scsi_sense_hdr +{ + __u8* dataLength; + __u8* mediumType; + __u8* devSpecParms; + __u8* blkDescLength; +}; + +typedef struct usb_stor_scsi_sense_hdr Usb_Stor_Scsi_Sense_Hdr; + +union usb_stor_scsi_sense_hdr_u +{ + Usb_Stor_Scsi_Sense_Hdr hdr; + __u8* array[USB_STOR_SCSI_SENSE_HDRSZ]; +}; + +typedef union usb_stor_scsi_sense_hdr_u Usb_Stor_Scsi_Sense_Hdr_u; + +struct usb_stor_scsi_sense_hdr_10 +{ + __u8* dataLengthMSB; + __u8* dataLengthLSB; + __u8* mediumType; + __u8* devSpecParms; + __u8* reserved1; + __u8* reserved2; + __u8* blkDescLengthMSB; + __u8* blkDescLengthLSB; +}; + +typedef struct usb_stor_scsi_sense_hdr_10 Usb_Stor_Scsi_Sense_Hdr_10; + +union usb_stor_scsi_sense_hdr_10_u +{ + Usb_Stor_Scsi_Sense_Hdr_10 hdr; + __u8* array[USB_STOR_SCSI_SENSE_10_HDRSZ]; +}; + +typedef union usb_stor_scsi_sense_hdr_10_u Usb_Stor_Scsi_Sense_Hdr_10_u; + +void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* , Usb_Stor_Scsi_Sense_Hdr_u*, + Usb_Stor_Scsi_Sense_Hdr_10_u*, int* ); + +int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 ) +{ + __u8 *buffer=0; + int outputBufferSize = 0; + int length=0; + struct scatterlist *sg = 0; + int i=0, j=0, element=0; + Usb_Stor_Scsi_Sense_Hdr_u the6Locations; + Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations; + int sb=0,si=0,db=0,di=0; + int sgLength=0; + + US_DEBUGP("-- converting 10 byte sense data to 6 byte\n"); + the10->cmnd[0] = the10->cmnd[0] & 0xBF; + + /* Determine buffer locations */ + usb_stor_scsiSenseParseBuffer( the10, &the6Locations, &the10Locations, + &length ); + + /* Work out minimum buffer to output */ + outputBufferSize = *the10Locations.hdr.dataLengthLSB; + outputBufferSize += USB_STOR_SCSI_SENSE_HDRSZ; + + /* Check to see if we need to trucate the output */ + if ( outputBufferSize > length ) + { + printk( KERN_WARNING USB_STORAGE + "Had to truncate MODE_SENSE_10 buffer into MODE_SENSE.\n" ); + printk( KERN_WARNING USB_STORAGE + "outputBufferSize is %d and length is %d.\n", + outputBufferSize, length ); + } + outputBufferSize = length; + + /* Data length */ + if ( *the10Locations.hdr.dataLengthMSB != 0 ) /* MSB must be zero */ + { + printk( KERN_WARNING USB_STORAGE + "Command will be truncated to fit in SENSE6 buffer.\n" ); + *the6Locations.hdr.dataLength = 0xff; + } + else + { + *the6Locations.hdr.dataLength = *the10Locations.hdr.dataLengthLSB; + } + + /* Medium type and DevSpecific parms */ + *the6Locations.hdr.mediumType = *the10Locations.hdr.mediumType; + *the6Locations.hdr.devSpecParms = *the10Locations.hdr.devSpecParms; + + /* Block descriptor length */ + if ( *the10Locations.hdr.blkDescLengthMSB != 0 ) /* MSB must be zero */ + { + printk( KERN_WARNING USB_STORAGE + "Command will be truncated to fit in SENSE6 buffer.\n" ); + *the6Locations.hdr.blkDescLength = 0xff; + } + else + { + *the6Locations.hdr.blkDescLength = *the10Locations.hdr.blkDescLengthLSB; + } + + if ( the10->use_sg == 0 ) + { + buffer = the10->request_buffer; + /* Copy the rest of the data */ + memmove( &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]), + &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), + outputBufferSize - USB_STOR_SCSI_SENSE_HDRSZ ); + /* initialise last bytes left in buffer due to smaller header */ + memset( &(buffer[outputBufferSize + -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ)]), + 0, + USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ ); + } + else + { + sg = (struct scatterlist *) the10->request_buffer; + /* scan through this scatterlist and figure out starting positions */ + for ( i=0; i < the10->use_sg; i++) + { + sgLength = sg[i].length; + for ( j=0; juse_sg; + } + element++; + } + } + + /* Now we know where to start the copy from */ + element = USB_STOR_SCSI_SENSE_HDRSZ; + while ( element < outputBufferSize + -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) ) + { + /* check limits */ + if ( sb >= the10->use_sg || + si >= sg[sb].length || + db >= the10->use_sg || + di >= sg[db].length ) + { + printk( KERN_ERR USB_STORAGE + "Buffer overrun averted, this shouldn't happen!\n" ); + break; + } + + /* copy one byte */ + sg[db].address[di] = sg[sb].address[si]; + + /* get next destination */ + if ( sg[db].length-1 == di ) + { + db++; + di=0; + } + else + { + di++; + } + + /* get next source */ + if ( sg[sb].length-1 == si ) + { + sb++; + si=0; + } + else + { + si++; + } + + element++; + } + /* zero the remaining bytes */ + while ( element < outputBufferSize ) + { + /* check limits */ + if ( db >= the10->use_sg || + di >= sg[db].length ) + { + printk( KERN_ERR USB_STORAGE + "Buffer overrun averted, this shouldn't happen!\n" ); + break; + } + + sg[db].address[di] = 0; + + /* get next destination */ + if ( sg[db].length-1 == di ) + { + db++; + di=0; + } + else + { + di++; + } + element++; + } + } + + /* All done any everything was fine */ + return 0; +} + +int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 ) +{ + /* will be used to store part of buffer */ + __u8 tempBuffer[USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ], + *buffer=0; + int outputBufferSize = 0; + int length=0; + struct scatterlist *sg = 0; + int i=0, j=0, element=0; + Usb_Stor_Scsi_Sense_Hdr_u the6Locations; + Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations; + int sb=0,si=0,db=0,di=0; + int lsb=0,lsi=0,ldb=0,ldi=0; + + US_DEBUGP("-- converting 6 byte sense data to 10 byte\n"); + the6->cmnd[0] = the6->cmnd[0] | 0x40; + + /* Determine buffer locations */ + usb_stor_scsiSenseParseBuffer( the6, &the6Locations, &the10Locations, + &length ); + + /* Work out minimum buffer to output */ + outputBufferSize = *the6Locations.hdr.dataLength; + outputBufferSize += USB_STOR_SCSI_SENSE_10_HDRSZ; + + /* Check to see if we need to trucate the output */ + if ( outputBufferSize > length ) + { + printk( KERN_WARNING USB_STORAGE + "Had to truncate MODE_SENSE into MODE_SENSE_10 buffer.\n" ); + printk( KERN_WARNING USB_STORAGE + "outputBufferSize is %d and length is %d.\n", + outputBufferSize, length ); + } + outputBufferSize = length; + + /* Block descriptor length - save these before overwriting */ + tempBuffer[2] = *the10Locations.hdr.blkDescLengthMSB; + tempBuffer[3] = *the10Locations.hdr.blkDescLengthLSB; + *the10Locations.hdr.blkDescLengthLSB = *the6Locations.hdr.blkDescLength; + *the10Locations.hdr.blkDescLengthMSB = 0; + + /* reserved - save these before overwriting */ + tempBuffer[0] = *the10Locations.hdr.reserved1; + tempBuffer[1] = *the10Locations.hdr.reserved2; + *the10Locations.hdr.reserved1 = *the10Locations.hdr.reserved2 = 0; + + /* Medium type and DevSpecific parms */ + *the10Locations.hdr.devSpecParms = *the6Locations.hdr.devSpecParms; + *the10Locations.hdr.mediumType = *the6Locations.hdr.mediumType; + + /* Data length */ + *the10Locations.hdr.dataLengthLSB = *the6Locations.hdr.dataLength; + *the10Locations.hdr.dataLengthMSB = 0; + + if ( !the6->use_sg ) + { + buffer = the6->request_buffer; + /* Copy the rest of the data */ + memmove( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), + &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]), + outputBufferSize-USB_STOR_SCSI_SENSE_10_HDRSZ ); + /* Put the first four bytes (after header) in place */ + memcpy( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), + tempBuffer, + USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ ); + } + else + { + sg = (struct scatterlist *) the6->request_buffer; + /* scan through this scatterlist and figure out ending positions */ + for ( i=0; i < the6->use_sg; i++) + { + for ( j=0; juse_sg; + break; + } + element++; + } + } + /* scan through this scatterlist and figure out starting positions */ + element = length-1; + /* destination is the last element */ + db=the6->use_sg-1; + di=sg[db].length-1; + for ( i=the6->use_sg-1; i >= 0; i--) + { + for ( j=sg[i].length-1; j>=0; j-- ) + { + /* get to end of header and find source for copy */ + if ( element == length - 1 + - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) ) + { + sb=i; + si=j; + /* we've found both sets now, exit loops */ + j=-1; + i=-1; + } + element--; + } + } + /* Now we know where to start the copy from */ + element = length-1 + - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ); + while ( element >= USB_STOR_SCSI_SENSE_10_HDRSZ ) + { + /* check limits */ + if ( ( sb <= lsb && si < lsi ) || + ( db <= ldb && di < ldi ) ) + { + printk( KERN_ERR USB_STORAGE + "Buffer overrun averted, this shouldn't happen!\n" ); + break; + } + + /* copy one byte */ + sg[db].address[di] = sg[sb].address[si]; + + /* get next destination */ + if ( di == 0 ) + { + db--; + di=sg[db].length-1; + } + else + { + di--; + } + + /* get next source */ + if ( si == 0 ) + { + sb--; + si=sg[sb].length-1; + } + else + { + si--; + } + + element--; + } + /* copy the remaining four bytes */ + while ( element >= USB_STOR_SCSI_SENSE_HDRSZ ) + { + /* check limits */ + if ( db <= ldb && di < ldi ) + { + printk( KERN_ERR USB_STORAGE + "Buffer overrun averted, this shouldn't happen!\n" ); + break; + } + + sg[db].address[di] = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ]; + + /* get next destination */ + if ( di == 0 ) + { + db--; + di=sg[db].length-1; + } + else + { + di--; + } + element--; + } + } + + /* All done and everything was fine */ + return 0; +} + +void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* the6, + Usb_Stor_Scsi_Sense_Hdr_10_u* the10, + int* length_p ) + +{ + int i = 0, j=0, element=0; + struct scatterlist *sg = 0; + int length = 0; + __u8* buffer=0; + + /* are we scatter-gathering? */ + if ( srb->use_sg != 0 ) + { + /* loop over all the scatter gather structures and + * get pointer to the data members in the headers + * (also work out the length while we're here) + */ + sg = (struct scatterlist *) srb->request_buffer; + for (i = 0; i < srb->use_sg; i++) + { + length += sg[i].length; + /* We only do the inner loop for the headers */ + if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ ) + { + /* scan through this scatterlist */ + for ( j=0; jarray[element] = &(sg[i].address[j]); + the10->array[element] = &(sg[i].address[j]); + } + else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ ) + { + /* only the longer headers still cares now */ + the10->array[element] = &(sg[i].address[j]); + } + /* increase element counter */ + element++; + } + } + } + } + else + { + length = srb->request_bufflen; + buffer = srb->request_buffer; + if ( length < USB_STOR_SCSI_SENSE_10_HDRSZ ) + printk( KERN_ERR USB_STORAGE + "Buffer length smaller than header!!" ); + for( i=0; iarray[i] = &(buffer[i]); + the10->array[i] = &(buffer[i]); + } + else + { + the10->array[i] = &(buffer[i]); + } + } + } + + /* Set value of length passed in */ + *length_p = length; +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/storage/scsiglue.h linux/drivers/usb/storage/scsiglue.h --- v2.4.0-test2/linux/drivers/usb/storage/scsiglue.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/scsiglue.h Wed Jun 28 19:46:22 2000 @@ -0,0 +1,54 @@ +/* Driver for USB Mass Storage compliant devices + * SCSI Connecting Glue Header File + * + * $Id: scsiglue.h,v 1.1 2000/06/27 01:25:28 mdharm Exp $ + * + * Current development and maintainance by: + * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * + * This driver is based on the 'USB Mass Storage Class' document. This + * describes in detail the protocol used to communicate with such + * devices. Clearly, the designers had SCSI and ATAPI commands in + * mind when they created this document. The commands are all very + * similar to commands in the SCSI-II and ATAPI specifications. + * + * It is important to note that in a number of cases this class + * exhibits class-specific exemptions from the USB specification. + * Notably the usage of NAK, STALL and ACK differs from the norm, in + * that they are used to communicate wait, failed and OK on commands. + * + * Also, for certain devices, the interrupt endpoint is used to convey + * status of a command. + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _SCSIGLUE_H_ +#define _SCSIGLUE_H_ + +#include +#include "scsi.h" +#include "hosts.h" + +extern unsigned char usb_stor_sense_notready[12]; +extern unsigned char us_direction[256/8]; +extern Scsi_Host_Template usb_stor_host_template; +extern int usb_stor_scsiSense10to6(Scsi_Cmnd*); +extern int usb_stor_scsiSense6to10(Scsi_Cmnd*); + +#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/storage/transport.c linux/drivers/usb/storage/transport.c --- v2.4.0-test2/linux/drivers/usb/storage/transport.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/transport.c Wed Jun 28 19:47:53 2000 @@ -0,0 +1,904 @@ +/* Driver for USB Mass Storage compliant devices + * + * $Id: transport.c,v 1.2 2000/06/27 10:20:39 mdharm Exp $ + * + * Current development and maintainance by: + * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * + * Developed with the assistance of: + * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) + * + * Initial work by: + * (c) 1999 Michael Gee (michael@linuxspecific.com) + * + * This driver is based on the 'USB Mass Storage Class' document. This + * describes in detail the protocol used to communicate with such + * devices. Clearly, the designers had SCSI and ATAPI commands in + * mind when they created this document. The commands are all very + * similar to commands in the SCSI-II and ATAPI specifications. + * + * It is important to note that in a number of cases this class + * exhibits class-specific exemptions from the USB specification. + * Notably the usage of NAK, STALL and ACK differs from the norm, in + * that they are used to communicate wait, failed and OK on commands. + * + * Also, for certain devices, the interrupt endpoint is used to convey + * status of a command. + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "transport.h" +#include "protocol.h" +#include "usb.h" +#include "debug.h" + +#include +#include +#include + +/*********************************************************************** + * Data transfer routines + ***********************************************************************/ + +/* This is the completion handler which will wake us up when an URB + * completes. + */ +static void usb_stor_blocking_completion(urb_t *urb) +{ + api_wrapper_data *awd = (api_wrapper_data *)urb->context; + + if (waitqueue_active(awd->wakeup)) + wake_up(awd->wakeup); +} + +/* This is our function to emulate usb_control_msg() but give us enough + * access to make aborts/resets work + */ +int usb_stor_control_msg(struct us_data *us, unsigned int pipe, + u8 request, u8 requesttype, u16 value, u16 index, + void *data, u16 size) +{ + DECLARE_WAITQUEUE(wait, current); + DECLARE_WAIT_QUEUE_HEAD(wqh); + api_wrapper_data awd; + int status; + devrequest *dr; + + /* allocate the device request structure */ + dr = kmalloc(sizeof(devrequest), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + /* fill in the structure */ + dr->requesttype = requesttype; + dr->request = request; + dr->value = cpu_to_le16(value); + dr->index = cpu_to_le16(index); + dr->length = cpu_to_le16(size); + + /* set up data structures for the wakeup system */ + awd.wakeup = &wqh; + awd.handler = 0; + init_waitqueue_head(&wqh); + add_wait_queue(&wqh, &wait); + + /* lock the URB */ + down(&(us->current_urb_sem)); + + /* fill the URB */ + FILL_CONTROL_URB(us->current_urb, us->pusb_dev, pipe, + (unsigned char*) dr, data, size, + usb_stor_blocking_completion, &awd); + + /* submit the URB */ + set_current_state(TASK_UNINTERRUPTIBLE); + status = usb_submit_urb(us->current_urb); + if (status) { + /* something went wrong */ + up(&(us->current_urb_sem)); + remove_wait_queue(&wqh, &wait); + kfree(dr); + return status; + } + + /* wait for the completion of the URB */ + up(&(us->current_urb_sem)); + if (us->current_urb->status == -EINPROGRESS) + schedule(); + down(&(us->current_urb_sem)); + + /* we either timed out or got woken up -- clean up either way */ + set_current_state(TASK_RUNNING); + remove_wait_queue(&wqh, &wait); + + /* return the actual length of the data transferred if no error*/ + status = us->current_urb->status; + if (status >= 0) + status = us->current_urb->actual_length; + + /* release the lock and return status */ + up(&(us->current_urb_sem)); + kfree(dr); + return status; +} + +/* This is our function to emulate usb_bulk_msg() but give us enough + * access to make aborts/resets work + */ +int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe, + unsigned int len, unsigned int *act_len) +{ + DECLARE_WAITQUEUE(wait, current); + DECLARE_WAIT_QUEUE_HEAD(wqh); + api_wrapper_data awd; + int status; + + /* set up data structures for the wakeup system */ + awd.wakeup = &wqh; + awd.handler = 0; + init_waitqueue_head(&wqh); + add_wait_queue(&wqh, &wait); + + /* lock the URB */ + down(&(us->current_urb_sem)); + + /* fill the URB */ + FILL_BULK_URB(us->current_urb, us->pusb_dev, pipe, data, len, + usb_stor_blocking_completion, &awd); + + /* submit the URB */ + set_current_state(TASK_UNINTERRUPTIBLE); + status = usb_submit_urb(us->current_urb); + if (status) { + /* something went wrong */ + up(&(us->current_urb_sem)); + remove_wait_queue(&wqh, &wait); + return status; + } + + /* wait for the completion of the URB */ + up(&(us->current_urb_sem)); + if (us->current_urb->status == -EINPROGRESS) + schedule(); + down(&(us->current_urb_sem)); + + /* we either timed out or got woken up -- clean up either way */ + set_current_state(TASK_RUNNING); + remove_wait_queue(&wqh, &wait); + + /* return the actual length of the data transferred */ + *act_len = us->current_urb->actual_length; + + /* release the lock and return status */ + up(&(us->current_urb_sem)); + return us->current_urb->status; +} + +/* + * Transfer one SCSI scatter-gather buffer via bulk transfer + * + * Note that this function is necessary because we want the ability to + * use scatter-gather memory. Good performance is achieved by a combination + * of scatter-gather and clustering (which makes each chunk bigger). + * + * Note that the lower layer will always retry when a NAK occurs, up to the + * timeout limit. Thus we don't have to worry about it for individual + * packets. + */ +static int us_transfer_partial(struct us_data *us, char *buf, int length) +{ + int result; + int partial; + int pipe; + + /* calculate the appropriate pipe information */ + if (US_DIRECTION(us->srb->cmnd[0])) + pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); + else + pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); + + /* transfer the data */ + US_DEBUGP("us_transfer_partial(): xfer %d bytes\n", length); + result = usb_stor_bulk_msg(us, buf, pipe, length, &partial); + US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %d/%d\n", + result, partial, length); + + /* if we stall, we need to clear it before we go on */ + if (result == -EPIPE) { + US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); + usb_clear_halt(us->pusb_dev, pipe); + } + + /* did we send all the data? */ + if (partial == length) { + US_DEBUGP("us_transfer_partial(): transfer complete\n"); + return US_BULK_TRANSFER_GOOD; + } + + /* uh oh... we have an error code, so something went wrong. */ + if (result) { + /* NAK - that means we've retried a few times allready */ + if (result == -ETIMEDOUT) { + US_DEBUGP("us_transfer_partial(): device NAKed\n"); + return US_BULK_TRANSFER_FAILED; + } + + /* -ENOENT -- we canceled this transfer */ + if (result == -ENOENT) { + US_DEBUGP("us_transfer_partial(): transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } + + /* the catch-all case */ + US_DEBUGP("us_transfer_partial(): unknown error\n"); + return US_BULK_TRANSFER_FAILED; + } + + /* no error code, so we must have transferred some data, + * just not all of it */ + return US_BULK_TRANSFER_SHORT; +} + +/* + * Transfer an entire SCSI command's worth of data payload over the bulk + * pipe. + * + * Note that this uses us_transfer_partial to achieve it's goals -- this + * function simply determines if we're going to use scatter-gather or not, + * and acts appropriately. For now, it also re-interprets the error codes. + */ +static void us_transfer(Scsi_Cmnd *srb, struct us_data* us, int dir_in) +{ + int i; + int result = -1; + struct scatterlist *sg; + + /* are we scatter-gathering? */ + if (srb->use_sg) { + + /* loop over all the scatter gather structures and + * make the appropriate requests for each, until done + */ + sg = (struct scatterlist *) srb->request_buffer; + for (i = 0; i < srb->use_sg; i++) { + result = us_transfer_partial(us, sg[i].address, + sg[i].length); + if (result) + break; + } + } + else + /* no scatter-gather, just make the request */ + result = us_transfer_partial(us, srb->request_buffer, + srb->request_bufflen); + + /* return the result in the data structure itself */ + srb->result = result; +} + +/* Calculate the length of the data transfer (not the command) for any + * given SCSI command + */ +static unsigned int us_transfer_length(Scsi_Cmnd *srb, struct us_data *us) +{ + int i; + unsigned int total = 0; + struct scatterlist *sg; + + /* support those devices which need the length calculated + * differently + */ + if (us->flags & US_FL_ALT_LENGTH) { + if (srb->cmnd[0] == INQUIRY) { + srb->cmnd[4] = 36; + } + + if ((srb->cmnd[0] == INQUIRY) || (srb->cmnd[0] == MODE_SENSE)) + return srb->cmnd[4]; + + if (srb->cmnd[0] == TEST_UNIT_READY) + return 0; + } + + /* Are we going to scatter gather? */ + if (srb->use_sg) { + /* Add up the sizes of all the scatter-gather segments */ + sg = (struct scatterlist *) srb->request_buffer; + for (i = 0; i < srb->use_sg; i++) + total += sg[i].length; + + return total; + } + else + /* Just return the length of the buffer */ + return srb->request_bufflen; +} + +/*********************************************************************** + * Transport routines + ***********************************************************************/ + +/* Invoke the transport and basic error-handling/recovery methods + * + * This is used by the protocol layers to actually send the message to + * the device and recieve the response. + */ +void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) +{ + int need_auto_sense; + int result; + + /* send the command to the transport layer */ + result = us->transport(srb, us); + + /* if the command gets aborted by the higher layers, we need to + * short-circuit all other processing + */ + if (result == USB_STOR_TRANSPORT_ABORTED) { + US_DEBUGP("-- transport indicates command was aborted\n"); + srb->result = DID_ABORT << 16; + return; + } + + /* Determine if we need to auto-sense + * + * I normally don't use a flag like this, but it's almost impossible + * to understand what's going on here if I don't. + */ + need_auto_sense = 0; + + /* + * If we're running the CB transport, which is incapable + * of determining status on it's own, we need to auto-sense almost + * every time. + */ + if (us->protocol == US_PR_CB) { + US_DEBUGP("-- CB transport device requiring auto-sense\n"); + need_auto_sense = 1; + + /* There are some exceptions to this. Notably, if this is + * a UFI device and the command is REQUEST_SENSE or INQUIRY, + * then it is impossible to truly determine status. + */ + if (us->subclass == US_SC_UFI && + ((srb->cmnd[0] == REQUEST_SENSE) || + (srb->cmnd[0] == INQUIRY))) { + US_DEBUGP("** no auto-sense for a special command\n"); + need_auto_sense = 0; + } + } + + /* + * If we have an error, we're going to do a REQUEST_SENSE + * automatically. Note that we differentiate between a command + * "failure" and an "error" in the transport mechanism. + */ + if (result == USB_STOR_TRANSPORT_FAILED) { + US_DEBUGP("-- transport indicates command failure\n"); + need_auto_sense = 1; + } + if (result == USB_STOR_TRANSPORT_ERROR) { + /* FIXME: we need to invoke a transport reset here */ + US_DEBUGP("-- transport indicates transport failure\n"); + need_auto_sense = 0; + srb->result = DID_ERROR << 16; + return; + } + + /* + * Also, if we have a short transfer on a command that can't have + * a short transfer, we're going to do this. + */ + if ((srb->result == US_BULK_TRANSFER_SHORT) && + !((srb->cmnd[0] == REQUEST_SENSE) || + (srb->cmnd[0] == INQUIRY) || + (srb->cmnd[0] == MODE_SENSE) || + (srb->cmnd[0] == LOG_SENSE) || + (srb->cmnd[0] == MODE_SENSE_10))) { + US_DEBUGP("-- unexpectedly short transfer\n"); + need_auto_sense = 1; + } + + /* Now, if we need to do the auto-sense, let's do it */ + if (need_auto_sense) { + int temp_result; + void* old_request_buffer; + int old_sg; + int old_request_bufflen; + unsigned char old_cmnd[MAX_COMMAND_SIZE]; + + US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); + + /* save the old command */ + memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE); + + /* set the command and the LUN */ + srb->cmnd[0] = REQUEST_SENSE; + srb->cmnd[1] = old_cmnd[1] & 0xE0; + srb->cmnd[2] = 0; + srb->cmnd[3] = 0; + srb->cmnd[4] = 18; + srb->cmnd[5] = 0; + + /* set the buffer length for transfer */ + old_request_buffer = srb->request_buffer; + old_request_bufflen = srb->request_bufflen; + old_sg = srb->use_sg; + srb->use_sg = 0; + srb->request_bufflen = 18; + srb->request_buffer = srb->sense_buffer; + + /* issue the auto-sense command */ + temp_result = us->transport(us->srb, us); + if (temp_result != USB_STOR_TRANSPORT_GOOD) { + /* FIXME: we need to invoke a transport reset here */ + US_DEBUGP("-- auto-sense failure\n"); + srb->result = DID_ERROR << 16; + return; + } + + US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); + US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", + srb->sense_buffer[0], + srb->sense_buffer[2] & 0xf, + srb->sense_buffer[12], + srb->sense_buffer[13]); + + /* set the result so the higher layers expect this data */ + srb->result = CHECK_CONDITION; + + /* we're done here, let's clean up */ + srb->request_buffer = old_request_buffer; + srb->request_bufflen = old_request_bufflen; + srb->use_sg = old_sg; + memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE); + + /* If things are really okay, then let's show that */ + if ((srb->sense_buffer[2] & 0xf) == 0x0) + srb->result = GOOD; + } else /* if (need_auto_sense) */ + srb->result = GOOD; + + /* Regardless of auto-sense, if we _know_ we have an error + * condition, show that in the result code + */ + if (result == USB_STOR_TRANSPORT_FAILED) + srb->result = CHECK_CONDITION; + + /* If we think we're good, then make sure the sense data shows it. + * This is necessary because the auto-sense for some devices always + * sets byte 0 == 0x70, even if there is no error + */ + if ((us->protocol == US_PR_CB) && + (result == USB_STOR_TRANSPORT_GOOD) && + ((srb->sense_buffer[2] & 0xf) == 0x0)) + srb->sense_buffer[0] = 0x0; +} + +/* + * Control/Bulk/Interrupt transport + */ + +/* The interrupt handler for CBI devices */ +void usb_stor_CBI_irq(struct urb *urb) +{ + struct us_data *us = (struct us_data *)urb->context; + + US_DEBUGP("USB IRQ recieved for device on host %d\n", us->host_no); + US_DEBUGP("-- IRQ data length is %d\n", urb->actual_length); + US_DEBUGP("-- IRQ state is %d\n", urb->status); + + /* is the device removed? */ + if (urb->status != -ENOENT) { + /* save the data for interpretation later */ + US_DEBUGP("-- Interrupt Status (0x%x, 0x%x)\n", + ((unsigned char*)urb->transfer_buffer)[0], + ((unsigned char*)urb->transfer_buffer)[1]); + + + /* was this a wanted interrupt? */ + if (us->ip_wanted) { + us->ip_wanted = 0; + up(&(us->ip_waitq)); + } else + US_DEBUGP("ERROR: Unwanted interrupt received!\n"); + } else + US_DEBUGP("-- device has been removed\n"); +} + +int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) +{ + int result; + + /* COMMAND STAGE */ + /* let's send the command via the control pipe */ + result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0), + US_CBI_ADSC, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, + us->ifnum, srb->cmnd, srb->cmd_len); + + /* check the return code for the command */ + US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result); + if (result < 0) { + /* if the command was aborted, indicate that */ + if (result == -ENOENT) + return USB_STOR_TRANSPORT_ABORTED; + + /* STALL must be cleared when they are detected */ + if (result == -EPIPE) { + US_DEBUGP("-- Stall on control pipe. Clearing\n"); + result = usb_clear_halt(us->pusb_dev, + usb_sndctrlpipe(us->pusb_dev, + 0)); + US_DEBUGP("-- usb_clear_halt() returns %d\n", result); + return USB_STOR_TRANSPORT_FAILED; + } + + /* Uh oh... serious problem here */ + return USB_STOR_TRANSPORT_ERROR; + } + + /* Set up for status notification */ + us->ip_wanted = 1; + + /* DATA STAGE */ + /* transfer the data payload for this command, if one exists*/ + if (us_transfer_length(srb, us)) { + us_transfer(srb, us, US_DIRECTION(srb->cmnd[0])); + US_DEBUGP("CBI data stage result is 0x%x\n", srb->result); + + /* if it was aborted, we need to indicate that */ + if (srb->result == USB_STOR_TRANSPORT_ABORTED) + return USB_STOR_TRANSPORT_ABORTED; + } + + /* STATUS STAGE */ + + /* go to sleep until we get this interrupt */ + down(&(us->ip_waitq)); + + /* if we were woken up by an abort instead of the actual interrupt */ + if (us->ip_wanted) { + US_DEBUGP("Did not get interrupt on CBI\n"); + us->ip_wanted = 0; + return USB_STOR_TRANSPORT_ABORTED; + } + + US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", + ((unsigned char*)us->irq_urb->transfer_buffer)[0], + ((unsigned char*)us->irq_urb->transfer_buffer)[1]); + + /* UFI gives us ASC and ASCQ, like a request sense + * + * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI + * devices, so we ignore the information for those commands. Note + * that this means we could be ignoring a real error on these + * commands, but that can't be helped. + */ + if (us->subclass == US_SC_UFI) { + if (srb->cmnd[0] == REQUEST_SENSE || + srb->cmnd[0] == INQUIRY) + return USB_STOR_TRANSPORT_GOOD; + else + if (((unsigned char*)us->irq_urb->transfer_buffer)[0]) + return USB_STOR_TRANSPORT_FAILED; + else + return USB_STOR_TRANSPORT_GOOD; + } + + /* If not UFI, we interpret the data as a result code + * The first byte should always be a 0x0 + * The second byte & 0x0F should be 0x0 for good, otherwise error + */ + if (((unsigned char*)us->irq_urb->transfer_buffer)[0]) { + US_DEBUGP("CBI IRQ data showed reserved bType\n"); + return USB_STOR_TRANSPORT_ERROR; + } + switch (((unsigned char*)us->irq_urb->transfer_buffer)[1] & 0x0F) { + case 0x00: + return USB_STOR_TRANSPORT_GOOD; + case 0x01: + return USB_STOR_TRANSPORT_FAILED; + default: + return USB_STOR_TRANSPORT_ERROR; + } + + /* we should never get here, but if we do, we're in trouble */ + return USB_STOR_TRANSPORT_ERROR; +} + +/* + * Control/Bulk transport + */ +int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us) +{ + int result; + + /* COMMAND STAGE */ + /* let's send the command via the control pipe */ + result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0), + US_CBI_ADSC, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, + us->ifnum, srb->cmnd, srb->cmd_len); + + /* check the return code for the command */ + US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result); + if (result < 0) { + /* if the command was aborted, indicate that */ + if (result == -ENOENT) + return USB_STOR_TRANSPORT_ABORTED; + + /* a stall is a fatal condition from the device */ + if (result == -EPIPE) { + US_DEBUGP("-- Stall on control pipe. Clearing\n"); + result = usb_clear_halt(us->pusb_dev, + usb_sndctrlpipe(us->pusb_dev, + 0)); + US_DEBUGP("-- usb_clear_halt() returns %d\n", result); + return USB_STOR_TRANSPORT_FAILED; + } + + /* Uh oh... serious problem here */ + return USB_STOR_TRANSPORT_ERROR; + } + + /* DATA STAGE */ + /* transfer the data payload for this command, if one exists*/ + if (us_transfer_length(srb, us)) { + us_transfer(srb, us, US_DIRECTION(srb->cmnd[0])); + US_DEBUGP("CB data stage result is 0x%x\n", srb->result); + + /* if it was aborted, we need to indicate that */ + if (srb->result == USB_STOR_TRANSPORT_ABORTED) + return USB_STOR_TRANSPORT_ABORTED; + } + + /* STATUS STAGE */ + /* NOTE: CB does not have a status stage. Silly, I know. So + * we have to catch this at a higher level. + */ + return USB_STOR_TRANSPORT_GOOD; +} + +/* + * Bulk only transport + */ + +/* Determine what the maximum LUN supported is */ +int usb_stor_Bulk_max_lun(struct us_data *us) +{ + unsigned char data; + int result; + int pipe; + + /* issue the command */ + pipe = usb_rcvctrlpipe(us->pusb_dev, 0); + result = usb_control_msg(us->pusb_dev, pipe, + US_BULK_GET_MAX_LUN, + USB_DIR_IN | USB_TYPE_CLASS | + USB_RECIP_INTERFACE, + 0, us->ifnum, &data, sizeof(data), HZ); + + US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", + result, data); + + /* if we have a successful request, return the result */ + if (result == 1) + return data; + + /* if we get a STALL, clear the stall */ + if (result == -EPIPE) { + US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); + usb_clear_halt(us->pusb_dev, pipe); + } + + /* return the default -- no LUNs */ + return 0; +} + +int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) +{ + struct bulk_cb_wrap bcb; + struct bulk_cs_wrap bcs; + int result; + int pipe; + int partial; + + /* set up the command wrapper */ + bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN); + bcb.DataTransferLength = cpu_to_le32(us_transfer_length(srb, us)); + bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7; + bcb.Tag = srb->serial_number; + bcb.Lun = srb->cmnd[1] >> 5; + bcb.Length = srb->cmd_len; + + /* construct the pipe handle */ + pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); + + /* copy the command payload */ + memset(bcb.CDB, 0, sizeof(bcb.CDB)); + memcpy(bcb.CDB, srb->cmnd, bcb.Length); + + /* send it to out endpoint */ + US_DEBUGP("Bulk command S 0x%x T 0x%x LUN %d L %d F %d CL %d\n", + le32_to_cpu(bcb.Signature), bcb.Tag, bcb.Lun, + bcb.DataTransferLength, bcb.Flags, bcb.Length); + result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN, + &partial); + US_DEBUGP("Bulk command transfer result=%d\n", result); + + /* if the command was aborted, indicate that */ + if (result == -ENOENT) + return USB_STOR_TRANSPORT_ABORTED; + + /* if we stall, we need to clear it before we go on */ + if (result == -EPIPE) { + US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); + usb_clear_halt(us->pusb_dev, pipe); + } else if (result) { + /* unknown error -- we've got a problem */ + return USB_STOR_TRANSPORT_ERROR; + } + + /* if the command transfered well, then we go to the data stage */ + if (result == 0) { + /* send/receive data payload, if there is any */ + if (bcb.DataTransferLength) { + us_transfer(srb, us, bcb.Flags); + US_DEBUGP("Bulk data transfer result 0x%x\n", + srb->result); + + /* if it was aborted, we need to indicate that */ + if (srb->result == USB_STOR_TRANSPORT_ABORTED) + return USB_STOR_TRANSPORT_ABORTED; + } + } + + /* See flow chart on pg 15 of the Bulk Only Transport spec for + * an explanation of how this code works. + */ + + /* construct the pipe handle */ + pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); + + /* get CSW for device status */ + US_DEBUGP("Attempting to get CSW...\n"); + result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN, + &partial); + + /* if the command was aborted, indicate that */ + if (result == -ENOENT) + return USB_STOR_TRANSPORT_ABORTED; + + /* did the attempt to read the CSW fail? */ + if (result == -EPIPE) { + US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); + usb_clear_halt(us->pusb_dev, pipe); + + /* get the status again */ + US_DEBUGP("Attempting to get CSW (2nd try)...\n"); + result = usb_stor_bulk_msg(us, &bcs, pipe, + US_BULK_CS_WRAP_LEN, &partial); + + /* if the command was aborted, indicate that */ + if (result == -ENOENT) + return USB_STOR_TRANSPORT_ABORTED; + + /* if it fails again, we need a reset and return an error*/ + if (result == -EPIPE) { + US_DEBUGP("clearing halt for pipe 0x%x\n", pipe); + usb_clear_halt(us->pusb_dev, pipe); + return USB_STOR_TRANSPORT_ERROR; + } + } + + /* if we still have a failure at this point, we're in trouble */ + US_DEBUGP("Bulk status result = %d\n", result); + if (result) { + return USB_STOR_TRANSPORT_ERROR; + } + + /* check bulk status */ + US_DEBUGP("Bulk status S 0x%x T 0x%x R %d V 0x%x\n", + le32_to_cpu(bcs.Signature), bcs.Tag, + bcs.Residue, bcs.Status); + if (bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) || + bcs.Tag != bcb.Tag || + bcs.Status > US_BULK_STAT_PHASE || partial != 13) { + US_DEBUGP("Bulk logical error\n"); + return USB_STOR_TRANSPORT_ERROR; + } + + /* based on the status code, we report good or bad */ + switch (bcs.Status) { + case US_BULK_STAT_OK: + /* command good -- note that we could be short on data */ + return USB_STOR_TRANSPORT_GOOD; + + case US_BULK_STAT_FAIL: + /* command failed */ + return USB_STOR_TRANSPORT_FAILED; + + case US_BULK_STAT_PHASE: + /* phase error */ + return USB_STOR_TRANSPORT_ERROR; + } + + /* we should never get here, but if we do, we're in trouble */ + return USB_STOR_TRANSPORT_ERROR; +} + +/*********************************************************************** + * Reset routines + ***********************************************************************/ + +/* This issues a CB[I] Reset to the device in question + */ +int usb_stor_CB_reset(struct us_data *us) +{ + unsigned char cmd[12]; + int result; + + US_DEBUGP("CB_reset() called\n"); + + memset(cmd, 0xFF, sizeof(cmd)); + cmd[0] = SEND_DIAGNOSTIC; + cmd[1] = 4; + result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), + US_CBI_ADSC, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, us->ifnum, cmd, sizeof(cmd), HZ*5); + + /* long wait for reset */ + schedule_timeout(HZ*6); + + US_DEBUGP("CB_reset: clearing endpoint halt\n"); + usb_clear_halt(us->pusb_dev, + usb_rcvbulkpipe(us->pusb_dev, us->ep_in)); + usb_clear_halt(us->pusb_dev, + usb_rcvbulkpipe(us->pusb_dev, us->ep_out)); + + US_DEBUGP("CB_reset done\n"); + return 0; +} + +/* FIXME: Does this work? */ +int usb_stor_Bulk_reset(struct us_data *us) +{ + int result; + + result = usb_control_msg(us->pusb_dev, + usb_sndctrlpipe(us->pusb_dev,0), + US_BULK_RESET_REQUEST, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, us->ifnum, NULL, 0, HZ*5); + + if (result < 0) + US_DEBUGP("Bulk hard reset failed %d\n", result); + + usb_clear_halt(us->pusb_dev, + usb_rcvbulkpipe(us->pusb_dev, us->ep_in)); + usb_clear_halt(us->pusb_dev, + usb_sndbulkpipe(us->pusb_dev, us->ep_out)); + + /* long wait for reset */ + schedule_timeout(HZ*6); + + return result; +} + diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/storage/transport.h linux/drivers/usb/storage/transport.h --- v2.4.0-test2/linux/drivers/usb/storage/transport.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/transport.h Wed Jun 28 19:46:22 2000 @@ -0,0 +1,132 @@ +/* Driver for USB Mass Storage compliant devices + * Transport Functions Header File + * + * $Id: transport.h,v 1.1 2000/06/27 01:25:28 mdharm Exp $ + * + * Current development and maintainance by: + * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * + * This driver is based on the 'USB Mass Storage Class' document. This + * describes in detail the protocol used to communicate with such + * devices. Clearly, the designers had SCSI and ATAPI commands in + * mind when they created this document. The commands are all very + * similar to commands in the SCSI-II and ATAPI specifications. + * + * It is important to note that in a number of cases this class + * exhibits class-specific exemptions from the USB specification. + * Notably the usage of NAK, STALL and ACK differs from the norm, in + * that they are used to communicate wait, failed and OK on commands. + * + * Also, for certain devices, the interrupt endpoint is used to convey + * status of a command. + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _TRANSPORT_H_ +#define _TRANSPORT_H_ + +#include +#include "usb.h" +#include "scsi.h" + +/* bit set if input */ +extern unsigned char us_direction[256/8]; +#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1) + +/* Protocols */ + +#define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */ +#define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */ +#define US_PR_BULK 0x50 /* bulk only */ + +/* + * Bulk only data structures + */ + +/* command block wrapper */ +struct bulk_cb_wrap { + __u32 Signature; /* contains 'USBC' */ + __u32 Tag; /* unique per command id */ + __u32 DataTransferLength; /* size of data */ + __u8 Flags; /* direction in bit 0 */ + __u8 Lun; /* LUN normally 0 */ + __u8 Length; /* of of the CDB */ + __u8 CDB[16]; /* max command */ +}; + +#define US_BULK_CB_WRAP_LEN 31 +#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */ +#define US_BULK_FLAG_IN 1 +#define US_BULK_FLAG_OUT 0 + +/* command status wrapper */ +struct bulk_cs_wrap { + __u32 Signature; /* should = 'USBS' */ + __u32 Tag; /* same as original command */ + __u32 Residue; /* amount not transferred */ + __u8 Status; /* see below */ + __u8 Filler[18]; +}; + +#define US_BULK_CS_WRAP_LEN 13 +#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ +#define US_BULK_STAT_OK 0 +#define US_BULK_STAT_FAIL 1 +#define US_BULK_STAT_PHASE 2 + +/* bulk-only class specific requests */ +#define US_BULK_RESET_REQUEST 0xff +#define US_BULK_GET_MAX_LUN 0xfe + +/* + * us_bulk_transfer() return codes + */ +#define US_BULK_TRANSFER_GOOD 0 /* good transfer */ +#define US_BULK_TRANSFER_SHORT 1 /* transfered less than expected */ +#define US_BULK_TRANSFER_FAILED 2 /* transfer died in the middle */ +#define US_BULK_TRANSFER_ABORTED 3 /* transfer canceled */ + +/* + * Transport return codes + */ + +#define USB_STOR_TRANSPORT_GOOD 0 /* Transport good, command good */ +#define USB_STOR_TRANSPORT_FAILED 1 /* Transport good, command failed */ +#define USB_STOR_TRANSPORT_ERROR 2 /* Transport bad (i.e. device dead) */ +#define USB_STOR_TRANSPORT_ABORTED 3 /* Transport aborted */ + +/* + * CBI accept device specific command + */ + +#define US_CBI_ADSC 0 + +extern void usb_stor_CBI_irq(struct urb*); +extern int usb_stor_CBI_transport(Scsi_Cmnd*, struct us_data*); + +extern int usb_stor_CB_transport(Scsi_Cmnd*, struct us_data*); +extern int usb_stor_CB_reset(struct us_data*); + +extern int usb_stor_Bulk_transport(Scsi_Cmnd*, struct us_data*); +extern int usb_stor_Bulk_max_lun(struct us_data*); +extern int usb_stor_Bulk_reset(struct us_data*); + +void usb_stor_invoke_transport(Scsi_Cmnd *, struct us_data *); + +#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/storage/usb.c linux/drivers/usb/storage/usb.c --- v2.4.0-test2/linux/drivers/usb/storage/usb.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/usb.c Wed Jun 28 19:47:53 2000 @@ -0,0 +1,803 @@ +/* Driver for USB Mass Storage compliant devices + * + * $Id: usb.c,v 1.3 2000/06/27 10:20:39 mdharm Exp $ + * + * Current development and maintainance by: + * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * + * Developed with the assistance of: + * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) + * + * Initial work by: + * (c) 1999 Michael Gee (michael@linuxspecific.com) + * + * This driver is based on the 'USB Mass Storage Class' document. This + * describes in detail the protocol used to communicate with such + * devices. Clearly, the designers had SCSI and ATAPI commands in + * mind when they created this document. The commands are all very + * similar to commands in the SCSI-II and ATAPI specifications. + * + * It is important to note that in a number of cases this class + * exhibits class-specific exemptions from the USB specification. + * Notably the usage of NAK, STALL and ACK differs from the norm, in + * that they are used to communicate wait, failed and OK on commands. + * + * Also, for certain devices, the interrupt endpoint is used to convey + * status of a command. + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "usb.h" +#include "scsiglue.h" +#include "transport.h" +#include "protocol.h" +#include "debug.h" + +#include + /*FIXME: note that this next include is needed for the new sleeping system + * which is not implemented yet + */ +#include +#include +#include +#include + +/* + * Per device data + */ + +static int my_host_number; + +/* + * kernel thread actions + */ + +#define US_ACT_COMMAND 1 +#define US_ACT_DEVICE_RESET 2 +#define US_ACT_BUS_RESET 3 +#define US_ACT_HOST_RESET 4 +#define US_ACT_EXIT 5 + +/* The list of structures and the protective lock for them */ +struct us_data *us_list; +struct semaphore us_list_semaphore; + +static void * storage_probe(struct usb_device *dev, unsigned int ifnum); +static void storage_disconnect(struct usb_device *dev, void *ptr); +static struct usb_driver storage_driver = { + name: "usb-storage", + probe: storage_probe, + disconnect: storage_disconnect, +}; + +static int usb_stor_control_thread(void * __us) +{ + struct us_data *us = (struct us_data *)__us; + int action; + + lock_kernel(); + + /* + * This thread doesn't need any user-level access, + * so get rid of all our resources.. + */ + daemonize(); + + /* set our name for identification purposes */ + sprintf(current->comm, "usb-storage-%d", us->host_number); + + unlock_kernel(); + + /* signal that we've started the thread */ + up(&(us->notify)); + + for(;;) { + US_DEBUGP("*** thread sleeping.\n"); + down(&(us->sleeper)); + down(&(us->queue_exclusion)); + US_DEBUGP("*** thread awakened.\n"); + + /* take the command off the queue */ + action = us->action; + us->action = 0; + us->srb = us->queue_srb; + + /* release the queue lock as fast as possible */ + up(&(us->queue_exclusion)); + + switch (action) { + case US_ACT_COMMAND: + /* reject if target != 0 or if LUN is higher than + * the maximum known LUN + */ + if (us->srb->target || (us->srb->lun > us->max_lun)) { + US_DEBUGP("Bad device number (%d/%d)\n", + us->srb->target, us->srb->lun); + + us->srb->result = DID_BAD_TARGET << 16; + + us->srb->scsi_done(us->srb); + us->srb = NULL; + break; + } + + /* handle those devices which can't do a START_STOP */ + if ((us->srb->cmnd[0] == START_STOP) && + (us->flags & US_FL_START_STOP)) { + us->srb->result = GOOD; + us->srb->scsi_done(us->srb); + us->srb = NULL; + break; + } + + /* lock the device pointers */ + down(&(us->dev_semaphore)); + + /* our device has gone - pretend not ready */ + if (!us->pusb_dev) { + US_DEBUGP("Request is for removed device\n"); + /* For REQUEST_SENSE, it's the data. But + * for anything else, it should look like + * we auto-sensed for it. + */ + if (us->srb->cmnd[0] == REQUEST_SENSE) { + memcpy(us->srb->request_buffer, + usb_stor_sense_notready, + sizeof(usb_stor_sense_notready)); + us->srb->result = GOOD; + } else { + memcpy(us->srb->sense_buffer, + usb_stor_sense_notready, + sizeof(usb_stor_sense_notready)); + us->srb->result = CHECK_CONDITION; + } + } else { /* !us->pusb_dev */ + /* we've got a command, let's do it! */ + US_DEBUG(usb_stor_show_command(us->srb)); + us->proto_handler(us->srb, us); + } + + /* unlock the device pointers */ + up(&(us->dev_semaphore)); + + /* indicate that the command is done */ + if (us->srb->result != DID_ABORT << 16) { + US_DEBUGP("scsi cmd done, result=0x%x\n", + us->srb->result); + us->srb->scsi_done(us->srb); + } else { + US_DEBUGP("scsi command aborted\n"); + up(&(us->notify)); + } + us->srb = NULL; + break; + + case US_ACT_DEVICE_RESET: + break; + + case US_ACT_BUS_RESET: + break; + + case US_ACT_HOST_RESET: + break; + + } /* end switch on action */ + + /* exit if we get a signal to exit */ + if (action == US_ACT_EXIT) { + US_DEBUGP("-- US_ACT_EXIT command recieved\n"); + break; + } + } /* for (;;) */ + + /* notify the exit routine that we're actually exiting now */ + up(&(us->notify)); + + return 0; +} + +/* This is the list of devices we recognize, along with their flag data */ +static struct us_unusual_dev us_unusual_dev_list[] = { + { 0x03f0, 0x0107, 0x0200, 0x0200, "HP USB CD-Writer Plus", + US_SC_8070, US_PR_CB, 0}, + { 0x04e6, 0x0001, 0x0200, 0x0200, "Matshita LS-120", + US_SC_8020, US_PR_CB, US_FL_SINGLE_LUN}, + { 0x04e6, 0x0002, 0x0100, 0x0100, "Shuttle eUSCSI Bridge", + US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, + { 0x04e6, 0x0006, 0x0100, 0x0100, "Shuttle eUSB MMC Adapter", + US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN}, + { 0x054c, 0x0010, 0x0210, 0x0210, "Sony DSC-S30/S70", + US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP | + US_FL_MODE_XLATE | US_FL_ALT_LENGTH | US_FL_ALT_LENGTH}, + { 0x054c, 0x002d, 0x0100, 0x0100, "Sony Memorystick MSAC-US1", + US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP | + US_FL_MODE_XLATE | US_FL_ALT_LENGTH}, + { 0x057b, 0x0000, 0x0000, 0x0299, "Y-E Data Flashbuster-U", + US_SC_UFI, US_PR_CB, US_FL_SINGLE_LUN}, + { 0x057b, 0x0000, 0x0300, 0x9999, "Y-E Data Flashbuster-U", + US_SC_UFI, US_PR_CBI, US_FL_SINGLE_LUN}, + { 0x0693, 0x0002, 0x0100, 0x0100, "Hagiwara FlashGate SmartMedia", + US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, + { 0x0781, 0x0001, 0x0200, 0x0200, "Sandisk ImageMate (SDDR-01)", + US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP}, + { 0x0781, 0x0002, 0x0009, 0x0009, "Sandisk Imagemate (SDDR-31)", + US_SC_SCSI, US_PR_BULK, US_FL_IGNORE_SER}, + { 0x07af, 0x0004, 0x0100, 0x0100, "Microtech USB-SCSI-DB25", + US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, + { 0x07af, 0x0005, 0x0100, 0x0100, "Microtech USB-SCSI-HD50", + US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, + { 0x05ab, 0x0031, 0x0100, 0x0100, "In-System USB/IDE Bridge", + US_SC_8070, US_PR_BULK, US_FL_ALT_LENGTH}, + { 0x0693, 0x0005, 0x0100, 0x0100, "Hagiwara Flashgate", + US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, + { 0 }}; + +/* Search our ususual device list, based on vendor/product combinations + * to see if we can support this device. Returns a pointer to a structure + * defining how we should support this device, or NULL if it's not in the + * list + */ +static struct us_unusual_dev* us_find_dev(u16 idVendor, u16 idProduct, + u16 bcdDevice) +{ + struct us_unusual_dev* ptr; + + US_DEBUGP("Searching unusual device list for (0x%x, 0x%x, 0x%x)...\n", + idVendor, idProduct, bcdDevice); + + ptr = us_unusual_dev_list; + while ((ptr->idVendor != 0x0000) && + !((ptr->idVendor == idVendor) && + (ptr->idProduct == idProduct) && + (ptr->bcdDeviceMin <= bcdDevice) && + (ptr->bcdDeviceMax >= bcdDevice))) + ptr++; + + /* if the search ended because we hit the end record, we failed */ + if (ptr->idVendor == 0x0000) { + US_DEBUGP("-- did not find a matching device\n"); + return NULL; + } + + /* otherwise, we found one! */ + US_DEBUGP("-- found matching device: %s\n", ptr->name); + return ptr; +} + +/* Set up the IRQ pipe and handler + * Note that this function assumes that all the data in the us_data + * strucuture is current. This includes the ep_int field, which gives us + * the endpoint for the interrupt. + * Returns non-zero on failure, zero on success + */ +static int usb_stor_allocate_irq(struct us_data *ss) +{ + unsigned int pipe; + int maxp; + int result; + + US_DEBUGP("Allocating IRQ for CBI transport\n"); + + /* lock access to the data structure */ + down(&(ss->irq_urb_sem)); + + /* allocate the URB */ + ss->irq_urb = usb_alloc_urb(0); + if (!ss->irq_urb) { + up(&(ss->irq_urb_sem)); + US_DEBUGP("couldn't allocate interrupt URB"); + return 1; + } + + /* calculate the pipe and max packet size */ + pipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int->bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK); + maxp = usb_maxpacket(ss->pusb_dev, pipe, usb_pipeout(pipe)); + if (maxp > sizeof(ss->irqbuf)) + maxp = sizeof(ss->irqbuf); + + /* fill in the URB with our data */ + FILL_INT_URB(ss->irq_urb, ss->pusb_dev, pipe, ss->irqbuf, maxp, + usb_stor_CBI_irq, ss, ss->ep_int->bInterval); + + /* submit the URB for processing */ + result = usb_submit_urb(ss->irq_urb); + US_DEBUGP("usb_submit_urb() returns %d\n", result); + if (result) { + usb_free_urb(ss->irq_urb); + up(&(ss->irq_urb_sem)); + return 2; + } + + /* unlock the data structure and return success */ + up(&(ss->irq_urb_sem)); + return 0; +} + +/* Probe to see if a new device is actually a SCSI device */ +static void * storage_probe(struct usb_device *dev, unsigned int ifnum) +{ + int i; + char mf[USB_STOR_STRING_LEN]; /* manufacturer */ + char prod[USB_STOR_STRING_LEN]; /* product */ + char serial[USB_STOR_STRING_LEN]; /* serial number */ + GUID(guid); /* Global Unique Identifier */ + unsigned int flags; + struct us_unusual_dev *unusual_dev; + struct us_data *ss = NULL; + int result; + + /* these are temporary copies -- we test on these, then put them + * in the us-data structure + */ + struct usb_endpoint_descriptor *ep_in = NULL; + struct usb_endpoint_descriptor *ep_out = NULL; + struct usb_endpoint_descriptor *ep_int = NULL; + u8 subclass = 0; + u8 protocol = 0; + + /* the altsettting 0 on the interface we're probing */ + struct usb_interface_descriptor *altsetting = + &(dev->actconfig->interface[ifnum].altsetting[0]); + + /* clear the temporary strings */ + memset(mf, 0, sizeof(mf)); + memset(prod, 0, sizeof(prod)); + memset(serial, 0, sizeof(serial)); + + /* search for this device in our unusual device list */ + unusual_dev = us_find_dev(dev->descriptor.idVendor, + dev->descriptor.idProduct, + dev->descriptor.bcdDevice); + + /* + * Can we support this device, either because we know about it + * from our unusual device list, or because it advertises that it's + * compliant to the specification? + */ + if (!unusual_dev && + !(dev->descriptor.bDeviceClass == 0 && + altsetting->bInterfaceClass == USB_CLASS_MASS_STORAGE && + altsetting->bInterfaceSubClass >= US_SC_MIN && + altsetting->bInterfaceSubClass <= US_SC_MAX)) { + /* if it's not a mass storage, we go no further */ + return NULL; + } + + /* At this point, we know we've got a live one */ + US_DEBUGP("USB Mass Storage device detected\n"); + + /* Determine subclass and protocol, or copy from the interface */ + if (unusual_dev) { + subclass = unusual_dev->useProtocol; + protocol = unusual_dev->useTransport; + flags = unusual_dev->flags; + } else { + subclass = altsetting->bInterfaceSubClass; + protocol = altsetting->bInterfaceProtocol; + flags = 0; + } + + /* + * Find the endpoints we need + * We are expecting a minimum of 2 endpoints - in and out (bulk). + * An optional interrupt is OK (necessary for CBI protocol). + * We will ignore any others. + */ + for (i = 0; i < altsetting->bNumEndpoints; i++) { + /* is it an BULK endpoint? */ + if ((altsetting->endpoint[i].bmAttributes & + USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { + /* BULK in or out? */ + if (altsetting->endpoint[i].bEndpointAddress & + USB_DIR_IN) + ep_in = &altsetting->endpoint[i]; + else + ep_out = &altsetting->endpoint[i]; + } + + /* is it an interrupt endpoint? */ + if ((altsetting->endpoint[i].bmAttributes & + USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { + ep_int = &altsetting->endpoint[i]; + } + } + US_DEBUGP("Endpoints: In: 0x%p Out: 0x%p Int: 0x%p (Period %d)\n", + ep_in, ep_out, ep_int, ep_int ? ep_int->bInterval : 0); + + /* set the interface -- STALL is an acceptable response here */ + result = usb_set_interface(dev, altsetting->bInterfaceNumber, 0); + US_DEBUGP("Result from usb_set_interface is %d\n", result); + if (result == -EPIPE) { + US_DEBUGP("-- clearing stall on control interface\n"); + usb_clear_halt(dev, usb_sndctrlpipe(dev, 0)); + } else if (result != 0) { + /* it's not a stall, but another error -- time to bail */ + US_DEBUGP("-- Unknown error. Rejecting device\n"); + return NULL; + } + + /* Do some basic sanity checks, and bail if we find a problem */ + if (!ep_in || !ep_out || (protocol == US_PR_CBI && !ep_int)) { + US_DEBUGP("Sanity check failed. Rejecting device.\n"); + return NULL; + } + + /* At this point, we're committed to using the device */ + + /* clear the GUID and fetch the strings */ + GUID_CLEAR(guid); + if (dev->descriptor.iManufacturer) + usb_string(dev, dev->descriptor.iManufacturer, + mf, sizeof(mf)); + if (dev->descriptor.iProduct) + usb_string(dev, dev->descriptor.iProduct, + prod, sizeof(prod)); + if (dev->descriptor.iSerialNumber && !(flags & US_FL_IGNORE_SER)) + usb_string(dev, dev->descriptor.iSerialNumber, + serial, sizeof(serial)); + + /* Create a GUID for this device */ + if (dev->descriptor.iSerialNumber && serial[0]) { + /* If we have a serial number, and it's a non-NULL string */ + make_guid(guid, dev->descriptor.idVendor, + dev->descriptor.idProduct, serial); + } else { + /* We don't have a serial number, so we use 0 */ + make_guid(guid, dev->descriptor.idVendor, + dev->descriptor.idProduct, "0"); + } + + /* lock access to the data structures */ + down(&us_list_semaphore); + + /* + * Now check if we have seen this GUID before + * We're looking for a device with a matching GUID that isn't + * allready on the system + */ + ss = us_list; + while ((ss != NULL) && + ((ss->pusb_dev) || !GUID_EQUAL(guid, ss->guid))) + ss = ss->next; + + if (ss != NULL) { + /* Existing device -- re-connect */ + US_DEBUGP("Found existing GUID " GUID_FORMAT "\n", + GUID_ARGS(guid)); + + /* establish the connection to the new device upon reconnect */ + ss->ifnum = ifnum; + ss->pusb_dev = dev; + + /* copy over the endpoint data */ + if (ep_in) + ss->ep_in = ep_in->bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + if (ep_out) + ss->ep_out = ep_out->bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + ss->ep_int = ep_int; + + /* allocate an IRQ callback if one is needed */ + if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) + return NULL; + } else { + /* New device -- allocate memory and initialize */ + US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid)); + + if ((ss = (struct us_data *)kmalloc(sizeof(struct us_data), + GFP_KERNEL)) == NULL) { + printk(KERN_WARNING USB_STORAGE "Out of memory\n"); + up(&us_list_semaphore); + return NULL; + } + memset(ss, 0, sizeof(struct us_data)); + + /* allocate the URB we're going to use */ + ss->current_urb = usb_alloc_urb(0); + if (!ss->current_urb) { + kfree(ss); + return NULL; + } + + /* Initialize the mutexes only when the struct is new */ + init_MUTEX_LOCKED(&(ss->sleeper)); + init_MUTEX_LOCKED(&(ss->notify)); + init_MUTEX_LOCKED(&(ss->ip_waitq)); + init_MUTEX(&(ss->queue_exclusion)); + init_MUTEX(&(ss->irq_urb_sem)); + init_MUTEX(&(ss->current_urb_sem)); + init_MUTEX(&(ss->dev_semaphore)); + + /* copy over the subclass and protocol data */ + ss->subclass = subclass; + ss->protocol = protocol; + ss->flags = flags; + + /* copy over the endpoint data */ + if (ep_in) + ss->ep_in = ep_in->bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + if (ep_out) + ss->ep_out = ep_out->bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + ss->ep_int = ep_int; + + /* establish the connection to the new device */ + ss->ifnum = ifnum; + ss->pusb_dev = dev; + + /* copy over the identifiying strings */ + strncpy(ss->vendor, mf, USB_STOR_STRING_LEN); + strncpy(ss->product, prod, USB_STOR_STRING_LEN); + strncpy(ss->serial, serial, USB_STOR_STRING_LEN); + if (strlen(ss->vendor) == 0) + strncpy(ss->vendor, "Unknown", USB_STOR_STRING_LEN); + if (strlen(ss->product) == 0) + strncpy(ss->product, "Unknown", USB_STOR_STRING_LEN); + if (strlen(ss->serial) == 0) + strncpy(ss->serial, "None", USB_STOR_STRING_LEN); + + /* copy the GUID we created before */ + memcpy(ss->guid, guid, sizeof(guid)); + + /* + * Set the handler pointers based on the protocol + * Again, this data is persistant across reattachments + */ + switch (ss->protocol) { + case US_PR_CB: + ss->transport_name = "Control/Bulk"; + ss->transport = usb_stor_CB_transport; + ss->transport_reset = usb_stor_CB_reset; + ss->max_lun = 7; + break; + + case US_PR_CBI: + ss->transport_name = "Control/Bulk/Interrupt"; + ss->transport = usb_stor_CBI_transport; + ss->transport_reset = usb_stor_CB_reset; + ss->max_lun = 7; + break; + + case US_PR_BULK: + ss->transport_name = "Bulk"; + ss->transport = usb_stor_Bulk_transport; + ss->transport_reset = usb_stor_Bulk_reset; + ss->max_lun = usb_stor_Bulk_max_lun(ss); + break; + + default: + ss->transport_name = "Unknown"; + up(&us_list_semaphore); + kfree(ss->current_urb); + kfree(ss); + return NULL; + break; + } + US_DEBUGP("Transport: %s\n", ss->transport_name); + + /* fix for single-lun devices */ + if (ss->flags & US_FL_SINGLE_LUN) + ss->max_lun = 0; + + switch (ss->subclass) { + case US_SC_RBC: + ss->protocol_name = "Reduced Block Commands (RBC)"; + ss->proto_handler = usb_stor_transparent_scsi_command; + break; + + case US_SC_8020: + ss->protocol_name = "8020i"; + ss->proto_handler = usb_stor_ATAPI_command; + break; + + case US_SC_QIC: + ss->protocol_name = "QIC-157"; + US_DEBUGP("Sorry, device not supported. Please\n"); + US_DEBUGP("contact mdharm-usb@one-eyed-alien.net\n"); + US_DEBUGP("if you see this message.\n"); + up(&us_list_semaphore); + kfree(ss->current_urb); + kfree(ss); + return NULL; + break; + + case US_SC_8070: + ss->protocol_name = "8070i"; + ss->proto_handler = usb_stor_ATAPI_command; + break; + + case US_SC_SCSI: + ss->protocol_name = "Transparent SCSI"; + ss->proto_handler = usb_stor_transparent_scsi_command; + break; + + case US_SC_UFI: + ss->protocol_name = "Uniform Floppy Interface (UFI)"; + ss->proto_handler = usb_stor_ufi_command; + break; + + default: + ss->protocol_name = "Unknown"; + up(&us_list_semaphore); + kfree(ss->current_urb); + kfree(ss); + return NULL; + break; + } + US_DEBUGP("Protocol: %s\n", ss->protocol_name); + + /* allocate an IRQ callback if one is needed */ + if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) + return NULL; + + /* + * Since this is a new device, we need to generate a scsi + * host definition, and register with the higher SCSI layers + */ + + /* Initialize the host template based on the default one */ + memcpy(&(ss->htmplt), &usb_stor_host_template, + sizeof(usb_stor_host_template)); + + /* Grab the next host number */ + ss->host_number = my_host_number++; + + /* We abuse this pointer so we can pass the ss pointer to + * the host controler thread in us_detect. But how else are + * we to do it? + */ + (struct us_data *)ss->htmplt.proc_dir = ss; + + /* start up our control thread */ + ss->pid = kernel_thread(usb_stor_control_thread, ss, + CLONE_FS | CLONE_FILES | + CLONE_SIGHAND); + if (ss->pid < 0) { + printk(KERN_WARNING USB_STORAGE + "Unable to start control thread\n"); + kfree(ss->current_urb); + kfree(ss); + return NULL; + } + + /* wait for the thread to start */ + down(&(ss->notify)); + + /* now register - our detect function will be called */ + ss->htmplt.module = THIS_MODULE; + scsi_register_module(MODULE_SCSI_HA, &(ss->htmplt)); + + /* put us in the list */ + ss->next = us_list; + us_list = ss; + } + + /* release the data structure lock */ + up(&us_list_semaphore); + + printk(KERN_DEBUG + "WARNING: USB Mass Storage data integrity not assured\n"); + printk(KERN_DEBUG + "USB Mass Storage device found at %d\n", dev->devnum); + + /* return a pointer for the disconnect function */ + return ss; +} + +/* Handle a disconnect event from the USB core */ +static void storage_disconnect(struct usb_device *dev, void *ptr) +{ + struct us_data *ss = ptr; + int result; + + US_DEBUGP("storage_disconnect() called\n"); + + /* this is the odd case -- we disconnected but weren't using it */ + if (!ss) { + US_DEBUGP("-- device was not in use\n"); + return; + } + + /* lock access to the device data structure */ + down(&(ss->dev_semaphore)); + + /* release the IRQ, if we have one */ + down(&(ss->irq_urb_sem)); + if (ss->irq_urb) { + US_DEBUGP("-- releasing irq handle\n"); + result = usb_unlink_urb(ss->irq_urb); + ss->irq_urb = NULL; + US_DEBUGP("-- usb_unlink_urb() returned %d\n", result); + usb_free_urb(ss->irq_urb); + } + up(&(ss->irq_urb_sem)); + + /* mark the device as gone */ + ss->pusb_dev = NULL; + + /* lock access to the device data structure */ + up(&(ss->dev_semaphore)); +} + +/*********************************************************************** + * Initialization and registration + ***********************************************************************/ + +int __init usb_stor_init(void) +{ + /* initialize internal global data elements */ + us_list = NULL; + init_MUTEX(&us_list_semaphore); + my_host_number = 0; + + /* register the driver, return -1 if error */ + if (usb_register(&storage_driver) < 0) + return -1; + + /* we're all set */ + printk(KERN_INFO "USB Mass Storage support registered.\n"); + return 0; +} + +void __exit usb_stor_exit(void) +{ + struct us_data *next; + + US_DEBUGP("usb_stor_exit() called\n"); + + /* Deregister the driver + * This eliminates races with probes and disconnects + */ + US_DEBUGP("-- calling usb_deregister()\n"); + usb_deregister(&storage_driver) ; + + /* lock access to the data structures */ + down(&us_list_semaphore); + + /* While there are still virtual hosts, unregister them + * + * Note that the us_release() routine will destroy the local data + * structure. So we have to peel these off the top of the list + * and keep updating the head pointer as we go. + */ + while (us_list) { + /* keep track of where the next one is */ + next = us_list->next; + + US_DEBUGP("-- calling scsi_unregister_module()\n"); + scsi_unregister_module(MODULE_SCSI_HA, &(us_list->htmplt)); + + /* Now that scsi_unregister_module is done with the host + * template, we can free the us_data structure (the host + * template is inline in this structure). */ + kfree (us_list); + + /* advance the list pointer */ + us_list = next; + } + + /* unlock the data structures */ + up(&us_list_semaphore); +} + +module_init(usb_stor_init) ; +module_exit(usb_stor_exit) ; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/storage/usb.h linux/drivers/usb/storage/usb.h --- v2.4.0-test2/linux/drivers/usb/storage/usb.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/usb.h Wed Jun 28 19:46:22 2000 @@ -0,0 +1,182 @@ +/* Driver for USB Mass Storage compliant devices + * Main Header File + * + * $Id: usb.h,v 1.1 2000/06/27 01:25:28 mdharm Exp $ + * + * Current development and maintainance by: + * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * + * Initial work by: + * (c) 1999 Michael Gee (michael@linuxspecific.com) + * + * This driver is based on the 'USB Mass Storage Class' document. This + * describes in detail the protocol used to communicate with such + * devices. Clearly, the designers had SCSI and ATAPI commands in + * mind when they created this document. The commands are all very + * similar to commands in the SCSI-II and ATAPI specifications. + * + * It is important to note that in a number of cases this class + * exhibits class-specific exemptions from the USB specification. + * Notably the usage of NAK, STALL and ACK differs from the norm, in + * that they are used to communicate wait, failed and OK on commands. + * + * Also, for certain devices, the interrupt endpoint is used to convey + * status of a command. + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _USB_H_ +#define _USB_H_ + +#include +#include +#include +#include "scsi.h" +#include "hosts.h" + +/* + * GUID definitions + */ + +#define GUID(x) __u32 x[3] +#define GUID_EQUAL(x, y) (x[0] == y[0] && x[1] == y[1] && x[2] == y[2]) +#define GUID_CLEAR(x) x[0] = x[1] = x[2] = 0; +#define GUID_NONE(x) (!x[0] && !x[1] && !x[2]) +#define GUID_FORMAT "%08x%08x%08x" +#define GUID_ARGS(x) x[0], x[1], x[2] + +static inline void make_guid( __u32 *pg, __u16 vendor, __u16 product, char *serial) +{ + pg[0] = (vendor << 16) | product; + pg[1] = pg[2] = 0; + while (*serial) { + pg[1] <<= 4; + pg[1] |= pg[2] >> 28; + pg[2] <<= 4; + if (*serial >= 'a') + *serial -= 'a' - 'A'; + pg[2] |= (*serial <= '9' && *serial >= '0') ? *serial - '0' + : *serial - 'A' + 10; + serial++; + } +} + +/* + * Unusual device list definitions + */ + +struct us_unusual_dev { + /* we search the list based on these parameters */ + __u16 idVendor; + __u16 idProduct; + __u16 bcdDeviceMin; + __u16 bcdDeviceMax; + + /* the list specifies these parameters */ + const char* name; + __u8 useProtocol; + __u8 useTransport; + unsigned int flags; +}; + +/* Flag definitions */ +#define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */ +#define US_FL_MODE_XLATE 0x00000002 /* translate _6 to _10 comands for + Win/MacOS compatibility */ +#define US_FL_START_STOP 0x00000004 /* ignore START_STOP commands */ +#define US_FL_ALT_LENGTH 0x00000008 /* use the alternate algorithm for + us_transfer_length() */ +#define US_FL_IGNORE_SER 0x00000010 /* Ignore the serial number given */ + +#define USB_STOR_STRING_LEN 32 + +struct us_data; + +typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*); +typedef int (*trans_reset)(struct us_data*); +typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*); + +/* we allocate one of these for every device that we remember */ +struct us_data { + struct us_data *next; /* next device */ + + /* the device we're working with */ + struct semaphore dev_semaphore; /* protect pusb_dev */ + struct usb_device *pusb_dev; /* this usb_device */ + + unsigned int flags; /* from filter initially */ + + /* information about the device -- always good */ + char vendor[USB_STOR_STRING_LEN]; + char product[USB_STOR_STRING_LEN]; + char serial[USB_STOR_STRING_LEN]; + char *transport_name; + char *protocol_name; + u8 subclass; + u8 protocol; + u8 max_lun; + + /* information about the device -- only good if device is attached */ + u8 ifnum; /* interface number */ + u8 ep_in; /* bulk in endpoint */ + u8 ep_out; /* bulk out endpoint */ + struct usb_endpoint_descriptor *ep_int; /* interrupt endpoint */ + + /* function pointers for this device */ + trans_cmnd transport; /* transport function */ + trans_reset transport_reset; /* transport device reset */ + proto_cmnd proto_handler; /* protocol handler */ + + /* SCSI interfaces */ + GUID(guid); /* unique dev id */ + struct Scsi_Host *host; /* our dummy host data */ + Scsi_Host_Template htmplt; /* own host template */ + int host_number; /* to find us */ + int host_no; /* allocated by scsi */ + Scsi_Cmnd *srb; /* current srb */ + + /* thread information */ + Scsi_Cmnd *queue_srb; /* the single queue slot */ + int action; /* what to do */ + int pid; /* control thread */ + + /* interrupt info for CBI devices -- only good if attached */ + struct semaphore ip_waitq; /* for CBI interrupts */ + int ip_wanted; /* is an IRQ expected? */ + + /* interrupt communications data */ + struct semaphore irq_urb_sem; /* to protect irq_urb */ + struct urb *irq_urb; /* for USB int requests */ + unsigned char irqbuf[2]; /* buffer for USB IRQ */ + + /* control and bulk communications data */ + struct semaphore current_urb_sem; /* to protect irq_urb */ + struct urb *current_urb; /* non-int USB requests */ + + /* mutual exclusion structures */ + struct semaphore notify; /* thread begin/end */ + struct semaphore sleeper; /* to sleep the thread on */ + struct semaphore queue_exclusion; /* to protect data structs */ +}; + +/* The list of structures and the protective lock for them */ +extern struct us_data *us_list; +extern struct semaphore us_list_semaphore; + +#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c --- v2.4.0-test2/linux/drivers/usb/usb-ohci.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/usb-ohci.c Wed Jul 5 11:16:41 2000 @@ -307,7 +307,7 @@ static void ohci_dump (ohci_t *controller, int verbose) { - dbg ("OHCI controller %p state", controller->regs); + dbg ("OHCI controller %s state", controller->ohci_dev->slot_name); // dumps some of the state we know about ohci_dump_status (controller); @@ -831,8 +831,8 @@ } break; - case INT: - int_branch = ed->int_branch; + case INT: + int_branch = ed->int_branch; interval = ed->int_interval; for (i = 0; i < ep_rev (6, interval); i += inter) { @@ -1392,6 +1392,14 @@ __u8 data[8]; num_ports = readl (&ohci->regs->roothub.a) & RH_A_NDP; + if (num_ports > MAX_ROOT_PORTS) { + err ("bogus NDP=%d for OHCI %s", num_ports, + ohci->ohci_dev->slot_name); + err ("rereads as NDP=%d", + readl (&ohci->regs->roothub.a) & RH_A_NDP); + /* retry later; "should not happen" */ + return 0; + } *(__u8 *) data = (readl (&ohci->regs->roothub.status) & (RH_HS_LPSC | RH_HS_OCIC)) ? 1: 0; ret = *(__u8 *) data; @@ -1424,8 +1432,12 @@ ohci_t * ohci = urb->dev->bus->hcpriv; if (ohci->disabled) - return; - + return; + + /* ignore timers firing during PM suspend, etc */ + if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) + return; + if(ohci->rh.send) { len = rh_send_irq (ohci, urb->transfer_buffer, urb->transfer_buffer_length); if (len > 0) { @@ -1702,7 +1714,9 @@ /* Disable HC interrupts */ writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); - dbg("USB HC reset_hc: %x ;", readl (&ohci->regs->control)); + dbg("USB HC reset_hc %s: ctrl = %x ;", + ohci->ohci_dev->slot_name, + readl (&ohci->regs->control)); /* Reset USB (needed by some controllers) */ writel (0, &ohci->regs->control); @@ -1793,17 +1807,24 @@ if ((ohci->hcca.done_head != 0) && !(le32_to_cpup (&ohci->hcca.done_head) & 0x01)) { ints = OHCI_INTR_WDH; - } else { - if ((ints = (readl (®s->intrstatus) & readl (®s->intrenable))) == 0) - return; + } else if ((ints = (readl (®s->intrstatus) & readl (®s->intrenable))) == 0) { + return; } // dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca.frame_no)); if (ints & OHCI_INTR_UE) { ohci->disabled++; - err ("OHCI Unrecoverable Error, controller disabled"); + err ("OHCI Unrecoverable Error, controller %s disabled", + ohci->ohci_dev->slot_name); // e.g. due to PCI Master/Target Abort + +#ifndef DEBUG + // FIXME: be optimistic, hope that bug won't repeat often. + // Make some non-interrupt context restart the controller. + // Count and limit the retries though; either hardware or + // software errors can go forever... +#endif } if (ints & OHCI_INTR_WDH) { @@ -1823,7 +1844,8 @@ if (ohci->ed_rm_list[!frame] != NULL) { dl_del_list (ohci, !frame); } - if (ohci->ed_rm_list[frame] != NULL) writel (OHCI_INTR_SF, ®s->intrenable); + if (ohci->ed_rm_list[frame] != NULL) + writel (OHCI_INTR_SF, ®s->intrenable); } writel (ints, ®s->intrstatus); writel (OHCI_INTR_MIE, ®s->intrenable); @@ -1885,20 +1907,20 @@ static void hc_release_ohci (ohci_t * ohci) { - dbg("USB HC release ohci"); + dbg ("USB HC release ohci %s", ohci->ohci_dev->slot_name); /* disconnect all devices */ if (ohci->bus->root_hub) usb_disconnect (&ohci->bus->root_hub); - hc_reset (ohci); - writel (OHCI_USB_RESET, &ohci->regs->control); - wait_ms (10); + if (!ohci->disabled) + hc_reset (ohci); if (ohci->irq >= 0) { free_irq (ohci->irq, ohci); ohci->irq = -1; } + ohci->ohci_dev->driver_data = 0; usb_deregister_bus (ohci->bus); usb_free_bus (ohci->bus); @@ -1926,13 +1948,15 @@ #endif printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n", (unsigned long) mem_base, bufp); - printk(KERN_INFO __FILE__ ": %s\n", dev->name); + printk(KERN_INFO __FILE__ ": pci slot %s, %s\n", dev->slot_name, dev->name); ohci = hc_alloc_ohci (mem_base); if (!ohci) { return -ENOMEM; } + ohci->ohci_dev = dev; + dev->driver_data = ohci; INIT_LIST_HEAD (&ohci->ohci_hcd_list); list_add (&ohci->ohci_hcd_list, &ohci_hcd_list); @@ -1960,7 +1984,6 @@ #ifdef DEBUG ohci_dump (ohci, 1); #endif - return 0; } err("request interrupt %d failed", irq); @@ -2037,7 +2060,7 @@ switch (rqst) { case PM_SUSPEND: /* act as if usb suspend can always be used */ - dbg("USB suspend: %p", ohci->regs); + dbg("USB suspend: %s", ohci->ohci_dev->slot_name); ohci->hc_control = OHCI_USB_SUSPEND; writel (ohci->hc_control, &ohci->regs->control); wait_ms (10); @@ -2050,7 +2073,7 @@ switch (temp) { case OHCI_USB_RESET: // lost power - dbg("USB reset: %p", ohci->regs); + dbg("USB reset: %s", ohci->ohci_dev->slot_name); ohci->disabled = 1; if (ohci->bus->root_hub) usb_disconnect (&ohci->bus->root_hub); @@ -2058,14 +2081,16 @@ if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) { ohci->disabled = 1; - err ("can't restart, %d", temp); + err ("can't restart %s, %d", + ohci->ohci_dev->slot_name, + temp); } dbg ("reset done"); break; case OHCI_USB_SUSPEND: // host wakeup case OHCI_USB_RESUME: // remote wakeup - dbg("USB resume: %p", ohci->regs); + dbg("USB resume: %s", ohci->ohci_dev->slot_name); ohci->hc_control = OHCI_USB_RESUME; writel (ohci->hc_control, &ohci->regs->control); wait_ms (20); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/usb-ohci.h linux/drivers/usb/usb-ohci.h --- v2.4.0-test2/linux/drivers/usb/usb-ohci.h Tue May 23 15:31:35 2000 +++ linux/drivers/usb/usb-ohci.h Wed Jul 5 11:16:41 2000 @@ -8,13 +8,9 @@ */ -#define MODSTR "ohci: " - - static int cc_to_error[16] = { /* mapping of the OHCI CC status to error codes */ -#ifdef USB_ST_CRC /* status codes */ /* No Error */ USB_ST_NOERROR, /* CRC Error */ USB_ST_CRC, /* Bit Stuff */ USB_ST_BITSTUFF, @@ -33,28 +29,6 @@ /* Not Access */ USB_ST_NORESPONSE }; -#else /* error codes */ - /* No Error */ 0, - /* CRC Error */ -EILSEQ, - /* Bit Stuff */ -EPROTO, - /* Data Togg */ -EILSEQ, - /* Stall */ -EPIPE, - /* DevNotResp */ -ETIMEDOUT, - /* PIDCheck */ -EPROTO, - /* UnExpPID */ -EPROTO, - /* DataOver */ -EOVERFLOW, - /* DataUnder */ -EREMOTEIO, - /* reservd */ -ETIMEDOUT, - /* reservd */ -ETIMEDOUT, - /* BufferOver */ -ECOMM, - /* BuffUnder */ -ECOMM, - /* Not Access */ -ETIMEDOUT, - /* Not Access */ -ETIMEDOUT -}; -#define USB_ST_URB_PENDING -EINPROGRESS -#endif - - struct ed; struct td; @@ -410,6 +384,7 @@ struct usb_bus * bus; struct usb_device * dev[128]; struct virt_root_hub rh; + struct pci_dev *ohci_dev; } ohci_t; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/usb-storage-debug.h linux/drivers/usb/usb-storage-debug.h --- v2.4.0-test2/linux/drivers/usb/usb-storage-debug.h Sat Feb 26 22:31:50 2000 +++ linux/drivers/usb/usb-storage-debug.h Wed Dec 31 16:00:00 1969 @@ -1,89 +0,0 @@ -#include -#ifdef CONFIG_USB_STORAGE_DEBUG - -/* Debug output for Driver for USB mass storage (scsi-like) devices - * - * (C) Michael Gee (michael@linuxspecific.com) 1999 - * - */ - -void us_show_command(Scsi_Cmnd *srb) -{ - char *what = NULL; - - switch (srb->cmnd[0]) { - case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break; - case REZERO_UNIT: what = "REZERO_UNIT"; break; - case REQUEST_SENSE: what = "REQUEST_SENSE"; break; - case FORMAT_UNIT: what = "FORMAT_UNIT"; break; - case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break; - case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break; - case READ_6: what = "READ_6"; break; - case WRITE_6: what = "WRITE_6"; break; - case SEEK_6: what = "SEEK_6"; break; - case READ_REVERSE: what = "READ_REVERSE"; break; - case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break; - case SPACE: what = "SPACE"; break; - case INQUIRY: what = "INQUIRY"; break; - case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break; - case MODE_SELECT: what = "MODE_SELECT"; break; - case RESERVE: what = "RESERVE"; break; - case RELEASE: what = "RELEASE"; break; - case COPY: what = "COPY"; break; - case ERASE: what = "ERASE"; break; - case MODE_SENSE: what = "MODE_SENSE"; break; - case START_STOP: what = "START_STOP"; break; - case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break; - case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break; - case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break; - case SET_WINDOW: what = "SET_WINDOW"; break; - case READ_CAPACITY: what = "READ_CAPACITY"; break; - case READ_10: what = "READ_10"; break; - case WRITE_10: what = "WRITE_10"; break; - case SEEK_10: what = "SEEK_10"; break; - case WRITE_VERIFY: what = "WRITE_VERIFY"; break; - case VERIFY: what = "VERIFY"; break; - case SEARCH_HIGH: what = "SEARCH_HIGH"; break; - case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break; - case SEARCH_LOW: what = "SEARCH_LOW"; break; - case SET_LIMITS: what = "SET_LIMITS"; break; - case READ_POSITION: what = "READ_POSITION"; break; - case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break; - case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break; - case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break; - case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break; - case COMPARE: what = "COMPARE"; break; - case COPY_VERIFY: what = "COPY_VERIFY"; break; - case WRITE_BUFFER: what = "WRITE_BUFFER"; break; - case READ_BUFFER: what = "READ_BUFFER"; break; - case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break; - case READ_LONG: what = "READ_LONG"; break; - case WRITE_LONG: what = "WRITE_LONG"; break; - case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break; - case WRITE_SAME: what = "WRITE_SAME"; break; - case READ_TOC: what = "READ_TOC"; break; - case LOG_SELECT: what = "LOG_SELECT"; break; - case LOG_SENSE: what = "LOG_SENSE"; break; - case MODE_SELECT_10: what = "MODE_SELECT_10"; break; - case MODE_SENSE_10: what = "MODE_SENSE_10"; break; - case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break; - case READ_12: what = "READ_12"; break; - case WRITE_12: what = "WRITE_12"; break; - case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break; - case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break; - case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break; - case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break; - case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break; - case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break; - case WRITE_LONG_2: what = "WRITE_LONG_2"; break; - default: break; - } - printk(KERN_DEBUG USB_STORAGE - "Command %s (%d bytes)\n", what, srb->cmd_len); - printk(KERN_DEBUG USB_STORAGE - " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5], - srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]); -} - -#endif diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/usb-storage.c linux/drivers/usb/usb-storage.c --- v2.4.0-test2/linux/drivers/usb/usb-storage.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/usb-storage.c Wed Dec 31 16:00:00 1969 @@ -1,2787 +0,0 @@ -/* Driver for USB Mass Storage compliant devices - * - * $Id: usb-storage.c,v 1.11 2000/06/20 03:19:31 mdharm Exp $ - * - * Current development and maintainance by: - * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) - * - * Developed with the assistance of: - * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) - * - * Initial work by: - * (c) 1999 Michael Gee (michael@linuxspecific.com) - * - * This driver is based on the 'USB Mass Storage Class' document. This - * describes in detail the protocol used to communicate with such - * devices. Clearly, the designers had SCSI and ATAPI commands in - * mind when they created this document. The commands are all very - * similar to commands in the SCSI-II and ATAPI specifications. - * - * It is important to note that in a number of cases this class - * exhibits class-specific exemptions from the USB specification. - * Notably the usage of NAK, STALL and ACK differs from the norm, in - * that they are used to communicate wait, failed and OK on commands. - * - * Also, for certain devices, the interrupt endpoint is used to convey - * status of a command. - * - * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more - * information about this driver. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "../scsi/scsi.h" -#include "../scsi/hosts.h" -#include "../scsi/sd.h" - -#include "usb-storage.h" -#include "usb-storage-debug.h" - -/* direction table -- this indicates the direction of the data - * transfer for each command code -- a 1 indicates input - */ -/* FIXME: we need to use the new direction indicators in the Scsi_Cmnd - * structure, not this table. First we need to evaluate if it's being set - * correctly for us, though - */ -unsigned char us_direction[256/8] = { - 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, - 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* - * Per device data - */ - -static int my_host_number; - -struct us_data; - -typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*); -typedef int (*trans_reset)(struct us_data*); -typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*); - -/* we allocate one of these for every device that we remember */ -struct us_data { - struct us_data *next; /* next device */ - - /* the device we're working with */ - struct semaphore dev_semaphore; /* protect pusb_dev */ - struct usb_device *pusb_dev; /* this usb_device */ - - unsigned int flags; /* from filter initially */ - - /* information about the device -- always good */ - char vendor[USB_STOR_STRING_LEN]; - char product[USB_STOR_STRING_LEN]; - char serial[USB_STOR_STRING_LEN]; - char *transport_name; - char *protocol_name; - u8 subclass; - u8 protocol; - u8 max_lun; - - /* information about the device -- only good if device is attached */ - u8 ifnum; /* interface number */ - u8 ep_in; /* bulk in endpoint */ - u8 ep_out; /* bulk out endpoint */ - struct usb_endpoint_descriptor *ep_int; /* interrupt endpoint */ - - /* function pointers for this device */ - trans_cmnd transport; /* transport function */ - trans_reset transport_reset; /* transport device reset */ - proto_cmnd proto_handler; /* protocol handler */ - - /* SCSI interfaces */ - GUID(guid); /* unique dev id */ - struct Scsi_Host *host; /* our dummy host data */ - Scsi_Host_Template htmplt; /* own host template */ - int host_number; /* to find us */ - int host_no; /* allocated by scsi */ - Scsi_Cmnd *srb; /* current srb */ - - /* thread information */ - Scsi_Cmnd *queue_srb; /* the single queue slot */ - int action; /* what to do */ - int pid; /* control thread */ - - /* interrupt info for CBI devices -- only good if attached */ - struct semaphore ip_waitq; /* for CBI interrupts */ - int ip_wanted; /* is an IRQ expected? */ - - /* interrupt communications data */ - struct semaphore irq_urb_sem; /* to protect irq_urb */ - struct urb *irq_urb; /* for USB int requests */ - unsigned char irqbuf[2]; /* buffer for USB IRQ */ - - /* control and bulk communications data */ - struct semaphore current_urb_sem; /* to protect irq_urb */ - struct urb *current_urb; /* non-int USB requests */ - - /* mutual exclusion structures */ - struct semaphore notify; /* thread begin/end */ - struct semaphore sleeper; /* to sleep the thread on */ - struct semaphore queue_exclusion; /* to protect data structs */ -}; - -/* - * kernel thread actions - */ - -#define US_ACT_COMMAND 1 -#define US_ACT_DEVICE_RESET 2 -#define US_ACT_BUS_RESET 3 -#define US_ACT_HOST_RESET 4 -#define US_ACT_EXIT 5 - -/* The list of structures and the protective lock for them */ -static struct us_data *us_list; -struct semaphore us_list_semaphore; - -static void * storage_probe(struct usb_device *dev, unsigned int ifnum); -static void storage_disconnect(struct usb_device *dev, void *ptr); -static struct usb_driver storage_driver = { - name: "usb-storage", - probe: storage_probe, - disconnect: storage_disconnect, -}; - -/*********************************************************************** - * Data transfer routines - ***********************************************************************/ - -/* This is the completion handler which will wake us up when an URB - * completes. - */ -static void usb_stor_blocking_completion(urb_t *urb) -{ - api_wrapper_data *awd = (api_wrapper_data *)urb->context; - - if (waitqueue_active(awd->wakeup)) - wake_up(awd->wakeup); -} - -/* This is our function to emulate usb_control_msg() but give us enough - * access to make aborts/resets work - */ -int usb_stor_control_msg(struct us_data *us, unsigned int pipe, - u8 request, u8 requesttype, u16 value, u16 index, - void *data, u16 size) -{ - DECLARE_WAITQUEUE(wait, current); - DECLARE_WAIT_QUEUE_HEAD(wqh); - api_wrapper_data awd; - int status; - devrequest *dr; - - /* allocate the device request structure */ - dr = kmalloc(sizeof(devrequest), GFP_KERNEL); - if (!dr) - return -ENOMEM; - - /* fill in the structure */ - dr->requesttype = requesttype; - dr->request = request; - dr->value = cpu_to_le16(value); - dr->index = cpu_to_le16(index); - dr->length = cpu_to_le16(size); - - /* set up data structures for the wakeup system */ - awd.wakeup = &wqh; - awd.handler = 0; - init_waitqueue_head(&wqh); - add_wait_queue(&wqh, &wait); - - /* lock the URB */ - down(&(us->current_urb_sem)); - - /* fill the URB */ - FILL_CONTROL_URB(us->current_urb, us->pusb_dev, pipe, - (unsigned char*) dr, data, size, - usb_stor_blocking_completion, &awd); - - /* submit the URB */ - set_current_state(TASK_UNINTERRUPTIBLE); - status = usb_submit_urb(us->current_urb); - if (status) { - /* something went wrong */ - up(&(us->current_urb_sem)); - remove_wait_queue(&wqh, &wait); - kfree(dr); - return status; - } - - /* wait for the completion of the URB */ - up(&(us->current_urb_sem)); - if (us->current_urb->status == -EINPROGRESS) - schedule_timeout(10*HZ); - down(&(us->current_urb_sem)); - - /* we either timed out or got woken up -- clean up either way */ - set_current_state(TASK_RUNNING); - remove_wait_queue(&wqh, &wait); - - /* did we time out? */ - if (us->current_urb->status == -EINPROGRESS) { - US_DEBUGP("usb_stor_control_msg() timeout\n"); - usb_unlink_urb(us->current_urb); - status = -ETIMEDOUT; - } else - status = us->current_urb->status; - - /* return the actual length of the data transferred if no error*/ - if (status >= 0) - status = us->current_urb->actual_length; - - /* release the lock and return status */ - up(&(us->current_urb_sem)); - kfree(dr); - return status; -} - -/* This is our function to emulate usb_bulk_msg() but give us enough - * access to make aborts/resets work - */ -int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe, - unsigned int len, unsigned int *act_len) -{ - DECLARE_WAITQUEUE(wait, current); - DECLARE_WAIT_QUEUE_HEAD(wqh); - api_wrapper_data awd; - int status; - - /* set up data structures for the wakeup system */ - awd.wakeup = &wqh; - awd.handler = 0; - init_waitqueue_head(&wqh); - add_wait_queue(&wqh, &wait); - - /* lock the URB */ - down(&(us->current_urb_sem)); - - /* fill the URB */ - FILL_BULK_URB(us->current_urb, us->pusb_dev, pipe, data, len, - usb_stor_blocking_completion, &awd); - - /* submit the URB */ - set_current_state(TASK_UNINTERRUPTIBLE); - status = usb_submit_urb(us->current_urb); - if (status) { - /* something went wrong */ - up(&(us->current_urb_sem)); - remove_wait_queue(&wqh, &wait); - return status; - } - - /* wait for the completion of the URB */ - up(&(us->current_urb_sem)); - if (us->current_urb->status == -EINPROGRESS) - schedule_timeout(10*HZ); - down(&(us->current_urb_sem)); - - /* we either timed out or got woken up -- clean up either way */ - set_current_state(TASK_RUNNING); - remove_wait_queue(&wqh, &wait); - - /* did we time out? */ - if (us->current_urb->status == -EINPROGRESS) { - US_DEBUGP("usb_stor_bulk_msg() timeout\n"); - usb_unlink_urb(us->current_urb); - status = -ETIMEDOUT; - } else - status = us->current_urb->status; - - /* return the actual length of the data transferred */ - *act_len = us->current_urb->actual_length; - - /* release the lock and return status */ - up(&(us->current_urb_sem)); - return status; -} - -/* - * Transfer one SCSI scatter-gather buffer via bulk transfer - * - * Note that this function is necessary because we want the ability to - * use scatter-gather memory. Good performance is achieved by a combination - * of scatter-gather and clustering (which makes each chunk bigger). - * - * Note that the lower layer will always retry when a NAK occurs, up to the - * timeout limit. Thus we don't have to worry about it for individual - * packets. - */ -static int us_transfer_partial(struct us_data *us, char *buf, int length) -{ - int result; - int partial; - int pipe; - - /* calculate the appropriate pipe information */ - if (US_DIRECTION(us->srb->cmnd[0])) - pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); - else - pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); - - /* transfer the data */ - US_DEBUGP("us_transfer_partial(): xfer %d bytes\n", length); - result = usb_stor_bulk_msg(us, buf, pipe, length, &partial); - US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %d/%d\n", - result, partial, length); - - /* if we stall, we need to clear it before we go on */ - if (result == -EPIPE) { - US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); - usb_clear_halt(us->pusb_dev, pipe); - } - - /* did we send all the data? */ - if (partial == length) { - US_DEBUGP("us_transfer_partial(): transfer complete\n"); - return US_BULK_TRANSFER_GOOD; - } - - /* uh oh... we have an error code, so something went wrong. */ - if (result) { - /* NAK - that means we've retried a few times allready */ - if (result == -ETIMEDOUT) { - US_DEBUGP("us_transfer_partial(): device NAKed\n"); - return US_BULK_TRANSFER_FAILED; - } - - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { - US_DEBUGP("us_transfer_partial(): transfer aborted\n"); - return US_BULK_TRANSFER_ABORTED; - } - - /* the catch-all case */ - US_DEBUGP("us_transfer_partial(): unknown error\n"); - return US_BULK_TRANSFER_FAILED; - } - - /* no error code, so we must have transferred some data, - * just not all of it */ - return US_BULK_TRANSFER_SHORT; -} - -/* - * Transfer an entire SCSI command's worth of data payload over the bulk - * pipe. - * - * Note that this uses us_transfer_partial to achieve it's goals -- this - * function simply determines if we're going to use scatter-gather or not, - * and acts appropriately. For now, it also re-interprets the error codes. - */ -static void us_transfer(Scsi_Cmnd *srb, struct us_data* us, int dir_in) -{ - int i; - int result = -1; - struct scatterlist *sg; - - /* are we scatter-gathering? */ - if (srb->use_sg) { - - /* loop over all the scatter gather structures and - * make the appropriate requests for each, until done - */ - sg = (struct scatterlist *) srb->request_buffer; - for (i = 0; i < srb->use_sg; i++) { - result = us_transfer_partial(us, sg[i].address, - sg[i].length); - if (result) - break; - } - } - else - /* no scatter-gather, just make the request */ - result = us_transfer_partial(us, srb->request_buffer, - srb->request_bufflen); - - /* return the result in the data structure itself */ - srb->result = result; -} - -/* Calculate the length of the data transfer (not the command) for any - * given SCSI command - */ -static unsigned int us_transfer_length(Scsi_Cmnd *srb, struct us_data *us) -{ - int i; - unsigned int total = 0; - struct scatterlist *sg; - - /* support those devices which need the length calculated - * differently - */ - if (us->flags & US_FL_ALT_LENGTH) { - if (srb->cmnd[0] == INQUIRY) { - srb->cmnd[4] = 36; - } - - if ((srb->cmnd[0] == INQUIRY) || (srb->cmnd[0] == MODE_SENSE)) - return srb->cmnd[4]; - - if (srb->cmnd[0] == TEST_UNIT_READY) - return 0; - } - - /* Are we going to scatter gather? */ - if (srb->use_sg) { - /* Add up the sizes of all the scatter-gather segments */ - sg = (struct scatterlist *) srb->request_buffer; - for (i = 0; i < srb->use_sg; i++) - total += sg[i].length; - - return total; - } - else - /* Just return the length of the buffer */ - return srb->request_bufflen; -} - -/*********************************************************************** - * Transport routines - ***********************************************************************/ - -/* Invoke the transport and basic error-handling/recovery methods - * - * This is used by the protocol layers to actually send the message to - * the device and recieve the response. - */ -static void invoke_transport(Scsi_Cmnd *srb, struct us_data *us) -{ - int need_auto_sense; - int result; - - /* send the command to the transport layer */ - result = us->transport(srb, us); - - /* Determine if we need to auto-sense - * - * I normally don't use a flag like this, but it's almost impossible - * to understand what's going on here if I don't. - */ - need_auto_sense = 0; - - /* - * If we're running the CB transport, which is incapable - * of determining status on it's own, we need to auto-sense almost - * every time. - */ - if (us->protocol == US_PR_CB) { - US_DEBUGP("-- CB transport device requiring auto-sense\n"); - need_auto_sense = 1; - - /* There are some exceptions to this. Notably, if this is - * a UFI device and the command is REQUEST_SENSE or INQUIRY, - * then it is impossible to truly determine status. - */ - if (us->subclass == US_SC_UFI && - ((srb->cmnd[0] == REQUEST_SENSE) || - (srb->cmnd[0] == INQUIRY))) { - US_DEBUGP("** no auto-sense for a special command\n"); - need_auto_sense = 0; - } - } - - /* - * If we have an error, we're going to do a REQUEST_SENSE - * automatically. Note that we differentiate between a command - * "failure" and an "error" in the transport mechanism. - */ - if (result == USB_STOR_TRANSPORT_FAILED) { - US_DEBUGP("-- transport indicates command failure\n"); - need_auto_sense = 1; - } - if (result == USB_STOR_TRANSPORT_ERROR) { - /* FIXME: we need to invoke a transport reset here */ - US_DEBUGP("-- transport indicates transport failure\n"); - need_auto_sense = 0; - srb->result = DID_ERROR << 16; - return; - } - - /* - * Also, if we have a short transfer on a command that can't have - * a short transfer, we're going to do this. - */ - if ((srb->result == US_BULK_TRANSFER_SHORT) && - !((srb->cmnd[0] == REQUEST_SENSE) || - (srb->cmnd[0] == INQUIRY) || - (srb->cmnd[0] == MODE_SENSE) || - (srb->cmnd[0] == LOG_SENSE) || - (srb->cmnd[0] == MODE_SENSE_10))) { - US_DEBUGP("-- unexpectedly short transfer\n"); - need_auto_sense = 1; - } - - /* Now, if we need to do the auto-sense, let's do it */ - if (need_auto_sense) { - int temp_result; - void* old_request_buffer; - int old_sg; - int old_request_bufflen; - unsigned char old_cmnd[MAX_COMMAND_SIZE]; - - US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); - - /* save the old command */ - memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE); - - /* set the command and the LUN */ - srb->cmnd[0] = REQUEST_SENSE; - srb->cmnd[1] = old_cmnd[1] & 0xE0; - srb->cmnd[2] = 0; - srb->cmnd[3] = 0; - srb->cmnd[4] = 18; - srb->cmnd[5] = 0; - - /* set the buffer length for transfer */ - old_request_buffer = srb->request_buffer; - old_request_bufflen = srb->request_bufflen; - old_sg = srb->use_sg; - srb->use_sg = 0; - srb->request_bufflen = 18; - srb->request_buffer = srb->sense_buffer; - - /* issue the auto-sense command */ - temp_result = us->transport(us->srb, us); - if (temp_result != USB_STOR_TRANSPORT_GOOD) { - /* FIXME: we need to invoke a transport reset here */ - US_DEBUGP("-- auto-sense failure\n"); - srb->result = DID_ERROR << 16; - return; - } - - US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); - US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", - srb->sense_buffer[0], - srb->sense_buffer[2] & 0xf, - srb->sense_buffer[12], - srb->sense_buffer[13]); - - /* set the result so the higher layers expect this data */ - srb->result = CHECK_CONDITION; - - /* we're done here, let's clean up */ - srb->request_buffer = old_request_buffer; - srb->request_bufflen = old_request_bufflen; - srb->use_sg = old_sg; - memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE); - - /* If things are really okay, then let's show that */ - if ((srb->sense_buffer[2] & 0xf) == 0x0) - srb->result = GOOD; - } else /* if (need_auto_sense) */ - srb->result = GOOD; - - /* Regardless of auto-sense, if we _know_ we have an error - * condition, show that in the result code - */ - if (result == USB_STOR_TRANSPORT_FAILED) - srb->result = CHECK_CONDITION; - - /* If we think we're good, then make sure the sense data shows it. - * This is necessary because the auto-sense for some devices always - * sets byte 0 == 0x70, even if there is no error - */ - if ((us->protocol == US_PR_CB) && - (result == USB_STOR_TRANSPORT_GOOD) && - ((srb->sense_buffer[2] & 0xf) == 0x0)) - srb->sense_buffer[0] = 0x0; -} - -/* - * Control/Bulk/Interrupt transport - */ - -/* The interrupt handler for CBI devices */ -static void CBI_irq(struct urb *urb) -{ - struct us_data *us = (struct us_data *)urb->context; - - US_DEBUGP("USB IRQ recieved for device on host %d\n", us->host_no); - US_DEBUGP("-- IRQ data length is %d\n", urb->actual_length); - US_DEBUGP("-- IRQ state is %d\n", urb->status); - - /* is the device removed? */ - if (urb->status != -ENOENT) { - /* save the data for interpretation later */ - US_DEBUGP("-- Interrupt Status (0x%x, 0x%x)\n", - ((unsigned char*)urb->transfer_buffer)[0], - ((unsigned char*)urb->transfer_buffer)[1]); - - - /* was this a wanted interrupt? */ - if (us->ip_wanted) { - us->ip_wanted = 0; - up(&(us->ip_waitq)); - } else - US_DEBUGP("ERROR: Unwanted interrupt received!\n"); - } else - US_DEBUGP("-- device has been removed\n"); -} - -static int CBI_transport(Scsi_Cmnd *srb, struct us_data *us) -{ - int result; - - /* COMMAND STAGE */ - /* let's send the command via the control pipe */ - result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0), - US_CBI_ADSC, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, - us->ifnum, srb->cmnd, srb->cmd_len); - - /* check the return code for the command */ - US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result); - if (result < 0) { - /* STALL must be cleared when they are detected */ - if (result == -EPIPE) { - US_DEBUGP("-- Stall on control pipe. Clearing\n"); - result = usb_clear_halt(us->pusb_dev, - usb_sndctrlpipe(us->pusb_dev, - 0)); - US_DEBUGP("-- usb_clear_halt() returns %d\n", result); - return USB_STOR_TRANSPORT_FAILED; - } - - /* Uh oh... serious problem here */ - return USB_STOR_TRANSPORT_ERROR; - } - - /* Set up for status notification */ - us->ip_wanted = 1; - - /* DATA STAGE */ - /* transfer the data payload for this command, if one exists*/ - if (us_transfer_length(srb, us)) { - us_transfer(srb, us, US_DIRECTION(srb->cmnd[0])); - US_DEBUGP("CBI data stage result is 0x%x\n", srb->result); - } - - /* STATUS STAGE */ - - /* go to sleep until we get this interrupt */ - down(&(us->ip_waitq)); - - /* if we were woken up by an abort instead of the actual interrupt */ - if (us->ip_wanted) { - US_DEBUGP("Did not get interrupt on CBI\n"); - us->ip_wanted = 0; - return USB_STOR_TRANSPORT_ERROR; - } - - US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", - ((unsigned char*)us->irq_urb->transfer_buffer)[0], - ((unsigned char*)us->irq_urb->transfer_buffer)[1]); - - /* UFI gives us ASC and ASCQ, like a request sense - * - * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI - * devices, so we ignore the information for those commands. Note - * that this means we could be ignoring a real error on these - * commands, but that can't be helped. - */ - if (us->subclass == US_SC_UFI) { - if (srb->cmnd[0] == REQUEST_SENSE || - srb->cmnd[0] == INQUIRY) - return USB_STOR_TRANSPORT_GOOD; - else - if (((unsigned char*)us->irq_urb->transfer_buffer)[0]) - return USB_STOR_TRANSPORT_FAILED; - else - return USB_STOR_TRANSPORT_GOOD; - } - - /* If not UFI, we interpret the data as a result code - * The first byte should always be a 0x0 - * The second byte & 0x0F should be 0x0 for good, otherwise error - */ - if (((unsigned char*)us->irq_urb->transfer_buffer)[0]) { - US_DEBUGP("CBI IRQ data showed reserved bType\n"); - return USB_STOR_TRANSPORT_ERROR; - } - switch (((unsigned char*)us->irq_urb->transfer_buffer)[1] & 0x0F) { - case 0x00: - return USB_STOR_TRANSPORT_GOOD; - case 0x01: - return USB_STOR_TRANSPORT_FAILED; - default: - return USB_STOR_TRANSPORT_ERROR; - } - - US_DEBUGP("CBI_transport() reached end of function\n"); - return USB_STOR_TRANSPORT_ERROR; -} - -/* - * Control/Bulk transport - */ -static int CB_transport(Scsi_Cmnd *srb, struct us_data *us) -{ - int result; - - /* COMMAND STAGE */ - /* let's send the command via the control pipe */ - result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0), - US_CBI_ADSC, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, - us->ifnum, srb->cmnd, srb->cmd_len); - - /* check the return code for the command */ - US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result); - if (result < 0) { - /* a stall is a fatal condition from the device */ - if (result == -EPIPE) { - US_DEBUGP("-- Stall on control pipe. Clearing\n"); - result = usb_clear_halt(us->pusb_dev, - usb_sndctrlpipe(us->pusb_dev, - 0)); - US_DEBUGP("-- usb_clear_halt() returns %d\n", result); - return USB_STOR_TRANSPORT_FAILED; - } - - /* Uh oh... serious problem here */ - return USB_STOR_TRANSPORT_ERROR; - } - - /* DATA STAGE */ - /* transfer the data payload for this command, if one exists*/ - if (us_transfer_length(srb, us)) { - us_transfer(srb, us, US_DIRECTION(srb->cmnd[0])); - US_DEBUGP("CB data stage result is 0x%x\n", srb->result); - } - - - /* STATUS STAGE */ - /* NOTE: CB does not have a status stage. Silly, I know. So - * we have to catch this at a higher level. - */ - return USB_STOR_TRANSPORT_GOOD; -} - -/* - * Bulk only transport - */ - -/* Determine what the maximum LUN supported is */ -static int Bulk_max_lun(struct us_data *us) -{ - unsigned char data; - int result; - int pipe; - - /* issue the command */ - pipe = usb_rcvctrlpipe(us->pusb_dev, 0); - result = usb_control_msg(us->pusb_dev, pipe, - US_BULK_GET_MAX_LUN, - USB_DIR_IN | USB_TYPE_CLASS | - USB_RECIP_INTERFACE, - 0, us->ifnum, &data, sizeof(data), HZ); - - US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", - result, data); - - /* if we have a successful request, return the result */ - if (result == 1) - return data; - - /* if we get a STALL, clear the stall */ - if (result == -EPIPE) { - US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); - usb_clear_halt(us->pusb_dev, pipe); - } - - /* return the default -- no LUNs */ - return 0; -} - -static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) -{ - struct bulk_cb_wrap bcb; - struct bulk_cs_wrap bcs; - int result; - int pipe; - int partial; - - /* set up the command wrapper */ - bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN); - bcb.DataTransferLength = cpu_to_le32(us_transfer_length(srb, us)); - bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7; - bcb.Tag = srb->serial_number; - bcb.Lun = srb->cmnd[1] >> 5; - bcb.Length = srb->cmd_len; - - /* construct the pipe handle */ - pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); - - /* copy the command payload */ - memset(bcb.CDB, 0, sizeof(bcb.CDB)); - memcpy(bcb.CDB, srb->cmnd, bcb.Length); - - /* send it to out endpoint */ - US_DEBUGP("Bulk command S 0x%x T 0x%x LUN %d L %d F %d CL %d\n", - le32_to_cpu(bcb.Signature), bcb.Tag, bcb.Lun, - bcb.DataTransferLength, bcb.Flags, bcb.Length); - result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN, - &partial); - US_DEBUGP("Bulk command transfer result=%d\n", result); - - /* if we stall, we need to clear it before we go on */ - if (result == -EPIPE) { - US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); - usb_clear_halt(us->pusb_dev, pipe); - } else if (result) { - /* unknown error -- we've got a problem */ - return USB_STOR_TRANSPORT_ERROR; - } - - /* if the command transfered well, then we go to the data stage */ - if (result == 0) { - /* send/receive data payload, if there is any */ - if (bcb.DataTransferLength) { - us_transfer(srb, us, bcb.Flags); - US_DEBUGP("Bulk data transfer result 0x%x\n", - srb->result); - } - } - - /* See flow chart on pg 15 of the Bulk Only Transport spec for - * an explanation of how this code works. - */ - - /* construct the pipe handle */ - pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); - - /* get CSW for device status */ - US_DEBUGP("Attempting to get CSW...\n"); - result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN, - &partial); - - /* did the attempt to read the CSW fail? */ - if (result == -EPIPE) { - US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); - usb_clear_halt(us->pusb_dev, pipe); - - /* get the status again */ - US_DEBUGP("Attempting to get CSW (2nd try)...\n"); - result = usb_stor_bulk_msg(us, &bcs, pipe, - US_BULK_CS_WRAP_LEN, &partial); - - /* if it fails again, we need a reset and return an error*/ - if (result == -EPIPE) { - US_DEBUGP("clearing halt for pipe 0x%x\n", pipe); - usb_clear_halt(us->pusb_dev, pipe); - return USB_STOR_TRANSPORT_ERROR; - } - } - - /* if we still have a failure at this point, we're in trouble */ - US_DEBUGP("Bulk status result = %d\n", result); - if (result) { - return USB_STOR_TRANSPORT_ERROR; - } - - /* check bulk status */ - US_DEBUGP("Bulk status S 0x%x T 0x%x R %d V 0x%x\n", - le32_to_cpu(bcs.Signature), bcs.Tag, - bcs.Residue, bcs.Status); - if (bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) || - bcs.Tag != bcb.Tag || - bcs.Status > US_BULK_STAT_PHASE || partial != 13) { - US_DEBUGP("Bulk logical error\n"); - return USB_STOR_TRANSPORT_ERROR; - } - - /* based on the status code, we report good or bad */ - switch (bcs.Status) { - case US_BULK_STAT_OK: - /* command good -- note that we could be short on data */ - return USB_STOR_TRANSPORT_GOOD; - - case US_BULK_STAT_FAIL: - /* command failed */ - return USB_STOR_TRANSPORT_FAILED; - - case US_BULK_STAT_PHASE: - /* phase error */ - return USB_STOR_TRANSPORT_ERROR; - } - - /* we should never get here, but if we do, we're in trouble */ - return USB_STOR_TRANSPORT_ERROR; -} - -/*********************************************************************** - * Protocol routines - ***********************************************************************/ - -static void ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) -{ - int old_cmnd = 0; - - /* Fix some commands -- this is a form of mode translation - * ATAPI devices only accept 12 byte long commands - * - * NOTE: This only works because a Scsi_Cmnd struct field contains - * a unsigned char cmnd[12], so we know we have storage available - */ - - /* set command length to 12 bytes */ - srb->cmd_len = 12; - - /* determine the correct (or minimum) data length for these commands */ - switch (srb->cmnd[0]) { - - /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ - case MODE_SENSE: - case MODE_SELECT: - /* save the command so we can tell what it was */ - old_cmnd = srb->cmnd[0]; - - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - srb->cmnd[8] = srb->cmnd[4]; - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = 0; - srb->cmnd[4] = 0; - srb->cmnd[3] = 0; - srb->cmnd[2] = srb->cmnd[2]; - srb->cmnd[1] = srb->cmnd[1]; - srb->cmnd[0] = srb->cmnd[0] | 0x40; - break; - - /* change READ_6/WRITE_6 to READ_10/WRITE_10, which - * are ATAPI commands */ - case WRITE_6: - case READ_6: - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - srb->cmnd[8] = srb->cmnd[4]; - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = srb->cmnd[3]; - srb->cmnd[4] = srb->cmnd[2]; - srb->cmnd[3] = srb->cmnd[1] & 0x1F; - srb->cmnd[2] = 0; - srb->cmnd[1] = srb->cmnd[1] & 0xE0; - srb->cmnd[0] = srb->cmnd[0] | 0x20; - break; - } /* end switch on cmnd[0] */ - - /* convert MODE_SELECT data here */ - if (old_cmnd == MODE_SELECT) - usb_stor_scsiSense6to10(srb); - - /* send the command to the transport layer */ - invoke_transport(srb, us); - - /* Fix the MODE_SENSE data if we translated the command */ - if ((old_cmnd == MODE_SENSE) && (srb->result == GOOD)) - usb_stor_scsiSense10to6(srb); - - /* Fix-up the return data from an INQUIRY command to show - * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us - */ - if (srb->cmnd[0] == INQUIRY) { - ((unsigned char *)us->srb->request_buffer)[2] |= 0x2; - } -} - - -static void ufi_command(Scsi_Cmnd *srb, struct us_data *us) -{ - int old_cmnd = 0; - - /* fix some commands -- this is a form of mode translation - * UFI devices only accept 12 byte long commands - * - * NOTE: This only works because a Scsi_Cmnd struct field contains - * a unsigned char cmnd[12], so we know we have storage available - */ - - /* set command length to 12 bytes (this affects the transport layer) */ - srb->cmd_len = 12; - - /* determine the correct (or minimum) data length for these commands */ - switch (srb->cmnd[0]) { - - /* for INQUIRY, UFI devices only ever return 36 bytes */ - case INQUIRY: - srb->cmnd[4] = 36; - break; - - /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ - case MODE_SENSE: - case MODE_SELECT: - /* save the command so we can tell what it was */ - old_cmnd = srb->cmnd[0]; - - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - - /* if we're sending data, we send all. If getting data, - * get the minimum */ - if (srb->cmnd[0] == MODE_SELECT) - srb->cmnd[8] = srb->cmnd[4]; - else - srb->cmnd[8] = 8; - - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = 0; - srb->cmnd[4] = 0; - srb->cmnd[3] = 0; - srb->cmnd[2] = srb->cmnd[2]; - srb->cmnd[1] = srb->cmnd[1]; - srb->cmnd[0] = srb->cmnd[0] | 0x40; - break; - - /* again, for MODE_SENSE_10, we get the minimum (8) */ - case MODE_SENSE_10: - srb->cmnd[7] = 0; - srb->cmnd[8] = 8; - break; - - /* for REQUEST_SENSE, UFI devices only ever return 18 bytes */ - case REQUEST_SENSE: - srb->cmnd[4] = 18; - break; - - /* change READ_6/WRITE_6 to READ_10/WRITE_10, which - * are UFI commands */ - case WRITE_6: - case READ_6: - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - srb->cmnd[8] = srb->cmnd[4]; - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = srb->cmnd[3]; - srb->cmnd[4] = srb->cmnd[2]; - srb->cmnd[3] = srb->cmnd[1] & 0x1F; - srb->cmnd[2] = 0; - srb->cmnd[1] = srb->cmnd[1] & 0xE0; - srb->cmnd[0] = srb->cmnd[0] | 0x20; - break; - } /* end switch on cmnd[0] */ - - /* convert MODE_SELECT data here */ - if (old_cmnd == MODE_SELECT) - usb_stor_scsiSense6to10(srb); - - /* send the command to the transport layer */ - invoke_transport(srb, us); - - /* Fix the MODE_SENSE data if we translated the command */ - if ((old_cmnd == MODE_SENSE) && (srb->result == GOOD)) - usb_stor_scsiSense10to6(srb); - - /* Fix-up the return data from an INQUIRY command to show - * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us - */ - if (srb->cmnd[0] == INQUIRY) { - ((unsigned char *)us->srb->request_buffer)[2] |= 0x2; - } -} - -static void transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us) -{ - /* This code supports devices which do not support {READ|WRITE}_6 - * Apparently, neither Windows or MacOS will use these commands, - * so some devices do not support them - */ - if (us->flags & US_FL_MODE_XLATE) { - - /* translate READ_6 to READ_10 */ - if (srb->cmnd[0] == 0x08) { - - /* get the control */ - srb->cmnd[9] = us->srb->cmnd[5]; - - /* get the length */ - srb->cmnd[8] = us->srb->cmnd[6]; - srb->cmnd[7] = 0; - - /* set the reserved area to 0 */ - srb->cmnd[6] = 0; - - /* get LBA */ - srb->cmnd[5] = us->srb->cmnd[3]; - srb->cmnd[4] = us->srb->cmnd[2]; - srb->cmnd[3] = 0; - srb->cmnd[2] = 0; - - /* LUN and other info in cmnd[1] can stay */ - - /* fix command code */ - srb->cmnd[0] = 0x28; - - US_DEBUGP("Changing READ_6 to READ_10\n"); - US_DEBUG(us_show_command(srb)); - } - - /* translate WRITE_6 to WRITE_10 */ - if (srb->cmnd[0] == 0x0A) { - - /* get the control */ - srb->cmnd[9] = us->srb->cmnd[5]; - - /* get the length */ - srb->cmnd[8] = us->srb->cmnd[4]; - srb->cmnd[7] = 0; - - /* set the reserved area to 0 */ - srb->cmnd[6] = 0; - - /* get LBA */ - srb->cmnd[5] = us->srb->cmnd[3]; - srb->cmnd[4] = us->srb->cmnd[2]; - srb->cmnd[3] = 0; - srb->cmnd[2] = 0; - - /* LUN and other info in cmnd[1] can stay */ - - /* fix command code */ - srb->cmnd[0] = 0x2A; - - US_DEBUGP("Changing WRITE_6 to WRITE_10\n"); - US_DEBUG(us_show_command(us->srb)); - } - } /* if (us->flags & US_FL_MODE_XLATE) */ - - /* send the command to the transport layer */ - invoke_transport(srb, us); - - /* fix the results of an INQUIRY */ - if (srb->cmnd[0] == INQUIRY) { - US_DEBUGP("Fixing INQUIRY data, setting SCSI rev to 2\n"); - ((unsigned char*)us->srb->request_buffer)[2] |= 2; - } -} - -/*********************************************************************** - * Reset routines - ***********************************************************************/ - -/* This issues a CB[I] Reset to the device in question - */ -static int CB_reset(struct us_data *us) -{ - unsigned char cmd[12]; - int result; - - US_DEBUGP("CB_reset() called\n"); - - memset(cmd, 0xFF, sizeof(cmd)); - cmd[0] = SEND_DIAGNOSTIC; - cmd[1] = 4; - result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), - US_CBI_ADSC, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, us->ifnum, cmd, sizeof(cmd), HZ*5); - - /* long wait for reset */ - schedule_timeout(HZ*6); - - US_DEBUGP("CB_reset: clearing endpoint halt\n"); - usb_clear_halt(us->pusb_dev, - usb_rcvbulkpipe(us->pusb_dev, us->ep_in)); - usb_clear_halt(us->pusb_dev, - usb_rcvbulkpipe(us->pusb_dev, us->ep_out)); - - US_DEBUGP("CB_reset done\n"); - return 0; -} - -/* FIXME: Does this work? */ -static int Bulk_reset(struct us_data *us) -{ - int result; - - result = usb_control_msg(us->pusb_dev, - usb_sndctrlpipe(us->pusb_dev,0), - US_BULK_RESET_REQUEST, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, us->ifnum, NULL, 0, HZ*5); - - if (result < 0) - US_DEBUGP("Bulk hard reset failed %d\n", result); - - usb_clear_halt(us->pusb_dev, - usb_rcvbulkpipe(us->pusb_dev, us->ep_in)); - usb_clear_halt(us->pusb_dev, - usb_sndbulkpipe(us->pusb_dev, us->ep_out)); - - /* long wait for reset */ - schedule_timeout(HZ*6); - - return result; -} - -/*********************************************************************** - * Host functions - ***********************************************************************/ - -static const char* us_info(struct Scsi_Host *host) -{ - return "SCSI emulation for USB Mass Storage devices"; -} - -/* detect a virtual adapter (always works) */ -static int us_detect(struct SHT *sht) -{ - struct us_data *us; - char local_name[32]; - - /* This is not nice at all, but how else are we to get the - * data here? */ - us = (struct us_data *)sht->proc_dir; - - /* set up the name of our subdirectory under /proc/scsi/ */ - sprintf(local_name, "usb-storage-%d", us->host_number); - sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL); - if (!sht->proc_name) - return 0; - strcpy(sht->proc_name, local_name); - - /* we start with no /proc directory entry */ - sht->proc_dir = NULL; - - /* register the host */ - us->host = scsi_register(sht, sizeof(us)); - if (us->host) { - us->host->hostdata[0] = (unsigned long)us; - us->host_no = us->host->host_no; - return 1; - } - - /* odd... didn't register properly. Abort and free pointers */ - kfree(sht->proc_name); - sht->proc_name = NULL; - return 0; -} - -/* Release all resources used by the virtual host - * - * NOTE: There is no contention here, because we're allready deregistered - * the driver and we're doing each virtual host in turn, not in parallel - */ -static int us_release(struct Scsi_Host *psh) -{ - struct us_data *us = (struct us_data *)psh->hostdata[0]; - - US_DEBUGP("us_release() called for host %s\n", us->htmplt.name); - - /* Kill the control threads - * - * Enqueue the command, wake up the thread, and wait for - * notification that it's exited. - */ - US_DEBUGP("-- sending US_ACT_EXIT command to thread\n"); - us->action = US_ACT_EXIT; - up(&(us->sleeper)); - down(&(us->notify)); - - /* free the data structure we were using */ - US_DEBUGP("-- freeing URB\n"); - kfree(us->current_urb); - (struct us_data*)psh->hostdata[0] = NULL; - - /* we always have a successful release */ - return 0; -} - -/* run command */ -static int us_command( Scsi_Cmnd *srb ) -{ - US_DEBUGP("Bad use of us_command\n"); - - return DID_BAD_TARGET << 16; -} - -/* run command */ -static int us_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *)) -{ - struct us_data *us = (struct us_data *)srb->host->hostdata[0]; - - US_DEBUGP("us_queuecommand() called\n"); - srb->host_scribble = (unsigned char *)us; - - /* get exclusive access to the structures we want */ - down(&(us->queue_exclusion)); - - /* enqueue the command */ - us->queue_srb = srb; - srb->scsi_done = done; - us->action = US_ACT_COMMAND; - - /* wake up the process task */ - up(&(us->queue_exclusion)); - up(&(us->sleeper)); - - return 0; -} - -/*********************************************************************** - * Error handling functions - ***********************************************************************/ - -/* Command abort - * - * Note that this is really only meaningful right now for CBI transport - * devices which have failed to give us the command completion interrupt - */ -static int us_abort( Scsi_Cmnd *srb ) -{ - struct us_data *us = (struct us_data *)srb->host->hostdata[0]; - - US_DEBUGP("us_abort() called\n"); - - /* if we're stuck waiting for an IRQ, simulate it */ - if (us->ip_wanted) { - US_DEBUGP("-- simulating missing IRQ\n"); - up(&(us->ip_waitq)); - return SUCCESS; - } - - return FAILED; -} - -/* FIXME: this doesn't do anything right now */ -static int us_bus_reset( Scsi_Cmnd *srb ) -{ - // struct us_data *us = (struct us_data *)srb->host->hostdata[0]; - - printk(KERN_CRIT "usb-storage: bus_reset() requested but not implemented\n" ); - US_DEBUGP("Bus reset requested\n"); - // us->transport_reset(us); - return FAILED; -} - -/* FIXME: This doesn't actually reset anything */ -static int us_host_reset( Scsi_Cmnd *srb ) -{ - printk(KERN_CRIT "usb-storage: host_reset() requested but not implemented\n" ); - return FAILED; -} - -/*********************************************************************** - * /proc/scsi/ functions - ***********************************************************************/ - -/* we use this macro to help us write into the buffer */ -#undef SPRINTF -#define SPRINTF(args...) \ - do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0) - -int usb_stor_proc_info (char *buffer, char **start, off_t offset, - int length, int hostno, int inout) -{ - struct us_data *us; - char *pos = buffer; - - /* if someone is sending us data, just throw it away */ - if (inout) - return length; - - /* lock the data structures */ - down(&us_list_semaphore); - - /* find our data from hostno */ - us = us_list; - while (us) { - if (us->host_no == hostno) - break; - us = us->next; - } - - /* if we couldn't find it, we return an error */ - if (!us) { - up(&us_list_semaphore); - return -ESRCH; - } - - /* print the controler name */ - SPRINTF(" Host scsi%d: usb-storage\n", hostno); - - /* print product, vendor, and serial number strings */ - SPRINTF(" Vendor: %s\n", us->vendor); - SPRINTF(" Product: %s\n", us->product); - SPRINTF("Serial Number: %s\n", us->serial); - - /* show the protocol and transport */ - SPRINTF(" Protocol: %s\n", us->protocol_name); - SPRINTF(" Transport: %s\n", us->transport_name); - - /* show the GUID of the device */ - SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid)); - - /* release our lock on the data structures */ - up(&us_list_semaphore); - - /* - * Calculate start of next buffer, and return value. - */ - *start = buffer + offset; - - if ((pos - buffer) < offset) - return (0); - else if ((pos - buffer - offset) < length) - return (pos - buffer - offset); - else - return (length); -} - -/* - * this defines our 'host' - */ - -static Scsi_Host_Template my_host_template = { - name: "usb-storage", - proc_info: usb_stor_proc_info, - info: us_info, - - detect: us_detect, - release: us_release, - command: us_command, - queuecommand: us_queuecommand, - - eh_abort_handler: us_abort, - eh_device_reset_handler:us_bus_reset, - eh_bus_reset_handler: us_bus_reset, - eh_host_reset_handler: us_host_reset, - - can_queue: 1, - this_id: -1, - - sg_tablesize: SG_ALL, - cmd_per_lun: 1, - present: 0, - unchecked_isa_dma: FALSE, - use_clustering: TRUE, - use_new_eh_code: TRUE, - emulated: TRUE -}; - -static unsigned char sense_notready[] = { - [0] = 0x70, /* current error */ - [2] = 0x02, /* not ready */ - [5] = 0x0a, /* additional length */ - [10] = 0x04, /* not ready */ - [11] = 0x03 /* manual intervention */ -}; - -static int usb_stor_control_thread(void * __us) -{ - struct us_data *us = (struct us_data *)__us; - int action; - - lock_kernel(); - - /* - * This thread doesn't need any user-level access, - * so get rid of all our resources.. - */ - daemonize(); - - /* set our name for identification purposes */ - sprintf(current->comm, "usb-storage-%d", us->host_number); - - unlock_kernel(); - - /* signal that we've started the thread */ - up(&(us->notify)); - - for(;;) { - US_DEBUGP("*** thread sleeping.\n"); - down(&(us->sleeper)); - down(&(us->queue_exclusion)); - US_DEBUGP("*** thread awakened.\n"); - - /* take the command off the queue */ - action = us->action; - us->action = 0; - us->srb = us->queue_srb; - - /* release the queue lock as fast as possible */ - up(&(us->queue_exclusion)); - - switch (action) { - case US_ACT_COMMAND: - /* reject if target != 0 or if LUN is higher than - * the maximum known LUN - */ - if (us->srb->target || (us->srb->lun > us->max_lun)) { - US_DEBUGP("Bad device number (%d/%d)\n", - us->srb->target, us->srb->lun); - - us->srb->result = DID_BAD_TARGET << 16; - - us->srb->scsi_done(us->srb); - us->srb = NULL; - break; - } - - /* handle those devices which can't do a START_STOP */ - if ((us->srb->cmnd[0] == START_STOP) && - (us->flags & US_FL_START_STOP)) { - us->srb->result = GOOD; - us->srb->scsi_done(us->srb); - us->srb = NULL; - break; - } - - /* lock the device pointers */ - down(&(us->dev_semaphore)); - - /* our device has gone - pretend not ready */ - if (!us->pusb_dev) { - US_DEBUGP("Request is for removed device\n"); - /* For REQUEST_SENSE, it's the data. But - * for anything else, it should look like - * we auto-sensed for it. - */ - if (us->srb->cmnd[0] == REQUEST_SENSE) { - memcpy(us->srb->request_buffer, - sense_notready, - sizeof(sense_notready)); - us->srb->result = GOOD; - } else { - memcpy(us->srb->sense_buffer, - sense_notready, - sizeof(sense_notready)); - us->srb->result = CHECK_CONDITION; - } - } else { /* !us->pusb_dev */ - /* we've got a command, let's do it! */ - US_DEBUG(us_show_command(us->srb)); - us->proto_handler(us->srb, us); - } - - /* unlock the device pointers */ - up(&(us->dev_semaphore)); - - /* indicate that the command is done */ - US_DEBUGP("scsi cmd done, result=0x%x\n", - us->srb->result); - us->srb->scsi_done(us->srb); - us->srb = NULL; - break; - - case US_ACT_DEVICE_RESET: - break; - - case US_ACT_BUS_RESET: - break; - - case US_ACT_HOST_RESET: - break; - - } /* end switch on action */ - - /* exit if we get a signal to exit */ - if (action == US_ACT_EXIT) { - US_DEBUGP("-- US_ACT_EXIT command recieved\n"); - break; - } - } /* for (;;) */ - - /* notify the exit routine that we're actually exiting now */ - up(&(us->notify)); - - return 0; -} - -/* This is the list of devices we recognize, along with their flag data */ -static struct us_unusual_dev us_unusual_dev_list[] = { - { 0x03f0, 0x0107, 0x0200, 0x0200, "HP USB CD-Writer Plus", - US_SC_8070, US_PR_CB, 0}, - { 0x04e6, 0x0001, 0x0200, 0x0200, "Matshita LS-120", - US_SC_8020, US_PR_CB, US_FL_SINGLE_LUN}, - { 0x04e6, 0x0002, 0x0100, 0x0100, "Shuttle eUSCSI Bridge", - US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, - { 0x04e6, 0x0006, 0x0100, 0x0100, "Shuttle eUSB MMC Adapter", - US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN}, - { 0x054c, 0x0010, 0x0210, 0x0210, "Sony DSC-S30", - US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP | - US_FL_MODE_XLATE | US_FL_ALT_LENGTH}, - { 0x054c, 0x002d, 0x0100, 0x0100, "Sony Memorystick MSAC-US1", - US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP | - US_FL_MODE_XLATE | US_FL_ALT_LENGTH}, - { 0x057b, 0x0000, 0x0000, 0x0299, "Y-E Data Flashbuster-U", - US_SC_UFI, US_PR_CB, US_FL_SINGLE_LUN}, - { 0x057b, 0x0000, 0x0300, 0x9999, "Y-E Data Flashbuster-U", - US_SC_UFI, US_PR_CBI, US_FL_SINGLE_LUN}, - { 0x0693, 0x0002, 0x0100, 0x0100, "Hagiwara FlashGate SmartMedia", - US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, - { 0x0781, 0x0001, 0x0200, 0x0200, "Sandisk ImageMate (SDDR-01)", - US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP}, - { 0x0781, 0x0002, 0x0009, 0x0009, "Sandisk Imagemate (SDDR-31)", - US_SC_SCSI, US_PR_BULK, US_FL_IGNORE_SER}, - { 0x07af, 0x0005, 0x0100, 0x0100, "Microtech USB-SCSI-HD50", - US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, - { 0x05ab, 0x0031, 0x0100, 0x0100, "In-System USB/IDE Bridge", - US_SC_8070, US_PR_BULK, US_FL_ALT_LENGTH}, - { 0x0693, 0x0005, 0x0100, 0x0100, "Hagiwara Flashgate", - US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, - { 0 }}; - -/* Search our ususual device list, based on vendor/product combinations - * to see if we can support this device. Returns a pointer to a structure - * defining how we should support this device, or NULL if it's not in the - * list - */ -static struct us_unusual_dev* us_find_dev(u16 idVendor, u16 idProduct, - u16 bcdDevice) -{ - struct us_unusual_dev* ptr; - - US_DEBUGP("Searching unusual device list for (0x%x, 0x%x, 0x%x)...\n", - idVendor, idProduct, bcdDevice); - - ptr = us_unusual_dev_list; - while ((ptr->idVendor != 0x0000) && - !((ptr->idVendor == idVendor) && - (ptr->idProduct == idProduct) && - (ptr->bcdDeviceMin <= bcdDevice) && - (ptr->bcdDeviceMax >= bcdDevice))) - ptr++; - - /* if the search ended because we hit the end record, we failed */ - if (ptr->idVendor == 0x0000) { - US_DEBUGP("-- did not find a matching device\n"); - return NULL; - } - - /* otherwise, we found one! */ - US_DEBUGP("-- found matching device: %s\n", ptr->name); - return ptr; -} - -/* Set up the IRQ pipe and handler - * Note that this function assumes that all the data in the us_data - * strucuture is current. This includes the ep_int field, which gives us - * the endpoint for the interrupt. - * Returns non-zero on failure, zero on success - */ -static int usb_stor_allocate_irq(struct us_data *ss) -{ - unsigned int pipe; - int maxp; - int result; - - US_DEBUGP("Allocating IRQ for CBI transport\n"); - - /* lock access to the data structure */ - down(&(ss->irq_urb_sem)); - - /* allocate the URB */ - ss->irq_urb = usb_alloc_urb(0); - if (!ss->irq_urb) { - up(&(ss->irq_urb_sem)); - US_DEBUGP("couldn't allocate interrupt URB"); - return 1; - } - - /* calculate the pipe and max packet size */ - pipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int->bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK); - maxp = usb_maxpacket(ss->pusb_dev, pipe, usb_pipeout(pipe)); - if (maxp > sizeof(ss->irqbuf)) - maxp = sizeof(ss->irqbuf); - - /* fill in the URB with our data */ - FILL_INT_URB(ss->irq_urb, ss->pusb_dev, pipe, ss->irqbuf, maxp, - CBI_irq, ss, ss->ep_int->bInterval); - - /* submit the URB for processing */ - result = usb_submit_urb(ss->irq_urb); - US_DEBUGP("usb_submit_urb() returns %d\n", result); - if (result) { - usb_free_urb(ss->irq_urb); - up(&(ss->irq_urb_sem)); - return 2; - } - - /* unlock the data structure and return success */ - up(&(ss->irq_urb_sem)); - return 0; -} - -/* Probe to see if a new device is actually a SCSI device */ -static void * storage_probe(struct usb_device *dev, unsigned int ifnum) -{ - int i; - char mf[USB_STOR_STRING_LEN]; /* manufacturer */ - char prod[USB_STOR_STRING_LEN]; /* product */ - char serial[USB_STOR_STRING_LEN]; /* serial number */ - GUID(guid); /* Global Unique Identifier */ - unsigned int flags; - struct us_unusual_dev *unusual_dev; - struct us_data *ss = NULL; - int result; - - /* these are temporary copies -- we test on these, then put them - * in the us-data structure - */ - struct usb_endpoint_descriptor *ep_in = NULL; - struct usb_endpoint_descriptor *ep_out = NULL; - struct usb_endpoint_descriptor *ep_int = NULL; - u8 subclass = 0; - u8 protocol = 0; - - /* the altsettting 0 on the interface we're probing */ - struct usb_interface_descriptor *altsetting = - &(dev->actconfig->interface[ifnum].altsetting[0]); - - /* clear the temporary strings */ - memset(mf, 0, sizeof(mf)); - memset(prod, 0, sizeof(prod)); - memset(serial, 0, sizeof(serial)); - - /* search for this device in our unusual device list */ - unusual_dev = us_find_dev(dev->descriptor.idVendor, - dev->descriptor.idProduct, - dev->descriptor.bcdDevice); - - /* - * Can we support this device, either because we know about it - * from our unusual device list, or because it advertises that it's - * compliant to the specification? - */ - if (!unusual_dev && - !(dev->descriptor.bDeviceClass == 0 && - altsetting->bInterfaceClass == USB_CLASS_MASS_STORAGE && - altsetting->bInterfaceSubClass >= US_SC_MIN && - altsetting->bInterfaceSubClass <= US_SC_MAX)) { - /* if it's not a mass storage, we go no further */ - return NULL; - } - - /* At this point, we know we've got a live one */ - US_DEBUGP("USB Mass Storage device detected\n"); - - /* Determine subclass and protocol, or copy from the interface */ - if (unusual_dev) { - subclass = unusual_dev->useProtocol; - protocol = unusual_dev->useTransport; - flags = unusual_dev->flags; - } else { - subclass = altsetting->bInterfaceSubClass; - protocol = altsetting->bInterfaceProtocol; - flags = 0; - } - - /* - * Find the endpoints we need - * We are expecting a minimum of 2 endpoints - in and out (bulk). - * An optional interrupt is OK (necessary for CBI protocol). - * We will ignore any others. - */ - for (i = 0; i < altsetting->bNumEndpoints; i++) { - /* is it an BULK endpoint? */ - if ((altsetting->endpoint[i].bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { - /* BULK in or out? */ - if (altsetting->endpoint[i].bEndpointAddress & - USB_DIR_IN) - ep_in = &altsetting->endpoint[i]; - else - ep_out = &altsetting->endpoint[i]; - } - - /* is it an interrupt endpoint? */ - if ((altsetting->endpoint[i].bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { - ep_int = &altsetting->endpoint[i]; - } - } - US_DEBUGP("Endpoints: In: 0x%p Out: 0x%p Int: 0x%p (Period %d)\n", - ep_in, ep_out, ep_int, ep_int ? ep_int->bInterval : 0); - - /* set the interface -- STALL is an acceptable response here */ - result = usb_set_interface(dev, altsetting->bInterfaceNumber, 0); - US_DEBUGP("Result from usb_set_interface is %d\n", result); - if (result == -EPIPE) { - US_DEBUGP("-- clearing stall on control interface\n"); - usb_clear_halt(dev, usb_sndctrlpipe(dev, 0)); - } else if (result != 0) { - /* it's not a stall, but another error -- time to bail */ - US_DEBUGP("-- Unknown error. Rejecting device\n"); - return NULL; - } - - /* Do some basic sanity checks, and bail if we find a problem */ - if (!ep_in || !ep_out || (protocol == US_PR_CBI && !ep_int)) { - US_DEBUGP("Sanity check failed. Rejecting device.\n"); - return NULL; - } - - /* At this point, we're committed to using the device */ - - /* clear the GUID and fetch the strings */ - GUID_CLEAR(guid); - if (dev->descriptor.iManufacturer) - usb_string(dev, dev->descriptor.iManufacturer, - mf, sizeof(mf)); - if (dev->descriptor.iProduct) - usb_string(dev, dev->descriptor.iProduct, - prod, sizeof(prod)); - if (dev->descriptor.iSerialNumber && !(flags & US_FL_IGNORE_SER)) - usb_string(dev, dev->descriptor.iSerialNumber, - serial, sizeof(serial)); - - /* Create a GUID for this device */ - if (dev->descriptor.iSerialNumber && serial[0]) { - /* If we have a serial number, and it's a non-NULL string */ - make_guid(guid, dev->descriptor.idVendor, - dev->descriptor.idProduct, serial); - } else { - /* We don't have a serial number, so we use 0 */ - make_guid(guid, dev->descriptor.idVendor, - dev->descriptor.idProduct, "0"); - } - - /* lock access to the data structures */ - down(&us_list_semaphore); - - /* - * Now check if we have seen this GUID before - * We're looking for a device with a matching GUID that isn't - * allready on the system - */ - ss = us_list; - while ((ss != NULL) && - ((ss->pusb_dev) || !GUID_EQUAL(guid, ss->guid))) - ss = ss->next; - - if (ss != NULL) { - /* Existing device -- re-connect */ - US_DEBUGP("Found existing GUID " GUID_FORMAT "\n", - GUID_ARGS(guid)); - - /* establish the connection to the new device upon reconnect */ - ss->ifnum = ifnum; - ss->pusb_dev = dev; - - /* copy over the endpoint data */ - if (ep_in) - ss->ep_in = ep_in->bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - if (ep_out) - ss->ep_out = ep_out->bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - ss->ep_int = ep_int; - - /* allocate an IRQ callback if one is needed */ - if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) - return NULL; - } else { - /* New device -- allocate memory and initialize */ - US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid)); - - if ((ss = (struct us_data *)kmalloc(sizeof(struct us_data), - GFP_KERNEL)) == NULL) { - printk(KERN_WARNING USB_STORAGE "Out of memory\n"); - up(&us_list_semaphore); - return NULL; - } - memset(ss, 0, sizeof(struct us_data)); - - /* allocate the URB we're going to use */ - ss->current_urb = usb_alloc_urb(0); - if (!ss->current_urb) { - kfree(ss); - return NULL; - } - - /* Initialize the mutexes only when the struct is new */ - init_MUTEX_LOCKED(&(ss->sleeper)); - init_MUTEX_LOCKED(&(ss->notify)); - init_MUTEX_LOCKED(&(ss->ip_waitq)); - init_MUTEX(&(ss->queue_exclusion)); - init_MUTEX(&(ss->irq_urb_sem)); - init_MUTEX(&(ss->current_urb_sem)); - init_MUTEX(&(ss->dev_semaphore)); - - /* copy over the subclass and protocol data */ - ss->subclass = subclass; - ss->protocol = protocol; - ss->flags = flags; - - /* copy over the endpoint data */ - if (ep_in) - ss->ep_in = ep_in->bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - if (ep_out) - ss->ep_out = ep_out->bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - ss->ep_int = ep_int; - - /* establish the connection to the new device */ - ss->ifnum = ifnum; - ss->pusb_dev = dev; - - /* copy over the identifiying strings */ - strncpy(ss->vendor, mf, USB_STOR_STRING_LEN); - strncpy(ss->product, prod, USB_STOR_STRING_LEN); - strncpy(ss->serial, serial, USB_STOR_STRING_LEN); - if (strlen(ss->vendor) == 0) - strncpy(ss->vendor, "Unknown", USB_STOR_STRING_LEN); - if (strlen(ss->product) == 0) - strncpy(ss->product, "Unknown", USB_STOR_STRING_LEN); - if (strlen(ss->serial) == 0) - strncpy(ss->serial, "None", USB_STOR_STRING_LEN); - - /* copy the GUID we created before */ - memcpy(ss->guid, guid, sizeof(guid)); - - /* - * Set the handler pointers based on the protocol - * Again, this data is persistant across reattachments - */ - switch (ss->protocol) { - case US_PR_CB: - ss->transport_name = "Control/Bulk"; - ss->transport = CB_transport; - ss->transport_reset = CB_reset; - ss->max_lun = 7; - break; - - case US_PR_CBI: - ss->transport_name = "Control/Bulk/Interrupt"; - ss->transport = CBI_transport; - ss->transport_reset = CB_reset; - ss->max_lun = 7; - break; - - case US_PR_BULK: - ss->transport_name = "Bulk"; - ss->transport = Bulk_transport; - ss->transport_reset = Bulk_reset; - ss->max_lun = Bulk_max_lun(ss); - break; - - default: - ss->transport_name = "Unknown"; - up(&us_list_semaphore); - kfree(ss->current_urb); - kfree(ss); - return NULL; - break; - } - US_DEBUGP("Transport: %s\n", ss->transport_name); - - /* fix for single-lun devices */ - if (ss->flags & US_FL_SINGLE_LUN) - ss->max_lun = 0; - - switch (ss->subclass) { - case US_SC_RBC: - ss->protocol_name = "Reduced Block Commands (RBC)"; - ss->proto_handler = transparent_scsi_command; - break; - - case US_SC_8020: - ss->protocol_name = "8020i"; - ss->proto_handler = ATAPI_command; - break; - - case US_SC_QIC: - ss->protocol_name = "QIC-157"; - US_DEBUGP("Sorry, device not supported. Please\n"); - US_DEBUGP("contact mdharm-usb@one-eyed-alien.net\n"); - US_DEBUGP("if you see this message.\n"); - up(&us_list_semaphore); - kfree(ss->current_urb); - kfree(ss); - return NULL; - break; - - case US_SC_8070: - ss->protocol_name = "8070i"; - ss->proto_handler = ATAPI_command; - break; - - case US_SC_SCSI: - ss->protocol_name = "Transparent SCSI"; - ss->proto_handler = transparent_scsi_command; - break; - - case US_SC_UFI: - ss->protocol_name = "Uniform Floppy Interface (UFI)"; - ss->proto_handler = ufi_command; - break; - - default: - ss->protocol_name = "Unknown"; - up(&us_list_semaphore); - kfree(ss->current_urb); - kfree(ss); - return NULL; - break; - } - US_DEBUGP("Protocol: %s\n", ss->protocol_name); - - /* allocate an IRQ callback if one is needed */ - if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) - return NULL; - - /* - * Since this is a new device, we need to generate a scsi - * host definition, and register with the higher SCSI layers - */ - - /* Initialize the host template based on the default one */ - memcpy(&(ss->htmplt), &my_host_template, - sizeof(my_host_template)); - - /* Grab the next host number */ - ss->host_number = my_host_number++; - - /* We abuse this pointer so we can pass the ss pointer to - * the host controler thread in us_detect. But how else are - * we to do it? - */ - (struct us_data *)ss->htmplt.proc_dir = ss; - - /* start up our control thread */ - ss->pid = kernel_thread(usb_stor_control_thread, ss, - CLONE_FS | CLONE_FILES | - CLONE_SIGHAND); - if (ss->pid < 0) { - printk(KERN_WARNING USB_STORAGE - "Unable to start control thread\n"); - kfree(ss->current_urb); - kfree(ss); - return NULL; - } - - /* wait for the thread to start */ - down(&(ss->notify)); - - /* now register - our detect function will be called */ - ss->htmplt.module = THIS_MODULE; - scsi_register_module(MODULE_SCSI_HA, &(ss->htmplt)); - - /* put us in the list */ - ss->next = us_list; - us_list = ss; - } - - /* release the data structure lock */ - up(&us_list_semaphore); - - printk(KERN_DEBUG - "WARNING: USB Mass Storage data integrity not assured\n"); - printk(KERN_DEBUG - "USB Mass Storage device found at %d\n", dev->devnum); - - /* return a pointer for the disconnect function */ - return ss; -} - -/* Handle a disconnect event from the USB core */ -static void storage_disconnect(struct usb_device *dev, void *ptr) -{ - struct us_data *ss = ptr; - int result; - - US_DEBUGP("storage_disconnect() called\n"); - - /* this is the odd case -- we disconnected but weren't using it */ - if (!ss) { - US_DEBUGP("-- device was not in use\n"); - return; - } - - /* lock access to the device data structure */ - down(&(ss->dev_semaphore)); - - /* release the IRQ, if we have one */ - down(&(ss->irq_urb_sem)); - if (ss->irq_urb) { - US_DEBUGP("-- releasing irq handle\n"); - result = usb_unlink_urb(ss->irq_urb); - ss->irq_urb = NULL; - US_DEBUGP("-- usb_unlink_urb() returned %d\n", result); - usb_free_urb(ss->irq_urb); - } - up(&(ss->irq_urb_sem)); - - /* mark the device as gone */ - ss->pusb_dev = NULL; - - /* lock access to the device data structure */ - up(&(ss->dev_semaphore)); -} - -/************************************************************** - **************************************************************/ - -#define USB_STOR_SCSI_SENSE_HDRSZ 4 -#define USB_STOR_SCSI_SENSE_10_HDRSZ 8 - -struct usb_stor_scsi_sense_hdr -{ - __u8* dataLength; - __u8* mediumType; - __u8* devSpecParms; - __u8* blkDescLength; -}; - -typedef struct usb_stor_scsi_sense_hdr Usb_Stor_Scsi_Sense_Hdr; - -union usb_stor_scsi_sense_hdr_u -{ - Usb_Stor_Scsi_Sense_Hdr hdr; - __u8* array[USB_STOR_SCSI_SENSE_HDRSZ]; -}; - -typedef union usb_stor_scsi_sense_hdr_u Usb_Stor_Scsi_Sense_Hdr_u; - -struct usb_stor_scsi_sense_hdr_10 -{ - __u8* dataLengthMSB; - __u8* dataLengthLSB; - __u8* mediumType; - __u8* devSpecParms; - __u8* reserved1; - __u8* reserved2; - __u8* blkDescLengthMSB; - __u8* blkDescLengthLSB; -}; - -typedef struct usb_stor_scsi_sense_hdr_10 Usb_Stor_Scsi_Sense_Hdr_10; - -union usb_stor_scsi_sense_hdr_10_u -{ - Usb_Stor_Scsi_Sense_Hdr_10 hdr; - __u8* array[USB_STOR_SCSI_SENSE_10_HDRSZ]; -}; - -typedef union usb_stor_scsi_sense_hdr_10_u Usb_Stor_Scsi_Sense_Hdr_10_u; - -void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* , Usb_Stor_Scsi_Sense_Hdr_u*, - Usb_Stor_Scsi_Sense_Hdr_10_u*, int* ); -void usb_stor_print_Scsi_Cmnd( Scsi_Cmnd* cmd ); - -int -usb_stor_scsiSense10to6( Scsi_Cmnd* the10 ) -{ - __u8 *buffer=0; - int outputBufferSize = 0; - int length=0; - struct scatterlist *sg = 0; - int i=0, j=0, element=0; - Usb_Stor_Scsi_Sense_Hdr_u the6Locations; - Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations; - int sb=0,si=0,db=0,di=0; - int sgLength=0; - -#if 0 - /* Make sure we get a MODE_SENSE_10 command */ - if ( the10->cmnd[0] != MODE_SENSE_10 ) - { - printk( KERN_ERR USB_STORAGE - "Scsi_Cmnd was not a MODE_SENSE_10.\n" ); - return -1; - } - - /* Now start to format the output */ - the10->cmnd[0] = MODE_SENSE; -#endif - US_DEBUGP("-- converting 10 byte sense data to 6 byte\n"); - the10->cmnd[0] = the10->cmnd[0] & 0xBF; - - /* Determine buffer locations */ - usb_stor_scsiSenseParseBuffer( the10, &the6Locations, &the10Locations, - &length ); - - /* Work out minimum buffer to output */ - outputBufferSize = *the10Locations.hdr.dataLengthLSB; - outputBufferSize += USB_STOR_SCSI_SENSE_HDRSZ; - - /* Check to see if we need to truncate the output */ - if ( outputBufferSize > length ) - { - printk( KERN_WARNING USB_STORAGE - "Had to truncate MODE_SENSE_10 buffer into MODE_SENSE.\n" ); - printk( KERN_WARNING USB_STORAGE - "outputBufferSize is %d and length is %d.\n", - outputBufferSize, length ); - } - outputBufferSize = length; - - /* Data length */ - if ( *the10Locations.hdr.dataLengthMSB != 0 ) /* MSB must be zero */ - { - printk( KERN_WARNING USB_STORAGE - "Command will be truncated to fit in SENSE6 buffer.\n" ); - *the6Locations.hdr.dataLength = 0xff; - } - else - { - *the6Locations.hdr.dataLength = *the10Locations.hdr.dataLengthLSB; - } - - /* Medium type and DevSpecific parms */ - *the6Locations.hdr.mediumType = *the10Locations.hdr.mediumType; - *the6Locations.hdr.devSpecParms = *the10Locations.hdr.devSpecParms; - - /* Block descriptor length */ - if ( *the10Locations.hdr.blkDescLengthMSB != 0 ) /* MSB must be zero */ - { - printk( KERN_WARNING USB_STORAGE - "Command will be truncated to fit in SENSE6 buffer.\n" ); - *the6Locations.hdr.blkDescLength = 0xff; - } - else - { - *the6Locations.hdr.blkDescLength = *the10Locations.hdr.blkDescLengthLSB; - } - - if ( the10->use_sg == 0 ) - { - buffer = the10->request_buffer; - /* Copy the rest of the data */ - memmove( &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]), - &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), - outputBufferSize - USB_STOR_SCSI_SENSE_HDRSZ ); - /* initialise last bytes left in buffer due to smaller header */ - memset( &(buffer[outputBufferSize - -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ)]), - 0, - USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ ); - } - else - { - sg = (struct scatterlist *) the10->request_buffer; - /* scan through this scatterlist and figure out starting positions */ - for ( i=0; i < the10->use_sg; i++) - { - sgLength = sg[i].length; - for ( j=0; juse_sg; - } - element++; - } - } - - /* Now we know where to start the copy from */ - element = USB_STOR_SCSI_SENSE_HDRSZ; - while ( element < outputBufferSize - -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) ) - { - /* check limits */ - if ( sb >= the10->use_sg || - si >= sg[sb].length || - db >= the10->use_sg || - di >= sg[db].length ) - { - printk( KERN_ERR USB_STORAGE - "Buffer overrun averted, this shouldn't happen!\n" ); - break; - } - - /* copy one byte */ - sg[db].address[di] = sg[sb].address[si]; - - /* get next destination */ - if ( sg[db].length-1 == di ) - { - db++; - di=0; - } - else - { - di++; - } - - /* get next source */ - if ( sg[sb].length-1 == si ) - { - sb++; - si=0; - } - else - { - si++; - } - - element++; - } - /* zero the remaining bytes */ - while ( element < outputBufferSize ) - { - /* check limits */ - if ( db >= the10->use_sg || - di >= sg[db].length ) - { - printk( KERN_ERR USB_STORAGE - "Buffer overrun averted, this shouldn't happen!\n" ); - break; - } - - sg[db].address[di] = 0; - - /* get next destination */ - if ( sg[db].length-1 == di ) - { - db++; - di=0; - } - else - { - di++; - } - element++; - } - } - - /* All done any everything was fine */ - return 0; -} - -int -usb_stor_scsiSense6to10( Scsi_Cmnd* the6 ) -{ - /* will be used to store part of buffer */ - __u8 tempBuffer[USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ], - *buffer=0; - int outputBufferSize = 0; - int length=0; - struct scatterlist *sg = 0; - int i=0, j=0, element=0; - Usb_Stor_Scsi_Sense_Hdr_u the6Locations; - Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations; - int sb=0,si=0,db=0,di=0; - int lsb=0,lsi=0,ldb=0,ldi=0; - -#if 0 - /* Make sure we get a MODE_SENSE command */ - if ( the6->cmnd[0] != MODE_SENSE ) - { - printk( KERN_ERR USB_STORAGE - "Scsi_Cmnd was not MODE_SENSE.\n" ); - return -1; - } - - /* Now start to format the output */ - the6->cmnd[0] = MODE_SENSE_10; -#endif - US_DEBUGP("-- converting 6 byte sense data to 10 byte\n"); - the6->cmnd[0] = the6->cmnd[0] | 0x40; - - /* Determine buffer locations */ - usb_stor_scsiSenseParseBuffer( the6, &the6Locations, &the10Locations, - &length ); - - /* Work out minimum buffer to output */ - outputBufferSize = *the6Locations.hdr.dataLength; - outputBufferSize += USB_STOR_SCSI_SENSE_10_HDRSZ; - - /* Check to see if we need to trucate the output */ - if ( outputBufferSize > length ) - { - printk( KERN_WARNING USB_STORAGE - "Had to truncate MODE_SENSE into MODE_SENSE_10 buffer.\n" ); - printk( KERN_WARNING USB_STORAGE - "outputBufferSize is %d and length is %d.\n", - outputBufferSize, length ); - } - outputBufferSize = length; - - /* Block descriptor length - save these before overwriting */ - tempBuffer[2] = *the10Locations.hdr.blkDescLengthMSB; - tempBuffer[3] = *the10Locations.hdr.blkDescLengthLSB; - *the10Locations.hdr.blkDescLengthLSB = *the6Locations.hdr.blkDescLength; - *the10Locations.hdr.blkDescLengthMSB = 0; - - /* reserved - save these before overwriting */ - tempBuffer[0] = *the10Locations.hdr.reserved1; - tempBuffer[1] = *the10Locations.hdr.reserved2; - *the10Locations.hdr.reserved1 = *the10Locations.hdr.reserved2 = 0; - - /* Medium type and DevSpecific parms */ - *the10Locations.hdr.devSpecParms = *the6Locations.hdr.devSpecParms; - *the10Locations.hdr.mediumType = *the6Locations.hdr.mediumType; - - /* Data length */ - *the10Locations.hdr.dataLengthLSB = *the6Locations.hdr.dataLength; - *the10Locations.hdr.dataLengthMSB = 0; - - if ( !the6->use_sg ) - { - buffer = the6->request_buffer; - /* Copy the rest of the data */ - memmove( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), - &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]), - outputBufferSize-USB_STOR_SCSI_SENSE_10_HDRSZ ); - /* Put the first four bytes (after header) in place */ - memcpy( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), - tempBuffer, - USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ ); - } - else - { - sg = (struct scatterlist *) the6->request_buffer; - /* scan through this scatterlist and figure out ending positions */ - for ( i=0; i < the6->use_sg; i++) - { - for ( j=0; juse_sg; - break; - } - element++; - } - } - /* scan through this scatterlist and figure out starting positions */ - element = length-1; - /* destination is the last element */ - db=the6->use_sg-1; - di=sg[db].length-1; - for ( i=the6->use_sg-1; i >= 0; i--) - { - for ( j=sg[i].length-1; j>=0; j-- ) - { - /* get to end of header and find source for copy */ - if ( element == length - 1 - - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) ) - { - sb=i; - si=j; - /* we've found both sets now, exit loops */ - j=-1; - i=-1; - } - element--; - } - } - /* Now we know where to start the copy from */ - element = length-1 - - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ); - while ( element >= USB_STOR_SCSI_SENSE_10_HDRSZ ) - { - /* check limits */ - if ( ( sb <= lsb && si < lsi ) || - ( db <= ldb && di < ldi ) ) - { - printk( KERN_ERR USB_STORAGE - "Buffer overrun averted, this shouldn't happen!\n" ); - break; - } - - /* copy one byte */ - sg[db].address[di] = sg[sb].address[si]; - - /* get next destination */ - if ( di == 0 ) - { - db--; - di=sg[db].length-1; - } - else - { - di--; - } - - /* get next source */ - if ( si == 0 ) - { - sb--; - si=sg[sb].length-1; - } - else - { - si--; - } - - element--; - } - /* copy the remaining four bytes */ - while ( element >= USB_STOR_SCSI_SENSE_HDRSZ ) - { - /* check limits */ - if ( db <= ldb && di < ldi ) - { - printk( KERN_ERR USB_STORAGE - "Buffer overrun averted, this shouldn't happen!\n" ); - break; - } - - sg[db].address[di] = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ]; - - /* get next destination */ - if ( di == 0 ) - { - db--; - di=sg[db].length-1; - } - else - { - di--; - } - element--; - } - } - - /* All done and everything was fine */ - return 0; -} - -void -usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* the6, - Usb_Stor_Scsi_Sense_Hdr_10_u* the10, - int* length_p ) - -{ - int i = 0, j=0, element=0; - struct scatterlist *sg = 0; - int length = 0; - __u8* buffer=0; - - /* are we scatter-gathering? */ - if ( srb->use_sg != 0 ) - { - /* loop over all the scatter gather structures and - * get pointer to the data members in the headers - * (also work out the length while we're here) - */ - sg = (struct scatterlist *) srb->request_buffer; - for (i = 0; i < srb->use_sg; i++) - { - length += sg[i].length; - /* We only do the inner loop for the headers */ - if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ ) - { - /* scan through this scatterlist */ - for ( j=0; jarray[element] = &(sg[i].address[j]); - the10->array[element] = &(sg[i].address[j]); - } - else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ ) - { - /* only the longer headers still cares now */ - the10->array[element] = &(sg[i].address[j]); - } - /* increase element counter */ - element++; - } - } - } - } - else - { - length = srb->request_bufflen; - buffer = srb->request_buffer; - if ( length < USB_STOR_SCSI_SENSE_10_HDRSZ ) - printk( KERN_ERR USB_STORAGE - "Buffer length smaller than header!!" ); - for( i=0; iarray[i] = &(buffer[i]); - the10->array[i] = &(buffer[i]); - } - else - { - the10->array[i] = &(buffer[i]); - } - } - } - - /* Set value of length passed in */ - *length_p = length; -} - -void -usb_stor_print_Scsi_Cmnd( Scsi_Cmnd* cmd ) -{ - int i=0, bufferSize = cmd->request_bufflen; - __u8* buffer = cmd->request_buffer; - struct scatterlist* sg = (struct scatterlist*)cmd->request_buffer; - - printk( KERN_ERR "Dumping information about %p.\n", cmd ); - printk( KERN_ERR "cmd->cmnd[0] value is %d.\n", cmd->cmnd[0] ); - printk( KERN_ERR "(MODE_SENSE is %d and MODE_SENSE_10 is %d)\n", - MODE_SENSE, MODE_SENSE_10 ); - - printk( KERN_ERR "buffer is %p with length %d.\n", buffer, bufferSize ); - for ( i=0; iuse_sg ); - for ( i=0; iuse_sg; i++ ) - { - printk( KERN_ERR "Length of scatterlist %d is %d.\n", i, sg[i].length ); - printk( KERN_ERR "%2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n", - sg[i].address[0], - sg[i].address[1], - sg[i].address[2], - sg[i].address[3], - sg[i].address[4], - sg[i].address[5], - sg[i].address[6], - sg[i].address[7], - sg[i].address[8], - sg[i].address[9], - sg[i].address[10], - sg[i].address[11], - sg[i].address[12], - sg[i].address[13], - sg[i].address[14], - sg[i].address[15] ); - } -} - -/************************************************************** - **************************************************************/ - -/*********************************************************************** - * Initialization and registration - ***********************************************************************/ - -int __init usb_stor_init(void) -{ - /* initialize internal global data elements */ - us_list = NULL; - init_MUTEX(&us_list_semaphore); - my_host_number = 0; - - /* register the driver, return -1 if error */ - if (usb_register(&storage_driver) < 0) - return -1; - - /* we're all set */ - printk(KERN_INFO "USB Mass Storage support registered.\n"); - return 0; -} - -void __exit usb_stor_exit(void) -{ - struct us_data *next; - - US_DEBUGP("usb_stor_exit() called\n"); - - /* Deregister the driver - * This eliminates races with probes and disconnects - */ - US_DEBUGP("-- calling usb_deregister()\n"); - usb_deregister(&storage_driver) ; - - /* lock access to the data structures */ - down(&us_list_semaphore); - - /* While there are still virtual hosts, unregister them - * - * Note that the us_release() routine will destroy the local data - * structure. So we have to peel these off the top of the list - * and keep updating the head pointer as we go. - */ - while (us_list) { - /* keep track of where the next one is */ - next = us_list->next; - - US_DEBUGP("-- calling scsi_unregister_module()\n"); - scsi_unregister_module(MODULE_SCSI_HA, &(us_list->htmplt)); - - /* Now that scsi_unregister_module is done with the host - * template, we can free the us_data structure (the host - * template is inline in this structure). */ - kfree (us_list); - - /* advance the list pointer */ - us_list = next; - } - - /* unlock the data structures */ - up(&us_list_semaphore); -} - -module_init(usb_stor_init) ; -module_exit(usb_stor_exit) ; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/usb-storage.h linux/drivers/usb/usb-storage.h --- v2.4.0-test2/linux/drivers/usb/usb-storage.h Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/usb-storage.h Wed Dec 31 16:00:00 1969 @@ -1,160 +0,0 @@ -/* Driver for USB mass storage - include file - * - * (c) 1999 Michael Gee (michael@linuxspecific.com) - * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) - * - */ - -#include - -#define USB_STORAGE "usb-storage.c: " -#define USB_STOR_STRING_LEN 32 - -#ifdef CONFIG_USB_STORAGE_DEBUG -void us_show_command(Scsi_Cmnd *srb); -#define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE ## x ) -#define US_DEBUGPX(x...) printk( ## x ) -#define US_DEBUG(x) x -#else -#define US_DEBUGP(x...) -#define US_DEBUGPX(x...) -#define US_DEBUG(x) -#endif - -/* bit set if input */ -extern unsigned char us_direction[256/8]; -#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1) - -/* Sub Classes */ - -#define US_SC_RBC 0x01 /* Typically, flash devices */ -#define US_SC_8020 0x02 /* CD-ROM */ -#define US_SC_QIC 0x03 /* QIC-157 Tapes */ -#define US_SC_UFI 0x04 /* Floppy */ -#define US_SC_8070 0x05 /* Removable media */ -#define US_SC_SCSI 0x06 /* Transparent */ -#define US_SC_MIN US_SC_RBC -#define US_SC_MAX US_SC_SCSI - -/* Protocols */ - -#define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */ -#define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */ -#define US_PR_BULK 0x50 /* bulk only */ - -/* - * Bulk only data structures - */ - -/* command block wrapper */ -struct bulk_cb_wrap { - __u32 Signature; /* contains 'USBC' */ - __u32 Tag; /* unique per command id */ - __u32 DataTransferLength; /* size of data */ - __u8 Flags; /* direction in bit 0 */ - __u8 Lun; /* LUN normally 0 */ - __u8 Length; /* of of the CDB */ - __u8 CDB[16]; /* max command */ -}; - -#define US_BULK_CB_WRAP_LEN 31 -#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */ -#define US_BULK_FLAG_IN 1 -#define US_BULK_FLAG_OUT 0 - -/* command status wrapper */ -struct bulk_cs_wrap { - __u32 Signature; /* should = 'USBS' */ - __u32 Tag; /* same as original command */ - __u32 Residue; /* amount not transferred */ - __u8 Status; /* see below */ - __u8 Filler[18]; -}; - -#define US_BULK_CS_WRAP_LEN 13 -#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ -#define US_BULK_STAT_OK 0 -#define US_BULK_STAT_FAIL 1 -#define US_BULK_STAT_PHASE 2 - -/* bulk-only class specific requests */ -#define US_BULK_RESET_REQUEST 0xff -#define US_BULK_GET_MAX_LUN 0xfe - -/* - * us_bulk_transfer() return codes - */ -#define US_BULK_TRANSFER_GOOD 0 /* good transfer */ -#define US_BULK_TRANSFER_SHORT 1 /* transfered less than expected */ -#define US_BULK_TRANSFER_FAILED 2 /* transfer died in the middle */ -#define US_BULK_TRANSFER_ABORTED 3 /* transfer canceled */ - -/* - * Transport return codes - */ - -#define USB_STOR_TRANSPORT_GOOD 0 /* Transport good, command good */ -#define USB_STOR_TRANSPORT_FAILED 1 /* Transport good, command failed */ -#define USB_STOR_TRANSPORT_ERROR 2 /* Transport bad (i.e. device dead) */ -#define USB_STOR_TRANSPORT_ABORTED 3 /* Transport aborted */ - -/* - * CBI accept device specific command - */ - -#define US_CBI_ADSC 0 - -/* - * GUID definitions - */ - -#define GUID(x) __u32 x[3] -#define GUID_EQUAL(x, y) (x[0] == y[0] && x[1] == y[1] && x[2] == y[2]) -#define GUID_CLEAR(x) x[0] = x[1] = x[2] = 0; -#define GUID_NONE(x) (!x[0] && !x[1] && !x[2]) -#define GUID_FORMAT "%08x%08x%08x" -#define GUID_ARGS(x) x[0], x[1], x[2] - -static inline void make_guid( __u32 *pg, __u16 vendor, __u16 product, char *serial) -{ - pg[0] = (vendor << 16) | product; - pg[1] = pg[2] = 0; - while (*serial) { - pg[1] <<= 4; - pg[1] |= pg[2] >> 28; - pg[2] <<= 4; - if (*serial >= 'a') - *serial -= 'a' - 'A'; - pg[2] |= (*serial <= '9' && *serial >= '0') ? *serial - '0' - : *serial - 'A' + 10; - serial++; - } -} - -/* - * Unusual device list definitions - */ - -struct us_unusual_dev { - /* we search the list based on these parameters */ - __u16 idVendor; - __u16 idProduct; - __u16 bcdDeviceMin; - __u16 bcdDeviceMax; - - /* the list specifies these parameters */ - const char* name; - __u8 useProtocol; - __u8 useTransport; - unsigned int flags; -}; - -/* Flag definitions */ -#define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */ -#define US_FL_MODE_XLATE 0x00000002 /* translate _6 to _10 comands for - Win/MacOS compatibility */ -#define US_FL_START_STOP 0x00000004 /* ignore START_STOP commands */ -#define US_FL_ALT_LENGTH 0x00000008 /* use the alternate algorithm for - us_transfer_length() */ -#define US_FL_IGNORE_SER 0x00000010 /* Ignore the serial number given */ - diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/usb-uhci-debug.h linux/drivers/usb/usb-uhci-debug.h --- v2.4.0-test2/linux/drivers/usb/usb-uhci-debug.h Tue Mar 14 19:10:40 2000 +++ linux/drivers/usb/usb-uhci-debug.h Sat Jul 8 19:38:16 2000 @@ -1,5 +1,5 @@ #ifdef DEBUG -static void uhci_show_qh (puhci_desc_t qh) +static void __attribute__((__unused__)) uhci_show_qh (puhci_desc_t qh) { if (qh->type != QH_TYPE) { dbg("qh has not QH_TYPE"); @@ -75,7 +75,7 @@ (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : "Breadth first")); } #ifdef DEBUG -static void uhci_show_td_queue (puhci_desc_t td) +static void __attribute__((__unused__)) uhci_show_td_queue (puhci_desc_t td) { //dbg("uhci_show_td_queue %p (%08lX):", td, virt_to_bus (td)); while (1) { @@ -91,7 +91,7 @@ } } -static void uhci_show_queue (puhci_desc_t qh) +static void __attribute__((__unused__)) uhci_show_queue (puhci_desc_t qh) { uhci_desc_t *start_qh=qh; @@ -119,7 +119,7 @@ } } -static void uhci_show_sc (int port, unsigned short status) +static void __attribute__((__unused__)) uhci_show_sc (int port, unsigned short status) { dbg(" stat%d = %04x %s%s%s%s%s%s%s%s", port, diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c --- v2.4.0-test2/linux/drivers/usb/usb-uhci.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/usb-uhci.c Wed Jul 5 11:14:52 2000 @@ -1393,8 +1393,10 @@ { uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; urb_priv_t *urb_priv = urb->hcpriv; +#ifdef ISO_SANITY_CHECK int pipe=urb->pipe; int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)); +#endif int n, ret, last=0; uhci_desc_t *td, **tdm; int status, destination; @@ -1422,18 +1424,18 @@ tdm[n] = 0; continue; } - - if(urb->iso_frame_desc[n].length > maxsze) { + #ifdef ISO_SANITY_CHECK + if(urb->iso_frame_desc[n].length > maxsze) { err("submit_iso: urb->iso_frame_desc[%d].length(%d)>%d",n , urb->iso_frame_desc[n].length, maxsze); tdm[n] = 0; ret=-EINVAL; goto inval; -#endif } - + else +#endif ret = alloc_td (&td, UHCI_PTR_DEPTH); - inval: + if (ret) { int i; // Cleanup allocated TDs diff -u --recursive --new-file v2.4.0-test2/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.4.0-test2/linux/drivers/usb/usb.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/usb.c Thu Jun 29 09:53:14 2000 @@ -1683,8 +1683,9 @@ usb_set_maxpacket(dev); /* we set the default configuration here */ - if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) { - err("failed to set default configuration"); + err = usb_set_configuration(dev, dev->config[0].bConfigurationValue); + if (err) { + err("failed to set default configuration (error=%d)", err); return -1; } diff -u --recursive --new-file v2.4.0-test2/linux/drivers/video/Config.in linux/drivers/video/Config.in --- v2.4.0-test2/linux/drivers/video/Config.in Fri Jun 23 21:55:10 2000 +++ linux/drivers/video/Config.in Wed Jul 5 10:56:12 2000 @@ -119,7 +119,7 @@ fi tristate ' ATI Mach64 display support (EXPERIMENTAL)' CONFIG_FB_ATY tristate ' ATI Rage 128 display support (EXPERIMENTAL)' CONFIG_FB_ATY128 - bool ' 3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)' CONFIG_FB_3DFX + tristate ' 3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)' CONFIG_FB_3DFX tristate ' SIS 630/540 display support (EXPERIMENTAL)' CONFIG_FB_SIS fi fi @@ -240,7 +240,7 @@ "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \ "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" -o \ "$CONFIG_FB_P9100" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \ - "$CONFIG_FB_RIVA" = "m" -o \ + "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_3DFX" = "m" -o \ "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \ "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_SIS" = "m" ]; then define_tristate CONFIG_FBCON_CFB8 m @@ -263,7 +263,7 @@ if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_VESA" = "m" -o \ "$CONFIG_FB_VIRTUAL" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \ - "$CONFIG_FB_Q40" = "m" -o \ + "$CONFIG_FB_Q40" = "m" -o "$CONFIG_FB_3DFX" = "m" -o \ "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \ "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ @@ -306,6 +306,7 @@ "$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \ "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \ + "$CONFIG_FB_3DFX" = "m" -o \ "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_SIS" = "m" ]; then define_tristate CONFIG_FBCON_CFB32 m fi diff -u --recursive --new-file v2.4.0-test2/linux/drivers/video/aty128fb.c linux/drivers/video/aty128fb.c --- v2.4.0-test2/linux/drivers/video/aty128fb.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/video/aty128fb.c Sun Jul 9 22:14:33 2000 @@ -75,9 +75,9 @@ #undef DEBUG #ifdef DEBUG -#define DBG(x) printk(KERN_DEBUG "aty128fb: %s\n",(x)); +#define DBG(fmt, args...) printk(KERN_DEBUG "aty128fb: %s " fmt, __FUNCTION__, ##args); #else -#define DBG(x) +#define DBG(fmt, args...) #endif #ifndef CONFIG_PPC @@ -104,10 +104,20 @@ #ifndef MODULE /* default modedb mode */ +/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */ static struct fb_videomode defaultmode __initdata = { - /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */ - NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, - 0, FB_VMODE_NONINTERLACED + refresh: 60, + xres: 640, + yres: 480, + pixclock: 39722, + left_margin: 48, + right_margin: 16, + upper_margin: 33, + lower_margin: 10, + hsync_len: 96, + vsync_len: 2, + sync: 0, + vmode: FB_VMODE_NONINTERLACED }; #endif /* MODULE */ @@ -141,32 +151,30 @@ /* packed BIOS settings */ #ifndef CONFIG_PPC -#pragma pack(1) typedef struct { - u8 clock_chip_type; - u8 struct_size; - u8 accelerator_entry; - u8 VGA_entry; - u16 VGA_table_offset; - u16 POST_table_offset; - u16 XCLK; - u16 MCLK; - u8 num_PLL_blocks; - u8 size_PLL_blocks; - u16 PCLK_ref_freq; - u16 PCLK_ref_divider; - u32 PCLK_min_freq; - u32 PCLK_max_freq; - u16 MCLK_ref_freq; - u16 MCLK_ref_divider; - u32 MCLK_min_freq; - u32 MCLK_max_freq; - u16 XCLK_ref_freq; - u16 XCLK_ref_divider; - u32 XCLK_min_freq; - u32 XCLK_max_freq; -} PLL_BLOCK; -#pragma pack() + u8 clock_chip_type; + u8 struct_size; + u8 accelerator_entry; + u8 VGA_entry; + u16 VGA_table_offset; + u16 POST_table_offset; + u16 XCLK; + u16 MCLK; + u8 num_PLL_blocks; + u8 size_PLL_blocks; + u16 PCLK_ref_freq; + u16 PCLK_ref_divider; + u32 PCLK_min_freq; + u32 PCLK_max_freq; + u16 MCLK_ref_freq; + u16 MCLK_ref_divider; + u32 MCLK_min_freq; + u32 MCLK_max_freq; + u16 XCLK_ref_freq; + u16 XCLK_ref_divider; + u32 XCLK_min_freq; + u32 XCLK_max_freq; +} __attribute__ ((packed)) PLL_BLOCK; #endif /* !CONFIG_PPC */ /* onboard memory information */ @@ -194,12 +202,9 @@ static const struct aty128_meminfo ddr_sgram = { 4, 4, 3, 3, 2, 3, 1, 16, 31, 16, "64-bit DDR SGRAM" }; -static int currcon = 0; - -static char *aty128fb_name = "ATY Rage128"; +static const char *aty128fb_name = "ATY Rage128"; static char fontname[40] __initdata = { 0 }; -static char noaccel __initdata = 0; -static unsigned int initdepth __initdata = 8; +static int noaccel __initdata = 0; #ifndef MODULE static const char *mode_option __initdata = NULL; @@ -291,13 +296,14 @@ u32 cfb32[16]; #endif } fbcon_cmap; - int blitter_may_be_busy; #ifdef CONFIG_PCI struct pci_dev *pdev; #endif #ifdef CONFIG_MTRR struct { int vram; int vram_valid; } mtrr; #endif + int currcon; + int blitter_may_be_busy; int fifo_slots; /* free slots in FIFO (64 max) */ }; @@ -515,10 +521,8 @@ break; } -#ifdef DEBUG if (reset) /* reset engine?? */ - DBG("PLL write timeout!"); -#endif + printk(KERN_DEBUG "aty128fb: PLL write timeout!"); } @@ -645,9 +649,7 @@ /* use old pio mode */ aty_st_le32(PM4_BUFFER_CNTL, PM4_BUFFER_CNTL_NONPM4); -#ifdef DEBUG DBG("engine reset"); -#endif } @@ -1075,12 +1077,10 @@ pll->feedback_divider = round_div(n, d); pll->vclk = vclk; -#ifdef DEBUG - printk(KERN_DEBUG "var_to_pll: post %d feedback %d vlck %d output %d ref_divider %d\n", - pll->post_divider, pll->feedback_divider, vclk, output_freq, - c.ref_divider); - printk(KERN_DEBUG "var_to_pll: vclk_per: %d\n", period_in_ps); -#endif + DBG("post %d feedback %d vlck %d output %d ref_divider %d " + "vclk_per: %d\n", pll->post_divider, + pll->feedback_divider, vclk, output_freq, + c.ref_divider, period_in_ps); return 0; } @@ -1134,9 +1134,8 @@ m->Tr2w + x; -#ifdef DEBUG - printk(KERN_DEBUG "aty128fb: x %x\n", x); -#endif + DBG("x %x\n", x); + b = 0; while (x) { x >>= 1; @@ -1155,10 +1154,9 @@ return -EINVAL; } -#ifdef DEBUG - printk(KERN_DEBUG "aty128fb: p: %x rloop: %x x: %x ron: %x roff: %x\n", - p, m->Rloop, x, ron, roff); -#endif + DBG("p: %x rloop: %x x: %x ron: %x roff: %x\n", + p, m->Rloop, x, ron, roff); + dsp->dda_config = p << 16 | m->Rloop << 20 | x; dsp->dda_on_off = ron << 16 | roff; @@ -1543,7 +1541,12 @@ aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { - if (con == currcon) /* current console? */ +#if 1 + fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2); +#else + struct fb_info_aty128 fb = (struct fb_info_aty128 *)info; + + if (con == fb->currcon) /* current console? */ return fb_get_cmap(cmap, kspc, aty128_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); @@ -1551,6 +1554,7 @@ int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 32; fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); } +#endif return 0; } @@ -1564,6 +1568,7 @@ struct fb_info *info) { int err; + struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info; struct display *disp; if (con >= 0) @@ -1577,7 +1582,7 @@ return err; } - if (con == currcon) /* current console? */ + if (con == fb->currcon) /* current console? */ return fb_set_cmap(cmap, kspc, aty128_setcolreg, info); else fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); @@ -1632,24 +1637,6 @@ fontname[i] = 0; } else if (!strncmp(this_opt, "noaccel", 7)) { noaccel = 1; - } else if (!strncmp(this_opt, "depth:", 6)) { - unsigned int depth = simple_strtoul(this_opt+6, NULL, 0); - switch (depth) { - case 0 ... 8: - initdepth = 8; - break; - case 9 ... 16: - initdepth = 16; - break; - case 17 ... 24: - initdepth = 24; - break; - case 25 ... 32: - initdepth = 32; - break; - default: - initdepth = 8; - } } #ifdef CONFIG_MTRR else if(!strncmp(this_opt, "nomtrr", 6)) { @@ -1762,7 +1749,7 @@ #endif /* CONFIG_PPC */ { if (fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, - &defaultmode, initdepth) == 0) + &defaultmode, 8) == 0) var = default_var; } #endif /* MODULE */ @@ -1859,16 +1846,6 @@ u32 fb_addr, reg_addr, io_addr = 0; int err; -#if 0 - /* Request resources we're going to use */ - io_addr = pci_resource_start(pdev, 1); - if (!request_region(io_addr, pci_resource_len(pdev, 1), - "aty128fb IO")) { - printk(KERN_ERR "aty128fb: cannot reserve I/O ports\n"); - goto err_out_none; - } -#endif - fb_addr = pci_resource_start(pdev, 0); if (!request_mem_region(fb_addr, pci_resource_len(pdev, 0), "aty128fb FB")) { @@ -1894,6 +1871,8 @@ /* Copy PCI device info into info->pdev */ info->pdev = pdev; + info->currcon = -1; + /* Virtualize mmio region */ info->regbase_phys = reg_addr; info->regbase = ioremap(reg_addr, 0x1FFF); @@ -1966,7 +1945,6 @@ err_free_fb: release_mem_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1)); -err_out_none: return -ENODEV; } #endif /* CONFIG_PCI */ @@ -2072,13 +2050,12 @@ if (bios_seg) iounmap(bios_seg); -#ifdef DEBUG - printk(KERN_DEBUG "get_pllinfo: ppll_max %d ppll_min %d xclk %d " - "ref_divider %d dotclock %d\n", - info->constants.ppll_max, info->constants.ppll_min, - info->constants.xclk, info->constants.ref_divider, - info->constants.dotclock); -#endif + DBG("ppll_max %d ppll_min %d xclk %d " + "ref_divider %d dotclock %d\n", + info->constants.ppll_max, info->constants.ppll_min, + info->constants.xclk, info->constants.ref_divider, + info->constants.dotclock); + return; } #endif /* !CONFIG_PPC */ @@ -2159,11 +2136,12 @@ struct aty128fb_par par; /* Do we have to save the colormap? */ - if (fb_display[currcon].cmap.len) - fb_get_cmap(&fb_display[currcon].cmap, 1, aty128_getcolreg, fb); + if (fb_display[info->currcon].cmap.len) + fb_get_cmap(&fb_display[info->currcon].cmap, 1, + aty128_getcolreg, fb); /* set the current console */ - currcon = con; + info->currcon = con; aty128_decode_var(&fb_display[con].var, &par, info); aty128_set_par(&par, info); @@ -2319,7 +2297,9 @@ static void do_install_cmap(int con, struct fb_info *info) { - if (con != currcon) + struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info; + + if (con != fb->currcon) return; if (fb_display[con].cmap.len) diff -u --recursive --new-file v2.4.0-test2/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c --- v2.4.0-test2/linux/drivers/video/atyfb.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/video/atyfb.c Wed Jul 5 10:56:12 2000 @@ -612,6 +612,7 @@ writeb (val, info->ati_regbase + regindex); } +#if defined(CONFIG_PPC) || defined(CONFIG_PMAC_PBOOK) static void aty_st_lcd(int index, u32 val, const struct fb_info_aty *info) { unsigned long temp; @@ -633,6 +634,7 @@ /* read the register value */ return aty_ld_le32(LCD_DATA, info); } +#endif /* * Generic Mach64 routines diff -u --recursive --new-file v2.4.0-test2/linux/drivers/video/clgenfb.c linux/drivers/video/clgenfb.c --- v2.4.0-test2/linux/drivers/video/clgenfb.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/video/clgenfb.c Wed Jul 5 10:56:12 2000 @@ -2557,7 +2557,6 @@ #endif /* CONFIG_FB_OF */ struct pci_dev *pdev; unsigned long board_addr, board_size; - u16 tmp16; DPRINTK ("ENTER\n"); @@ -2618,14 +2617,12 @@ } if (!request_mem_region(board_addr, board_size, "clgenfb")) { - pci_write_config_word (pdev, PCI_COMMAND, tmp16); printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abort\n", board_addr); return -1; } #if 0 /* if the system didn't claim this region, we would... */ if (!request_mem_region(0xA0000, 65535, "clgenfb")) { - pci_write_config_word (pdev, PCI_COMMAND, tmp16); printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abort\n", 0xA0000L); release_mem_region(board_addr, board_size); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c --- v2.4.0-test2/linux/drivers/video/fbmem.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/video/fbmem.c Thu Jun 29 18:25:51 2000 @@ -292,19 +292,27 @@ struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops; struct fb_fix_screeninfo fix; - char *base_addr; - ssize_t copy_size; if (! fb || ! info->disp) return -ENODEV; fb->fb_get_fix(&fix,PROC_CONSOLE(info), info); - base_addr=info->disp->screen_base; - copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p); - if (copy_to_user(buf, base_addr+p, copy_size)) - return -EFAULT; - *ppos += copy_size; - return copy_size; + if (p >= fix.smem_len) + return 0; + if (count >= fix.smem_len) + count = fix.smem_len; + if (count + p > fix.smem_len) + count = fix.smem_len - p; + if (count) { + char *base_addr; + + base_addr = info->disp->screen_base; + count -= copy_to_user(buf, base_addr+p, count); + if (!count) + return -EFAULT; + *ppos += count; + } + return count; } static ssize_t @@ -316,19 +324,32 @@ struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops; struct fb_fix_screeninfo fix; - char *base_addr; - ssize_t copy_size; + int err; if (! fb || ! info->disp) return -ENODEV; fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); - base_addr=info->disp->screen_base; - copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p); - if (copy_from_user(base_addr+p, buf, copy_size)) - return -EFAULT; - file->f_pos += copy_size; - return copy_size; + if (p > fix.smem_len) + return -ENOSPC; + if (count >= fix.smem_len) + count = fix.smem_len; + err = 0; + if (count + p > fix.smem_len) { + count = fix.smem_len - p; + err = -ENOSPC; + } + if (count) { + char *base_addr; + + base_addr = info->disp->screen_base; + count -= copy_from_user(base_addr+p, buf, count); + *ppos += count; + err = -EFAULT; + } + if (count) + return count; + return err; } #ifdef CONFIG_KMOD @@ -688,7 +709,7 @@ create_proc_read_entry("fb", 0, 0, fbmem_read_proc, NULL); - devfs_handle = devfs_mk_dir (NULL, "fb", 0, NULL); + devfs_handle = devfs_mk_dir (NULL, "fb", NULL); if (devfs_register_chrdev(FB_MAJOR,"fb",&fb_fops)) printk("unable to get major %d for fb devs\n", FB_MAJOR); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/video/igafb.c linux/drivers/video/igafb.c --- v2.4.0-test2/linux/drivers/video/igafb.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/video/igafb.c Wed Jul 5 22:15:25 2000 @@ -356,7 +356,7 @@ pci_outb(info, green, DAC_DATA); pci_outb(info, blue, DAC_DATA); - if (regno < 16) + if (regno < 16) { switch (default_var.bits_per_pixel) { #ifdef FBCON_HAS_CFB16 case 16: @@ -372,11 +372,14 @@ #endif #ifdef FBCON_HAS_CFB32 case 32: + { int i; i = (regno << 8) | regno; info->fbcon_cmap.cfb32[regno] = (i << 16) | i; + } break; #endif } + } return 0; } @@ -510,6 +513,8 @@ break; #endif default: + printk(KERN_WARNING "igafb_set_disp: unknown resolution %d\n", + default_var.bits_per_pixel); return; } memcpy(&info->dispsw, sw, sizeof(*sw)); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/video/matrox/matroxfb_DAC1064.c linux/drivers/video/matrox/matroxfb_DAC1064.c --- v2.4.0-test2/linux/drivers/video/matrox/matroxfb_DAC1064.c Sat Feb 26 22:31:51 2000 +++ linux/drivers/video/matrox/matroxfb_DAC1064.c Wed Jul 5 11:55:45 2000 @@ -169,9 +169,9 @@ if (mode == CM_ERASE) { if (ACCESS_FBINFO(cursor.state) != CM_ERASE) { + del_timer_sync(&ACCESS_FBINFO(cursor.timer)); matroxfb_DAC_lock_irqsave(flags); ACCESS_FBINFO(cursor.state) = CM_ERASE; - del_timer(&ACCESS_FBINFO(cursor.timer)); outDAC1064(PMINFO M1064_XCURCTRL, M1064_XCURCTRL_DIS); matroxfb_DAC_unlock_irqrestore(flags); } @@ -184,6 +184,7 @@ y -= p->var.yoffset; if (p->var.vmode & FB_VMODE_DOUBLE) y *= 2; + del_timer_sync(&ACCESS_FBINFO(cursor.timer)); matroxfb_DAC_lock_irqsave(flags); if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y)) || ACCESS_FBINFO(cursor.redraw)) { ACCESS_FBINFO(cursor.redraw) = 0; @@ -339,16 +340,18 @@ #if defined(CONFIG_FB_MATROX_MAVEN) || defined(CONFIG_FB_MATROX_MAVEN_MODULE) if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) { hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_EXT; - hw->DACreg[POS1064_XMISCCTRL] |= G400_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_MAFC12; - } else if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) - hw->DACreg[POS1064_XMISCCTRL] |= G400_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12; + hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_MAFC12; + } else if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) { + hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12; + } else +#endif + if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP) + hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12; else - hw->DACreg[POS1064_XMISCCTRL] |= G400_XMISCCTRL_MFC_DIS; + hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS; + if ((ACCESS_FBINFO(output.ph) | ACCESS_FBINFO(output.sh)) & MATROXFB_OUTPUT_CONN_PRIMARY) hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN; -#else - hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_MFC_DIS | M1064_XMISCCTRL_DAC_EN; -#endif } void DAC1064_global_restore(CPMINFO const struct matrox_hw_state* hw) { diff -u --recursive --new-file v2.4.0-test2/linux/drivers/video/matrox/matroxfb_DAC1064.h linux/drivers/video/matrox/matroxfb_DAC1064.h --- v2.4.0-test2/linux/drivers/video/matrox/matroxfb_DAC1064.h Sat Feb 26 22:31:51 2000 +++ linux/drivers/video/matrox/matroxfb_DAC1064.h Wed Jul 5 11:55:45 2000 @@ -84,10 +84,10 @@ #define M1064_XMISCCTRL_MFC_VGA 0x00 #define M1064_XMISCCTRL_MFC_MAFC 0x02 #define M1064_XMISCCTRL_MFC_DIS 0x06 -#define G400_XMISCCTRL_MFC_MAFC 0x02 -#define G400_XMISCCTRL_MFC_PANELLINK 0x04 -#define G400_XMISCCTRL_MFC_DIS 0x06 -#define G400_XMISCCTRL_MFC_MASK 0x06 +#define GX00_XMISCCTRL_MFC_MAFC 0x02 +#define GX00_XMISCCTRL_MFC_PANELLINK 0x04 +#define GX00_XMISCCTRL_MFC_DIS 0x06 +#define GX00_XMISCCTRL_MFC_MASK 0x06 #define M1064_XMISCCTRL_DAC_6BIT 0x00 #define M1064_XMISCCTRL_DAC_8BIT 0x08 #define M1064_XMISCCTRL_DAC_WIDTHMASK 0x08 diff -u --recursive --new-file v2.4.0-test2/linux/drivers/video/matrox/matroxfb_Ti3026.c linux/drivers/video/matrox/matroxfb_Ti3026.c --- v2.4.0-test2/linux/drivers/video/matrox/matroxfb_Ti3026.c Sat Feb 26 22:31:51 2000 +++ linux/drivers/video/matrox/matroxfb_Ti3026.c Wed Jul 5 11:55:45 2000 @@ -352,9 +352,9 @@ if (mode == CM_ERASE) { if (ACCESS_FBINFO(cursor.state) != CM_ERASE) { + del_timer_sync(&ACCESS_FBINFO(cursor.timer)); matroxfb_DAC_lock_irqsave(flags); ACCESS_FBINFO(cursor.state) = CM_ERASE; - del_timer(&ACCESS_FBINFO(cursor.timer)); outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->DACreg[POS3026_XCURCTRL])); matroxfb_DAC_unlock_irqrestore(flags); } @@ -367,6 +367,7 @@ y -= p->var.yoffset; if (p->var.vmode & FB_VMODE_DOUBLE) y *= 2; + del_timer_sync(&ACCESS_FBINFO(cursor.timer)); matroxfb_DAC_lock_irqsave(flags); if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y)) || ACCESS_FBINFO(cursor.redraw)) { ACCESS_FBINFO(cursor.redraw) = 0; diff -u --recursive --new-file v2.4.0-test2/linux/drivers/video/matrox/matroxfb_base.c linux/drivers/video/matrox/matroxfb_base.c --- v2.4.0-test2/linux/drivers/video/matrox/matroxfb_base.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/video/matrox/matroxfb_base.c Wed Jul 5 11:55:45 2000 @@ -97,7 +97,6 @@ #if defined(CONFIG_FB_OF) unsigned char nvram_read_byte(int); -int matrox_of_init(struct device_node *dp); static int default_vmode = VMODE_NVRAM; static int default_cmode = CMODE_NVRAM; #endif @@ -192,7 +191,7 @@ } matroxfb_unregister_device(MINFO); unregister_framebuffer(&ACCESS_FBINFO(fbcon)); - del_timer(&ACCESS_FBINFO(cursor.timer)); + del_timer_sync(&ACCESS_FBINFO(cursor.timer)); #ifdef CONFIG_MTRR if (ACCESS_FBINFO(mtrr.vram_valid)) mtrr_del(ACCESS_FBINFO(mtrr.vram), ACCESS_FBINFO(video.base), ACCESS_FBINFO(video.len)); @@ -827,7 +826,7 @@ /* copy last setting... */ memcpy(hw, ohw, sizeof(*hw)); - del_timer(&ACCESS_FBINFO(cursor.timer)); + del_timer_sync(&ACCESS_FBINFO(cursor.timer)); ACCESS_FBINFO(cursor.state) = CM_ERASE; ACCESS_FBINFO(hw_switch->init(PMINFO hw, &mt, display)); @@ -845,7 +844,7 @@ hw->CRTC[0x0C] = (pos & 0xFF00) >> 8; hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40); hw->CRTCEXT[8] = pos >> 21; - if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_PRIMARY) { + if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) { if (ACCESS_FBINFO(primout)) ACCESS_FBINFO(primout)->compute(MINFO, &mt, hw); } @@ -856,7 +855,7 @@ up_read(&ACCESS_FBINFO(altout.lock)); } ACCESS_FBINFO(hw_switch->restore(PMINFO hw, ohw, display)); - if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_PRIMARY) { + if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) { if (ACCESS_FBINFO(primout)) ACCESS_FBINFO(primout)->program(MINFO, hw); } @@ -869,7 +868,7 @@ ACCESS_FBINFO(cursor.redraw) = 1; ACCESS_FBINFO(currenthw) = hw; ACCESS_FBINFO(newhw) = ohw; - if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_PRIMARY) { + if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) { if (ACCESS_FBINFO(primout)) ACCESS_FBINFO(primout)->start(MINFO); } @@ -881,7 +880,7 @@ } matrox_cfbX_init(PMINFO display); do_install_cmap(PMINFO display); -#if defined(CONFIG_FB_OF) && defined(CONFIG_FB_COMPAT_XPMAC) +#if defined(CONFIG_FB_COMPAT_XPMAC) if (console_fb_info == &ACCESS_FBINFO(fbcon)) { int vmode, cmode; @@ -899,7 +898,7 @@ display_info.cmap_data_address = 0; display_info.disp_reg_address = ACCESS_FBINFO(mmio.base); } -#endif /* CONFIG_FB_OF && CONFIG_FB_COMPAT_XPMAC */ +#endif /* CONFIG_FB_COMPAT_XPMAC */ } } return 0; @@ -1065,6 +1064,13 @@ up_read(&ACCESS_FBINFO(crtc2.lock)); } return 0; + case MATROXFB_OUTPUT_DFP: + if (!(ACCESS_FBINFO(output.all) & MATROXFB_OUTPUT_CONN_DFP)) + return -ENXIO; + if (mom.mode!= MATROXFB_OUTPUT_MODE_MONITOR) + return -EINVAL; + /* mode did not change... */ + return 0; default: return -EINVAL; } @@ -1091,6 +1097,11 @@ if (val) return val; break; + case MATROXFB_OUTPUT_DFP: + if (!(ACCESS_FBINFO(output.all) & MATROXFB_OUTPUT_CONN_DFP)) + return -ENXIO; + mom.mode = MATROXFB_OUTPUT_MODE_MONITOR; + break; default: return -EINVAL; } @@ -1106,6 +1117,12 @@ return -EINVAL; if (tmp & ACCESS_FBINFO(output.sh)) return -EINVAL; + if (tmp & MATROXFB_OUTPUT_CONN_DFP) { + if (tmp & MATROXFB_OUTPUT_CONN_SECONDARY) + return -EINVAL; + if (ACCESS_FBINFO(output.sh)) + return -EINVAL; + } if (tmp == ACCESS_FBINFO(output.ph)) return 0; ACCESS_FBINFO(output.ph) = tmp; @@ -1122,6 +1139,10 @@ u_int32_t tmp; tmp = ACCESS_FBINFO(output.all) & ~ACCESS_FBINFO(output.sh); + if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP) + tmp &= ~MATROXFB_OUTPUT_CONN_SECONDARY; + if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) + tmp &= ~MATROXFB_OUTPUT_CONN_DFP; put_user_ret(tmp, (u_int32_t*)arg, -EFAULT); return 0; } @@ -1290,6 +1311,7 @@ static unsigned int fv = 0; /* "matrox:fv:xxxxx" */ static unsigned int fh = 0; /* "matrox:fh:xxxxxk" */ static unsigned int maxclk = 0; /* "matrox:maxclk:xxxxM" */ +static int dfp = 0; /* "matrox:dfp */ static char fontname[64]; /* "matrox:font:xxxxx" */ #ifndef MODULE @@ -1386,11 +1408,13 @@ #define DEVF_TEXT16B 0x0400 #define DEVF_CRTC2 0x0800 #define DEVF_MAVEN_CAPABLE 0x1000 +#define DEVF_PANELLINK_CAPABLE 0x2000 #define DEVF_GCORE (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB | DEVF_DDC_8_2) +#define DEVF_G2CORE (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_MAVEN_CAPABLE | DEVF_PANELLINK_CAPABLE) #define DEVF_G100 (DEVF_GCORE) /* no doc, no vxres... */ -#define DEVF_G200 (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_MAVEN_CAPABLE) -#define DEVF_G400 (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_MAVEN_CAPABLE | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2) +#define DEVF_G200 (DEVF_G2CORE) +#define DEVF_G400 (DEVF_G2CORE | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2) static struct board { unsigned short vendor, device, rev, svid, sid; @@ -1586,6 +1610,12 @@ ACCESS_FBINFO(devflags.precise_width) = !(b->flags & DEVF_ANY_VXRES); ACCESS_FBINFO(devflags.crtc2) = b->flags & DEVF_CRTC2; ACCESS_FBINFO(devflags.maven_capable) = b->flags & DEVF_MAVEN_CAPABLE; + if (b->flags & DEVF_PANELLINK_CAPABLE) { + ACCESS_FBINFO(output.all) |= MATROXFB_OUTPUT_CONN_DFP; + if (dfp) + ACCESS_FBINFO(output.ph) |= MATROXFB_OUTPUT_CONN_DFP; + } + ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode); ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode); @@ -1791,7 +1821,7 @@ } /* FIXME: Where to move this?! */ -#if defined(CONFIG_FB_OF) +#if defined(CONFIG_PPC) #if defined(CONFIG_FB_COMPAT_XPMAC) strcpy(ACCESS_FBINFO(matrox_name), "MTRX,"); /* OpenFirmware naming convension */ strncat(ACCESS_FBINFO(matrox_name), b->name, 26); @@ -1817,7 +1847,7 @@ vesafb_defined = var; /* Note: mac_vmode_to_var() doesnot set all parameters */ } } -#endif +#endif /* CONFIG_PPC */ vesafb_defined.xres_virtual = vesafb_defined.xres; if (nopan) { vesafb_defined.yres_virtual = vesafb_defined.yres; @@ -2383,6 +2413,8 @@ blink = value; else if (!strcmp(this_opt, "grayscale")) grayscale = value; + else if (!strcmp(this_opt, "dfp")) + dfp = value; else { strncpy(videomode, this_opt, sizeof(videomode)-1); } @@ -2407,21 +2439,6 @@ return 0; } -#if defined(CONFIG_FB_OF) -int __init matrox_of_init(struct device_node *dp){ - DBG("matrox_of_init"); - - if (disabled) - return -ENXIO; - if (!initialized) { - initialized = 1; - matrox_init(); - } - /* failure? */ - return 0; -} -#endif /* CONFIG_FB_OF */ - #else /* *************************** init module code **************************** */ @@ -2500,6 +2517,8 @@ MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)"); MODULE_PARM(cross4MB, "i"); MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. (default=autodetected)"); +MODULE_PARM(dfp, "i"); +MODULE_PARM_DESC(dfp, "Specifies whether to use digital flat panel interface of G200/G400 (0 or 1) (default=0)"); #ifdef CONFIG_FB_OF MODULE_PARM(vmode, "i"); MODULE_PARM_DESC(vmode, "Specify the vmode mode number that should be used (640x480 default)"); diff -u --recursive --new-file v2.4.0-test2/linux/drivers/video/matrox/matroxfb_base.h linux/drivers/video/matrox/matroxfb_base.h --- v2.4.0-test2/linux/drivers/video/matrox/matroxfb_base.h Sat Feb 26 22:31:51 2000 +++ linux/drivers/video/matrox/matroxfb_base.h Wed Jul 5 11:55:45 2000 @@ -56,10 +56,10 @@ #include