summaryrefslogtreecommitdiffstats
path: root/common/recipes-utils/jbi/files/code
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-utils/jbi/files/code')
-rw-r--r--common/recipes-utils/jbi/files/code/COPYING340
-rw-r--r--common/recipes-utils/jbi/files/code/Makefile26
-rw-r--r--common/recipes-utils/jbi/files/code/jbicomp.c416
-rw-r--r--common/recipes-utils/jbi/files/code/jbicomp.h37
-rw-r--r--common/recipes-utils/jbi/files/code/jbiexprt.h224
-rw-r--r--common/recipes-utils/jbi/files/code/jbijtag.c1675
-rw-r--r--common/recipes-utils/jbi/files/code/jbijtag.h147
-rw-r--r--common/recipes-utils/jbi/files/code/jbimain.c3290
-rw-r--r--common/recipes-utils/jbi/files/code/jbiport.h45
-rw-r--r--common/recipes-utils/jbi/files/code/jbistub.c2222
10 files changed, 8422 insertions, 0 deletions
diff --git a/common/recipes-utils/jbi/files/code/COPYING b/common/recipes-utils/jbi/files/code/COPYING
new file mode 100644
index 0000000..3912109
--- /dev/null
+++ b/common/recipes-utils/jbi/files/code/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/common/recipes-utils/jbi/files/code/Makefile b/common/recipes-utils/jbi/files/code/Makefile
new file mode 100644
index 0000000..ca84b02
--- /dev/null
+++ b/common/recipes-utils/jbi/files/code/Makefile
@@ -0,0 +1,26 @@
+# Copyright 2015-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+
+all: jbi
+
+jbi: jbicomp.o jbijtag.o jbimain.o jbistub.o
+ $(CC) -g -o $@ $^ $(LDFLAGS) -lgpio
+
+.PHONY: clean
+
+clean:
+ rm -rf *.o jbi
diff --git a/common/recipes-utils/jbi/files/code/jbicomp.c b/common/recipes-utils/jbi/files/code/jbicomp.c
new file mode 100644
index 0000000..99ba515
--- /dev/null
+++ b/common/recipes-utils/jbi/files/code/jbicomp.c
@@ -0,0 +1,416 @@
+/****************************************************************************/
+/* */
+/* Module: jbicomp.c */
+/* */
+/* Copyright (C) Altera Corporation 1997-2001 */
+/* */
+/* Description: Contains the code for compressing and uncompressing */
+/* Boolean array data. */
+/* */
+/* This algorithm works by searching previous bytes in the */
+/* data that match the current data. If a match is found, */
+/* then the offset and length of the matching data can */
+/* replace the actual data in the output. */
+/* */
+/* Revisions: 2.2 fixed /W4 warnings */
+/* */
+/****************************************************************************/
+
+#include "jbiport.h"
+#include "jbiexprt.h"
+#include "jbicomp.h"
+
+#define SHORT_BITS 16
+#define CHAR_BITS 8
+#define DATA_BLOB_LENGTH 3
+#define MATCH_DATA_LENGTH 8192
+#define JBI_ACA_REQUEST_SIZE 1024
+#define JBI_ACA_BUFFER_SIZE (MATCH_DATA_LENGTH + JBI_ACA_REQUEST_SIZE)
+
+unsigned long jbi_in_length = 0L;
+unsigned long jbi_in_index = 0L; /* byte index into compressed array */
+unsigned int jbi_bits_avail = CHAR_BITS;
+
+#if PORT == DOS
+int jbi_current_variable_id = -1;
+int jbi_current_page = -1;
+int jbi_version = 0;
+unsigned long jbi_out_length = 0L;
+unsigned int jbi_out_index = 0; /* byte index into jbi_aca_out_buffer[] */
+unsigned long jbi_aca_in_offset = 0L;
+unsigned char jbi_aca_out_buffer[JBI_ACA_BUFFER_SIZE];
+#endif
+
+/****************************************************************************/
+/* */
+/* The following functions implement incremental decompression of Boolean */
+/* array data, using a small memory window. */
+/* */
+/* This algorithm works by searching previous bytes in the data that match */
+/* the current data. If a match is found, then the offset and length of */
+/* the matching data can replace the actual data in the output. */
+/* */
+/* Memory usage is reduced by maintaining a "window" buffer which contains */
+/* the uncompressed data for one 8K page, plus some extra amount specified */
+/* by JBI_ACA_REQUEST_SIZE. The function jbi_uncompress_page() is used to */
+/* request a subrange of the uncompressed data, starting at a particular */
+/* bit position and extending a maximum of JBI_ACA_REQUEST_SIZE bytes. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+
+unsigned int jbi_bits_required(unsigned int n)
+
+/* */
+/* Description: Calculate the minimum number of bits required to */
+/* represent n. */
+/* */
+/* Returns: Number of bits. */
+/* */
+/****************************************************************************/
+{
+ unsigned int result = SHORT_BITS;
+
+ if (n == 0)
+ {
+ result = 1;
+ }
+ else
+ {
+ /* Look for the highest non-zero bit position */
+ while ((n & (1 << (SHORT_BITS - 1))) == 0)
+ {
+ n <<= 1;
+ --result;
+ }
+ }
+
+ return (result);
+}
+
+/****************************************************************************/
+/* */
+
+unsigned int jbi_read_packed
+(
+#if PORT!=DOS
+ unsigned char *buffer,
+#endif
+ unsigned int bits
+)
+
+/* */
+/* Description: Read the next value from the input array "buffer". */
+/* Read only "bits" bits from the array. The amount of */
+/* bits that have already been read from "buffer" is */
+/* stored internally to this function. */
+/* */
+/* Returns: Up to 16 bit value. -1 if buffer overrun. */
+/* */
+/****************************************************************************/
+{
+ unsigned int result = 0;
+ unsigned int shift = 0;
+ unsigned int databyte = 0;
+
+ while (bits > 0)
+ {
+#if PORT==DOS
+ databyte = GET_BYTE(jbi_aca_in_offset + jbi_in_index);
+#else
+ databyte = buffer[jbi_in_index];
+#endif
+ result |= (((databyte >> (CHAR_BITS - jbi_bits_avail))
+ & (0xFF >> (CHAR_BITS - jbi_bits_avail))) << shift);
+
+ if (bits <= jbi_bits_avail)
+ {
+ result &= (0xFFFF >> (SHORT_BITS - (bits + shift)));
+ jbi_bits_avail -= bits;
+ bits = 0;
+ }
+ else
+ {
+ ++jbi_in_index;
+ shift += jbi_bits_avail;
+ bits -= jbi_bits_avail;
+ jbi_bits_avail = CHAR_BITS;
+ }
+ }
+
+ return (result);
+}
+
+#if PORT==DOS
+
+/****************************************************************************/
+/* */
+
+void jbi_uncompress_next_page(int version)
+
+/* */
+/* Description: Uncompresses one page of compressed data, using */
+/* data page as reference for repeated sections. */
+/* Overwrites previous page of data in buffer. */
+/* */
+/* Returns: TRUE for success, FALSE if error encountered */
+/* */
+/****************************************************************************/
+{
+ unsigned int i, j, offset, length;
+ unsigned int end_index;
+ unsigned long tmp_in_index = jbi_in_index;
+ unsigned int tmp_out_index = jbi_out_index;
+ unsigned int tmp_bits_avail = jbi_bits_avail;
+ unsigned int prev[3];
+ unsigned long long_end;
+ unsigned int match_data_length = MATCH_DATA_LENGTH;
+
+ if (version > 0) --match_data_length;
+
+ if (jbi_current_page < 0)
+ {
+ /* this is the first page of the array */
+ jbi_current_page = 0;
+ jbi_in_index = 4; /* skip over length field */
+ jbi_out_index = 0;
+ end_index = (jbi_out_length < JBI_ACA_BUFFER_SIZE) ?
+ (unsigned int) jbi_out_length : JBI_ACA_BUFFER_SIZE;
+ }
+ else
+ {
+ /* this is not the first page */
+ ++jbi_current_page;
+ jbi_out_index -= MATCH_DATA_LENGTH;
+ long_end = jbi_out_length -
+ ((long) jbi_current_page * (long) MATCH_DATA_LENGTH);
+ end_index = (long_end < JBI_ACA_BUFFER_SIZE) ?
+ (unsigned int) long_end : JBI_ACA_BUFFER_SIZE;
+
+ /* copy extra data from end of circular buffer to beginning */
+ for (i = 0; i < jbi_out_index; ++i)
+ {
+ jbi_aca_out_buffer[i] = jbi_aca_out_buffer[i + MATCH_DATA_LENGTH];
+ }
+ }
+
+ while (jbi_out_index < end_index)
+ {
+ /* save state so we can undo the last packet when we reach the end */
+ tmp_in_index = jbi_in_index;
+ tmp_out_index = jbi_out_index;
+ tmp_bits_avail = jbi_bits_avail;
+
+ /* A 0 bit indicates literal data. */
+ if (jbi_read_packed(1) == 0)
+ {
+ for (i = 0; i < DATA_BLOB_LENGTH; ++i)
+ {
+ if (jbi_out_index < end_index)
+ {
+ if (version == 0)
+ {
+ prev[i] = jbi_aca_out_buffer[jbi_out_index] & 0xff;
+ }
+ jbi_aca_out_buffer[jbi_out_index++] =
+ (unsigned char) jbi_read_packed(CHAR_BITS);
+ }
+ }
+ }
+ else
+ {
+ /* A 1 bit indicates offset/length to follow. */
+ offset = jbi_read_packed(jbi_bits_required(
+ (jbi_current_page > 0) ? match_data_length :
+ (jbi_out_index > match_data_length ? match_data_length :
+ jbi_out_index)));
+ length = jbi_read_packed(CHAR_BITS);
+
+ if ((version == 0) && (offset == match_data_length + 3))
+ {
+ jbi_aca_out_buffer[jbi_out_index++] = (unsigned char) prev[0];
+ jbi_aca_out_buffer[jbi_out_index++] = (unsigned char) prev[1];
+ jbi_aca_out_buffer[jbi_out_index++] = (unsigned char) prev[2];
+ length -= 3;
+ }
+
+ for (i = 0; i < length; ++i)
+ {
+ if (jbi_out_index < end_index)
+ {
+ if (offset > jbi_out_index)
+ {
+ j = jbi_out_index + MATCH_DATA_LENGTH - offset;
+ }
+ else j = jbi_out_index - offset;
+ jbi_aca_out_buffer[jbi_out_index] = jbi_aca_out_buffer[j];
+ ++jbi_out_index;
+ }
+ }
+
+ if (version == 0)
+ {
+ prev[0] = jbi_aca_out_buffer[jbi_out_index - 3] & 0xff;
+ prev[1] = jbi_aca_out_buffer[jbi_out_index - 2] & 0xff;
+ prev[2] = jbi_aca_out_buffer[jbi_out_index - 1] & 0xff;
+ }
+ }
+ }
+
+ /* restore the state before the previous packet */
+ jbi_in_index = tmp_in_index;
+ jbi_out_index = tmp_out_index;
+ jbi_bits_avail = tmp_bits_avail;
+}
+
+/****************************************************************************/
+/* */
+
+void jbi_uncompress_page
+(
+ int variable_id,
+ int page,
+ int version
+)
+
+/* */
+/* Description: Uncompress requested page of variable data. Stores */
+/* uncompressed data in jbi_aca_out_buffer[]. */
+/* */
+/* Returns: TRUE if successful, otherwise FALSE if: */
+/* 1) variable is not a compressed array */
+/* 2) compressed data is illegal or corrupted */
+/* 3) requested page is beyond the end of the array */
+/* 4) internal error in the code */
+/* */
+/****************************************************************************/
+{
+ unsigned long symbol_table;
+ unsigned long data_section;
+ unsigned long offset;
+ unsigned long value;
+ int delta = version * 2;
+
+ if (variable_id != jbi_current_variable_id)
+ {
+ /* initialize to uncompress the desired variable */
+ symbol_table = GET_DWORD(16 + (version * 8));
+ data_section = GET_DWORD(20 + (version * 8));
+ offset = symbol_table + ((11 + delta) * variable_id);
+ value = GET_DWORD(offset + 3 + delta);
+ jbi_current_variable_id = variable_id;
+ jbi_current_page = -1;
+ jbi_bits_avail = CHAR_BITS;
+ jbi_in_length = GET_DWORD(offset + 7 + delta);
+ jbi_out_length =
+ (((unsigned long) GET_BYTE(data_section + value)) |
+ (((unsigned long) GET_BYTE(data_section + value + 1)) << 8) |
+ (((unsigned long) GET_BYTE(data_section + value + 2)) << 16) |
+ (((unsigned long) GET_BYTE(data_section + value + 3)) << 24));
+ jbi_in_index = 4; /* skip over length field */
+ jbi_out_index = 0;
+ jbi_aca_in_offset = data_section + value;
+ }
+
+ /* to look back at an earlier page, start over at the beginning */
+ if (page < jbi_current_page)
+ {
+ jbi_current_page = -1;
+ jbi_in_index = 4; /* skip over length field */
+ jbi_bits_avail = CHAR_BITS;
+ }
+
+ /* uncompress sequentially up to the desired page */
+ while (page > jbi_current_page)
+ {
+ jbi_uncompress_next_page(version);
+ }
+}
+
+#else
+
+/****************************************************************************/
+/* */
+
+unsigned long jbi_uncompress
+(
+ unsigned char *in,
+ unsigned long in_length,
+ unsigned char *out,
+ unsigned long out_length,
+ int version
+)
+
+/* */
+/* Description: Uncompress data in "in" and write result to "out". */
+/* */
+/* Returns: Length of uncompressed data. -1 if: */
+/* 1) out_length is too small */
+/* 2) Internal error in the code */
+/* 3) in doesn't contain ACA compressed data. */
+/* */
+/****************************************************************************/
+{
+ unsigned long i, j, data_length = 0L;
+ unsigned int offset, length;
+ unsigned int match_data_length = MATCH_DATA_LENGTH;
+
+ if (version > 0) --match_data_length;
+
+ jbi_in_length = in_length;
+ jbi_bits_avail = CHAR_BITS;
+ jbi_in_index = 0L;
+ for (i = 0; i < out_length; ++i) out[i] = 0;
+
+ /* Read number of bytes in data. */
+ for (i = 0; i < sizeof (in_length); ++i)
+ {
+ data_length = data_length | ((unsigned long)
+ jbi_read_packed(in, CHAR_BITS) << (i * CHAR_BITS));
+ }
+
+ if (data_length > out_length)
+ {
+ data_length = 0L;
+ }
+ else
+ {
+ i = 0;
+ while (i < data_length)
+ {
+ /* A 0 bit indicates literal data. */
+ if (jbi_read_packed(in, 1) == 0)
+ {
+ for (j = 0; j < DATA_BLOB_LENGTH; ++j)
+ {
+ if (i < data_length)
+ {
+ out[i] = (unsigned char) jbi_read_packed(in, CHAR_BITS);
+ i++;
+ }
+ }
+ }
+ else
+ {
+ /* A 1 bit indicates offset/length to follow. */
+ offset = jbi_read_packed(in, jbi_bits_required((short) (i > match_data_length ? match_data_length : i)));
+ length = jbi_read_packed(in, CHAR_BITS);
+
+ for (j = 0; j < length; ++j)
+ {
+ if (i < data_length)
+ {
+ out[i] = out[i - offset];
+ i++;
+ }
+ }
+ }
+ }
+ }
+
+ return (data_length);
+}
+
+#endif
diff --git a/common/recipes-utils/jbi/files/code/jbicomp.h b/common/recipes-utils/jbi/files/code/jbicomp.h
new file mode 100644
index 0000000..382995d
--- /dev/null
+++ b/common/recipes-utils/jbi/files/code/jbicomp.h
@@ -0,0 +1,37 @@
+/****************************************************************************/
+/* */
+/* Module: jbicomp.h */
+/* */
+/* Copyright (C) Altera Corporation 1997-2001 */
+/* */
+/* Description: Contains the function prototypes for compressing */
+/* and uncompressing Boolean array data. */
+/* */
+/****************************************************************************/
+
+#ifndef INC_JBICOMP_H
+#define INC_JBICOMP_H
+
+#if PORT==DOS
+
+void jbi_uncompress_page
+(
+ int variable_id,
+ int page,
+ int version
+);
+
+#else
+
+unsigned long jbi_uncompress
+(
+ unsigned char *in,
+ unsigned long in_length,
+ unsigned char *out,
+ unsigned long out_length,
+ int version
+);
+
+#endif /* PORT==DOS */
+
+#endif /* INC_JBICOMP_H */
diff --git a/common/recipes-utils/jbi/files/code/jbiexprt.h b/common/recipes-utils/jbi/files/code/jbiexprt.h
new file mode 100644
index 0000000..6d6a401
--- /dev/null
+++ b/common/recipes-utils/jbi/files/code/jbiexprt.h
@@ -0,0 +1,224 @@
+/****************************************************************************/
+/* */
+/* Module: jbiexprt.h */
+/* */
+/* Copyright (C) Altera Corporation 1998-2001 */
+/* */
+/* Description: Jam STAPL ByteCode Player Export Header File */
+/* */
+/* Revisions: */
+/* */
+/****************************************************************************/
+
+#ifndef INC_JBIEXPRT_H
+#define INC_JBIEXPRT_H
+
+/****************************************************************************/
+/* */
+/* Return codes from most JBI functions */
+/* */
+/****************************************************************************/
+
+#define JBI_RETURN_TYPE int
+
+#define JBIC_SUCCESS 0
+#define JBIC_OUT_OF_MEMORY 1
+#define JBIC_IO_ERROR 2
+/* #define JAMC_SYNTAX_ERROR 3 */
+#define JBIC_UNEXPECTED_END 4
+#define JBIC_UNDEFINED_SYMBOL 5
+/* #define JAMC_REDEFINED_SYMBOL 6 */
+#define JBIC_INTEGER_OVERFLOW 7
+#define JBIC_DIVIDE_BY_ZERO 8
+#define JBIC_CRC_ERROR 9
+#define JBIC_INTERNAL_ERROR 10
+#define JBIC_BOUNDS_ERROR 11
+/* #define JAMC_TYPE_MISMATCH 12 */
+/* #define JAMC_ASSIGN_TO_CONST 13 */
+/* #define JAMC_NEXT_UNEXPECTED 14 */
+/* #define JAMC_POP_UNEXPECTED 15 */
+/* #define JAMC_RETURN_UNEXPECTED 16 */
+/* #define JAMC_ILLEGAL_SYMBOL 17 */
+#define JBIC_VECTOR_MAP_FAILED 18
+#define JBIC_USER_ABORT 19
+#define JBIC_STACK_OVERFLOW 20
+#define JBIC_ILLEGAL_OPCODE 21
+/* #define JAMC_PHASE_ERROR 22 */
+/* #define JAMC_SCOPE_ERROR 23 */
+#define JBIC_ACTION_NOT_FOUND 24
+
+/****************************************************************************/
+/* */
+/* Macro Definitions */
+/* */
+/****************************************************************************/
+
+/*
+* For DOS port, program data is stored in a set of 16K pages, accessed
+* through a pointer table. For 32-bit version, the buffer is continuous.
+* The macro GET_BYTE gets a single byte for either case.
+*/
+#if PORT==DOS
+#define PROGRAM_PTR unsigned char **
+#else
+#define PROGRAM_PTR unsigned char *
+#endif
+
+#if PORT==DOS
+#define GET_BYTE(x) (jbi_program[(x) >> 14L][(x) & 0x3fffL])
+#else
+#define GET_BYTE(x) (program[x])
+#endif
+
+#define GET_WORD(x) \
+ (((((unsigned short) GET_BYTE(x)) << 8) & 0xFF00) | \
+ (((unsigned short) GET_BYTE((x)+1)) & 0x00FF))
+
+#define GET_DWORD(x) \
+ (((((unsigned long) GET_BYTE(x)) << 24L) & 0xFF000000L) | \
+ ((((unsigned long) GET_BYTE((x)+1)) << 16L) & 0x00FF0000L) | \
+ ((((unsigned long) GET_BYTE((x)+2)) << 8L) & 0x0000FF00L) | \
+ (((unsigned long) GET_BYTE((x)+3)) & 0x000000FFL))
+
+/****************************************************************************/
+/* */
+/* Structured Types */
+/* */
+/****************************************************************************/
+
+typedef struct JBI_PROCINFO_STRUCT
+{
+ char *name;
+ unsigned char attributes;
+ struct JBI_PROCINFO_STRUCT *next;
+}
+JBI_PROCINFO;
+
+/****************************************************************************/
+/* */
+/* Global Data Prototypes */
+/* */
+/****************************************************************************/
+
+#if PORT==DOS
+extern unsigned char jbi_aca_out_buffer[8192 + 1024];
+#endif
+
+extern PROGRAM_PTR jbi_program;
+
+extern char *jbi_workspace;
+
+extern long jbi_workspace_size;
+
+/****************************************************************************/
+/* */
+/* Function Prototypes */
+/* */
+/****************************************************************************/
+
+JBI_RETURN_TYPE jbi_execute
+(
+ PROGRAM_PTR program,
+ long program_size,
+ char *workspace,
+ long workspace_size,
+ char *action,
+ char **init_list,
+ int reset_jtag,
+ long *error_address,
+ int *exit_code,
+ int *format_version
+);
+
+JBI_RETURN_TYPE jbi_get_note
+(
+ PROGRAM_PTR program,
+ long program_size,
+ long *offset,
+ char *key,
+ char *value,
+ int length
+);
+
+JBI_RETURN_TYPE jbi_check_crc
+(
+ PROGRAM_PTR program,
+ long program_size,
+ unsigned short *expected_crc,
+ unsigned short *actual_crc
+);
+
+JBI_RETURN_TYPE jbi_get_file_info
+(
+ PROGRAM_PTR program,
+ long program_size,
+ int *format_version,
+ int *action_count,
+ int *procedure_count
+);
+
+JBI_RETURN_TYPE jbi_get_action_info
+(
+ PROGRAM_PTR program,
+ long program_size,
+ int index,
+ char **name,
+ char **description,
+ JBI_PROCINFO **procedure_list
+);
+
+int jbi_jtag_io
+(
+ int tms,
+ int tdi,
+ int read_tdo
+);
+
+void jbi_message
+(
+ char *message_text
+);
+
+void jbi_export_integer
+(
+ char *key,
+ long value
+);
+
+void jbi_export_boolean_array
+(
+ char *key,
+ unsigned char *data,
+ long count
+);
+
+void jbi_delay
+(
+ long microseconds
+);
+
+int jbi_vector_map
+(
+ int signal_count,
+ char **signals
+);
+
+int jbi_vector_io
+(
+ int signal_count,
+ long *dir_vect,
+ long *data_vect,
+ long *capture_vect
+);
+
+void *jbi_malloc
+(
+ unsigned int size
+);
+
+void jbi_free
+(
+ void *ptr
+);
+
+#endif /* INC_JBIEXPRT_H */
diff --git a/common/recipes-utils/jbi/files/code/jbijtag.c b/common/recipes-utils/jbi/files/code/jbijtag.c
new file mode 100644
index 0000000..728ab6a
--- /dev/null
+++ b/common/recipes-utils/jbi/files/code/jbijtag.c
@@ -0,0 +1,1675 @@
+/****************************************************************************/
+/* */
+/* Module: jbijtag.c */
+/* */
+/* Copyright (C) Altera Corporation 1998-2001 */
+/* */
+/* Description: Contains JTAG interface functions */
+/* */
+/* Revisions: 2.2 updated state transition paths */
+/* 2.0 added multi-page scan code for 16-bit PORT */
+/* */
+/****************************************************************************/
+
+#include "jbiport.h"
+#include "jbiexprt.h"
+#include "jbicomp.h"
+#include "jbijtag.h"
+
+#define NULL 0
+
+char *jbi_workspace = NULL;
+long jbi_workspace_size = 0L;
+
+/****************************************************************************/
+/* */
+/* Enumerated Types */
+/* */
+/****************************************************************************/
+
+/* maximum JTAG IR and DR lengths (in bits) */
+#define JBIC_MAX_JTAG_IR_PREAMBLE 256
+#define JBIC_MAX_JTAG_IR_POSTAMBLE 256
+#define JBIC_MAX_JTAG_IR_LENGTH 512
+#define JBIC_MAX_JTAG_DR_PREAMBLE 1024
+#define JBIC_MAX_JTAG_DR_POSTAMBLE 1024
+#define JBIC_MAX_JTAG_DR_LENGTH 2048
+
+/*
+* Global variable to store the current JTAG state
+*/
+JBIE_JTAG_STATE jbi_jtag_state = JBI_ILLEGAL_JTAG_STATE;
+
+/*
+* Store current stop-state for DR and IR scan commands
+*/
+JBIE_JTAG_STATE jbi_drstop_state = IDLE;
+JBIE_JTAG_STATE jbi_irstop_state = IDLE;
+
+/*
+* Store current padding values
+*/
+unsigned int jbi_dr_preamble = 0;
+unsigned int jbi_dr_postamble = 0;
+unsigned int jbi_ir_preamble = 0;
+unsigned int jbi_ir_postamble = 0;
+unsigned int jbi_dr_length = 0;
+unsigned int jbi_ir_length = 0;
+unsigned char *jbi_dr_preamble_data = NULL;
+unsigned char *jbi_dr_postamble_data = NULL;
+unsigned char *jbi_ir_preamble_data = NULL;
+unsigned char *jbi_ir_postamble_data = NULL;
+unsigned char *jbi_dr_buffer = NULL;
+unsigned char *jbi_ir_buffer = NULL;
+
+/*
+* This structure shows, for each JTAG state, which state is reached after
+* a single TCK clock cycle with TMS high or TMS low, respectively. This
+* describes all possible state transitions in the JTAG state machine.
+*/
+struct JBIS_JTAG_MACHINE
+{
+ JBIE_JTAG_STATE tms_high;
+ JBIE_JTAG_STATE tms_low;
+} jbi_jtag_state_transitions[] =
+{
+/* RESET */ { RESET, IDLE },
+/* IDLE */ { DRSELECT, IDLE },
+/* DRSELECT */ { IRSELECT, DRCAPTURE },
+/* DRCAPTURE */ { DREXIT1, DRSHIFT },
+/* DRSHIFT */ { DREXIT1, DRSHIFT },
+/* DREXIT1 */ { DRUPDATE, DRPAUSE },
+/* DRPAUSE */ { DREXIT2, DRPAUSE },
+/* DREXIT2 */ { DRUPDATE, DRSHIFT },
+/* DRUPDATE */ { DRSELECT, IDLE },
+/* IRSELECT */ { RESET, IRCAPTURE },
+/* IRCAPTURE */ { IREXIT1, IRSHIFT },
+/* IRSHIFT */ { IREXIT1, IRSHIFT },
+/* IREXIT1 */ { IRUPDATE, IRPAUSE },
+/* IRPAUSE */ { IREXIT2, IRPAUSE },
+/* IREXIT2 */ { IRUPDATE, IRSHIFT },
+/* IRUPDATE */ { DRSELECT, IDLE }
+};
+
+/*
+* This table contains the TMS value to be used to take the NEXT STEP on
+* the path to the desired state. The array index is the current state,
+* and the bit position is the desired endstate. To find out which state
+* is used as the intermediate state, look up the TMS value in the
+* jbi_jtag_state_transitions[] table.
+*/
+unsigned short jbi_jtag_path_map[16] =
+{
+/* RST RTI SDRS CDR SDR E1DR PDR E2DR */
+ 0x0001, 0xFFFD, 0xFE01, 0xFFE7, 0xFFEF, 0xFF0F, 0xFFBF, 0xFFFF,
+/* UDR SIRS CIR SIR E1IR PIR E2IR UIR */
+ 0xFEFD, 0x0001, 0xF3FF, 0xF7FF, 0x87FF, 0xDFFF, 0xFFFF, 0x7FFD
+};
+
+/*
+* Flag bits for jbi_jtag_io() function
+*/
+#define TMS_HIGH 1
+#define TMS_LOW 0
+#define TDI_HIGH 1
+#define TDI_LOW 0
+#define READ_TDO 1
+#define IGNORE_TDO 0
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_init_jtag()
+
+/* */
+/****************************************************************************/
+{
+ /* initial JTAG state is unknown */
+ jbi_jtag_state = JBI_ILLEGAL_JTAG_STATE;
+
+ /* initialize global variables to default state */
+ jbi_drstop_state = IDLE;
+ jbi_irstop_state = IDLE;
+ jbi_dr_preamble = 0;
+ jbi_dr_postamble = 0;
+ jbi_ir_preamble = 0;
+ jbi_ir_postamble = 0;
+ jbi_dr_length = 0;
+ jbi_ir_length = 0;
+
+ if (jbi_workspace != NULL)
+ {
+ jbi_dr_preamble_data = (unsigned char *) jbi_workspace;
+ jbi_dr_postamble_data = &jbi_dr_preamble_data[JBIC_MAX_JTAG_DR_PREAMBLE / 8];
+ jbi_ir_preamble_data = &jbi_dr_postamble_data[JBIC_MAX_JTAG_DR_POSTAMBLE / 8];
+ jbi_ir_postamble_data = &jbi_ir_preamble_data[JBIC_MAX_JTAG_IR_PREAMBLE / 8];
+ jbi_dr_buffer = &jbi_ir_postamble_data[JBIC_MAX_JTAG_IR_POSTAMBLE / 8];
+ jbi_ir_buffer = &jbi_dr_buffer[JBIC_MAX_JTAG_DR_LENGTH / 8];
+ }
+ else
+ {
+ jbi_dr_preamble_data = NULL;
+ jbi_dr_postamble_data = NULL;
+ jbi_ir_preamble_data = NULL;
+ jbi_ir_postamble_data = NULL;
+ jbi_dr_buffer = NULL;
+ jbi_ir_buffer = NULL;
+ }
+
+ return (JBIC_SUCCESS);
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_set_drstop_state
+(
+ JBIE_JTAG_STATE state
+)
+
+/* */
+/****************************************************************************/
+{
+ jbi_drstop_state = state;
+
+ return (JBIC_SUCCESS);
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_set_irstop_state
+(
+ JBIE_JTAG_STATE state
+)
+
+/* */
+/****************************************************************************/
+{
+ jbi_irstop_state = state;
+
+ return (JBIC_SUCCESS);
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_set_dr_preamble
+(
+ unsigned int count,
+ unsigned int start_index,
+ unsigned char *preamble_data
+)
+
+/* */
+/****************************************************************************/
+{
+ JBI_RETURN_TYPE status = JBIC_SUCCESS;
+ unsigned int i;
+ unsigned int j;
+
+ if (jbi_workspace != NULL)
+ {
+ if (count > JBIC_MAX_JTAG_DR_PREAMBLE)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ jbi_dr_preamble = count;
+ }
+ }
+ else
+ {
+ if (count > jbi_dr_preamble)
+ {
+ jbi_free(jbi_dr_preamble_data);
+ jbi_dr_preamble_data = (unsigned char *) jbi_malloc((count + 7) >> 3);
+
+ if (jbi_dr_preamble_data == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ jbi_dr_preamble = count;
+ }
+ }
+ else
+ {
+ jbi_dr_preamble = count;
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ for (i = 0; i < count; ++i)
+ {
+ j = i + start_index;
+
+ if (preamble_data == NULL)
+ {
+ jbi_dr_preamble_data[i >> 3] |= (1 << (i & 7));
+ }
+ else
+ {
+ if (preamble_data[j >> 3] & (1 << (j & 7)))
+ {
+ jbi_dr_preamble_data[i >> 3] |= (1 << (i & 7));
+ }
+ else
+ {
+ jbi_dr_preamble_data[i >> 3] &=
+ ~(unsigned int) (1 << (i & 7));
+ }
+ }
+ }
+ }
+
+ return (status);
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_set_ir_preamble
+(
+ unsigned int count,
+ unsigned int start_index,
+ unsigned char *preamble_data
+)
+
+/* */
+/****************************************************************************/
+{
+ JBI_RETURN_TYPE status = JBIC_SUCCESS;
+ unsigned int i;
+ unsigned int j;
+
+ if (jbi_workspace != NULL)
+ {
+ if (count > JBIC_MAX_JTAG_IR_PREAMBLE)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ jbi_ir_preamble = count;
+ }
+ }
+ else
+ {
+ if (count > jbi_ir_preamble)
+ {
+ jbi_free(jbi_ir_preamble_data);
+ jbi_ir_preamble_data = (unsigned char *) jbi_malloc((count + 7) >> 3);
+
+ if (jbi_ir_preamble_data == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ jbi_ir_preamble = count;
+ }
+ }
+ else
+ {
+ jbi_ir_preamble = count;
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ for (i = 0; i < count; ++i)
+ {
+ j = i + start_index;
+
+ if (preamble_data == NULL)
+ {
+ jbi_ir_preamble_data[i >> 3] |= (1 << (i & 7));
+ }
+ else
+ {
+ if (preamble_data[j >> 3] & (1 << (j & 7)))
+ {
+ jbi_ir_preamble_data[i >> 3] |= (1 << (i & 7));
+ }
+ else
+ {
+ jbi_ir_preamble_data[i >> 3] &=
+ ~(unsigned int) (1 << (i & 7));
+ }
+ }
+ }
+ }
+
+ return (status);
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_set_dr_postamble
+(
+ unsigned int count,
+ unsigned int start_index,
+ unsigned char *postamble_data
+)
+
+/* */
+/****************************************************************************/
+{
+ JBI_RETURN_TYPE status = JBIC_SUCCESS;
+ unsigned int i;
+ unsigned int j;
+
+ if (jbi_workspace != NULL)
+ {
+ if (count > JBIC_MAX_JTAG_DR_POSTAMBLE)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ jbi_dr_postamble = count;
+ }
+ }
+ else
+ {
+ if (count > jbi_dr_postamble)
+ {
+ jbi_free(jbi_dr_postamble_data);
+ jbi_dr_postamble_data = (unsigned char *) jbi_malloc((count + 7) >> 3);
+
+ if (jbi_dr_postamble_data == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ jbi_dr_postamble = count;
+ }
+ }
+ else
+ {
+ jbi_dr_postamble = count;
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ for (i = 0; i < count; ++i)
+ {
+ j = i + start_index;
+
+ if (postamble_data == NULL)
+ {
+ jbi_dr_postamble_data[i >> 3] |= (1 << (i & 7));
+ }
+ else
+ {
+ if (postamble_data[j >> 3] & (1 << (j & 7)))
+ {
+ jbi_dr_postamble_data[i >> 3] |= (1 << (i & 7));
+ }
+ else
+ {
+ jbi_dr_postamble_data[i >> 3] &=
+ ~(unsigned int) (1 << (i & 7));
+ }
+ }
+ }
+ }
+
+ return (status);
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_set_ir_postamble
+(
+ unsigned int count,
+ unsigned int start_index,
+ unsigned char *postamble_data
+)
+
+/* */
+/****************************************************************************/
+{
+ JBI_RETURN_TYPE status = JBIC_SUCCESS;
+ unsigned int i;
+ unsigned int j;
+
+ if (jbi_workspace != NULL)
+ {
+ if (count > JBIC_MAX_JTAG_IR_POSTAMBLE)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ jbi_ir_postamble = count;
+ }
+ }
+ else
+ {
+ if (count > jbi_ir_postamble)
+ {
+ jbi_free(jbi_ir_postamble_data);
+ jbi_ir_postamble_data = (unsigned char *) jbi_malloc((count + 7) >> 3);
+
+ if (jbi_ir_postamble_data == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ jbi_ir_postamble = count;
+ }
+ }
+ else
+ {
+ jbi_ir_postamble = count;
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ for (i = 0; i < count; ++i)
+ {
+ j = i + start_index;
+
+ if (postamble_data == NULL)
+ {
+ jbi_ir_postamble_data[i >> 3] |= (1 << (i & 7));
+ }
+ else
+ {
+ if (postamble_data[j >> 3] & (1 << (j & 7)))
+ {
+ jbi_ir_postamble_data[i >> 3] |= (1 << (i & 7));
+ }
+ else
+ {
+ jbi_ir_postamble_data[i >> 3] &=
+ ~(unsigned int) (1 << (i & 7));
+ }
+ }
+ }
+ }
+
+ return (status);
+}
+
+/****************************************************************************/
+/* */
+
+void jbi_jtag_reset_idle(void)
+
+/* */
+/****************************************************************************/
+{
+ int i;
+
+ /*
+ * Go to Test Logic Reset (no matter what the starting state may be)
+ */
+ for (i = 0; i < 5; ++i)
+ {
+ jbi_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO);
+ }
+
+ /*
+ * Now step to Run Test / Idle
+ */
+ jbi_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
+
+ jbi_jtag_state = IDLE;
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_goto_jtag_state
+(
+ JBIE_JTAG_STATE state
+)
+
+/* */
+/****************************************************************************/
+{
+ int tms;
+ int count = 0;
+ JBI_RETURN_TYPE status = JBIC_SUCCESS;
+
+ if (jbi_jtag_state == JBI_ILLEGAL_JTAG_STATE)
+ {
+ /* initialize JTAG chain to known state */
+ jbi_jtag_reset_idle();
+ }
+
+ if (jbi_jtag_state == state)
+ {
+ /*
+ * We are already in the desired state. If it is a stable state,
+ * loop here. Otherwise do nothing (no clock cycles).
+ */
+ if ((state == IDLE) ||
+ (state == DRSHIFT) ||
+ (state == DRPAUSE) ||
+ (state == IRSHIFT) ||
+ (state == IRPAUSE))
+ {
+ jbi_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
+ }
+ else if (state == RESET)
+ {
+ jbi_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO);
+ }
+ }
+ else
+ {
+ while ((jbi_jtag_state != state) && (count < 9))
+ {
+ /*
+ * Get TMS value to take a step toward desired state
+ */
+ tms = (jbi_jtag_path_map[jbi_jtag_state] & (1 << state)) ?
+ TMS_HIGH : TMS_LOW;
+
+ /*
+ * Take a step
+ */
+ jbi_jtag_io(tms, TDI_LOW, IGNORE_TDO);
+
+ if (tms)
+ {
+ jbi_jtag_state =
+ jbi_jtag_state_transitions[jbi_jtag_state].tms_high;
+ }
+ else
+ {
+ jbi_jtag_state =
+ jbi_jtag_state_transitions[jbi_jtag_state].tms_low;
+ }
+
+ ++count;
+ }
+ }
+
+ if (jbi_jtag_state != state)
+ {
+ status = JBIC_INTERNAL_ERROR;
+ }
+
+ return (status);
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_do_wait_cycles
+(
+ long cycles,
+ JBIE_JTAG_STATE wait_state
+)
+
+/* */
+/* Description: Causes JTAG hardware to loop in the specified stable */
+/* state for the specified number of TCK clock cycles. */
+/* */
+/* Returns: JBIC_SUCCESS for success, else appropriate error code */
+/* */
+/****************************************************************************/
+{
+ int tms;
+ long count;
+ JBI_RETURN_TYPE status = JBIC_SUCCESS;
+
+ if (jbi_jtag_state != wait_state)
+ {
+ status = jbi_goto_jtag_state(wait_state);
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ /*
+ * Set TMS high to loop in RESET state
+ * Set TMS low to loop in any other stable state
+ */
+ tms = (wait_state == RESET) ? TMS_HIGH : TMS_LOW;
+
+ for (count = 0L; count < cycles; count++)
+ {
+ jbi_jtag_io(tms, TDI_LOW, IGNORE_TDO);
+ }
+ }
+
+ return (status);
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_do_wait_microseconds
+(
+ long microseconds,
+ JBIE_JTAG_STATE wait_state
+)
+
+/* */
+/* Description: Causes JTAG hardware to sit in the specified stable */
+/* state for the specified duration of real time. If */
+/* no JTAG operations have been performed yet, then only */
+/* a delay is performed. This permits the WAIT USECS */
+/* statement to be used in VECTOR programs without causing */
+/* any JTAG operations. */
+/* */
+/* Returns: JBIC_SUCCESS for success, else appropriate error code */
+/* */
+/****************************************************************************/
+{
+ JBI_RETURN_TYPE status = JBIC_SUCCESS;
+
+ if ((jbi_jtag_state != JBI_ILLEGAL_JTAG_STATE) &&
+ (jbi_jtag_state != wait_state))
+ {
+ status = jbi_goto_jtag_state(wait_state);
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ /*
+ * Wait for specified time interval
+ */
+ jbi_delay(microseconds);
+ }
+
+ return (status);
+}
+
+/****************************************************************************/
+/* */
+
+void jbi_jtag_concatenate_data
+(
+ unsigned char *buffer,
+ unsigned char *preamble_data,
+ unsigned int preamble_count,
+ unsigned char *target_data,
+ unsigned long start_index,
+ unsigned int target_count,
+ unsigned char *postamble_data,
+ unsigned int postamble_count
+)
+
+/* */
+/* Description: Copies preamble data, target data, and postamble data */
+/* into one buffer for IR or DR scans. */
+/* */
+/* Returns: nothing */
+/* */
+/****************************************************************************/
+{
+ unsigned long i;
+ unsigned long j;
+ unsigned long k;
+
+ for (i = 0L; i < preamble_count; ++i)
+ {
+ if (preamble_data[i >> 3L] & (1L << (i & 7L)))
+ {
+ buffer[i >> 3L] |= (1L << (i & 7L));
+ }
+ else
+ {
+ buffer[i >> 3L] &= ~(unsigned int) (1L << (i & 7L));
+ }
+ }
+
+ j = start_index;
+ k = preamble_count + target_count;
+ for (; i < k; ++i, ++j)
+ {
+ if (target_data[j >> 3L] & (1L << (j & 7L)))
+ {
+ buffer[i >> 3L] |= (1L << (i & 7L));
+ }
+ else
+ {
+ buffer[i >> 3L] &= ~(unsigned int) (1L << (i & 7L));
+ }
+ }
+
+ j = 0L;
+ k = preamble_count + target_count + postamble_count;
+ for (; i < k; ++i, ++j)
+ {
+ if (postamble_data[j >> 3L] & (1L << (j & 7L)))
+ {
+ buffer[i >> 3L] |= (1L << (i & 7L));
+ }
+ else
+ {
+ buffer[i >> 3L] &= ~(unsigned int) (1L << (i & 7L));
+ }
+ }
+}
+
+int jbi_jtag_drscan
+(
+ int start_state,
+ int count,
+ unsigned char *tdi,
+ unsigned char *tdo
+)
+{
+ int i = 0;
+ int tdo_bit = 0;
+ int status = 1;
+
+ /*
+ * First go to DRSHIFT state
+ */
+ switch (start_state)
+ {
+ case 0: /* IDLE */
+ jbi_jtag_io(1, 0, 0); /* DRSELECT */
+ jbi_jtag_io(0, 0, 0); /* DRCAPTURE */
+ jbi_jtag_io(0, 0, 0); /* DRSHIFT */
+ break;
+
+ case 1: /* DRPAUSE */
+ jbi_jtag_io(1, 0, 0); /* DREXIT2 */
+ jbi_jtag_io(1, 0, 0); /* DRUPDATE */
+ jbi_jtag_io(1, 0, 0); /* DRSELECT */
+ jbi_jtag_io(0, 0, 0); /* DRCAPTURE */
+ jbi_jtag_io(0, 0, 0); /* DRSHIFT */
+ break;
+
+ case 2: /* IRPAUSE */
+ jbi_jtag_io(1, 0, 0); /* IREXIT2 */
+ jbi_jtag_io(1, 0, 0); /* IRUPDATE */
+ jbi_jtag_io(1, 0, 0); /* DRSELECT */
+ jbi_jtag_io(0, 0, 0); /* DRCAPTURE */
+ jbi_jtag_io(0, 0, 0); /* DRSHIFT */
+ break;
+
+ default:
+ status = 0;
+ }
+
+ if (status)
+ {
+ /* loop in the SHIFT-DR state */
+ for (i = 0; i < count; i++)
+ {
+ tdo_bit = jbi_jtag_io(
+ (i == count - 1),
+ tdi[i >> 3] & (1 << (i & 7)),
+ (tdo != NULL));
+
+ if (tdo != NULL)
+ {
+ if (tdo_bit)
+ {
+ tdo[i >> 3] |= (1 << (i & 7));
+ }
+ else
+ {
+ tdo[i >> 3] &= ~(unsigned int) (1 << (i & 7));
+ }
+ }
+ }
+
+ jbi_jtag_io(0, 0, 0); /* DRPAUSE */
+ }
+
+ return (status);
+}
+
+int jbi_jtag_irscan
+(
+ int start_state,
+ int count,
+ unsigned char *tdi,
+ unsigned char *tdo
+)
+{
+ int i = 0;
+ int tdo_bit = 0;
+ int status = 1;
+
+ /*
+ * First go to IRSHIFT state
+ */
+ switch (start_state)
+ {
+ case 0: /* IDLE */
+ jbi_jtag_io(1, 0, 0); /* DRSELECT */
+ jbi_jtag_io(1, 0, 0); /* IRSELECT */
+ jbi_jtag_io(0, 0, 0); /* IRCAPTURE */
+ jbi_jtag_io(0, 0, 0); /* IRSHIFT */
+ break;
+
+ case 1: /* DRPAUSE */
+ jbi_jtag_io(1, 0, 0); /* DREXIT2 */
+ jbi_jtag_io(1, 0, 0); /* DRUPDATE */
+ jbi_jtag_io(1, 0, 0); /* DRSELECT */
+ jbi_jtag_io(1, 0, 0); /* IRSELECT */
+ jbi_jtag_io(0, 0, 0); /* IRCAPTURE */
+ jbi_jtag_io(0, 0, 0); /* IRSHIFT */
+ break;
+
+ case 2: /* IRPAUSE */
+ jbi_jtag_io(1, 0, 0); /* IREXIT2 */
+ jbi_jtag_io(1, 0, 0); /* IRUPDATE */
+ jbi_jtag_io(1, 0, 0); /* DRSELECT */
+ jbi_jtag_io(1, 0, 0); /* IRSELECT */
+ jbi_jtag_io(0, 0, 0); /* IRCAPTURE */
+ jbi_jtag_io(0, 0, 0); /* IRSHIFT */
+ break;
+
+ default:
+ status = 0;
+ }
+
+ if (status)
+ {
+ /* loop in the SHIFT-IR state */
+ for (i = 0; i < count; i++)
+ {
+ tdo_bit = jbi_jtag_io(
+ (i == count - 1),
+ tdi[i >> 3] & (1 << (i & 7)),
+ (tdo != NULL));
+
+ if (tdo != NULL)
+ {
+ if (tdo_bit)
+ {
+ tdo[i >> 3] |= (1 << (i & 7));
+ }
+ else
+ {
+ tdo[i >> 3] &= ~(unsigned int) (1 << (i & 7));
+ }
+ }
+ }
+
+ jbi_jtag_io(0, 0, 0); /* IRPAUSE */
+ }
+
+ return (status);
+}
+
+/****************************************************************************/
+/* */
+
+void jbi_jtag_extract_target_data
+(
+ unsigned char *buffer,
+ unsigned char *target_data,
+ unsigned int start_index,
+ unsigned int preamble_count,
+ unsigned int target_count
+)
+
+/* */
+/* Description: Copies target data from scan buffer, filtering out */
+/* preamble and postamble data. */
+/* */
+/* Returns: nothing */
+/* */
+/****************************************************************************/
+{
+ unsigned int i;
+ unsigned int j;
+ unsigned int k;
+
+ j = preamble_count;
+ k = start_index + target_count;
+ for (i = start_index; i < k; ++i, ++j)
+ {
+ if (buffer[j >> 3] & (1 << (j & 7)))
+ {
+ target_data[i >> 3] |= (1 << (i & 7));
+ }
+ else
+ {
+ target_data[i >> 3] &= ~(unsigned int) (1 << (i & 7));
+ }
+ }
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_do_irscan
+(
+ unsigned int count,
+ unsigned char *tdi_data,
+ unsigned int start_index
+)
+
+/* */
+/* Description: Shifts data into instruction register */
+/* */
+/* Returns: JBIC_SUCCESS for success, else appropriate error code */
+/* */
+/****************************************************************************/
+{
+ int start_code = 0;
+ unsigned int alloc_chars = 0;
+ unsigned int shift_count = jbi_ir_preamble + count + jbi_ir_postamble;
+ JBI_RETURN_TYPE status = JBIC_SUCCESS;
+ JBIE_JTAG_STATE start_state = JBI_ILLEGAL_JTAG_STATE;
+
+ switch (jbi_jtag_state)
+ {
+ case JBI_ILLEGAL_JTAG_STATE:
+ case RESET:
+ case IDLE:
+ start_code = 0;
+ start_state = IDLE;
+ break;
+
+ case DRSELECT:
+ case DRCAPTURE:
+ case DRSHIFT:
+ case DREXIT1:
+ case DRPAUSE:
+ case DREXIT2:
+ case DRUPDATE:
+ start_code = 1;
+ start_state = DRPAUSE;
+ break;
+
+ case IRSELECT:
+ case IRCAPTURE:
+ case IRSHIFT:
+ case IREXIT1:
+ case IRPAUSE:
+ case IREXIT2:
+ case IRUPDATE:
+ start_code = 2;
+ start_state = IRPAUSE;
+ break;
+
+ default:
+ status = JBIC_INTERNAL_ERROR;
+ break;
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ if (jbi_jtag_state != start_state)
+ {
+ status = jbi_goto_jtag_state(start_state);
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ if (jbi_workspace != NULL)
+ {
+ if (shift_count > JBIC_MAX_JTAG_IR_LENGTH)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ }
+ else if (shift_count > jbi_ir_length)
+ {
+ alloc_chars = (shift_count + 7) >> 3;
+ jbi_free(jbi_ir_buffer);
+ jbi_ir_buffer = (unsigned char *) jbi_malloc(alloc_chars);
+
+ if (jbi_ir_buffer == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ jbi_ir_length = alloc_chars * 8;
+ }
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ /*
+ * Copy preamble data, IR data, and postamble data into a buffer
+ */
+ jbi_jtag_concatenate_data
+ (
+ jbi_ir_buffer,
+ jbi_ir_preamble_data,
+ jbi_ir_preamble,
+ tdi_data,
+ start_index,
+ count,
+ jbi_ir_postamble_data,
+ jbi_ir_postamble
+ );
+
+ /*
+ * Do the IRSCAN
+ */
+ jbi_jtag_irscan
+ (
+ start_code,
+ shift_count,
+ jbi_ir_buffer,
+ NULL
+ );
+
+ /* jbi_jtag_irscan() always ends in IRPAUSE state */
+ jbi_jtag_state = IRPAUSE;
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ if (jbi_irstop_state != IRPAUSE)
+ {
+ status = jbi_goto_jtag_state(jbi_irstop_state);
+ }
+ }
+
+ return (status);
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_swap_ir
+(
+ unsigned int count,
+ unsigned char *in_data,
+ unsigned int in_index,
+ unsigned char *out_data,
+ unsigned int out_index
+)
+
+/* */
+/* Description: Shifts data into instruction register, capturing output */
+/* data */
+/* */
+/* Returns: JBIC_SUCCESS for success, else appropriate error code */
+/* */
+/****************************************************************************/
+{
+ int start_code = 0;
+ unsigned int alloc_chars = 0;
+ unsigned int shift_count = jbi_ir_preamble + count + jbi_ir_postamble;
+ JBI_RETURN_TYPE status = JBIC_SUCCESS;
+ JBIE_JTAG_STATE start_state = JBI_ILLEGAL_JTAG_STATE;
+
+ switch (jbi_jtag_state)
+ {
+ case JBI_ILLEGAL_JTAG_STATE:
+ case RESET:
+ case IDLE:
+ start_code = 0;
+ start_state = IDLE;
+ break;
+
+ case DRSELECT:
+ case DRCAPTURE:
+ case DRSHIFT:
+ case DREXIT1:
+ case DRPAUSE:
+ case DREXIT2:
+ case DRUPDATE:
+ start_code = 1;
+ start_state = DRPAUSE;
+ break;
+
+ case IRSELECT:
+ case IRCAPTURE:
+ case IRSHIFT:
+ case IREXIT1:
+ case IRPAUSE:
+ case IREXIT2:
+ case IRUPDATE:
+ start_code = 2;
+ start_state = IRPAUSE;
+ break;
+
+ default:
+ status = JBIC_INTERNAL_ERROR;
+ break;
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ if (jbi_jtag_state != start_state)
+ {
+ status = jbi_goto_jtag_state(start_state);
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ if (jbi_workspace != NULL)
+ {
+ if (shift_count > JBIC_MAX_JTAG_IR_LENGTH)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ }
+ else if (shift_count > jbi_ir_length)
+ {
+ alloc_chars = (shift_count + 7) >> 3;
+ jbi_free(jbi_ir_buffer);
+ jbi_ir_buffer = (unsigned char *) jbi_malloc(alloc_chars);
+
+ if (jbi_ir_buffer == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ jbi_ir_length = alloc_chars * 8;
+ }
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ /*
+ * Copy preamble data, IR data, and postamble data into a buffer
+ */
+ jbi_jtag_concatenate_data
+ (
+ jbi_ir_buffer,
+ jbi_ir_preamble_data,
+ jbi_ir_preamble,
+ in_data,
+ in_index,
+ count,
+ jbi_ir_postamble_data,
+ jbi_ir_postamble
+ );
+
+ /*
+ * Do the IRSCAN
+ */
+ jbi_jtag_irscan
+ (
+ start_code,
+ shift_count,
+ jbi_ir_buffer,
+ jbi_ir_buffer
+ );
+
+ /* jbi_jtag_irscan() always ends in IRPAUSE state */
+ jbi_jtag_state = IRPAUSE;
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ if (jbi_irstop_state != IRPAUSE)
+ {
+ status = jbi_goto_jtag_state(jbi_irstop_state);
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ /*
+ * Now extract the returned data from the buffer
+ */
+ jbi_jtag_extract_target_data
+ (
+ jbi_ir_buffer,
+ out_data,
+ out_index,
+ jbi_ir_preamble,
+ count
+ );
+ }
+
+ return (status);
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_do_drscan
+(
+ unsigned int count,
+ unsigned char *tdi_data,
+ unsigned long start_index
+)
+
+/* */
+/* Description: Shifts data into data register (ignoring output data) */
+/* */
+/* Returns: JBIC_SUCCESS for success, else appropriate error code */
+/* */
+/****************************************************************************/
+{
+ int start_code = 0;
+ unsigned int alloc_chars = 0;
+ unsigned int shift_count = jbi_dr_preamble + count + jbi_dr_postamble;
+ JBI_RETURN_TYPE status = JBIC_SUCCESS;
+ JBIE_JTAG_STATE start_state = JBI_ILLEGAL_JTAG_STATE;
+
+ switch (jbi_jtag_state)
+ {
+ case JBI_ILLEGAL_JTAG_STATE:
+ case RESET:
+ case IDLE:
+ start_code = 0;
+ start_state = IDLE;
+ break;
+
+ case DRSELECT:
+ case DRCAPTURE:
+ case DRSHIFT:
+ case DREXIT1:
+ case DRPAUSE:
+ case DREXIT2:
+ case DRUPDATE:
+ start_code = 1;
+ start_state = DRPAUSE;
+ break;
+
+ case IRSELECT:
+ case IRCAPTURE:
+ case IRSHIFT:
+ case IREXIT1:
+ case IRPAUSE:
+ case IREXIT2:
+ case IRUPDATE:
+ start_code = 2;
+ start_state = IRPAUSE;
+ break;
+
+ default:
+ status = JBIC_INTERNAL_ERROR;
+ break;
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ if (jbi_jtag_state != start_state)
+ {
+ status = jbi_goto_jtag_state(start_state);
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ if (jbi_workspace != NULL)
+ {
+ if (shift_count > JBIC_MAX_JTAG_DR_LENGTH)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ }
+ else if (shift_count > jbi_dr_length)
+ {
+ alloc_chars = (shift_count + 7) >> 3;
+ jbi_free(jbi_dr_buffer);
+ jbi_dr_buffer = (unsigned char *) jbi_malloc(alloc_chars);
+
+ if (jbi_dr_buffer == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ jbi_dr_length = alloc_chars * 8;
+ }
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ /*
+ * Copy preamble data, DR data, and postamble data into a buffer
+ */
+ jbi_jtag_concatenate_data
+ (
+ jbi_dr_buffer,
+ jbi_dr_preamble_data,
+ jbi_dr_preamble,
+ tdi_data,
+ start_index,
+ count,
+ jbi_dr_postamble_data,
+ jbi_dr_postamble
+ );
+
+ /*
+ * Do the DRSCAN
+ */
+ jbi_jtag_drscan
+ (
+ start_code,
+ shift_count,
+ jbi_dr_buffer,
+ NULL
+ );
+
+ /* jbi_jtag_drscan() always ends in DRPAUSE state */
+ jbi_jtag_state = DRPAUSE;
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ if (jbi_drstop_state != DRPAUSE)
+ {
+ status = jbi_goto_jtag_state(jbi_drstop_state);
+ }
+ }
+
+ return (status);
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_swap_dr
+(
+ unsigned int count,
+ unsigned char *in_data,
+ unsigned long in_index,
+ unsigned char *out_data,
+ unsigned int out_index
+)
+
+/* */
+/* Description: Shifts data into data register, capturing output data */
+/* */
+/* Returns: JBIC_SUCCESS for success, else appropriate error code */
+/* */
+/****************************************************************************/
+{
+ int start_code = 0;
+ unsigned int alloc_chars = 0;
+ unsigned int shift_count = jbi_dr_preamble + count + jbi_dr_postamble;
+ JBI_RETURN_TYPE status = JBIC_SUCCESS;
+ JBIE_JTAG_STATE start_state = JBI_ILLEGAL_JTAG_STATE;
+
+ switch (jbi_jtag_state)
+ {
+ case JBI_ILLEGAL_JTAG_STATE:
+ case RESET:
+ case IDLE:
+ start_code = 0;
+ start_state = IDLE;
+ break;
+
+ case DRSELECT:
+ case DRCAPTURE:
+ case DRSHIFT:
+ case DREXIT1:
+ case DRPAUSE:
+ case DREXIT2:
+ case DRUPDATE:
+ start_code = 1;
+ start_state = DRPAUSE;
+ break;
+
+ case IRSELECT:
+ case IRCAPTURE:
+ case IRSHIFT:
+ case IREXIT1:
+ case IRPAUSE:
+ case IREXIT2:
+ case IRUPDATE:
+ start_code = 2;
+ start_state = IRPAUSE;
+ break;
+
+ default:
+ status = JBIC_INTERNAL_ERROR;
+ break;
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ if (jbi_jtag_state != start_state)
+ {
+ status = jbi_goto_jtag_state(start_state);
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ if (jbi_workspace != NULL)
+ {
+ if (shift_count > JBIC_MAX_JTAG_DR_LENGTH)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ }
+ else if (shift_count > jbi_dr_length)
+ {
+ alloc_chars = (shift_count + 7) >> 3;
+ jbi_free(jbi_dr_buffer);
+ jbi_dr_buffer = (unsigned char *) jbi_malloc(alloc_chars);
+
+ if (jbi_dr_buffer == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ jbi_dr_length = alloc_chars * 8;
+ }
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ /*
+ * Copy preamble data, DR data, and postamble data into a buffer
+ */
+ jbi_jtag_concatenate_data
+ (
+ jbi_dr_buffer,
+ jbi_dr_preamble_data,
+ jbi_dr_preamble,
+ in_data,
+ in_index,
+ count,
+ jbi_dr_postamble_data,
+ jbi_dr_postamble
+ );
+
+ /*
+ * Do the DRSCAN
+ */
+ jbi_jtag_drscan
+ (
+ start_code,
+ shift_count,
+ jbi_dr_buffer,
+ jbi_dr_buffer
+ );
+
+ /* jbi_jtag_drscan() always ends in DRPAUSE state */
+ jbi_jtag_state = DRPAUSE;
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ if (jbi_drstop_state != DRPAUSE)
+ {
+ status = jbi_goto_jtag_state(jbi_drstop_state);
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ /*
+ * Now extract the returned data from the buffer
+ */
+ jbi_jtag_extract_target_data
+ (
+ jbi_dr_buffer,
+ out_data,
+ out_index,
+ jbi_dr_preamble,
+ count
+ );
+ }
+
+ return (status);
+}
+
+/****************************************************************************/
+/* */
+
+void jbi_free_jtag_padding_buffers(int reset_jtag)
+
+/* */
+/* Description: Frees memory allocated for JTAG IR and DR buffers */
+/* */
+/* Returns: nothing */
+/* */
+/****************************************************************************/
+{
+ /*
+ * If the JTAG interface was used, reset it to TLR
+ */
+ if (reset_jtag && (jbi_jtag_state != JBI_ILLEGAL_JTAG_STATE))
+ {
+ jbi_jtag_reset_idle();
+ }
+
+ if (jbi_workspace == NULL)
+ {
+ if (jbi_dr_preamble_data != NULL)
+ {
+ jbi_free(jbi_dr_preamble_data);
+ jbi_dr_preamble_data = NULL;
+ }
+
+ if (jbi_dr_postamble_data != NULL)
+ {
+ jbi_free(jbi_dr_postamble_data);
+ jbi_dr_postamble_data = NULL;
+ }
+
+ if (jbi_dr_buffer != NULL)
+ {
+ jbi_free(jbi_dr_buffer);
+ jbi_dr_buffer = NULL;
+ }
+
+ if (jbi_ir_preamble_data != NULL)
+ {
+ jbi_free(jbi_ir_preamble_data);
+ jbi_ir_preamble_data = NULL;
+ }
+
+ if (jbi_ir_postamble_data != NULL)
+ {
+ jbi_free(jbi_ir_postamble_data);
+ jbi_ir_postamble_data = NULL;
+ }
+
+ if (jbi_ir_buffer != NULL)
+ {
+ jbi_free(jbi_ir_buffer);
+ jbi_ir_buffer = NULL;
+ }
+ }
+}
+
+#if PORT==DOS
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_do_drscan_multi_page
+(
+ unsigned int variable_id,
+ unsigned long count,
+ unsigned long start_index,
+ int version
+)
+
+/* */
+/* Description: Shifts data into data register (ignoring output data) */
+/* Scan data comes from compressed Boolean array. */
+/* */
+/* Returns: JBIC_SUCCESS for success, else appropriate error code */
+/* */
+/****************************************************************************/
+{
+ JBI_RETURN_TYPE status = JBIC_SUCCESS;
+ unsigned long shift_count = jbi_dr_preamble + count + jbi_dr_postamble;
+ unsigned long i;
+ unsigned long j;
+ unsigned long k;
+ unsigned int bi;
+
+
+ if (status == JBIC_SUCCESS)
+ {
+ status = jbi_goto_jtag_state(DRSHIFT);
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ /*
+ * Get preamble data, DR data, and postamble data one bit at a time
+ * and immediately scan it into the JTAG chain
+ */
+
+ for (i = 0L; i < jbi_dr_preamble; ++i)
+ {
+ jbi_jtag_io((i == shift_count - 1),
+ (int) (jbi_dr_preamble_data[i >> 3L] & (1L << (i & 7L))), 0);
+ }
+
+ j = start_index;
+ k = jbi_dr_preamble + count;
+
+ jbi_uncompress_page(variable_id, (unsigned int) (j >> 16L), version);
+
+ for (; i < k; ++i, ++j)
+ {
+ bi = (unsigned int) (j & 0x0000ffffL);
+
+ /* check for page boundary - load next page if necessary */
+ if (bi == 0)
+ {
+ jbi_uncompress_page(variable_id, (unsigned int) (j >> 16L), version);
+ }
+
+ jbi_jtag_io((i == shift_count - 1),
+ (int) (jbi_aca_out_buffer[bi >> 3] & (1 << (bi & 7))), 0);
+ }
+
+ j = 0L;
+ k = jbi_dr_preamble + count + jbi_dr_postamble;
+ for (; i < k; ++i, ++j)
+ {
+ jbi_jtag_io((i == shift_count - 1),
+ (int) (jbi_dr_postamble_data[j >> 3L] & (1L << (j & 7L))), 0);
+ }
+
+ jbi_jtag_io(0, 0, 0); /* DRPAUSE */
+
+
+ /* jbi_jtag_drscan() always ends in DRPAUSE state */
+ jbi_jtag_state = DRPAUSE;
+
+ if (jbi_drstop_state != DRPAUSE)
+ {
+ status = jbi_goto_jtag_state(jbi_drstop_state);
+ }
+ }
+
+ return (status);
+}
+
+#endif
diff --git a/common/recipes-utils/jbi/files/code/jbijtag.h b/common/recipes-utils/jbi/files/code/jbijtag.h
new file mode 100644
index 0000000..27299f0
--- /dev/null
+++ b/common/recipes-utils/jbi/files/code/jbijtag.h
@@ -0,0 +1,147 @@
+/****************************************************************************/
+/* */
+/* Module: jbijtag.h */
+/* */
+/* Copyright (C) Altera Corporation 1998-2001 */
+/* */
+/* Description: Definitions of JTAG constants, types, and functions */
+/* */
+/****************************************************************************/
+
+#ifndef INC_JBIJTAG_H
+#define INC_JBIJTAG_H
+
+/****************************************************************************/
+/* */
+/* Function Prototypes */
+/* */
+/****************************************************************************/
+typedef enum
+{
+ JBI_ILLEGAL_JTAG_STATE = -1,
+ RESET = 0,
+ IDLE = 1,
+ DRSELECT = 2,
+ DRCAPTURE = 3,
+ DRSHIFT = 4,
+ DREXIT1 = 5,
+ DRPAUSE = 6,
+ DREXIT2 = 7,
+ DRUPDATE = 8,
+ IRSELECT = 9,
+ IRCAPTURE = 10,
+ IRSHIFT = 11,
+ IREXIT1 = 12,
+ IRPAUSE = 13,
+ IREXIT2 = 14,
+ IRUPDATE = 15
+
+} JBIE_JTAG_STATE;
+
+
+JBI_RETURN_TYPE jbi_init_jtag
+(
+ void
+);
+
+JBI_RETURN_TYPE jbi_set_drstop_state
+(
+ JBIE_JTAG_STATE state
+);
+
+JBI_RETURN_TYPE jbi_set_irstop_state
+(
+ JBIE_JTAG_STATE state
+);
+
+JBI_RETURN_TYPE jbi_set_dr_preamble
+(
+ unsigned int count,
+ unsigned int start_index,
+ unsigned char *preamble_data
+);
+
+JBI_RETURN_TYPE jbi_set_ir_preamble
+(
+ unsigned int count,
+ unsigned int start_index,
+ unsigned char *preamble_data
+);
+
+JBI_RETURN_TYPE jbi_set_dr_postamble
+(
+ unsigned int count,
+ unsigned int start_index,
+ unsigned char *postamble_data
+);
+
+JBI_RETURN_TYPE jbi_set_ir_postamble
+(
+ unsigned int count,
+ unsigned int start_index,
+ unsigned char *postamble_data
+);
+
+JBI_RETURN_TYPE jbi_goto_jtag_state
+(
+ JBIE_JTAG_STATE state
+);
+
+JBI_RETURN_TYPE jbi_do_wait_cycles
+(
+ long cycles,
+ JBIE_JTAG_STATE wait_state
+);
+
+JBI_RETURN_TYPE jbi_do_wait_microseconds
+(
+ long microseconds,
+ JBIE_JTAG_STATE wait_state
+);
+
+JBI_RETURN_TYPE jbi_do_irscan
+(
+ unsigned int count,
+ unsigned char *tdi_data,
+ unsigned int start_index
+);
+
+JBI_RETURN_TYPE jbi_swap_ir
+(
+ unsigned int count,
+ unsigned char *in_data,
+ unsigned int in_index,
+ unsigned char *out_data,
+ unsigned int out_index
+);
+
+JBI_RETURN_TYPE jbi_do_drscan
+(
+ unsigned int count,
+ unsigned char *tdi_data,
+ unsigned long start_index
+);
+
+JBI_RETURN_TYPE jbi_swap_dr
+(
+ unsigned int count,
+ unsigned char *in_data,
+ unsigned long in_index,
+ unsigned char *out_data,
+ unsigned int out_index
+);
+
+void jbi_free_jtag_padding_buffers
+(
+ int reset_jtag
+);
+
+JBI_RETURN_TYPE jbi_do_drscan_multi_page
+(
+ unsigned int variable_id,
+ unsigned long long_count,
+ unsigned long long_index,
+ int version
+);
+
+#endif /* INC_JBIJTAG_H */
diff --git a/common/recipes-utils/jbi/files/code/jbimain.c b/common/recipes-utils/jbi/files/code/jbimain.c
new file mode 100644
index 0000000..79bdf69
--- /dev/null
+++ b/common/recipes-utils/jbi/files/code/jbimain.c
@@ -0,0 +1,3290 @@
+/****************************************************************************/
+/* */
+/* Module: jbimain.c */
+/* */
+/* Copyright (C) Altera Corporation 1998-2001 */
+/* */
+/* Description: Jam STAPL ByteCode Player (Interpreter) */
+/* */
+/* Revisions: 2.2 fixed /W4 warnings */
+/* 2.0 added support for STAPL ByteCode format */
+/* */
+/****************************************************************************/
+
+#include "jbiport.h"
+#include "jbiexprt.h"
+#include "jbijtag.h"
+#include "jbicomp.h"
+
+/****************************************************************************/
+/* */
+/* MACROS */
+/* */
+/****************************************************************************/
+
+#define NULL 0
+
+#define JBI_STACK_SIZE 128
+
+#define JBIC_MESSAGE_LENGTH 1024
+
+/*
+* This macro checks if enough parameters are available on the stack. The
+* argument is the number of parameters needed.
+*/
+#define IF_CHECK_STACK(x) \
+ if (stack_ptr < (int) (x)) \
+ { \
+ status = JBIC_STACK_OVERFLOW; \
+ } \
+ else
+
+/*
+* This macro checks if a code address is inside the code section
+*/
+#define CHECK_PC \
+ if ((pc < code_section) || (pc >= debug_section)) \
+ { \
+ status = JBIC_BOUNDS_ERROR; \
+ }
+
+/****************************************************************************/
+/* */
+/* GLOBAL VARIABLES */
+/* */
+/****************************************************************************/
+
+#if PORT==DOS
+/*
+* jbi_program is a global pointer used by macros GET_BYTE, GET_WORD, and
+* GET_DWORD to read data from the JBC file
+*/
+PROGRAM_PTR jbi_program;
+#endif
+
+/****************************************************************************/
+/* */
+/* UTILITY FUNCTIONS */
+/* */
+/****************************************************************************/
+
+int jbi_strlen(char *string)
+{
+ int len = 0;
+
+ while (string[len] != '\0') ++len;
+
+ return (len);
+}
+
+long jbi_atol(char *buffer)
+{
+ long result = 0L;
+ int index = 0;
+
+ while ((buffer[index] >= '0') && (buffer[index] <= '9'))
+ {
+ result = (result * 10) + (buffer[index] - '0');
+ ++index;
+ }
+
+ return (result);
+}
+
+void jbi_ltoa(char *buffer, long number)
+{
+ int index = 0;
+ int rev_index = 0;
+ char reverse[32];
+
+ if (number < 0L)
+ {
+ buffer[index++] = '-';
+ number = 0 - number;
+ }
+ else if (number == 0)
+ {
+ buffer[index++] = '0';
+ }
+
+ while (number != 0)
+ {
+ reverse[rev_index++] = (char) ((number % 10) + '0');
+ number /= 10;
+ }
+
+ while (rev_index > 0)
+ {
+ buffer[index++] = reverse[--rev_index];
+ }
+
+ buffer[index] = '\0';
+}
+
+char jbi_toupper(char ch)
+{
+ return ((char) (((ch >= 'a') && (ch <= 'z')) ? (ch + 'A' - 'a') : ch));
+}
+
+int jbi_stricmp(char *left, char *right)
+{
+ int result = 0;
+ char l, r;
+
+ do
+ {
+ l = jbi_toupper(*left);
+ r = jbi_toupper(*right);
+ result = l - r;
+ ++left;
+ ++right;
+ }
+ while ((result == 0) && (l != '\0') && (r != '\0'));
+
+ return (result);
+}
+
+void jbi_strncpy(char *left, char *right, int count)
+{
+ char ch;
+
+ do
+ {
+ *left = *right;
+ ch = *right;
+ ++left;
+ ++right;
+ --count;
+ }
+ while ((ch != '\0') && (count != 0));
+}
+
+void jbi_make_dword(unsigned char *buf, unsigned long num)
+{
+ buf[0] = (unsigned char) num;
+ buf[1] = (unsigned char) (num >> 8L);
+ buf[2] = (unsigned char) (num >> 16L);
+ buf[3] = (unsigned char) (num >> 24L);
+}
+
+unsigned long jbi_get_dword(unsigned char *buf)
+{
+ return
+ (((unsigned long) buf[0]) |
+ (((unsigned long) buf[1]) << 8L) |
+ (((unsigned long) buf[2]) << 16L) |
+ (((unsigned long) buf[3]) << 24L));
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_execute
+(
+ PROGRAM_PTR program,
+ long program_size,
+ char *workspace,
+ long workspace_size,
+ char *action,
+ char **init_list,
+ int reset_jtag,
+ long *error_address,
+ int *exit_code,
+ int *format_version
+)
+
+/* */
+/* Description: */
+/* */
+/* Returns: */
+/* */
+/****************************************************************************/
+{
+ JBI_RETURN_TYPE status = JBIC_SUCCESS;
+ unsigned long first_word = 0L;
+ unsigned long action_table = 0L;
+ unsigned long proc_table = 0L;
+ unsigned long string_table = 0L;
+ unsigned long symbol_table = 0L;
+ unsigned long data_section = 0L;
+ unsigned long code_section = 0L;
+ unsigned long debug_section = 0L;
+ unsigned long action_count = 0L;
+ unsigned long proc_count = 0L;
+ unsigned long symbol_count = 0L;
+ char message_buffer[JBIC_MESSAGE_LENGTH + 1];
+ long *variables = NULL;
+ long *variable_size = NULL;
+ char *attributes = NULL;
+ unsigned char *proc_attributes = NULL;
+ unsigned long pc;
+ unsigned long opcode_address;
+ unsigned long args[3];
+ unsigned int opcode;
+ unsigned long name_id;
+ long stack[JBI_STACK_SIZE] = {0};
+ unsigned char charbuf[4];
+ long long_temp;
+ unsigned int variable_id;
+ unsigned char *charptr_temp;
+ unsigned char *charptr_temp2;
+ long *longptr_temp;
+ int version = 0;
+ int delta = 0;
+ int stack_ptr = 0;
+ unsigned int arg_count;
+ int done = 0;
+ int bad_opcode = 0;
+ unsigned int count;
+ unsigned int index;
+ unsigned int index2;
+ long long_count;
+ long long_index;
+ long long_index2;
+ unsigned int i;
+ unsigned int j;
+ unsigned long uncompressed_size;
+ unsigned int offset;
+ unsigned long value;
+ int current_proc = 0;
+ char *equal_ptr;
+ int length;
+ int reverse;
+
+#if PORT==DOS
+ char name[33];
+#else
+ char *name;
+#endif
+
+ jbi_workspace = workspace;
+ jbi_workspace_size = workspace_size;
+
+#if PORT==DOS
+ jbi_program = program;
+#endif
+
+ /*
+ * Read header information
+ */
+ if (program_size > 52L)
+ {
+ first_word = GET_DWORD(0);
+ version = (int) (first_word & 1L);
+ *format_version = version + 1;
+ delta = version * 8;
+
+ action_table = GET_DWORD(4);
+ proc_table = GET_DWORD(8);
+ string_table = GET_DWORD(4 + delta);
+ symbol_table = GET_DWORD(16 + delta);
+ data_section = GET_DWORD(20 + delta);
+ code_section = GET_DWORD(24 + delta);
+ debug_section = GET_DWORD(28 + delta);
+ action_count = GET_DWORD(40 + delta);
+ proc_count = GET_DWORD(44 + delta);
+ symbol_count = GET_DWORD(48 + (2 * delta));
+ }
+
+ if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L))
+ {
+ done = 1;
+ status = JBIC_IO_ERROR;
+ }
+
+ if ((status == JBIC_SUCCESS) && (symbol_count > 0))
+ {
+ variables = (long *) jbi_malloc(
+ (unsigned int) symbol_count * sizeof(long));
+
+ if (variables == NULL) status = JBIC_OUT_OF_MEMORY;
+
+ if (status == JBIC_SUCCESS)
+ {
+ variable_size = (long *) jbi_malloc(
+ (unsigned int) symbol_count * sizeof(long));
+
+ if (variable_size == NULL) status = JBIC_OUT_OF_MEMORY;
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ attributes = (char *) jbi_malloc((unsigned int) symbol_count);
+
+ if (attributes == NULL) status = JBIC_OUT_OF_MEMORY;
+ }
+
+ if ((status == JBIC_SUCCESS) && (version > 0))
+ {
+ proc_attributes = (unsigned char *) jbi_malloc((unsigned int) proc_count);
+
+ if (proc_attributes == NULL) status = JBIC_OUT_OF_MEMORY;
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ delta = version * 2;
+
+ for (i = 0; i < (unsigned int) symbol_count; ++i)
+ {
+ offset = (unsigned int) (symbol_table + ((11 + delta) * i));
+
+ value = GET_DWORD(offset + 3 + delta);
+
+ attributes[i] = GET_BYTE(offset);
+
+ /* use bit 7 of attribute byte to indicate that this buffer */
+ /* was dynamically allocated and should be freed later */
+ attributes[i] &= 0x7f;
+
+ variable_size[i] = GET_DWORD(offset + 7 + delta);
+
+ /*
+ * Attribute bits:
+ * bit 0: 0 = read-only, 1 = read-write
+ * bit 1: 0 = not compressed, 1 = compressed
+ * bit 2: 0 = not initialized, 1 = initialized
+ * bit 3: 0 = scalar, 1 = array
+ * bit 4: 0 = Boolean, 1 = integer
+ * bit 5: 0 = declared variable,
+ * 1 = compiler created temporary variable
+ */
+
+ if ((attributes[i] & 0x0c) == 0x04)
+ {
+ /* initialized scalar variable */
+ variables[i] = value;
+ }
+ else if ((attributes[i] & 0x1e) == 0x0e)
+ {
+ /* initialized compressed Boolean array */
+#if PORT==DOS
+ /* for DOS port, get the size but do not uncompress */
+ long_index = data_section + value;
+ uncompressed_size =
+ (((unsigned long) GET_BYTE(long_index)) |
+ (((unsigned long) GET_BYTE(long_index + 1L)) << 8L) |
+ (((unsigned long) GET_BYTE(long_index + 2L)) << 16L) |
+ (((unsigned long) GET_BYTE(long_index + 3L)) << 24L));
+ variable_size[i] = uncompressed_size;
+#else
+ uncompressed_size = jbi_get_dword(
+ &program[data_section + value]);
+
+ /* allocate a buffer for the uncompressed data */
+ variables[i] = (long) jbi_malloc(uncompressed_size);
+
+ if (variables[i] == 0L)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ /* set flag so buffer will be freed later */
+ attributes[i] |= 0x80;
+
+ /* uncompress the data */
+ if (jbi_uncompress(
+ &program[data_section + value],
+ variable_size[i],
+ (unsigned char *) variables[i],
+ uncompressed_size,
+ version)
+ != uncompressed_size)
+ {
+ /* decompression failed */
+ status = JBIC_IO_ERROR;
+ }
+ else
+ {
+ variable_size[i] = uncompressed_size * 8L;
+ }
+ }
+#endif
+ }
+ else if ((attributes[i] & 0x1e) == 0x0c)
+ {
+ /* initialized Boolean array */
+#if PORT==DOS
+ /* flag attributes so that memory is freed */
+ attributes[i] |= 0x80;
+
+ if (variable_size[i] > 0)
+ {
+ unsigned int size = (unsigned int)
+ ((variable_size[i] + 7L) / 8L);
+
+ variables[i] = (long) jbi_malloc(size);
+
+ if (variables[i] == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ unsigned char *p = (unsigned char *) variables[i];
+ /* copy array values into buffer */
+ for (j = 0; j < size; ++j)
+ {
+ p[j] = GET_BYTE(data_section + value + j);
+ }
+ }
+ }
+ else
+ {
+ variables[i] = 0;
+ }
+#else
+ variables[i] = value + data_section + (long) program;
+#endif
+ }
+ else if ((attributes[i] & 0x1c) == 0x1c)
+ {
+ /* initialized integer array */
+ variables[i] = value + data_section;
+ }
+ else if ((attributes[i] & 0x0c) == 0x08)
+ {
+ /* uninitialized array */
+
+ /* flag attributes so that memory is freed */
+ attributes[i] |= 0x80;
+
+ if (variable_size[i] > 0)
+ {
+ unsigned int size;
+
+ if (attributes[i] & 0x10)
+ {
+ /* integer array */
+ size = (unsigned int)
+ (variable_size[i] * sizeof(long));
+ }
+ else
+ {
+ /* Boolean array */
+ size = (unsigned int)
+ ((variable_size[i] + 7L) / 8L);
+ }
+
+ variables[i] = (long) jbi_malloc(size);
+
+ if (variables[i] == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ /* zero out memory */
+ for (j = 0; j < size; ++j)
+ {
+ ((unsigned char *)(variables[i]))[j] = 0;
+ }
+ }
+ }
+ else
+ {
+ variables[i] = 0;
+ }
+ }
+ else
+ {
+ variables[i] = 0;
+ }
+ }
+ }
+ }
+
+ /*
+ * Initialize variables listed in init_list
+ */
+ if ((status == JBIC_SUCCESS) && (init_list != NULL) && (version == 0))
+ {
+ delta = version * 2;
+ count = 0;
+ while (init_list[count] != NULL)
+ {
+ equal_ptr = init_list[count];
+ length = 0;
+ while ((*equal_ptr != '=') && (*equal_ptr != '\0'))
+ {
+ ++equal_ptr;
+ ++length;
+ }
+ if (*equal_ptr == '=')
+ {
+ ++equal_ptr;
+ value = jbi_atol(equal_ptr);
+ jbi_strncpy(message_buffer, init_list[count], length);
+ message_buffer[length] = '\0';
+ for (i = 0; i < (unsigned int) symbol_count; ++i)
+ {
+ offset = (unsigned int) (symbol_table + ((11 + delta) * i));
+ name_id = (version == 0) ? GET_WORD(offset + 1) :
+ GET_DWORD(offset + 1);
+#if PORT==DOS
+ for (j = 0; j < 32; ++j)
+ {
+ name[j] = GET_BYTE(string_table + name_id + j);
+ }
+ name[32] = '\0';
+#else
+ name = (char *) &program[string_table + name_id];
+#endif
+
+ if (jbi_stricmp(message_buffer, name) == 0)
+ {
+ variables[i] = value;
+ }
+ }
+ }
+
+ ++count;
+ }
+ }
+
+ if (status != JBIC_SUCCESS) done = 1;
+
+ jbi_init_jtag();
+
+ pc = code_section;
+ message_buffer[0] = '\0';
+
+ /*
+ * For JBC version 2, we will execute the procedures corresponding to
+ * the selected ACTION
+ */
+ if (version > 0)
+ {
+ if (action == NULL)
+ {
+ status = JBIC_ACTION_NOT_FOUND;
+ done = 1;
+ }
+ else
+ {
+ int action_found = 0;
+
+ for (i = 0; (i < action_count) && !action_found; ++i)
+ {
+ name_id = GET_DWORD(action_table + (12 * i));
+
+#if PORT==DOS
+ for (j = 0; j < 32; ++j)
+ {
+ name[j] = GET_BYTE(string_table + name_id + j);
+ }
+ name[32] = '\0';
+#else
+ name = (char *) &program[string_table + name_id];
+#endif
+
+ if (jbi_stricmp(action, name) == 0)
+ {
+ action_found = 1;
+ current_proc = (int) GET_DWORD(action_table + (12 * i) + 8);
+ }
+ }
+
+ if (!action_found)
+ {
+ status = JBIC_ACTION_NOT_FOUND;
+ done = 1;
+ }
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ int first_time = 1;
+ i = current_proc;
+ while ((i != 0) || first_time)
+ {
+ first_time = 0;
+ /* check procedure attribute byte */
+ proc_attributes[i] = (unsigned char)
+ (GET_BYTE(proc_table + (13 * i) + 8) & 0x03);
+
+ if (proc_attributes[i] != 0)
+ {
+ /*
+ * BIT0 - OPTIONAL
+ * BIT1 - RECOMMENDED
+ * BIT6 - FORCED OFF
+ * BIT7 - FORCED ON
+ */
+ if (init_list != NULL)
+ {
+ name_id = GET_DWORD(proc_table + (13 * i));
+#if PORT==DOS
+ for (j = 0; j < 32; ++j)
+ {
+ name[j] = GET_BYTE(string_table + name_id + j);
+ }
+ name[32] = '\0';
+#else
+ name = (char *) &program[string_table + name_id];
+#endif
+ count = 0;
+ while (init_list[count] != NULL)
+ {
+ equal_ptr = init_list[count];
+ length = 0;
+ while ((*equal_ptr != '=') && (*equal_ptr != '\0'))
+ {
+ ++equal_ptr;
+ ++length;
+ }
+ if (*equal_ptr == '=')
+ {
+ ++equal_ptr;
+ jbi_strncpy(message_buffer, init_list[count], length);
+ message_buffer[length] = '\0';
+
+ if (jbi_stricmp(message_buffer, name) == 0)
+ {
+ if (jbi_atol(equal_ptr) == 0)
+ {
+ proc_attributes[i] |= 0x40;
+ }
+ else
+ {
+ proc_attributes[i] |= 0x80;
+ }
+ }
+ }
+
+ ++count;
+ }
+ }
+ }
+
+ i = (unsigned int) GET_DWORD(proc_table + (13 * i) + 4);
+ }
+
+ /*
+ * Set current_proc to the first procedure to be executed
+ */
+ i = current_proc;
+ while ((i != 0) &&
+ ((proc_attributes[i] == 1) ||
+ ((proc_attributes[i] & 0xc0) == 0x40)))
+ {
+ i = (unsigned int) GET_DWORD(proc_table + (13 * i) + 4);
+ }
+
+ if ((i != 0) || ((i == 0) && (current_proc == 0) &&
+ ((proc_attributes[0] != 1) &&
+ ((proc_attributes[0] & 0xc0) != 0x40))))
+ {
+ current_proc = i;
+ pc = code_section + GET_DWORD(proc_table + (13 * i) + 9);
+ CHECK_PC;
+ }
+ else
+ {
+ /* there are no procedures to execute! */
+ done = 1;
+ }
+ }
+ }
+
+ message_buffer[0] = '\0';
+
+ while (!done)
+ {
+ opcode = (unsigned int) (GET_BYTE(pc) & 0xff);
+ opcode_address = pc;
+ ++pc;
+
+ arg_count = (opcode >> 6) & 3;
+ for (i = 0; i < arg_count; ++i)
+ {
+ args[i] = GET_DWORD(pc);
+ pc += 4;
+ }
+
+ switch (opcode)
+ {
+ case 0x00: /* NOP */
+ /* do nothing */
+ break;
+
+ case 0x01: /* DUP */
+ IF_CHECK_STACK(1)
+ {
+ stack[stack_ptr] = stack[stack_ptr - 1];
+ ++stack_ptr;
+ }
+ break;
+
+ case 0x02: /* SWP */
+ IF_CHECK_STACK(2)
+ {
+ long_temp = stack[stack_ptr - 2];
+ stack[stack_ptr - 2] = stack[stack_ptr - 1];
+ stack[stack_ptr - 1] = long_temp;
+ }
+ break;
+
+ case 0x03: /* ADD */
+ IF_CHECK_STACK(2)
+ {
+ --stack_ptr;
+ stack[stack_ptr - 1] += stack[stack_ptr];
+ }
+ break;
+
+ case 0x04: /* SUB */
+ IF_CHECK_STACK(2)
+ {
+ --stack_ptr;
+ stack[stack_ptr - 1] -= stack[stack_ptr];
+ }
+ break;
+
+ case 0x05: /* MULT */
+ IF_CHECK_STACK(2)
+ {
+ --stack_ptr;
+ stack[stack_ptr - 1] *= stack[stack_ptr];
+ }
+ break;
+
+ case 0x06: /* DIV */
+ IF_CHECK_STACK(2)
+ {
+ --stack_ptr;
+ stack[stack_ptr - 1] /= stack[stack_ptr];
+ }
+ break;
+
+ case 0x07: /* MOD */
+ IF_CHECK_STACK(2)
+ {
+ --stack_ptr;
+ stack[stack_ptr - 1] %= stack[stack_ptr];
+ }
+ break;
+
+ case 0x08: /* SHL */
+ IF_CHECK_STACK(2)
+ {
+ --stack_ptr;
+ stack[stack_ptr - 1] <<= stack[stack_ptr];
+ }
+ break;
+
+ case 0x09: /* SHR */
+ IF_CHECK_STACK(2)
+ {
+ --stack_ptr;
+ stack[stack_ptr - 1] >>= stack[stack_ptr];
+ }
+ break;
+
+ case 0x0A: /* NOT */
+ IF_CHECK_STACK(1)
+ {
+ stack[stack_ptr - 1] ^= (-1L);
+ }
+ break;
+
+ case 0x0B: /* AND */
+ IF_CHECK_STACK(2)
+ {
+ --stack_ptr;
+ stack[stack_ptr - 1] &= stack[stack_ptr];
+ }
+ break;
+
+ case 0x0C: /* OR */
+ IF_CHECK_STACK(2)
+ {
+ --stack_ptr;
+ stack[stack_ptr - 1] |= stack[stack_ptr];
+ }
+ break;
+
+ case 0x0D: /* XOR */
+ IF_CHECK_STACK(2)
+ {
+ --stack_ptr;
+ stack[stack_ptr - 1] ^= stack[stack_ptr];
+ }
+ break;
+
+ case 0x0E: /* INV */
+ IF_CHECK_STACK(1)
+ {
+ stack[stack_ptr - 1] = stack[stack_ptr - 1] ? 0L : 1L;
+ }
+ break;
+
+ case 0x0F: /* GT */
+ IF_CHECK_STACK(2)
+ {
+ --stack_ptr;
+ stack[stack_ptr - 1] =
+ (stack[stack_ptr - 1] > stack[stack_ptr]) ? 1L : 0L;
+ }
+ break;
+
+ case 0x10: /* LT */
+ IF_CHECK_STACK(2)
+ {
+ --stack_ptr;
+ stack[stack_ptr - 1] =
+ (stack[stack_ptr - 1] < stack[stack_ptr]) ? 1L : 0L;
+ }
+ break;
+
+ case 0x11: /* RET */
+ if ((version > 0) && (stack_ptr == 0))
+ {
+ /*
+ * We completed one of the main procedures of an ACTION.
+ * Find the next procedure to be executed and jump to it.
+ * If there are no more procedures, then EXIT.
+ */
+ i = (unsigned int) GET_DWORD(proc_table + (13 * current_proc) + 4);
+ while ((i != 0) &&
+ ((proc_attributes[i] == 1) ||
+ ((proc_attributes[i] & 0xc0) == 0x40)))
+ {
+ i = (unsigned int) GET_DWORD(proc_table + (13 * i) + 4);
+ }
+
+ if (i == 0)
+ {
+ /* there are no procedures to execute! */
+ done = 1;
+ *exit_code = 0; /* success */
+ }
+ else
+ {
+ current_proc = i;
+ pc = code_section + GET_DWORD(proc_table + (13 * i) + 9);
+ CHECK_PC;
+ }
+ }
+ else IF_CHECK_STACK(1)
+ {
+ pc = stack[--stack_ptr] + code_section;
+ CHECK_PC;
+ if (pc == code_section)
+ {
+ status = JBIC_BOUNDS_ERROR;
+ }
+ }
+ break;
+
+ case 0x12: /* CMPS */
+ /*
+ * Array short compare
+ * ...stack 0 is source 1 value
+ * ...stack 1 is source 2 value
+ * ...stack 2 is mask value
+ * ...stack 3 is count
+ */
+ IF_CHECK_STACK(4)
+ {
+ long a = stack[--stack_ptr];
+ long b = stack[--stack_ptr];
+ long_temp = stack[--stack_ptr];
+ count = (unsigned int) stack[stack_ptr - 1];
+
+ if ((count < 1) || (count > 32))
+ {
+ status = JBIC_BOUNDS_ERROR;
+ }
+ else
+ {
+ long_temp &= ((-1L) >> (32 - count));
+
+ stack[stack_ptr - 1] =
+ ((a & long_temp) == (b & long_temp)) ? 1L : 0L;
+ }
+ }
+ break;
+
+ case 0x13: /* PINT */
+ /*
+ * PRINT add integer
+ * ...stack 0 is integer value
+ */
+ IF_CHECK_STACK(1)
+ {
+ jbi_ltoa(&message_buffer[jbi_strlen(message_buffer)],
+ stack[--stack_ptr]);
+ }
+ break;
+
+ case 0x14: /* PRNT */
+ /*
+ * PRINT finish
+ */
+ jbi_message(message_buffer);
+ message_buffer[0] = '\0';
+ break;
+
+ case 0x15: /* DSS */
+ /*
+ * DRSCAN short
+ * ...stack 0 is scan data
+ * ...stack 1 is count
+ */
+ IF_CHECK_STACK(2)
+ {
+ long_temp = stack[--stack_ptr];
+ count = (unsigned int) stack[--stack_ptr];
+ jbi_make_dword(charbuf, long_temp);
+ status = jbi_do_drscan(count, charbuf, 0);
+ }
+ break;
+
+ case 0x16: /* DSSC */
+ /*
+ * DRSCAN short with capture
+ * ...stack 0 is scan data
+ * ...stack 1 is count
+ */
+ IF_CHECK_STACK(2)
+ {
+ long_temp = stack[--stack_ptr];
+ count = (unsigned int) stack[stack_ptr - 1];
+ jbi_make_dword(charbuf, long_temp);
+ status = jbi_swap_dr(count, charbuf, 0, charbuf, 0);
+ stack[stack_ptr - 1] = jbi_get_dword(charbuf);
+ }
+ break;
+
+ case 0x17: /* ISS */
+ /*
+ * IRSCAN short
+ * ...stack 0 is scan data
+ * ...stack 1 is count
+ */
+ IF_CHECK_STACK(2)
+ {
+ long_temp = stack[--stack_ptr];
+ count = (unsigned int) stack[--stack_ptr];
+ jbi_make_dword(charbuf, long_temp);
+ status = jbi_do_irscan(count, charbuf, 0);
+ }
+ break;
+
+ case 0x18: /* ISSC */
+ /*
+ * IRSCAN short with capture
+ * ...stack 0 is scan data
+ * ...stack 1 is count
+ */
+ IF_CHECK_STACK(2)
+ {
+ long_temp = stack[--stack_ptr];
+ count = (unsigned int) stack[stack_ptr - 1];
+ jbi_make_dword(charbuf, long_temp);
+ status = jbi_swap_ir(count, charbuf, 0, charbuf, 0);
+ stack[stack_ptr - 1] = jbi_get_dword(charbuf);
+ }
+ break;
+
+ case 0x19: /* VSS */
+ /*
+ * VECTOR short
+ * ...stack 0 is scan data
+ * ...stack 1 is count
+ */
+ bad_opcode = 1;
+ break;
+
+ case 0x1A: /* VSSC */
+ /*
+ * VECTOR short with capture
+ * ...stack 0 is scan data
+ * ...stack 1 is count
+ */
+ bad_opcode = 1;
+ break;
+
+ case 0x1B: /* VMPF */
+ /*
+ * VMAP finish
+ */
+ bad_opcode = 1;
+ break;
+
+ case 0x1C: /* DPR */
+ IF_CHECK_STACK(1)
+ {
+ count = (unsigned int) stack[--stack_ptr];
+ status = jbi_set_dr_preamble(count, 0, NULL);
+ }
+ break;
+
+ case 0x1D: /* DPRL */
+ /*
+ * DRPRE with literal data
+ * ...stack 0 is count
+ * ...stack 1 is literal data
+ */
+ IF_CHECK_STACK(2)
+ {
+ count = (unsigned int) stack[--stack_ptr];
+ long_temp = stack[--stack_ptr];
+ jbi_make_dword(charbuf, long_temp);
+ status = jbi_set_dr_preamble(count, 0, charbuf);
+ }
+ break;
+
+ case 0x1E: /* DPO */
+ /*
+ * DRPOST
+ * ...stack 0 is count
+ */
+ IF_CHECK_STACK(1)
+ {
+ count = (unsigned int) stack[--stack_ptr];
+ status = jbi_set_dr_postamble(count, 0, NULL);
+ }
+ break;
+
+ case 0x1F: /* DPOL */
+ /*
+ * DRPOST with literal data
+ * ...stack 0 is count
+ * ...stack 1 is literal data
+ */
+ IF_CHECK_STACK(2)
+ {
+ count = (unsigned int) stack[--stack_ptr];
+ long_temp = stack[--stack_ptr];
+ jbi_make_dword(charbuf, long_temp);
+ status = jbi_set_dr_postamble(count, 0, charbuf);
+ }
+ break;
+
+ case 0x20: /* IPR */
+ IF_CHECK_STACK(1)
+ {
+ count = (unsigned int) stack[--stack_ptr];
+ status = jbi_set_ir_preamble(count, 0, NULL);
+ }
+ break;
+
+ case 0x21: /* IPRL */
+ /*
+ * IRPRE with literal data
+ * ...stack 0 is count
+ * ...stack 1 is literal data
+ */
+ IF_CHECK_STACK(2)
+ {
+ count = (unsigned int) stack[--stack_ptr];
+ long_temp = stack[--stack_ptr];
+ jbi_make_dword(charbuf, long_temp);
+ status = jbi_set_ir_preamble(count, 0, charbuf);
+ }
+ break;
+
+ case 0x22: /* IPO */
+ /*
+ * IRPOST
+ * ...stack 0 is count
+ */
+ IF_CHECK_STACK(1)
+ {
+ count = (unsigned int) stack[--stack_ptr];
+ status = jbi_set_ir_postamble(count, 0, NULL);
+ }
+ break;
+
+ case 0x23: /* IPOL */
+ /*
+ * IRPOST with literal data
+ * ...stack 0 is count
+ * ...stack 1 is literal data
+ */
+ IF_CHECK_STACK(2)
+ {
+ count = (unsigned int) stack[--stack_ptr];
+ long_temp = stack[--stack_ptr];
+ jbi_make_dword(charbuf, long_temp);
+ status = jbi_set_ir_postamble(count, 0, charbuf);
+ }
+ break;
+
+ case 0x24: /* PCHR */
+ IF_CHECK_STACK(1)
+ {
+ unsigned char ch;
+ count = jbi_strlen(message_buffer);
+ ch = (char) stack[--stack_ptr];
+ if ((ch < 1) || (ch > 127))
+ {
+ /* character code out of range */
+ /* instead of flagging an error, force the value to 127 */
+ ch = 127;
+ }
+ message_buffer[count] = ch;
+ message_buffer[count + 1] = '\0';
+ }
+ break;
+
+ case 0x25: /* EXIT */
+ IF_CHECK_STACK(1)
+ {
+ *exit_code = (int) stack[--stack_ptr];
+ }
+ done = 1;
+ break;
+
+ case 0x26: /* EQU */
+ IF_CHECK_STACK(2)
+ {
+ --stack_ptr;
+ stack[stack_ptr - 1] =
+ (stack[stack_ptr - 1] == stack[stack_ptr]) ? 1L : 0L;
+ }
+ break;
+
+ case 0x27: /* POPT */
+ IF_CHECK_STACK(1)
+ {
+ --stack_ptr;
+ }
+ break;
+
+ case 0x28: /* TRST */
+ bad_opcode = 1;
+ break;
+
+ case 0x29: /* FRQ */
+ bad_opcode = 1;
+ break;
+
+ case 0x2A: /* FRQU */
+ bad_opcode = 1;
+ break;
+
+ case 0x2B: /* PD32 */
+ bad_opcode = 1;
+ break;
+
+ case 0x2C: /* ABS */
+ IF_CHECK_STACK(1)
+ {
+ if (stack[stack_ptr - 1] < 0)
+ {
+ stack[stack_ptr - 1] = 0 - stack[stack_ptr - 1];
+ }
+ }
+ break;
+
+ case 0x2D: /* BCH0 */
+ /*
+ * Batch operation 0
+ * SWP
+ * SWPN 7
+ * SWP
+ * SWPN 6
+ * DUPN 8
+ * SWPN 2
+ * SWP
+ * DUPN 6
+ * DUPN 6
+ */
+
+ /* SWP */
+ IF_CHECK_STACK(2)
+ {
+ long_temp = stack[stack_ptr - 2];
+ stack[stack_ptr - 2] = stack[stack_ptr - 1];
+ stack[stack_ptr - 1] = long_temp;
+ }
+
+ /* SWPN 7 */
+ index = 7 + 1;
+ IF_CHECK_STACK(index)
+ {
+ long_temp = stack[stack_ptr - index];
+ stack[stack_ptr - index] = stack[stack_ptr - 1];
+ stack[stack_ptr - 1] = long_temp;
+ }
+
+ /* SWP */
+ IF_CHECK_STACK(2)
+ {
+ long_temp = stack[stack_ptr - 2];
+ stack[stack_ptr - 2] = stack[stack_ptr - 1];
+ stack[stack_ptr - 1] = long_temp;
+ }
+
+ /* SWPN 6 */
+ index = 6 + 1;
+ IF_CHECK_STACK(index)
+ {
+ long_temp = stack[stack_ptr - index];
+ stack[stack_ptr - index] = stack[stack_ptr - 1];
+ stack[stack_ptr - 1] = long_temp;
+ }
+
+ /* DUPN 8 */
+ index = 8 + 1;
+ IF_CHECK_STACK(index)
+ {
+ stack[stack_ptr] = stack[stack_ptr - index];
+ ++stack_ptr;
+ }
+
+ /* SWPN 2 */
+ index = 2 + 1;
+ IF_CHECK_STACK(index)
+ {
+ long_temp = stack[stack_ptr - index];
+ stack[stack_ptr - index] = stack[stack_ptr - 1];
+ stack[stack_ptr - 1] = long_temp;
+ }
+
+ /* SWP */
+ IF_CHECK_STACK(2)
+ {
+ long_temp = stack[stack_ptr - 2];
+ stack[stack_ptr - 2] = stack[stack_ptr - 1];
+ stack[stack_ptr - 1] = long_temp;
+ }
+
+ /* DUPN 6 */
+ index = 6 + 1;
+ IF_CHECK_STACK(index)
+ {
+ stack[stack_ptr] = stack[stack_ptr - index];
+ ++stack_ptr;
+ }
+
+ /* DUPN 6 */
+ index = 6 + 1;
+ IF_CHECK_STACK(index)
+ {
+ stack[stack_ptr] = stack[stack_ptr - index];
+ ++stack_ptr;
+ }
+ break;
+
+ case 0x2E: /* BCH1 */
+ /*
+ * Batch operation 1
+ * SWPN 8
+ * SWP
+ * SWPN 9
+ * SWPN 3
+ * SWP
+ * SWPN 2
+ * SWP
+ * SWPN 7
+ * SWP
+ * SWPN 6
+ * DUPN 5
+ * DUPN 5
+ */
+ bad_opcode = 1;
+ break;
+
+ case 0x2F: /* PSH0 */
+ stack[stack_ptr++] = 0;
+ break;
+
+ case 0x40: /* PSHL */
+ stack[stack_ptr++] = (long) args[0];
+ break;
+
+ case 0x41: /* PSHV */
+ stack[stack_ptr++] = variables[args[0]];
+ break;
+
+ case 0x42: /* JMP */
+ pc = args[0] + code_section;
+ CHECK_PC;
+ break;
+
+ case 0x43: /* CALL */
+ stack[stack_ptr++] = pc;
+ pc = args[0] + code_section;
+ CHECK_PC;
+ break;
+
+ case 0x44: /* NEXT */
+ /*
+ * Process FOR / NEXT loop
+ * ...argument 0 is variable ID
+ * ...stack 0 is step value
+ * ...stack 1 is end value
+ * ...stack 2 is top address
+ */
+ IF_CHECK_STACK(3)
+ {
+ long step = stack[stack_ptr - 1];
+ long end = stack[stack_ptr - 2];
+ long top = stack[stack_ptr - 3];
+ long iterator = variables[args[0]];
+ int break_out = 0;
+
+ if (step < 0)
+ {
+ if (iterator <= end) break_out = 1;
+ }
+ else
+ {
+ if (iterator >= end) break_out = 1;
+ }
+
+ if (break_out)
+ {
+ stack_ptr -= 3;
+ }
+ else
+ {
+ variables[args[0]] = iterator + step;
+ pc = top + code_section;
+ CHECK_PC;
+ }
+ }
+ break;
+
+ case 0x45: /* PSTR */
+ /*
+ * PRINT add string
+ * ...argument 0 is string ID
+ */
+#if PORT==DOS
+ long_index = string_table + args[0];
+ index2 = jbi_strlen(message_buffer);
+
+ do
+ {
+ i = GET_BYTE(long_index);
+ message_buffer[index2] = (char) i;
+ ++long_index;
+ ++index2;
+ }
+ while ((i != '\0') && (index2 < JBIC_MESSAGE_LENGTH));
+#else
+ count = jbi_strlen(message_buffer);
+ jbi_strncpy(&message_buffer[count],
+ (char *) &program[string_table + args[0]],
+ JBIC_MESSAGE_LENGTH - count);
+#endif
+ message_buffer[JBIC_MESSAGE_LENGTH] = '\0';
+ break;
+
+ case 0x46: /* VMAP */
+ /*
+ * VMAP add signal name
+ * ...argument 0 is string ID
+ */
+ bad_opcode = 1;
+ break;
+
+ case 0x47: /* SINT */
+ /*
+ * STATE intermediate state
+ * ...argument 0 is state code
+ */
+ status = jbi_goto_jtag_state((int) args[0]);
+ break;
+
+ case 0x48: /* ST */
+ /*
+ * STATE final state
+ * ...argument 0 is state code
+ */
+ status = jbi_goto_jtag_state((int) args[0]);
+ break;
+
+ case 0x49: /* ISTP */
+ /*
+ * IRSTOP state
+ * ...argument 0 is state code
+ */
+ status = jbi_set_irstop_state((int) args[0]);
+ break;
+
+ case 0x4A: /* DSTP */
+ /*
+ * DRSTOP state
+ * ...argument 0 is state code
+ */
+ status = jbi_set_drstop_state((int) args[0]);
+ break;
+
+ case 0x4B: /* SWPN */
+ /*
+ * Exchange top with Nth stack value
+ * ...argument 0 is 0-based stack entry to swap with top element
+ */
+ index = ((int) args[0]) + 1;
+ IF_CHECK_STACK(index)
+ {
+ long_temp = stack[stack_ptr - index];
+ stack[stack_ptr - index] = stack[stack_ptr - 1];
+ stack[stack_ptr - 1] = long_temp;
+ }
+ break;
+
+ case 0x4C: /* DUPN */
+ /*
+ * Duplicate Nth stack value
+ * ...argument 0 is 0-based stack entry to duplicate
+ */
+ index = ((int) args[0]) + 1;
+ IF_CHECK_STACK(index)
+ {
+ stack[stack_ptr] = stack[stack_ptr - index];
+ ++stack_ptr;
+ }
+ break;
+
+ case 0x4D: /* POPV */
+ /*
+ * Pop stack into scalar variable
+ * ...argument 0 is variable ID
+ * ...stack 0 is value
+ */
+ IF_CHECK_STACK(1)
+ {
+ variables[args[0]] = stack[--stack_ptr];
+ }
+ break;
+
+ case 0x4E: /* POPE */
+ /*
+ * Pop stack into integer array element
+ * ...argument 0 is variable ID
+ * ...stack 0 is array index
+ * ...stack 1 is value
+ */
+ IF_CHECK_STACK(2)
+ {
+ variable_id = (unsigned int) args[0];
+
+ /*
+ * If variable is read-only, convert to writable array
+ */
+ if ((version > 0) &&
+ ((attributes[variable_id] & 0x9c) == 0x1c))
+ {
+ /*
+ * Allocate a writable buffer for this array
+ */
+ count = (unsigned int) variable_size[variable_id];
+ long_temp = variables[variable_id];
+ longptr_temp = (long *) jbi_malloc(count * sizeof(long));
+ variables[variable_id] = (long) longptr_temp;
+
+ if (variables[variable_id] == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ break;
+ }
+ else
+ {
+ /* copy previous contents into buffer */
+ for (i = 0; i < count; ++i)
+ {
+ longptr_temp[i] = GET_DWORD(long_temp);
+ long_temp += 4L;
+ }
+
+ /* set bit 7 - buffer was dynamically allocated */
+ attributes[variable_id] |= 0x80;
+
+ /* clear bit 2 - variable is writable */
+ attributes[variable_id] &= ~0x04;
+ attributes[variable_id] |= 0x01;
+ }
+ }
+
+#if PORT==DOS
+ /* for 16-bit version, allow writing in allocated buffers */
+ if ((version > 0) &&
+ ((attributes[variable_id] & 0x9c) == 0x9c))
+ {
+ attributes[variable_id] &= ~0x04;
+ attributes[variable_id] |= 0x01;
+ }
+#endif
+
+ /* check that variable is a writable integer array */
+ if ((attributes[variable_id] & 0x1c) != 0x18)
+ {
+ status = JBIC_BOUNDS_ERROR;
+ }
+ else
+ {
+ longptr_temp = (long *) variables[variable_id];
+
+ /* pop the array index */
+ index = (unsigned int) stack[--stack_ptr];
+
+ /* pop the value and store it into the array */
+ longptr_temp[index] = stack[--stack_ptr];
+ }
+ }
+ break;
+
+ case 0x4F: /* POPA */
+ /*
+ * Pop stack into Boolean array
+ * ...argument 0 is variable ID
+ * ...stack 0 is count
+ * ...stack 1 is array index
+ * ...stack 2 is value
+ */
+ IF_CHECK_STACK(3)
+ {
+ variable_id = (unsigned int) args[0];
+
+ /*
+ * If variable is read-only, convert to writable array
+ */
+ if ((version > 0) &&
+ ((attributes[variable_id] & 0x9c) == 0x0c))
+ {
+ /*
+ * Allocate a writable buffer for this array
+ */
+ long_temp = (variable_size[variable_id] + 7L) >> 3L;
+ charptr_temp2 = (unsigned char *) variables[variable_id];
+ charptr_temp = jbi_malloc((unsigned int) long_temp);
+ variables[variable_id] = (long) charptr_temp;
+
+ if (variables[variable_id] == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ /* zero the buffer */
+ for (long_index = 0L;
+ long_index < long_temp;
+ ++long_index)
+ {
+ charptr_temp[long_index] = 0;
+ }
+
+ /* copy previous contents into buffer */
+ for (long_index = 0L;
+ long_index < variable_size[variable_id];
+ ++long_index)
+ {
+#if PORT==DOS
+ if ((attributes[variable_id] & 0x02) &&
+ ((long_index & 0x0000FFFF) == 0L))
+ {
+ /* initialized compressed Boolean array */
+ jbi_uncompress_page(variable_id,
+ (int) (long_index >> 16), version);
+ charptr_temp = jbi_aca_out_buffer;
+ long_index2 = long_index & 0xFFFF;
+ }
+#else
+ long_index2 = long_index;
+#endif
+
+ if (charptr_temp2[long_index2 >> 3] &
+ (1 << (long_index2 & 7)))
+ {
+ charptr_temp[long_index >> 3] |=
+ (1 << (long_index & 7));
+ }
+ }
+
+ /* set bit 7 - buffer was dynamically allocated */
+ attributes[variable_id] |= 0x80;
+
+ /* clear bit 2 - variable is writable */
+ attributes[variable_id] &= ~0x04;
+ attributes[variable_id] |= 0x01;
+ }
+ }
+
+#if PORT==DOS
+ /* for 16-bit version, allow writing in allocated buffers */
+ if ((version > 0) &&
+ ((attributes[variable_id] & 0x9c) == 0x8c))
+ {
+ attributes[variable_id] &= ~0x04;
+ attributes[variable_id] |= 0x01;
+ }
+#endif
+
+ /* check that variable is a writable Boolean array */
+ if ((attributes[variable_id] & 0x1c) != 0x08)
+ {
+ status = JBIC_BOUNDS_ERROR;
+ }
+ else
+ {
+ charptr_temp = (unsigned char *) variables[variable_id];
+
+ /* pop the count (number of bits to copy) */
+ long_count = stack[--stack_ptr];
+
+ /* pop the array index */
+ long_index = stack[--stack_ptr];
+
+ reverse = 0;
+
+ if (version > 0)
+ {
+ /* stack 0 = array right index */
+ /* stack 1 = array left index */
+
+ if (long_index > long_count)
+ {
+ reverse = 1;
+ long_temp = long_count;
+ long_count = 1 + long_index - long_count;
+ long_index = long_temp;
+
+ /* reverse POPA is not supported */
+ status = JBIC_BOUNDS_ERROR;
+ break;
+ }
+ else
+ {
+ long_count = 1 + long_count - long_index;
+ }
+ }
+
+ /* pop the data */
+ long_temp = stack[--stack_ptr];
+
+ if (long_count < 1)
+ {
+ status = JBIC_BOUNDS_ERROR;
+ }
+ else
+ {
+ for (i = 0; i < (unsigned int) long_count; ++i)
+ {
+ if (long_temp & (1L << (long) i))
+ {
+ charptr_temp[long_index >> 3L] |=
+ (1L << (long_index & 7L));
+ }
+ else
+ {
+ charptr_temp[long_index >> 3L] &=
+ ~ (unsigned int) (1L << (long_index & 7L));
+ }
+ ++long_index;
+ }
+ }
+ }
+ }
+ break;
+
+ case 0x50: /* JMPZ */
+ /*
+ * Pop stack and branch if zero
+ * ...argument 0 is address
+ * ...stack 0 is condition value
+ */
+ IF_CHECK_STACK(1)
+ {
+ if (stack[--stack_ptr] == 0)
+ {
+ pc = args[0] + code_section;
+ CHECK_PC;
+ }
+ }
+ break;
+
+ case 0x51: /* DS */
+ case 0x52: /* IS */
+ /*
+ * DRSCAN
+ * IRSCAN
+ * ...argument 0 is scan data variable ID
+ * ...stack 0 is array index
+ * ...stack 1 is count
+ */
+ IF_CHECK_STACK(2)
+ {
+ long_index = stack[--stack_ptr];
+ long_count = stack[--stack_ptr];
+
+ reverse = 0;
+
+ if (version > 0)
+ {
+ /* stack 0 = array right index */
+ /* stack 1 = array left index */
+ /* stack 2 = count */
+ long_temp = long_count;
+ long_count = stack[--stack_ptr];
+
+ if (long_index > long_temp)
+ {
+ reverse = 1;
+ long_index = long_temp;
+ }
+ }
+
+#if PORT==DOS
+ if (((long_index & 0xFFFF0000) == 0) &&
+ ((long_count & 0xFFFF0000) == 0))
+ {
+ variable_id = (unsigned int) args[0];
+ if ((attributes[variable_id] & 0x1e) == 0x0e)
+ {
+ /* initialized compressed Boolean array */
+ jbi_uncompress_page(variable_id,
+ (int) (long_index >> 16), version);
+ long_index &= 0x0000ffff;
+ charptr_temp = jbi_aca_out_buffer;
+ }
+ else
+ {
+ charptr_temp = (unsigned char *) variables[variable_id];
+ }
+
+ if (reverse)
+ {
+ /* allocate a buffer and reverse the data order */
+ charptr_temp2 = charptr_temp;
+ charptr_temp = jbi_malloc((unsigned int)
+ ((long_count >> 3L) + 1L));
+
+ if (charptr_temp == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ break;
+ }
+ else
+ {
+ long_temp = long_index + long_count - 1;
+ long_index2 = 0;
+ while (long_index2 < long_count)
+ {
+ if (charptr_temp2[long_temp >> 3] &
+ (1 << (long_temp & 7)))
+ {
+ charptr_temp[long_index2 >> 3] |=
+ (1 << (long_index2 & 7));
+ }
+ else
+ {
+ charptr_temp[long_index2 >> 3] &=
+ ~(1 << (long_index2 & 7));
+ }
+
+ --long_temp;
+ ++long_index2;
+ }
+ }
+ }
+
+ if (opcode == 0x51) /* DS */
+ {
+ status = jbi_do_drscan((unsigned int) long_count,
+ charptr_temp, (unsigned long) long_index);
+ }
+ else /* IS */
+ {
+ status = jbi_do_irscan((unsigned int) long_count,
+ charptr_temp, (unsigned int) long_index);
+ }
+
+ if (reverse) jbi_free(charptr_temp);
+ }
+ else if ((opcode == 0x51) && !reverse)
+ {
+ status = jbi_do_drscan_multi_page(
+ (unsigned int) args[0],
+ (unsigned long) long_count,
+ (unsigned long) long_index, version);
+ }
+ else
+ {
+ /* reverse multi-page scans are not supported */
+ /* multi-page IR scans are not supported */
+ status = JBIC_BOUNDS_ERROR;
+ }
+#else
+ charptr_temp = (unsigned char *) variables[args[0]];
+
+ if (reverse)
+ {
+ /* allocate a buffer and reverse the data order */
+ charptr_temp2 = charptr_temp;
+ charptr_temp = jbi_malloc((long_count >> 3) + 1);
+ if (charptr_temp == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ break;
+ }
+ else
+ {
+ long_temp = long_index + long_count - 1;
+ long_index2 = 0;
+ while (long_index2 < long_count)
+ {
+ if (charptr_temp2[long_temp >> 3] &
+ (1 << (long_temp & 7)))
+ {
+ charptr_temp[long_index2 >> 3] |=
+ (1 << (long_index2 & 7));
+ }
+ else
+ {
+ charptr_temp[long_index2 >> 3] &=
+ ~(1 << (long_index2 & 7));
+ }
+
+ --long_temp;
+ ++long_index2;
+ }
+ }
+ }
+
+ if (opcode == 0x51) /* DS */
+ {
+ status = jbi_do_drscan((unsigned int) long_count,
+ charptr_temp, (unsigned long) long_index);
+ }
+ else /* IS */
+ {
+ status = jbi_do_irscan((unsigned int) long_count,
+ charptr_temp, (unsigned int) long_index);
+ }
+#endif
+
+ if (reverse && (charptr_temp != NULL))
+ {
+ jbi_free(charptr_temp);
+ }
+ }
+ break;
+
+ case 0x53: /* DPRA */
+ /*
+ * DRPRE with array data
+ * ...argument 0 is variable ID
+ * ...stack 0 is array index
+ * ...stack 1 is count
+ */
+ IF_CHECK_STACK(2)
+ {
+ index = (unsigned int) stack[--stack_ptr];
+ count = (unsigned int) stack[--stack_ptr];
+
+ if (version > 0)
+ {
+ /* stack 0 = array right index */
+ /* stack 1 = array left index */
+ count = 1 + count - index;
+ }
+
+ charptr_temp = (unsigned char *) variables[args[0]];
+ status = jbi_set_dr_preamble(count, index, charptr_temp);
+ }
+ break;
+
+ case 0x54: /* DPOA */
+ /*
+ * DRPOST with array data
+ * ...argument 0 is variable ID
+ * ...stack 0 is array index
+ * ...stack 1 is count
+ */
+ IF_CHECK_STACK(2)
+ {
+ index = (unsigned int) stack[--stack_ptr];
+ count = (unsigned int) stack[--stack_ptr];
+
+ if (version > 0)
+ {
+ /* stack 0 = array right index */
+ /* stack 1 = array left index */
+ count = 1 + count - index;
+ }
+
+ charptr_temp = (unsigned char *) variables[args[0]];
+ status = jbi_set_dr_postamble(count, index, charptr_temp);
+ }
+ break;
+
+ case 0x55: /* IPRA */
+ /*
+ * IRPRE with array data
+ * ...argument 0 is variable ID
+ * ...stack 0 is array index
+ * ...stack 1 is count
+ */
+ IF_CHECK_STACK(2)
+ {
+ index = (unsigned int) stack[--stack_ptr];
+ count = (unsigned int) stack[--stack_ptr];
+
+ if (version > 0)
+ {
+ /* stack 0 = array right index */
+ /* stack 1 = array left index */
+ count = 1 + count - index;
+ }
+
+ charptr_temp = (unsigned char *) variables[args[0]];
+ status = jbi_set_ir_preamble(count, index, charptr_temp);
+ }
+ break;
+
+ case 0x56: /* IPOA */
+ /*
+ * IRPOST with array data
+ * ...argument 0 is variable ID
+ * ...stack 0 is array index
+ * ...stack 1 is count
+ */
+ IF_CHECK_STACK(2)
+ {
+ index = (unsigned int) stack[--stack_ptr];
+ count = (unsigned int) stack[--stack_ptr];
+
+ if (version > 0)
+ {
+ /* stack 0 = array right index */
+ /* stack 1 = array left index */
+ count = 1 + count - index;
+ }
+
+ charptr_temp = (unsigned char *) variables[args[0]];
+ status = jbi_set_ir_postamble(count, index, charptr_temp);
+ }
+ break;
+
+ case 0x57: /* EXPT */
+ /*
+ * EXPORT
+ * ...argument 0 is string ID
+ * ...stack 0 is integer expression
+ */
+ IF_CHECK_STACK(1)
+ {
+#if PORT==DOS
+ name_id = args[0];
+ for (j = 0; j < 32; ++j)
+ {
+ name[j] = GET_BYTE(string_table + name_id + j);
+ }
+ name[32] = '\0';
+#else
+ name = (char *) &program[string_table + args[0]];
+#endif
+ long_temp = stack[--stack_ptr];
+ jbi_export_integer(name, long_temp);
+ }
+ break;
+
+ case 0x58: /* PSHE */
+ /*
+ * Push integer array element
+ * ...argument 0 is variable ID
+ * ...stack 0 is array index
+ */
+ IF_CHECK_STACK(1)
+ {
+ variable_id = (unsigned int) args[0];
+ index = (unsigned int) stack[stack_ptr - 1];
+
+ /* check variable type */
+ if ((attributes[variable_id] & 0x1f) == 0x19)
+ {
+ /* writable integer array */
+ longptr_temp = (long *) variables[variable_id];
+ stack[stack_ptr - 1] = longptr_temp[index];
+ }
+ else if ((attributes[variable_id] & 0x1f) == 0x1c)
+ {
+ /* read-only integer array */
+ long_temp = variables[variable_id] + (4L * index);
+ stack[stack_ptr - 1] = GET_DWORD(long_temp);
+ }
+ else
+ {
+ status = JBIC_BOUNDS_ERROR;
+ }
+ }
+ break;
+
+ case 0x59: /* PSHA */
+ /*
+ * Push Boolean array
+ * ...argument 0 is variable ID
+ * ...stack 0 is count
+ * ...stack 1 is array index
+ */
+ IF_CHECK_STACK(2)
+ {
+ variable_id = (unsigned int) args[0];
+
+ /* check that variable is a Boolean array */
+ if ((attributes[variable_id] & 0x18) != 0x08)
+ {
+ status = JBIC_BOUNDS_ERROR;
+ }
+ else
+ {
+ charptr_temp = (unsigned char *) variables[variable_id];
+
+ /* pop the count (number of bits to copy) */
+ count = (unsigned int) stack[--stack_ptr];
+
+ /* pop the array index */
+ index = (unsigned int) stack[stack_ptr - 1];
+
+ if (version > 0)
+ {
+ /* stack 0 = array right index */
+ /* stack 1 = array left index */
+ count = 1 + count - index;
+ }
+
+ if ((count < 1) || (count > 32))
+ {
+ status = JBIC_BOUNDS_ERROR;
+ }
+ else
+ {
+#if PORT==DOS
+ if ((attributes[variable_id] & 0x1e) == 0x0e)
+ {
+ /* initialized compressed Boolean array */
+ jbi_uncompress_page(variable_id,
+ (int) (stack[stack_ptr - 1] >> 16), version);
+ charptr_temp = jbi_aca_out_buffer;
+ }
+#endif
+ long_temp = 0L;
+
+ for (i = 0; i < count; ++i)
+ {
+ if (charptr_temp[(i + index) >> 3] &
+ (1 << ((i + index) & 7)))
+ {
+ long_temp |= (1L << i);
+ }
+ }
+
+ stack[stack_ptr - 1] = long_temp;
+ }
+ }
+ }
+ break;
+
+ case 0x5A: /* DYNA */
+ /*
+ * Dynamically change size of array
+ * ...argument 0 is variable ID
+ * ...stack 0 is new size
+ */
+ IF_CHECK_STACK(1)
+ {
+ variable_id = (unsigned int) args[0];
+ long_temp = stack[--stack_ptr];
+
+ if (long_temp > variable_size[variable_id])
+ {
+ variable_size[variable_id] = long_temp;
+
+ if (attributes[variable_id] & 0x10)
+ {
+ /* allocate integer array */
+ long_temp *= 4;
+ }
+ else
+ {
+ /* allocate Boolean array */
+ long_temp = (long_temp + 7) >> 3;
+ }
+
+ /*
+ * If the buffer was previously allocated, free it
+ */
+ if ((attributes[variable_id] & 0x80) &&
+ (variables[variable_id] != NULL))
+ {
+ jbi_free((void *) variables[variable_id]);
+ variables[variable_id] = NULL;
+ }
+
+ /*
+ * Allocate a new buffer of the requested size
+ */
+ variables[variable_id] = (long)
+ jbi_malloc((unsigned int) long_temp);
+
+ if (variables[variable_id] == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ /*
+ * Set the attribute bit to indicate that this buffer
+ * was dynamically allocated and should be freed later
+ */
+ attributes[variable_id] |= 0x80;
+
+ /* zero out memory */
+ count = (unsigned int)
+ ((variable_size[variable_id] + 7L) / 8L);
+ charptr_temp = (unsigned char *)
+ (variables[variable_id]);
+ for (index = 0; index < count; ++index)
+ {
+ charptr_temp[index] = 0;
+ }
+ }
+ }
+ }
+ break;
+
+ case 0x5B: /* EXPR */
+ bad_opcode = 1;
+ break;
+
+ case 0x5C: /* EXPV */
+ /*
+ * Export Boolean array
+ * ...argument 0 is string ID
+ * ...stack 0 is variable ID
+ * ...stack 1 is array right index
+ * ...stack 2 is array left index
+ */
+ IF_CHECK_STACK(3)
+ {
+ if (version == 0)
+ {
+ /* EXPV is not supported in JBC 1.0 */
+ bad_opcode = 1;
+ break;
+ }
+#if PORT==DOS
+ name_id = args[0];
+ for (j = 0; j < 32; ++j)
+ {
+ name[j] = GET_BYTE(string_table + name_id + j);
+ }
+ name[32] = '\0';
+#else
+ name = (char *) &program[string_table + args[0]];
+#endif
+ variable_id = (unsigned int) stack[--stack_ptr];
+ long_index = stack[--stack_ptr]; /* right index */
+ long_index2 = stack[--stack_ptr]; /* left index */
+
+ if (long_index > long_index2)
+ {
+ /* reverse indices not supported */
+ status = JBIC_BOUNDS_ERROR;
+ break;
+ }
+
+ long_count = 1 + long_index2 - long_index;
+
+ charptr_temp = (unsigned char *) variables[variable_id];
+ charptr_temp2 = NULL;
+
+#if PORT==DOS
+ if ((attributes[variable_id] & 0x1e) == 0x0e)
+ {
+ /* initialized compressed Boolean array */
+ jbi_uncompress_page(variable_id,
+ (int) (long_index >> 16), version);
+ charptr_temp = jbi_aca_out_buffer;
+ long_index &= 0x0000FFFF;
+ }
+#endif
+
+ if ((long_index & 7L) != 0)
+ {
+ charptr_temp2 = jbi_malloc((unsigned int)
+ ((long_count + 7L) / 8L));
+ if (charptr_temp2 == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ break;
+ }
+ else
+ {
+ long k = long_index;
+ for (i = 0; i < (unsigned int) long_count; ++i)
+ {
+ if (charptr_temp[k >> 3] & (1 << (k & 7)))
+ {
+ charptr_temp2[i >> 3] |= (1 << (i & 7));
+ }
+ else
+ {
+ charptr_temp2[i >> 3] &= ~(1 << (i & 7));
+ }
+
+ ++k;
+ }
+ charptr_temp = charptr_temp2;
+ }
+ }
+ else if (long_index != 0)
+ {
+ charptr_temp = &charptr_temp[long_index >> 3];
+ }
+
+ jbi_export_boolean_array(name, charptr_temp, long_count);
+
+ /* free allocated buffer */
+ if (((long_index & 7L) != 0) && (charptr_temp2 != NULL))
+ {
+ jbi_free(charptr_temp2);
+ }
+ }
+ break;
+
+ case 0x80: /* COPY */
+ /*
+ * Array copy
+ * ...argument 0 is dest ID
+ * ...argument 1 is source ID
+ * ...stack 0 is count
+ * ...stack 1 is dest index
+ * ...stack 2 is source index
+ */
+ IF_CHECK_STACK(3)
+ {
+ long copy_count = stack[--stack_ptr];
+ long copy_index = stack[--stack_ptr];
+ long copy_index2 = stack[--stack_ptr];
+ long destleft;
+ long src_count;
+ long dest_count;
+ int src_reverse = 0;
+ int dest_reverse = 0;
+
+ reverse = 0;
+
+ if (version > 0)
+ {
+ /* stack 0 = source right index */
+ /* stack 1 = source left index */
+ /* stack 2 = destination right index */
+ /* stack 3 = destination left index */
+ destleft = stack[--stack_ptr];
+
+ if (copy_count > copy_index)
+ {
+ src_reverse = 1;
+ reverse = 1;
+ src_count = 1 + copy_count - copy_index;
+ /* copy_index = source start index */
+ }
+ else
+ {
+ src_count = 1 + copy_index - copy_count;
+ copy_index = copy_count; /* source start index */
+ }
+
+ if (copy_index2 > destleft)
+ {
+ dest_reverse = 1;
+ reverse = !reverse;
+ dest_count = 1 + copy_index2 - destleft;
+ copy_index2 = destleft; /* destination start index */
+ }
+ else
+ {
+ dest_count = 1 + destleft - copy_index2;
+ /* copy_index2 = destination start index */
+ }
+
+ copy_count = (src_count < dest_count) ? src_count : dest_count;
+
+ if ((src_reverse || dest_reverse) &&
+ (src_count != dest_count))
+ {
+ /* If either the source or destination is reversed, */
+ /* we can't tolerate a length mismatch, because we */
+ /* "left justify" the arrays when copying. This */
+ /* won't work correctly with reversed arrays. */
+ status = JBIC_BOUNDS_ERROR;
+ }
+ }
+
+ count = (unsigned int) copy_count;
+ index = (unsigned int) copy_index;
+ index2 = (unsigned int) copy_index2;
+
+ /*
+ * If destination is a read-only array, allocate a buffer
+ * and convert it to a writable array
+ */
+ variable_id = (unsigned int) args[1];
+ if ((version > 0) && ((attributes[variable_id] & 0x9c) == 0x0c))
+ {
+ /*
+ * Allocate a writable buffer for this array
+ */
+ long_temp = (variable_size[variable_id] + 7L) >> 3L;
+ charptr_temp2 = (unsigned char *) variables[variable_id];
+ charptr_temp = jbi_malloc((unsigned int) long_temp);
+ variables[variable_id] = (long) charptr_temp;
+
+ if (variables[variable_id] == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ break;
+ }
+ else
+ {
+ /* zero the buffer */
+ for (long_index = 0L;
+ long_index < long_temp;
+ ++long_index)
+ {
+ charptr_temp[long_index] = 0;
+ }
+
+ /* copy previous contents into buffer */
+ for (long_index = 0L;
+ long_index < variable_size[variable_id];
+ ++long_index)
+ {
+#if PORT==DOS
+ if ((attributes[variable_id] & 0x02) &&
+ ((long_index & 0x0000FFFF) == 0L))
+ {
+ /* initialized compressed Boolean array */
+ jbi_uncompress_page(variable_id,
+ (int) (long_index >> 16), version);
+ charptr_temp = jbi_aca_out_buffer;
+ long_index2 = long_index & 0xFFFF;
+ }
+#else
+ long_index2 = long_index;
+#endif
+
+ if (charptr_temp2[long_index2 >> 3] &
+ (1 << (long_index2 & 7)))
+ {
+ charptr_temp[long_index >> 3] |=
+ (1 << (long_index & 7));
+ }
+ }
+
+ /* set bit 7 - buffer was dynamically allocated */
+ attributes[variable_id] |= 0x80;
+
+ /* clear bit 2 - variable is writable */
+ attributes[variable_id] &= ~0x04;
+ attributes[variable_id] |= 0x01;
+ }
+ }
+
+#if PORT==DOS
+ /* for 16-bit version, allow writing in allocated buffers */
+ if ((version > 0) &&
+ ((attributes[variable_id] & 0x9c) == 0x8c))
+ {
+ attributes[variable_id] &= ~0x04;
+ attributes[variable_id] |= 0x01;
+ }
+#endif
+
+ charptr_temp = (unsigned char *) variables[args[1]];
+ charptr_temp2 = (unsigned char *) variables[args[0]];
+
+#if PORT==DOS
+ variable_id = (unsigned int) args[0];
+ if ((attributes[variable_id] & 0x1e) == 0x0e)
+ {
+ /* initialized compressed Boolean array */
+ jbi_uncompress_page(variable_id,
+ (int) (copy_index >> 16), version);
+ charptr_temp2 = jbi_aca_out_buffer;
+ }
+#endif
+
+ /* check that destination is a writable Boolean array */
+ if ((attributes[args[1]] & 0x1c) != 0x08)
+ {
+ status = JBIC_BOUNDS_ERROR;
+ break;
+ }
+
+ if (count < 1)
+ {
+ status = JBIC_BOUNDS_ERROR;
+ }
+ else
+ {
+ if (reverse)
+ {
+ index2 += (count - 1);
+ }
+
+ for (i = 0; i < count; ++i)
+ {
+ if (charptr_temp2[index >> 3] & (1 << (index & 7)))
+ {
+ charptr_temp[index2 >> 3] |= (1 << (index2 & 7));
+ }
+ else
+ {
+ charptr_temp[index2 >> 3] &=
+ ~(unsigned int) (1 << (index2 & 7));
+ }
+ ++index;
+ if (reverse) --index2; else ++index2;
+ }
+ }
+ }
+ break;
+
+ case 0x81: /* REVA */
+ /*
+ * ARRAY COPY reversing bit order
+ * ...argument 0 is dest ID
+ * ...argument 1 is source ID
+ * ...stack 0 is dest index
+ * ...stack 1 is source index
+ * ...stack 2 is count
+ */
+ bad_opcode = 1;
+ break;
+
+ case 0x82: /* DSC */
+ case 0x83: /* ISC */
+ /*
+ * DRSCAN with capture
+ * IRSCAN with capture
+ * ...argument 0 is scan data variable ID
+ * ...argument 1 is capture variable ID
+ * ...stack 0 is capture index
+ * ...stack 1 is scan data index
+ * ...stack 2 is count
+ */
+ IF_CHECK_STACK(3)
+ {
+ long scan_right, scan_left;
+ long capture_count = 0;
+ long scan_count = 0;
+ long capture_index = stack[--stack_ptr];
+ long scan_index = stack[--stack_ptr];
+ if (version > 0)
+ {
+ /* stack 0 = capture right index */
+ /* stack 1 = capture left index */
+ /* stack 2 = scan right index */
+ /* stack 3 = scan left index */
+ /* stack 4 = count */
+ scan_right = stack[--stack_ptr];
+ scan_left = stack[--stack_ptr];
+ capture_count = 1 + scan_index - capture_index;
+ scan_count = 1 + scan_left - scan_right;
+ scan_index = scan_right;
+ }
+ long_count = stack[--stack_ptr];
+
+ /*
+ * If capture array is read-only, allocate a buffer
+ * and convert it to a writable array
+ */
+ variable_id = (unsigned int) args[1];
+ if ((version > 0) && ((attributes[variable_id] & 0x9c) == 0x0c))
+ {
+ /*
+ * Allocate a writable buffer for this array
+ */
+ long_temp = (variable_size[variable_id] + 7L) >> 3L;
+ charptr_temp2 = (unsigned char *) variables[variable_id];
+ charptr_temp = jbi_malloc((unsigned int) long_temp);
+ variables[variable_id] = (long) charptr_temp;
+
+ if (variables[variable_id] == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ break;
+ }
+ else
+ {
+ /* zero the buffer */
+ for (long_index = 0L;
+ long_index < long_temp;
+ ++long_index)
+ {
+ charptr_temp[long_index] = 0;
+ }
+
+ /* copy previous contents into buffer */
+ for (long_index = 0L;
+ long_index < variable_size[variable_id];
+ ++long_index)
+ {
+#if PORT==DOS
+ if ((attributes[variable_id] & 0x02) &&
+ ((long_index & 0x0000FFFF) == 0L))
+ {
+ /* initialized compressed Boolean array */
+ jbi_uncompress_page(variable_id,
+ (int) (long_index >> 16), version);
+ charptr_temp = jbi_aca_out_buffer;
+ long_index2 = long_index & 0xFFFF;
+ }
+#else
+ long_index2 = long_index;
+#endif
+
+ if (charptr_temp2[long_index2 >> 3] &
+ (1 << (long_index2 & 7)))
+ {
+ charptr_temp[long_index >> 3] |=
+ (1 << (long_index & 7));
+ }
+ }
+
+ /* set bit 7 - buffer was dynamically allocated */
+ attributes[variable_id] |= 0x80;
+
+ /* clear bit 2 - variable is writable */
+ attributes[variable_id] &= ~0x04;
+ attributes[variable_id] |= 0x01;
+ }
+ }
+
+#if PORT==DOS
+ /* for 16-bit version, allow writing in allocated buffers */
+ if ((version > 0) &&
+ ((attributes[variable_id] & 0x9c) == 0x8c))
+ {
+ attributes[variable_id] &= ~0x04;
+ attributes[variable_id] |= 0x01;
+ }
+#endif
+
+ charptr_temp = (unsigned char *) variables[args[0]];
+ charptr_temp2 = (unsigned char *) variables[args[1]];
+
+#if PORT==DOS
+ variable_id = (unsigned int) args[0];
+ if ((attributes[variable_id] & 0x1e) == 0x0e)
+ {
+ /* initialized compressed Boolean array */
+ jbi_uncompress_page(variable_id,
+ (int) (scan_index >> 16), version);
+ scan_index &= 0x0000ffff;
+ charptr_temp = jbi_aca_out_buffer;
+ }
+#endif
+
+ if ((version > 0) &&
+ ((long_count > capture_count) || (long_count > scan_count)))
+ {
+ status = JBIC_BOUNDS_ERROR;
+ }
+
+ /* check that capture array is a writable Boolean array */
+ if ((attributes[args[1]] & 0x1c) != 0x08)
+ {
+ status = JBIC_BOUNDS_ERROR;
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ if (opcode == 0x82) /* DSC */
+ {
+ status = jbi_swap_dr((unsigned int) long_count,
+ charptr_temp, (unsigned long) scan_index,
+ charptr_temp2, (unsigned int) capture_index);
+ }
+ else /* ISC */
+ {
+ status = jbi_swap_ir((unsigned int) long_count,
+ charptr_temp, (unsigned int) scan_index,
+ charptr_temp2, (unsigned int) capture_index);
+ }
+ }
+ }
+ break;
+
+ case 0x84: /* WAIT */
+ /*
+ * WAIT
+ * ...argument 0 is wait state
+ * ...argument 1 is end state
+ * ...stack 0 is cycles
+ * ...stack 1 is microseconds
+ */
+ IF_CHECK_STACK(2)
+ {
+ long_temp = stack[--stack_ptr];
+
+ if (long_temp != 0L)
+ {
+ status = jbi_do_wait_cycles(long_temp, (unsigned int) args[0]);
+ }
+
+ long_temp = stack[--stack_ptr];
+
+ if ((status == JBIC_SUCCESS) && (long_temp != 0L))
+ {
+ status = jbi_do_wait_microseconds(long_temp, (unsigned int) args[0]);
+ }
+
+ if ((status == JBIC_SUCCESS) && (args[1] != args[0]))
+ {
+ status = jbi_goto_jtag_state((unsigned int) args[1]);
+ }
+
+ if (version > 0)
+ {
+ --stack_ptr; /* throw away MAX cycles */
+ --stack_ptr; /* throw away MAX microseconds */
+ }
+ }
+ break;
+
+ case 0x85: /* VS */
+ /*
+ * VECTOR
+ * ...argument 0 is dir data variable ID
+ * ...argument 1 is scan data variable ID
+ * ...stack 0 is dir array index
+ * ...stack 1 is scan array index
+ * ...stack 2 is count
+ */
+ bad_opcode = 1;
+ break;
+
+ case 0xC0: /* CMPA */
+ /*
+ * Array compare
+ * ...argument 0 is source 1 ID
+ * ...argument 1 is source 2 ID
+ * ...argument 2 is mask ID
+ * ...stack 0 is source 1 index
+ * ...stack 1 is source 2 index
+ * ...stack 2 is mask index
+ * ...stack 3 is count
+ */
+ IF_CHECK_STACK(4)
+ {
+ long a, b;
+ unsigned char *source1 = (unsigned char *) variables[args[0]];
+ unsigned char *source2 = (unsigned char *) variables[args[1]];
+ unsigned char *mask = (unsigned char *) variables[args[2]];
+ unsigned long index1 = stack[--stack_ptr];
+ unsigned long index2 = stack[--stack_ptr];
+ unsigned long mask_index = stack[--stack_ptr];
+ long_count = stack[--stack_ptr];
+
+ if (version > 0)
+ {
+ /* stack 0 = source 1 right index */
+ /* stack 1 = source 1 left index */
+ /* stack 2 = source 2 right index */
+ /* stack 3 = source 2 left index */
+ /* stack 4 = mask right index */
+ /* stack 5 = mask left index */
+ long mask_right = stack[--stack_ptr];
+ long mask_left = stack[--stack_ptr];
+ a = 1 + index2 - index1; /* source 1 count */
+ b = 1 + long_count - mask_index; /* source 2 count */
+ a = (a < b) ? a : b;
+ b = 1 + mask_left - mask_right; /* mask count */
+ a = (a < b) ? a : b;
+ index2 = mask_index; /* source 2 start index */
+ mask_index = mask_right; /* mask start index */
+ long_count = a;
+ }
+
+ long_temp = 1L;
+
+ if (long_count < 1)
+ {
+ status = JBIC_BOUNDS_ERROR;
+ }
+ else
+ {
+#if PORT==DOS
+ variable_id = (unsigned int) args[0];
+ if ((attributes[variable_id] & 0x1e) == 0x0e)
+ {
+ jbi_uncompress_page(variable_id,
+ (int) (index1 >> 16), version);
+ index1 &= 0x0000ffff;
+ source1 = jbi_aca_out_buffer;
+ }
+
+ variable_id = (unsigned int) args[1];
+ if ((attributes[variable_id] & 0x1e) == 0x0e)
+ {
+ jbi_uncompress_page(variable_id,
+ (int) (index2 >> 16), version);
+ index2 &= 0x0000ffff;
+ source2 = jbi_aca_out_buffer;
+ }
+#endif
+ count = (unsigned int) long_count;
+
+ for (i = 0; i < count; ++i)
+ {
+ if (mask[mask_index >> 3] & (1 << (mask_index & 7)))
+ {
+ a = source1[index1 >> 3] & (1 << (index1 & 7))
+ ? 1 : 0;
+ b = source2[index2 >> 3] & (1 << (index2 & 7))
+ ? 1 : 0;
+
+ if (a != b) long_temp = 0L; /* failure */
+ }
+ ++index1;
+ ++index2;
+ ++mask_index;
+ }
+ }
+
+ stack[stack_ptr++] = long_temp;
+ }
+ break;
+
+ case 0xC1: /* VSC */
+ /*
+ * VECTOR with capture
+ * ...argument 0 is dir data variable ID
+ * ...argument 1 is scan data variable ID
+ * ...argument 2 is capture variable ID
+ * ...stack 0 is capture index
+ * ...stack 1 is scan data index
+ * ...stack 2 is dir data index
+ * ...stack 3 is count
+ */
+ bad_opcode = 1;
+ break;
+
+ default:
+ /*
+ * Unrecognized opcode -- ERROR!
+ */
+ bad_opcode = 1;
+ break;
+ }
+
+ if (bad_opcode)
+ {
+ status = JBIC_ILLEGAL_OPCODE;
+ }
+
+ if ((stack_ptr < 0) || (stack_ptr >= JBI_STACK_SIZE))
+ {
+ status = JBIC_STACK_OVERFLOW;
+ }
+
+ if (status != JBIC_SUCCESS)
+ {
+ done = 1;
+ *error_address = (long) (opcode_address - code_section);
+ }
+ }
+
+ jbi_free_jtag_padding_buffers(reset_jtag);
+
+ /*
+ * Free all dynamically allocated arrays
+ */
+ if ((attributes != NULL) && (variables != NULL))
+ {
+ for (i = 0; i < (unsigned int) symbol_count; ++i)
+ {
+ if ((attributes[i] & 0x80) && (variables[i] != NULL))
+ {
+ jbi_free((void *) variables[i]);
+ }
+ }
+ }
+
+ if (variables != NULL) jbi_free(variables);
+
+ if (variable_size != NULL) jbi_free(variable_size);
+
+ if (attributes != NULL) jbi_free(attributes);
+
+ if (proc_attributes != NULL) jbi_free(proc_attributes);
+
+ return (status);
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_get_note
+(
+ PROGRAM_PTR program,
+ long program_size,
+ long *offset,
+ char *key,
+ char *value,
+ int length
+)
+
+/* */
+/* Description: Gets key and value of NOTE fields in the JBC file. */
+/* Can be called in two modes: if offset pointer is NULL, */
+/* then the function searches for note fields which match */
+/* the key string provided. If offset is not NULL, then */
+/* the function finds the next note field of any key, */
+/* starting at the offset specified by the offset pointer. */
+/* */
+/* Returns: JBIC_SUCCESS for success, else appropriate error code */
+/* */
+/****************************************************************************/
+{
+ JBI_RETURN_TYPE status = JBIC_UNEXPECTED_END;
+ unsigned long note_strings = 0L;
+ unsigned long note_table = 0L;
+ unsigned long note_count = 0L;
+ unsigned long first_word = 0L;
+ int version = 0;
+ int delta = 0;
+ char *key_ptr;
+ char *value_ptr;
+ int i;
+
+#if PORT==DOS
+ int count = 0;
+ int done = 0;
+ long long_index = 0;
+ char key_buffer[256];
+ char value_buffer[256];
+
+ jbi_program = program;
+#endif
+
+ /*
+ * Read header information
+ */
+ if (program_size > 52L)
+ {
+ first_word = GET_DWORD(0);
+ version = (int) (first_word & 1L);
+ delta = version * 8;
+
+ note_strings = GET_DWORD(8 + delta);
+ note_table = GET_DWORD(12 + delta);
+ note_count = GET_DWORD(44 + (2 * delta));
+ }
+
+ if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L))
+ {
+ status = JBIC_IO_ERROR;
+ }
+ else if (note_count > 0L)
+ {
+ if (offset == NULL)
+ {
+ /*
+ * We will search for the first note with a specific key, and
+ * return only the value
+ */
+ for (i = 0; (i < (int) note_count) && (status != JBIC_SUCCESS); ++i)
+ {
+#if PORT==DOS
+ done = 0;
+ count = 0;
+ long_index = note_strings + GET_DWORD(note_table + (8 * i));
+ while ((count < 255) && !done)
+ {
+ key_buffer[count] = GET_BYTE(long_index);
+ if (key_buffer[count] == '\0') done = 1;
+ ++long_index;
+ ++count;
+ }
+ key_buffer[255] = '\0';
+ key_ptr = key_buffer;
+#else
+ key_ptr = (char *) &program[note_strings +
+ GET_DWORD(note_table + (8 * i))];
+#endif
+ if ((key != NULL) && (jbi_stricmp(key, key_ptr) == 0))
+ {
+ status = JBIC_SUCCESS;
+
+#if PORT==DOS
+ done = 0;
+ count = 0;
+ long_index = note_strings + GET_DWORD(note_table + (8 * i) + 4);
+ while ((count < 255) && !done)
+ {
+ value_buffer[count] = GET_BYTE(long_index);
+ if (value_buffer[count] == '\0') done = 1;
+ ++long_index;
+ ++count;
+ }
+ value_buffer[255] = '\0';
+ value_ptr = value_buffer;
+#else
+ value_ptr = (char *) &program[note_strings +
+ GET_DWORD(note_table + (8 * i) + 4)];
+#endif
+
+ if (value != NULL)
+ {
+ jbi_strncpy(value, value_ptr, length);
+ }
+ }
+ }
+ }
+ else
+ {
+ /*
+ * We will search for the next note, regardless of the key, and
+ * return both the value and the key
+ */
+
+ i = (int) *offset;
+
+ if ((i >= 0) && (i < (int) note_count))
+ {
+ status = JBIC_SUCCESS;
+
+ if (key != NULL)
+ {
+#if PORT==DOS
+ done = 0;
+ count = 0;
+ long_index = note_strings +
+ GET_DWORD(note_table + (8 * i));
+
+ while ((count < length) && !done)
+ {
+ key[count] = GET_BYTE(long_index);
+ if (key[count] == '\0') done = 1;
+ ++long_index;
+ ++count;
+ }
+#else
+ jbi_strncpy(key, (char *) &program[note_strings +
+ GET_DWORD(note_table + (8 * i))], length);
+#endif
+ }
+
+ if (value != NULL)
+ {
+#if PORT==DOS
+ done = 0;
+ count = 0;
+ long_index = note_strings +
+ GET_DWORD(note_table + (8 * i) + 4);
+
+ while ((count < length) && !done)
+ {
+ value[count] = GET_BYTE(long_index);
+ if (value[count] == '\0') done = 1;
+ ++long_index;
+ ++count;
+ }
+#else
+ jbi_strncpy(value, (char *) &program[note_strings +
+ GET_DWORD(note_table + (8 * i) + 4)], length);
+#endif
+ }
+
+ *offset = i + 1;
+ }
+ }
+ }
+
+ return (status);
+}
+
+/****************************************************************************/
+/* */
+
+JBI_RETURN_TYPE jbi_check_crc
+(
+ PROGRAM_PTR program,
+ long program_size,
+ unsigned short *expected_crc,
+ unsigned short *actual_crc
+)
+
+/* */
+/* Description: This function reads the entire input file and computes */
+/* the CRC of everything up to the CRC field. */
+/* */
+/* Returns: JBIC_SUCCESS for success, JBIC_CRC_ERROR for failure */
+/* */
+/****************************************************************************/
+{
+ JBI_RETURN_TYPE status = JBIC_SUCCESS;
+ unsigned short local_expected, local_actual, shift_reg = 0xffff;
+ int bit, feedback;
+ unsigned char databyte;
+ unsigned long i;
+ unsigned long crc_section = 0L;
+ unsigned long first_word = 0L;
+ int version = 0;
+ int delta = 0;
+
+#if PORT==DOS
+ jbi_program = program;
+#endif
+
+ if (program_size > 52L)
+ {
+ first_word = GET_DWORD(0);
+ version = (int) (first_word & 1L);
+ delta = version * 8;
+
+ crc_section = GET_DWORD(32 + delta);
+ }
+
+ if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L))
+ {
+ status = JBIC_IO_ERROR;
+ }
+
+ if (crc_section >= (unsigned long) program_size)
+ {
+ status = JBIC_IO_ERROR;
+ }
+
+ if (status == JBIC_SUCCESS)
+ {
+ local_expected = (unsigned short) GET_WORD(crc_section);
+ if (expected_crc != NULL) *expected_crc = local_expected;
+
+ for (i = 0; i < crc_section; ++i)
+ {
+ databyte = GET_BYTE(i);
+ for (bit = 0; bit < 8; bit++) /* compute for each bit */
+ {
+ feedback = (databyte ^ shift_reg) & 0x01;
+ shift_reg >>= 1; /* shift the shift register */
+ if (feedback) shift_reg ^= 0x8408; /* invert selected bits */
+ databyte >>= 1; /* get the next bit of input_byte */
+ }
+ }
+
+ local_actual = (unsigned short) ~shift_reg;
+ if (actual_crc != NULL) *actual_crc = local_actual;
+
+ if (local_expected != local_actual)
+ {
+ status = JBIC_CRC_ERROR;
+ }
+ }
+
+ return (status);
+}
+
+JBI_RETURN_TYPE jbi_get_file_info
+(
+ PROGRAM_PTR program,
+ long program_size,
+ int *format_version,
+ int *action_count,
+ int *procedure_count
+)
+{
+ JBI_RETURN_TYPE status = JBIC_IO_ERROR;
+ unsigned long first_word = 0;
+ int version = 0;
+
+#if PORT==DOS
+ jbi_program = program;
+#endif
+
+ /*
+ * Read header information
+ */
+ if (program_size > 52L)
+ {
+ first_word = GET_DWORD(0);
+
+ if ((first_word == 0x4A414D00L) || (first_word == 0x4A414D01L))
+ {
+ status = JBIC_SUCCESS;
+
+ version = (int) (first_word & 1L);
+ *format_version = version + 1;
+
+ if (version > 0)
+ {
+ *action_count = (int) GET_DWORD(48);
+ *procedure_count = (int) GET_DWORD(52);
+ }
+ }
+
+ }
+
+ return (status);
+}
+
+JBI_RETURN_TYPE jbi_get_action_info
+(
+ PROGRAM_PTR program,
+ long program_size,
+ int index,
+ char **name,
+ char **description,
+ JBI_PROCINFO **procedure_list
+)
+{
+ JBI_RETURN_TYPE status = JBIC_IO_ERROR;
+ JBI_PROCINFO *procptr = NULL;
+ JBI_PROCINFO *tmpptr = NULL;
+ unsigned long first_word = 0L;
+ unsigned long action_table = 0L;
+ unsigned long proc_table = 0L;
+ unsigned long string_table = 0L;
+ unsigned long note_strings = 0L;
+ unsigned long action_count = 0L;
+ unsigned long proc_count = 0L;
+ unsigned long act_name_id = 0L;
+ unsigned long act_desc_id = 0L;
+ unsigned long act_proc_id = 0L;
+ unsigned long act_proc_name = 0L;
+ unsigned char act_proc_attribute = 0;
+
+#if PORT==DOS
+ int i, length;
+ jbi_program = program;
+#endif
+
+ /*
+ * Read header information
+ */
+ if (program_size > 52L)
+ {
+ first_word = GET_DWORD(0);
+
+ if (first_word == 0x4A414D01L)
+ {
+ action_table = GET_DWORD(4);
+ proc_table = GET_DWORD(8);
+ string_table = GET_DWORD(12);
+ note_strings = GET_DWORD(16);
+ action_count = GET_DWORD(48);
+ proc_count = GET_DWORD(52);
+
+ if (index < (int) action_count)
+ {
+ act_name_id = GET_DWORD(action_table + (12 * index));
+ act_desc_id = GET_DWORD(action_table + (12 * index) + 4);
+ act_proc_id = GET_DWORD(action_table + (12 * index) + 8);
+
+#if PORT==DOS
+ length = 0;
+ while (GET_BYTE(string_table + act_name_id + length) != 0) ++length;
+ *name = jbi_malloc(length + 1);
+ if (*name == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ for (i = 0; i < length; ++i)
+ {
+ (*name)[i] = GET_BYTE(string_table + act_name_id + i);
+ }
+ (*name)[length] = '\0';
+ }
+#else
+ *name = (char *) &program[string_table + act_name_id];
+#endif
+
+ if (act_desc_id < (note_strings - string_table))
+ {
+#if PORT==DOS
+ length = 0;
+ while (GET_BYTE(string_table + act_desc_id + length) != 0) ++length;
+ *description = jbi_malloc(length + 1);
+ if (*description == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ for (i = 0; i < length; ++i)
+ {
+ (*description)[i] = GET_BYTE(string_table + act_desc_id + i);
+ }
+ (*description)[length] = '\0';
+ }
+#else
+ *description = (char *) &program[string_table + act_desc_id];
+#endif
+ }
+
+ do
+ {
+ act_proc_name = GET_DWORD(proc_table + (13 * act_proc_id));
+ act_proc_attribute = (unsigned char)
+ (GET_BYTE(proc_table + (13 * act_proc_id) + 8) & 0x03);
+
+ procptr = (JBI_PROCINFO *) jbi_malloc(sizeof(JBI_PROCINFO));
+
+ if (procptr == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+#if PORT==DOS
+ length = 0;
+ while (GET_BYTE(string_table + act_proc_name + length) != 0) ++length;
+ procptr->name = jbi_malloc(length + 1);
+ if (procptr->name == NULL)
+ {
+ status = JBIC_OUT_OF_MEMORY;
+ }
+ else
+ {
+ for (i = 0; i < length; ++i)
+ {
+ procptr->name[i] =
+ GET_BYTE(string_table + act_proc_name + i);
+ }
+ procptr->name[length] = '\0';
+ }
+#else
+ procptr->name = (char *)
+ &program[string_table + act_proc_name];
+#endif
+ procptr->attributes = act_proc_attribute;
+ procptr->next = NULL;
+
+ /* add record to end of linked list */
+ if (*procedure_list == NULL)
+ {
+ *procedure_list = procptr;
+ }
+ else
+ {
+ tmpptr = *procedure_list;
+ while (tmpptr->next != NULL) tmpptr = tmpptr->next;
+ tmpptr->next = procptr;
+ }
+ }
+
+ act_proc_id =
+ GET_DWORD(proc_table + (13 * act_proc_id) + 4);
+ }
+ while ((act_proc_id != 0) && (act_proc_id < proc_count));
+ }
+ }
+
+ }
+
+ return (status);
+}
diff --git a/common/recipes-utils/jbi/files/code/jbiport.h b/common/recipes-utils/jbi/files/code/jbiport.h
new file mode 100644
index 0000000..885e84d
--- /dev/null
+++ b/common/recipes-utils/jbi/files/code/jbiport.h
@@ -0,0 +1,45 @@
+/****************************************************************************/
+/* */
+/* Module: jbiport.h */
+/* */
+/* Copyright (C) Altera Corporation 2000-2001 */
+/* */
+/* Description: Defines porting macros */
+/* */
+/****************************************************************************/
+
+#ifndef INC_JBIPORT_H
+#define INC_JBIPORT_H
+
+/*
+* PORT defines the target platform: DOS, WINDOWS, UNIX, or EMBEDDED
+*
+* PORT = DOS means a 16-bit DOS console-mode application
+*
+* PORT = WINDOWS means a 32-bit WIN32 console-mode application for
+* Windows 95, 98, 2000, ME or NT. On NT this will use the
+* DeviceIoControl() API to access the Parallel Port.
+*
+* PORT = UNIX means any UNIX system. BitBlaster access is support via
+* the standard ANSI system calls open(), read(), write().
+* The ByteBlaster is not supported.
+*
+* PORT = EMBEDDED means all DOS, WINDOWS, and UNIX code is excluded.
+* Remaining code supports 16 and 32-bit compilers.
+* Additional porting steps may be necessary. See readme
+* file for more details.
+*/
+
+#define DOS 2
+#define WINDOWS 3
+#define UNIX 4
+#define EMBEDDED 5
+
+#ifndef PORT
+/* change this line to build a different port */
+#define PORT UNIX
+#endif
+
+#define OPENBMC
+
+#endif /* INC_JBIPORT_H */
diff --git a/common/recipes-utils/jbi/files/code/jbistub.c b/common/recipes-utils/jbi/files/code/jbistub.c
new file mode 100644
index 0000000..87e9066
--- /dev/null
+++ b/common/recipes-utils/jbi/files/code/jbistub.c
@@ -0,0 +1,2222 @@
+/****************************************************************************/
+/* */
+/* Module: jbistub.c */
+/* */
+/* Copyright (C) Altera Corporation 1997-2001 */
+/* */
+/* Description: Jam STAPL ByteCode Player main source file */
+/* */
+/* Supports Altera ByteBlaster hardware download cable */
+/* on Windows 95 and Windows NT operating systems. */
+/* (A device driver is required for Windows NT.) */
+/* */
+/* Also supports BitBlaster hardware download cable on */
+/* Windows 95, Windows NT, and UNIX platforms. */
+/* */
+/* Revisions: 1.1 fixed control port initialization for ByteBlaster */
+/* 2.0 added support for STAPL bytecode format, added code */
+/* to get printer port address from Windows registry */
+/* 2.1 improved messages, fixed delay-calibration bug in */
+/* 16-bit DOS port, added support for "alternative */
+/* cable X", added option to control whether to reset */
+/* the TAP after execution, moved porting macros into */
+/* jbiport.h */
+/* 2.2 added support for static memory */
+/* fixed /W4 warnings */
+/* */
+/****************************************************************************/
+
+#ifndef NO_ALTERA_STDIO
+#define NO_ALTERA_STDIO
+#endif
+
+#if ( _MSC_VER >= 800 )
+#pragma warning(disable:4115)
+#pragma warning(disable:4201)
+#pragma warning(disable:4214)
+#pragma warning(disable:4514)
+#endif
+
+#include "jbiport.h"
+
+#if PORT == WINDOWS
+#include <windows.h>
+#else
+typedef int BOOL;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef OPENBMC
+#include <io.h>
+#endif
+#include <fcntl.h>
+#ifndef OPENBMC
+#include <process.h>
+#endif
+#if defined(USE_STATIC_MEMORY)
+ #define N_STATIC_MEMORY_KBYTES ((unsigned int) USE_STATIC_MEMORY)
+ #define N_STATIC_MEMORY_BYTES (N_STATIC_MEMORY_KBYTES * 1024)
+ #define POINTER_ALIGNMENT sizeof(DWORD)
+#else /* USE_STATIC_MEMORY */
+ #include <malloc.h>
+ #define POINTER_ALIGNMENT sizeof(BYTE)
+#endif /* USE_STATIC_MEMORY */
+#include <time.h>
+#ifndef OPENBMC
+#include <conio.h>
+#endif
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef OPENBMC
+//#define VERBOSE
+//#define DEBUG
+#include <openbmc/gpio.h>
+#include <openbmc/log.h>
+#include <errno.h>
+#endif
+
+#if PORT == DOS
+#include <bios.h>
+#endif
+
+#include "jbiexprt.h"
+
+#if PORT == WINDOWS
+#define PGDC_IOCTL_GET_DEVICE_INFO_PP 0x00166A00L
+#define PGDC_IOCTL_READ_PORT_PP 0x00166A04L
+#define PGDC_IOCTL_WRITE_PORT_PP 0x0016AA08L
+#define PGDC_IOCTL_PROCESS_LIST_PP 0x0016AA1CL
+#define PGDC_READ_INFO 0x0a80
+#define PGDC_READ_PORT 0x0a81
+#define PGDC_WRITE_PORT 0x0a82
+#define PGDC_PROCESS_LIST 0x0a87
+#define PGDC_HDLC_NTDRIVER_VERSION 2
+#define PORT_IO_BUFFER_SIZE 256
+#endif
+
+#if PORT == WINDOWS
+#ifdef __BORLANDC__
+/* create dummy inp() and outp() functions for Borland 32-bit compile */
+WORD inp(WORD address) { address = address; return(0); }
+void outp(WORD address, WORD data) { address = address; data = data; }
+#else
+#pragma intrinsic (inp, outp)
+#endif
+#endif
+
+/*
+* For Borland C compiler (16-bit), set the stack size
+*/
+#if PORT == DOS
+#ifdef __BORLANDC__
+extern unsigned int _stklen = 50000;
+#endif
+#endif
+
+/************************************************************************
+*
+* Global variables
+*/
+
+/* file buffer for Jam STAPL ByteCode input file */
+#if PORT == DOS
+unsigned char **file_buffer = NULL;
+#else
+unsigned char *file_buffer = NULL;
+#endif
+long file_pointer = 0L;
+long file_length = 0L;
+
+/* delay count for one millisecond delay */
+long one_ms_delay = 0L;
+
+/* serial port interface available on all platforms */
+BOOL jtag_hardware_initialized = FALSE;
+char *serial_port_name = NULL;
+BOOL specified_com_port = FALSE;
+int com_port = -1;
+void initialize_jtag_hardware(void);
+void close_jtag_hardware(void);
+
+#ifdef OPENBMC
+int g_tck = -1;
+int g_tms = -1;
+int g_tdo = -1;
+int g_tdi = -1;
+gpio_st g_gpio_tck;
+gpio_st g_gpio_tms;
+gpio_st g_gpio_tdo;
+gpio_st g_gpio_tdi;
+#endif
+
+#if defined(USE_STATIC_MEMORY)
+ unsigned char static_memory_heap[N_STATIC_MEMORY_BYTES] = { 0 };
+#endif /* USE_STATIC_MEMORY */
+
+#if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER)
+ unsigned int n_bytes_allocated = 0;
+#endif /* USE_STATIC_MEMORY || MEM_TRACKER */
+
+#if defined(MEM_TRACKER)
+ unsigned int peak_memory_usage = 0;
+ unsigned int peak_allocations = 0;
+ unsigned int n_allocations = 0;
+#if defined(USE_STATIC_MEMORY)
+ unsigned int n_bytes_not_recovered = 0;
+#endif /* USE_STATIC_MEMORY */
+ const DWORD BEGIN_GUARD = 0x01234567;
+ const DWORD END_GUARD = 0x76543210;
+#endif /* MEM_TRACKER */
+
+#if PORT == WINDOWS || PORT == DOS
+/* parallel port interface available on PC only */
+BOOL specified_lpt_port = FALSE;
+BOOL specified_lpt_addr = FALSE;
+int lpt_port = 1;
+int initial_lpt_ctrl = 0;
+WORD lpt_addr = 0x3bc;
+WORD lpt_addr_table[3] = { 0x3bc, 0x378, 0x278 };
+BOOL alternative_cable_l = FALSE;
+BOOL alternative_cable_x = FALSE;
+void write_byteblaster(int port, int data);
+int read_byteblaster(int port);
+#endif
+
+#if PORT==WINDOWS
+#ifndef __BORLANDC__
+WORD lpt_addresses_from_registry[4] = { 0 };
+#endif
+#endif
+
+#if PORT == WINDOWS
+/* variables to manage cached I/O under Windows NT */
+BOOL windows_nt = FALSE;
+int port_io_count = 0;
+HANDLE nt_device_handle = INVALID_HANDLE_VALUE;
+struct PORT_IO_LIST_STRUCT
+{
+ USHORT command;
+ USHORT data;
+} port_io_buffer[PORT_IO_BUFFER_SIZE];
+extern void flush_ports(void);
+BOOL initialize_nt_driver(void);
+#endif
+
+/* function prototypes to allow forward reference */
+extern void delay_loop(long count);
+
+/*
+* This structure stores information about each available vector signal
+*/
+struct VECTOR_LIST_STRUCT
+{
+ char *signal_name;
+ int hardware_bit;
+ int vector_index;
+};
+
+struct VECTOR_LIST_STRUCT vector_list[] =
+{
+ /* add a record here for each vector signal */
+ { "", 0, -1 }
+};
+
+#define VECTOR_SIGNAL_COUNT ((int)(sizeof(vector_list)/sizeof(vector_list[0])))
+
+BOOL verbose = FALSE;
+
+/************************************************************************
+*
+* Customized interface functions for Jam STAPL ByteCode Player I/O:
+*
+* jbi_jtag_io()
+* jbi_message()
+* jbi_delay()
+*/
+
+#ifdef OPENBMC
+
+/*
+ * The threshold (ns) to use spin instead of nanosleep().
+ * Before adding the high resolution timer support, either spin or nanosleep()
+ * will not bring the process wakeup within 10ms. It turns out the system time
+ * update is also controlled by HZ (100).
+ * After I added the high resolution timer support, the spin works as the
+ * system time is updated more frequently. However, nanosleep() solution is
+ * still noticable slower comparing with spin. There could be some kernel
+ * scheduling tweak missing. Did not get time on that yet.
+ * For now, use 10ms as the threshold to determine if spin or nanosleep()
+ * is used.
+ */
+#define SPIN_THRESHOLD (10 * 1000 * 1000)
+#define NANOSEC_IN_SEC (1000 * 1000 * 1000)
+
+static int sleep_ns(unsigned long clk)
+{
+ struct timespec req, rem;
+ int rc = 0;
+ if (clk <= SPIN_THRESHOLD) {
+ struct timespec orig;
+ rc = clock_gettime(CLOCK_MONOTONIC, &req);
+ orig = req;
+ while (!rc && clk) {
+ unsigned long tmp;
+ rc = clock_gettime(CLOCK_MONOTONIC, &rem);
+ tmp = (rem.tv_sec - req.tv_sec) * NANOSEC_IN_SEC;
+ if (rem.tv_nsec >= req.tv_nsec) {
+ tmp += rem.tv_nsec - req.tv_nsec;
+ } else {
+ tmp -= req.tv_nsec - rem.tv_nsec;
+ }
+ if (tmp >= clk) {
+ break;
+ }
+ clk -= tmp;
+ req = rem;
+ }
+ } else {
+ req.tv_sec = 0;
+ req.tv_nsec = clk;
+ while ((rc = nanosleep(&req, &rem)) == -1 && errno == EINTR) {
+ req = rem;
+ }
+ }
+ if (rc == -1) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to sleep %u nanoseconds", clk);
+ }
+ return rc;
+}
+
+int initialize_jtag_gpios()
+{
+ if (gpio_open(&g_gpio_tck, g_tck) || gpio_open(&g_gpio_tms, g_tms)
+ || gpio_open(&g_gpio_tdo, g_tdo) || gpio_open(&g_gpio_tdi, g_tdi)) {
+ return -1;
+ }
+
+ /* change GPIO directions, only TDO is input, all others are output */
+ if (gpio_change_direction(&g_gpio_tck, GPIO_DIRECTION_OUT)
+ || gpio_change_direction(&g_gpio_tms, GPIO_DIRECTION_OUT)
+ || gpio_change_direction(&g_gpio_tdo, GPIO_DIRECTION_IN)
+ || gpio_change_direction(&g_gpio_tdi, GPIO_DIRECTION_OUT)) {
+ return -1;
+ }
+
+ /* set tck, tms, tdi to low */
+ gpio_write(&g_gpio_tck, GPIO_VALUE_LOW);
+ gpio_write(&g_gpio_tms, GPIO_VALUE_LOW);
+ gpio_write(&g_gpio_tdi, GPIO_VALUE_LOW);
+
+ jbi_delay(1);
+
+ LOG_DBG("Opened TCK(GPIO %d), TMS(GPIO %d), TDI(GPIO %d), and TDO(GPIO %d)",
+ g_tck, g_tms, g_tdi, g_tdo);
+
+ return 0;
+}
+
+int jbi_jtag_io(int tms, int tdi, int read_tdo)
+{
+ int tdo = 0;
+
+ if (!jtag_hardware_initialized) {
+ initialize_jtag_gpios();
+ jtag_hardware_initialized = TRUE;
+ }
+
+ gpio_write(&g_gpio_tms, tms ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW);
+ gpio_write(&g_gpio_tdi, tdi ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW);
+
+ /* sleep 500ns to make sure the signal shows up on wire */
+ sleep_ns(500);
+ /*
+ * if we need to read data, the data should be ready from the
+ * previous clock falling edge. Read it now.
+ */
+ if (read_tdo) {
+ tdo = gpio_read(&g_gpio_tdo) == GPIO_VALUE_HIGH ? 1 : 0;
+ }
+
+ /* do rising edge to clock out the data */
+ gpio_write(&g_gpio_tck, GPIO_VALUE_HIGH);
+ sleep_ns(500);
+ /* do falling edge clocking */
+ gpio_write(&g_gpio_tck, GPIO_VALUE_LOW);
+
+ LOG_VER("tms=%d tdi=%d do_read=%d tdo=%d", tms, tdi, read_tdo, tdo);
+
+ return tdo;
+}
+
+#else
+
+int jbi_jtag_io(int tms, int tdi, int read_tdo)
+{
+ int data = 0;
+ int tdo = 0;
+ int i = 0;
+ int result = 0;
+ char ch_data = 0;
+
+ if (!jtag_hardware_initialized)
+ {
+ initialize_jtag_hardware();
+ jtag_hardware_initialized = TRUE;
+ }
+
+ if (specified_com_port)
+ {
+ ch_data = (char)
+ ((tdi ? 0x01 : 0) | (tms ? 0x02 : 0) | 0x60);
+
+ write(com_port, &ch_data, 1);
+
+ if (read_tdo)
+ {
+ ch_data = 0x7e;
+ write(com_port, &ch_data, 1);
+ for (i = 0; (i < 100) && (result != 1); ++i)
+ {
+ result = read(com_port, &ch_data, 1);
+ }
+ if (result == 1)
+ {
+ tdo = ch_data & 0x01;
+ }
+ else
+ {
+ fprintf(stderr, "Error: BitBlaster not responding\n");
+ }
+ }
+
+ ch_data = (char)
+ ((tdi ? 0x01 : 0) | (tms ? 0x02 : 0) | 0x64);
+
+ write(com_port, &ch_data, 1);
+ }
+ else
+ {
+#if PORT == WINDOWS || PORT == DOS
+ data = (alternative_cable_l ? ((tdi ? 0x01 : 0) | (tms ? 0x04 : 0)) :
+ (alternative_cable_x ? ((tdi ? 0x01 : 0) | (tms ? 0x04 : 0) | 0x10) :
+ ((tdi ? 0x40 : 0) | (tms ? 0x02 : 0))));
+
+ write_byteblaster(0, data);
+
+ if (read_tdo)
+ {
+ tdo = read_byteblaster(1);
+ tdo = (alternative_cable_l ? ((tdo & 0x40) ? 1 : 0) :
+ (alternative_cable_x ? ((tdo & 0x10) ? 1 : 0) :
+ ((tdo & 0x80) ? 0 : 1)));
+ }
+
+ write_byteblaster(0, data | (alternative_cable_l ? 0x02 : (alternative_cable_x ? 0x02: 0x01)));
+
+ write_byteblaster(0, data);
+#else
+ /* parallel port interface not available */
+ tdo = 0;
+#endif
+ }
+
+ return (tdo);
+}
+
+#endif
+
+void jbi_message(char *message_text)
+{
+ puts(message_text);
+ fflush(stdout);
+}
+
+void jbi_export_integer(char *key, long value)
+{
+ if (verbose)
+ {
+ printf("Export: key = \"%s\", value = %ld\n", key, value);
+ fflush(stdout);
+ }
+}
+
+#define HEX_LINE_CHARS 72
+#define HEX_LINE_BITS (HEX_LINE_CHARS * 4)
+
+char conv_to_hex(unsigned long value)
+{
+ char c;
+
+ if (value > 9)
+ {
+ c = (char) (value + ('A' - 10));
+ }
+ else
+ {
+ c = (char) (value + '0');
+ }
+
+ return (c);
+}
+
+void jbi_export_boolean_array(char *key, unsigned char *data, long count)
+{
+ char string[HEX_LINE_CHARS + 1];
+ long i, offset;
+ unsigned long size, line, lines, linebits, value, j, k;
+
+ if (verbose)
+ {
+ if (count > HEX_LINE_BITS)
+ {
+ printf("Export: key = \"%s\", %ld bits, value = HEX\n", key, count);
+ lines = (count + (HEX_LINE_BITS - 1)) / HEX_LINE_BITS;
+
+ for (line = 0; line < lines; ++line)
+ {
+ if (line < (lines - 1))
+ {
+ linebits = HEX_LINE_BITS;
+ size = HEX_LINE_CHARS;
+ offset = count - ((line + 1) * HEX_LINE_BITS);
+ }
+ else
+ {
+ linebits = count - ((lines - 1) * HEX_LINE_BITS);
+ size = (linebits + 3) / 4;
+ offset = 0L;
+ }
+
+ string[size] = '\0';
+ j = size - 1;
+ value = 0;
+
+ for (k = 0; k < linebits; ++k)
+ {
+ i = k + offset;
+ if (data[i >> 3] & (1 << (i & 7))) value |= (1 << (i & 3));
+ if ((i & 3) == 3)
+ {
+ string[j] = conv_to_hex(value);
+ value = 0;
+ --j;
+ }
+ }
+ if ((k & 3) > 0) string[j] = conv_to_hex(value);
+
+ printf("%s\n", string);
+ }
+
+ fflush(stdout);
+ }
+ else
+ {
+ size = (count + 3) / 4;
+ string[size] = '\0';
+ j = size - 1;
+ value = 0;
+
+ for (i = 0; i < count; ++i)
+ {
+ if (data[i >> 3] & (1 << (i & 7))) value |= (1 << (i & 3));
+ if ((i & 3) == 3)
+ {
+ string[j] = conv_to_hex(value);
+ value = 0;
+ --j;
+ }
+ }
+ if ((i & 3) > 0) string[j] = conv_to_hex(value);
+
+ printf("Export: key = \"%s\", %ld bits, value = HEX %s\n",
+ key, count, string);
+ fflush(stdout);
+ }
+ }
+}
+
+void jbi_delay(long microseconds)
+{
+#if PORT == WINDOWS
+ /* if Windows NT, flush I/O cache buffer before delay loop */
+ if (windows_nt && (port_io_count > 0)) flush_ports();
+#endif
+
+#ifdef OPENBMC
+ sleep_ns(microseconds * 1000);
+#else
+ delay_loop(microseconds *
+ ((one_ms_delay / 1000L) + ((one_ms_delay % 1000L) ? 1 : 0)));
+#endif
+}
+
+int jbi_vector_map
+(
+ int signal_count,
+ char **signals
+)
+{
+ int signal, vector, ch_index, diff;
+ int matched_count = 0;
+ char l, r;
+
+ for (vector = 0; (vector < VECTOR_SIGNAL_COUNT); ++vector)
+ {
+ vector_list[vector].vector_index = -1;
+ }
+
+ for (signal = 0; signal < signal_count; ++signal)
+ {
+ diff = 1;
+ for (vector = 0; (diff != 0) && (vector < VECTOR_SIGNAL_COUNT);
+ ++vector)
+ {
+ if (vector_list[vector].vector_index == -1)
+ {
+ ch_index = 0;
+ do
+ {
+ l = signals[signal][ch_index];
+ r = vector_list[vector].signal_name[ch_index];
+ diff = (((l >= 'a') && (l <= 'z')) ? (l - ('a' - 'A')) : l)
+ - (((r >= 'a') && (r <= 'z')) ? (r - ('a' - 'A')) : r);
+ ++ch_index;
+ }
+ while ((diff == 0) && (l != '\0') && (r != '\0'));
+
+ if (diff == 0)
+ {
+ vector_list[vector].vector_index = signal;
+ ++matched_count;
+ }
+ }
+ }
+ }
+
+ return (matched_count);
+}
+
+int jbi_vector_io
+(
+ int signal_count,
+ long *dir_vect,
+ long *data_vect,
+ long *capture_vect
+)
+{
+ int signal, vector, bit;
+ int matched_count = 0;
+ int data = 0;
+ int mask = 0;
+ int dir = 0;
+ int i = 0;
+ int result = 0;
+ char ch_data = 0;
+
+ if (!jtag_hardware_initialized)
+ {
+ initialize_jtag_hardware();
+ jtag_hardware_initialized = TRUE;
+ }
+
+ /*
+ * Collect information about output signals
+ */
+ for (vector = 0; vector < VECTOR_SIGNAL_COUNT; ++vector)
+ {
+ signal = vector_list[vector].vector_index;
+
+ if ((signal >= 0) && (signal < signal_count))
+ {
+ bit = (1 << vector_list[vector].hardware_bit);
+
+ mask |= bit;
+ if (data_vect[signal >> 5] & (1L << (signal & 0x1f))) data |= bit;
+ if (dir_vect[signal >> 5] & (1L << (signal & 0x1f))) dir |= bit;
+
+ ++matched_count;
+ }
+ }
+
+ /*
+ * Write outputs to hardware interface, if any
+ */
+ if (dir != 0)
+ {
+ if (specified_com_port)
+ {
+ ch_data = (char) (((data >> 6) & 0x01) | (data & 0x02) |
+ ((data << 2) & 0x04) | ((data << 3) & 0x08) | 0x60);
+ write(com_port, &ch_data, 1);
+ }
+ else
+ {
+#if PORT == WINDOWS || PORT == DOS
+
+ write_byteblaster(0, data);
+
+#endif
+ }
+ }
+
+ /*
+ * Read the input signals and save information in capture_vect[]
+ */
+ if ((dir != mask) && (capture_vect != NULL))
+ {
+ if (specified_com_port)
+ {
+ ch_data = 0x7e;
+ write(com_port, &ch_data, 1);
+ for (i = 0; (i < 100) && (result != 1); ++i)
+ {
+ result = read(com_port, &ch_data, 1);
+ }
+ if (result == 1)
+ {
+ data = ((ch_data << 7) & 0x80) | ((ch_data << 3) & 0x10);
+ }
+ else
+ {
+ fprintf(stderr, "Error: BitBlaster not responding\n");
+ }
+ }
+ else
+ {
+#if PORT == WINDOWS || PORT == DOS
+
+ data = read_byteblaster(1) ^ 0x80; /* parallel port inverts bit 7 */
+
+#endif
+ }
+
+ for (vector = 0; vector < VECTOR_SIGNAL_COUNT; ++vector)
+ {
+ signal = vector_list[vector].vector_index;
+
+ if ((signal >= 0) && (signal < signal_count))
+ {
+ bit = (1 << vector_list[vector].hardware_bit);
+
+ if ((dir & bit) == 0) /* if it is an input signal... */
+ {
+ if (data & bit)
+ {
+ capture_vect[signal >> 5] |= (1L << (signal & 0x1f));
+ }
+ else
+ {
+ capture_vect[signal >> 5] &= ~(unsigned long)
+ (1L << (signal & 0x1f));
+ }
+ }
+ }
+ }
+ }
+
+ return (matched_count);
+}
+
+void *jbi_malloc(unsigned int size)
+{
+ unsigned int n_bytes_to_allocate =
+#if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER)
+ sizeof(unsigned int) +
+#endif /* USE_STATIC_MEMORY || MEM_TRACKER */
+#if defined(MEM_TRACKER)
+ (2 * sizeof(DWORD)) +
+#endif /* MEM_TRACKER */
+ (POINTER_ALIGNMENT * ((size + POINTER_ALIGNMENT - 1) / POINTER_ALIGNMENT));
+
+ unsigned char *ptr = 0;
+
+
+#if defined(MEM_TRACKER)
+ if ((n_bytes_allocated + n_bytes_to_allocate) > peak_memory_usage)
+ {
+ peak_memory_usage = n_bytes_allocated + n_bytes_to_allocate;
+ }
+ if ((n_allocations + 1) > peak_allocations)
+ {
+ peak_allocations = n_allocations + 1;
+ }
+#endif /* MEM_TRACKER */
+
+#if defined(USE_STATIC_MEMORY)
+ if ((n_bytes_allocated + n_bytes_to_allocate) <= N_STATIC_MEMORY_BYTES)
+ {
+ ptr = (&(static_memory_heap[n_bytes_allocated]));
+ }
+#else /* USE_STATIC_MEMORY */
+ ptr = (unsigned char *) malloc(n_bytes_to_allocate);
+#endif /* USE_STATIC_MEMORY */
+
+#if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER)
+ if (ptr != 0)
+ {
+ unsigned int i = 0;
+
+#if defined(MEM_TRACKER)
+ for (i = 0; i < sizeof(DWORD); ++i)
+ {
+ *ptr = (unsigned char) (BEGIN_GUARD >> (8 * i));
+ ++ptr;
+ }
+#endif /* MEM_TRACKER */
+
+ for (i = 0; i < sizeof(unsigned int); ++i)
+ {
+ *ptr = (unsigned char) (size >> (8 * i));
+ ++ptr;
+ }
+
+#if defined(MEM_TRACKER)
+ for (i = 0; i < sizeof(DWORD); ++i)
+ {
+ *(ptr + size + i) = (unsigned char) (END_GUARD >> (8 * i));
+ /* don't increment ptr */
+ }
+
+ ++n_allocations;
+#endif /* MEM_TRACKER */
+
+ n_bytes_allocated += n_bytes_to_allocate;
+ }
+#endif /* USE_STATIC_MEMORY || MEM_TRACKER */
+
+ return ptr;
+}
+
+void jbi_free(void *ptr)
+{
+ if
+ (
+#if defined(MEM_TRACKER)
+ (n_allocations > 0) &&
+#endif /* MEM_TRACKER */
+ (ptr != 0)
+ )
+ {
+ unsigned char *tmp_ptr = (unsigned char *) ptr;
+
+#if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER)
+ unsigned int n_bytes_to_free = 0;
+ unsigned int i = 0;
+ unsigned int size = 0;
+#endif /* USE_STATIC_MEMORY || MEM_TRACKER */
+#if defined(MEM_TRACKER)
+ DWORD begin_guard = 0;
+ DWORD end_guard = 0;
+
+
+ tmp_ptr -= sizeof(DWORD);
+#endif /* MEM_TRACKER */
+#if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER)
+ tmp_ptr -= sizeof(unsigned int);
+#endif /* USE_STATIC_MEMORY || MEM_TRACKER */
+ ptr = tmp_ptr;
+
+#if defined(MEM_TRACKER)
+ for (i = 0; i < sizeof(DWORD); ++i)
+ {
+ begin_guard |= (((DWORD)(*tmp_ptr)) << (8 * i));
+ ++tmp_ptr;
+ }
+#endif /* MEM_TRACKER */
+
+#if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER)
+ for (i = 0; i < sizeof(unsigned int); ++i)
+ {
+ size |= (((unsigned int)(*tmp_ptr)) << (8 * i));
+ ++tmp_ptr;
+ }
+#endif /* USE_STATIC_MEMORY || MEM_TRACKER */
+
+#if defined(MEM_TRACKER)
+ tmp_ptr += size;
+
+ for (i = 0; i < sizeof(DWORD); ++i)
+ {
+ end_guard |= (((DWORD)(*tmp_ptr)) << (8 * i));
+ ++tmp_ptr;
+ }
+
+ if ((begin_guard != BEGIN_GUARD) || (end_guard != END_GUARD))
+ {
+ fprintf(stderr, "Error: memory corruption detected for allocation #%d... bad %s guard\n",
+ n_allocations, (begin_guard != BEGIN_GUARD) ? "begin" : "end");
+ }
+
+ --n_allocations;
+#endif /* MEM_TRACKER */
+
+#if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER)
+ n_bytes_to_free =
+#if defined(MEM_TRACKER)
+ (2 * sizeof(DWORD)) +
+#endif /* MEM_TRACKER */
+ sizeof(unsigned int) +
+ (POINTER_ALIGNMENT * ((size + POINTER_ALIGNMENT - 1) / POINTER_ALIGNMENT));
+#endif /* USE_STATIC_MEMORY || MEM_TRACKER */
+
+#if defined(USE_STATIC_MEMORY)
+ if ((((unsigned long) ptr - (unsigned long) static_memory_heap) + n_bytes_to_free) == (unsigned long) n_bytes_allocated)
+ {
+ n_bytes_allocated -= n_bytes_to_free;
+ }
+#if defined(MEM_TRACKER)
+ else
+ {
+ n_bytes_not_recovered += n_bytes_to_free;
+ }
+#endif /* MEM_TRACKER */
+#else /* USE_STATIC_MEMORY */
+#if defined(MEM_TRACKER)
+ n_bytes_allocated -= n_bytes_to_free;
+#endif /* MEM_TRACKER */
+ free(ptr);
+#endif /* USE_STATIC_MEMORY */
+ }
+#if defined(MEM_TRACKER)
+ else
+ {
+ if (ptr != 0)
+ {
+ fprintf(stderr, "Error: attempt to free unallocated memory\n");
+ }
+ }
+#endif /* MEM_TRACKER */
+}
+
+/************************************************************************
+*
+* get_tick_count() -- Get system tick count in milliseconds
+*
+* for DOS, use BIOS function _bios_timeofday()
+* for WINDOWS use GetTickCount() function
+* for UNIX use clock() system function
+*/
+DWORD get_tick_count(void)
+{
+ DWORD tick_count = 0L;
+
+#if PORT == WINDOWS
+ tick_count = GetTickCount();
+#elif PORT == DOS
+ _bios_timeofday(_TIME_GETCLOCK, (long *)&tick_count);
+ tick_count *= 55L; /* convert to milliseconds */
+#else
+ /* assume clock() function returns microseconds */
+ tick_count = (DWORD) (clock() / 1000L);
+#endif
+
+ return (tick_count);
+}
+
+#define DELAY_SAMPLES 10
+#define DELAY_CHECK_LOOPS 10000
+
+void calibrate_delay(void)
+{
+ int sample = 0;
+ int count = 0;
+ DWORD tick_count1 = 0L;
+ DWORD tick_count2 = 0L;
+
+ one_ms_delay = 0L;
+
+#if PORT == WINDOWS || PORT == DOS || defined(OPENBMC)
+ for (sample = 0; sample < DELAY_SAMPLES; ++sample)
+ {
+ count = 0;
+ tick_count1 = get_tick_count();
+ while ((tick_count2 = get_tick_count()) == tick_count1) {};
+ do { delay_loop(DELAY_CHECK_LOOPS); count++; } while
+ ((tick_count1 = get_tick_count()) == tick_count2);
+ one_ms_delay += ((DELAY_CHECK_LOOPS * (DWORD)count) /
+ (tick_count1 - tick_count2));
+ }
+
+ one_ms_delay /= DELAY_SAMPLES;
+#else
+ /* This is system-dependent! Update this number for target system */
+ one_ms_delay = 1000L;
+#endif
+}
+
+char *error_text[] =
+{
+/* JBIC_SUCCESS 0 */ "success",
+/* JBIC_OUT_OF_MEMORY 1 */ "out of memory",
+/* JBIC_IO_ERROR 2 */ "file access error",
+/* JAMC_SYNTAX_ERROR 3 */ "syntax error",
+/* JBIC_UNEXPECTED_END 4 */ "unexpected end of file",
+/* JBIC_UNDEFINED_SYMBOL 5 */ "undefined symbol",
+/* JAMC_REDEFINED_SYMBOL 6 */ "redefined symbol",
+/* JBIC_INTEGER_OVERFLOW 7 */ "integer overflow",
+/* JBIC_DIVIDE_BY_ZERO 8 */ "divide by zero",
+/* JBIC_CRC_ERROR 9 */ "CRC mismatch",
+/* JBIC_INTERNAL_ERROR 10 */ "internal error",
+/* JBIC_BOUNDS_ERROR 11 */ "bounds error",
+/* JAMC_TYPE_MISMATCH 12 */ "type mismatch",
+/* JAMC_ASSIGN_TO_CONST 13 */ "assignment to constant",
+/* JAMC_NEXT_UNEXPECTED 14 */ "NEXT unexpected",
+/* JAMC_POP_UNEXPECTED 15 */ "POP unexpected",
+/* JAMC_RETURN_UNEXPECTED 16 */ "RETURN unexpected",
+/* JAMC_ILLEGAL_SYMBOL 17 */ "illegal symbol name",
+/* JBIC_VECTOR_MAP_FAILED 18 */ "vector signal name not found",
+/* JBIC_USER_ABORT 19 */ "execution cancelled",
+/* JBIC_STACK_OVERFLOW 20 */ "stack overflow",
+/* JBIC_ILLEGAL_OPCODE 21 */ "illegal instruction code",
+/* JAMC_PHASE_ERROR 22 */ "phase error",
+/* JAMC_SCOPE_ERROR 23 */ "scope error",
+/* JBIC_ACTION_NOT_FOUND 24 */ "action not found",
+};
+
+#define MAX_ERROR_CODE (int)((sizeof(error_text)/sizeof(error_text[0]))+1)
+
+/************************************************************************/
+
+int main(int argc, char **argv)
+{
+ BOOL help = FALSE;
+ BOOL error = FALSE;
+ char *filename = NULL;
+ long offset = 0L;
+ long error_address = 0L;
+ JBI_RETURN_TYPE crc_result = JBIC_SUCCESS;
+ JBI_RETURN_TYPE exec_result = JBIC_SUCCESS;
+ unsigned short expected_crc = 0;
+ unsigned short actual_crc = 0;
+ char key[33] = {0};
+ char value[257] = {0};
+ int exit_status = 0;
+ int arg = 0;
+ int exit_code = 0;
+ int format_version = 0;
+ time_t start_time = 0;
+ time_t end_time = 0;
+ int time_delta = 0;
+ char *workspace = NULL;
+ char *action = NULL;
+ char *init_list[10];
+ int init_count = 0;
+ FILE *fp = NULL;
+ struct stat sbuf;
+ long workspace_size = 0;
+ char *exit_string = NULL;
+ int reset_jtag = 1;
+ int execute_program = 1;
+ int action_count = 0;
+ int procedure_count = 0;
+ int index = 0;
+ char *action_name = NULL;
+ char *description = NULL;
+ JBI_PROCINFO *procedure_list = NULL;
+ JBI_PROCINFO *procptr = NULL;
+
+ verbose = FALSE;
+
+ init_list[0] = NULL;
+
+ /* print out the version string and copyright message */
+ fprintf(stderr, "Jam STAPL ByteCode Player Version 2.2\nCopyright (C) 1998-2001 Altera Corporation\n\n");
+
+ for (arg = 1; arg < argc; arg++)
+ {
+#if PORT == UNIX
+ if (argv[arg][0] == '-')
+#else
+ if ((argv[arg][0] == '-') || (argv[arg][0] == '/'))
+#endif
+ {
+ switch(toupper(argv[arg][1]))
+ {
+ case 'A': /* set action name */
+ if (action == NULL)
+ {
+ action = &argv[arg][2];
+ }
+ else
+ {
+ error = TRUE;
+ }
+ break;
+
+#if PORT == WINDOWS || PORT == DOS
+ case 'C': /* Use alternative ISP download cable */
+ if(toupper(argv[arg][2]) == 'L')
+ alternative_cable_l = TRUE;
+ else if(toupper(argv[arg][2]) == 'X')
+ alternative_cable_x = TRUE;
+ break;
+#endif
+
+ case 'D': /* initialization list */
+ if (argv[arg][2] == '"')
+ {
+ init_list[init_count] = &argv[arg][3];
+ }
+ else
+ {
+ init_list[init_count] = &argv[arg][2];
+ }
+ init_list[++init_count] = NULL;
+ break;
+
+#if PORT == WINDOWS || PORT == DOS
+ case 'P': /* set LPT port address */
+ specified_lpt_port = TRUE;
+ if (sscanf(&argv[arg][2], "%d", &lpt_port) != 1) error = TRUE;
+ if ((lpt_port < 1) || (lpt_port > 3)) error = TRUE;
+ if (error)
+ {
+ if (sscanf(&argv[arg][2], "%x", &lpt_port) == 1)
+ {
+ if ((lpt_port == 0x3bc) ||
+ (lpt_port == 0x378) ||
+ (lpt_port == 0x278))
+ {
+ error = FALSE;
+ specified_lpt_addr = TRUE;
+ lpt_addr = (WORD) lpt_port;
+ lpt_port = 1;
+ }
+ }
+ }
+ break;
+#endif
+
+ case 'R': /* don't reset the JTAG chain after use */
+ reset_jtag = 0;
+ break;
+
+#ifdef OPENBMC
+ case 'G': /* GPIO directory */
+ switch (toupper(argv[arg][2])) {
+ case 'C':
+ g_tck = atoi(&argv[arg][3]);
+ break;
+ case 'S':
+ g_tms = atoi(&argv[arg][3]);
+ break;
+ case 'I':
+ g_tdi = atoi(&argv[arg][3]);
+ break;
+ case 'O':
+ g_tdo = atoi(&argv[arg][3]);
+ break;
+ }
+ break;
+#else
+ case 'S': /* set serial port address */
+ serial_port_name = &argv[arg][2];
+ specified_com_port = TRUE;
+ break;
+#endif
+
+ case 'M': /* set memory size */
+ if (sscanf(&argv[arg][2], "%ld", &workspace_size) != 1)
+ error = TRUE;
+ if (workspace_size == 0) error = TRUE;
+ break;
+
+ case 'H': /* help */
+ help = TRUE;
+ break;
+
+ case 'V': /* verbose */
+ verbose = TRUE;
+ break;
+
+ case 'I': /* show info only, do not execute */
+ verbose = TRUE;
+ execute_program = 0;
+ break;
+
+ default:
+ error = TRUE;
+ break;
+ }
+ }
+ else
+ {
+ /* it's a filename */
+ if (filename == NULL)
+ {
+ filename = argv[arg];
+ }
+ else
+ {
+ /* error -- we already found a filename */
+ error = TRUE;
+ }
+ }
+
+ if (error)
+ {
+ fprintf(stderr, "Illegal argument: \"%s\"\n", argv[arg]);
+ help = TRUE;
+ error = FALSE;
+ }
+ }
+
+#if PORT == WINDOWS || PORT == DOS
+ if (specified_lpt_port && specified_com_port)
+ {
+ fprintf(stderr, "Error: -s and -p options may not be used together\n\n");
+ help = TRUE;
+ }
+#endif
+
+#ifdef OPENBMC
+ if (execute_program) {
+ if (g_tck == -1 || g_tms == -1 || g_tdo == -1 || g_tdi == -1) {
+ fprintf(stderr, "Error: -gc, -gs, -gi, and -go must be specified\n");
+ help = TRUE;
+ }
+ }
+#endif
+
+ if (help || (filename == NULL))
+ {
+ fprintf(stderr, "Usage: jbi [options] <filename>\n");
+ fprintf(stderr, "\nAvailable options:\n");
+ fprintf(stderr, " -h : show help message\n");
+ fprintf(stderr, " -v : show verbose messages\n");
+ fprintf(stderr, " -i : show file info only - does not execute any action\n");
+ fprintf(stderr, " -a<action> : specify an action name (Jam STAPL)\n");
+ fprintf(stderr, " -d<var=val> : initialize variable to specified value (Jam 1.1)\n");
+ fprintf(stderr, " -d<proc=1> : enable optional procedure (Jam STAPL)\n");
+ fprintf(stderr, " -d<proc=0> : disable recommended procedure (Jam STAPL)\n");
+#if PORT == WINDOWS || PORT == DOS
+ fprintf(stderr, " -p<port> : parallel port number or address (for ByteBlaster)\n");
+ fprintf(stderr, " -c<cable> : alternative download cable compatibility: -cl or -cx\n");
+#endif
+#ifdef OPENBMC
+ fprintf(stderr, " -gc<clock> : GPIO directory for TCK\n");
+ fprintf(stderr, " -gs<clock> : GPIO directory for TMS\n");
+ fprintf(stderr, " -gi<clock> : GPIO directory for TDI\n");
+ fprintf(stderr, " -go<clock> : GPIO directory for TDO\n");
+#else
+ fprintf(stderr, " -s<port> : serial port name (for BitBlaster)\n");
+#endif
+ fprintf(stderr, " -r : don't reset JTAG TAP after use\n");
+ exit_status = 1;
+ }
+ else if ((workspace_size > 0) &&
+ ((workspace = (char *) jbi_malloc((size_t) workspace_size)) == NULL))
+ {
+ fprintf(stderr, "Error: can't allocate memory (%d Kbytes)\n",
+ (int) (workspace_size / 1024L));
+ exit_status = 1;
+ }
+ else if (access(filename, 0) != 0)
+ {
+ fprintf(stderr, "Error: can't access file \"%s\"\n", filename);
+ exit_status = 1;
+ }
+ else
+ {
+ /* get length of file */
+ if (stat(filename, &sbuf) == 0) file_length = sbuf.st_size;
+
+ if ((fp = fopen(filename, "rb")) == NULL)
+ {
+ fprintf(stderr, "Error: can't open file \"%s\"\n", filename);
+ exit_status = 1;
+ }
+ else
+ {
+ /*
+ * Read entire file into a buffer
+ */
+#if PORT == DOS
+ int pages = 1 + (int) (file_length >> 14L);
+ int page;
+ file_buffer = (unsigned char **) jbi_malloc(
+ (size_t) (pages * sizeof(char *)));
+
+ for (page = 0; page < pages; ++page)
+ {
+ /* allocate enough 16K blocks to store the file */
+ file_buffer[page] = (unsigned char *) jbi_malloc (0x4000);
+ if (file_buffer[page] == NULL)
+ {
+ /* flag error and break out of loop */
+ file_buffer = NULL;
+ page = pages;
+ }
+ }
+#else
+ file_buffer = (unsigned char *) jbi_malloc((size_t) file_length);
+#endif
+
+ if (file_buffer == NULL)
+ {
+ fprintf(stderr, "Error: can't allocate memory (%d Kbytes)\n",
+ (int) (file_length / 1024L));
+ exit_status = 1;
+ }
+ else
+ {
+#if PORT == DOS
+ int pages = 1 + (int) (file_length >> 14L);
+ int page;
+ size_t page_size = 0x4000;
+ for (page = 0; (page < pages) && (exit_status == 0); ++page)
+ {
+ if (page == (pages - 1))
+ {
+ /* last page may not be full 16K bytes */
+ page_size = (size_t) (file_length & 0x3fffL);
+ }
+ if (fread(file_buffer[page], 1, page_size, fp) != page_size)
+ {
+ fprintf(stderr, "Error reading file \"%s\"\n", filename);
+ exit_status = 1;
+ }
+ }
+#else
+ if (fread(file_buffer, 1, (size_t) file_length, fp) !=
+ (size_t) file_length)
+ {
+ fprintf(stderr, "Error reading file \"%s\"\n", filename);
+ exit_status = 1;
+ }
+#endif
+ }
+
+ fclose(fp);
+ }
+
+ if (exit_status == 0)
+ {
+ /*
+ * Get Operating System type
+ */
+#if PORT == WINDOWS
+ windows_nt = !(GetVersion() & 0x80000000);
+#endif
+
+ /*
+ * Calibrate the delay loop function
+ */
+ calibrate_delay();
+
+ /*
+ * Check CRC
+ */
+ crc_result = jbi_check_crc(file_buffer, file_length,
+ &expected_crc, &actual_crc);
+
+ if (verbose || (crc_result == JBIC_CRC_ERROR))
+ {
+ switch (crc_result)
+ {
+ case JBIC_SUCCESS:
+ printf("CRC matched: CRC value = %04X\n", actual_crc);
+ break;
+
+ case JBIC_CRC_ERROR:
+ printf("CRC mismatch: expected %04X, actual %04X\n",
+ expected_crc, actual_crc);
+ break;
+
+ case JBIC_UNEXPECTED_END:
+ printf("Expected CRC not found, actual CRC value = %04X\n",
+ actual_crc);
+ break;
+
+ case JBIC_IO_ERROR:
+ printf("Error: File format is not recognized.\n");
+ exit(1);
+ break;
+
+ default:
+ printf("CRC function returned error code %d\n", crc_result);
+ break;
+ }
+ }
+
+ if (verbose)
+ {
+ /*
+ * Display file format version
+ */
+ jbi_get_file_info(file_buffer, file_length,
+ &format_version, &action_count, &procedure_count);
+
+ printf("File format is %s ByteCode format\n",
+ (format_version == 2) ? "Jam STAPL" : "pre-standardized Jam 1.1");
+
+ /*
+ * Dump out NOTE fields
+ */
+ while (jbi_get_note(file_buffer, file_length,
+ &offset, key, value, 256) == 0)
+ {
+ printf("NOTE \"%s\" = \"%s\"\n", key, value);
+ }
+
+ /*
+ * Dump the action table
+ */
+ if ((format_version == 2) && (action_count > 0))
+ {
+ printf("\nActions available in this file:\n");
+
+ for (index = 0; index < action_count; ++index)
+ {
+ jbi_get_action_info(file_buffer, file_length,
+ index, &action_name, &description, &procedure_list);
+
+ if (description == NULL)
+ {
+ printf("%s\n", action_name);
+ }
+ else
+ {
+ printf("%s \"%s\"\n", action_name, description);
+ }
+
+#if PORT == DOS
+ if (action_name != NULL) jbi_free(action_name);
+ if (description != NULL) jbi_free(description);
+#endif
+
+ procptr = procedure_list;
+ while (procptr != NULL)
+ {
+ if (procptr->attributes != 0)
+ {
+ printf(" %s (%s)\n", procptr->name,
+ (procptr->attributes == 1) ?
+ "optional" : "recommended");
+ }
+
+#if PORT == DOS
+ if (procptr->name != NULL) jbi_free(procptr->name);
+#endif
+
+ procedure_list = procptr->next;
+ jbi_free(procptr);
+ procptr = procedure_list;
+ }
+ }
+
+ /* add a blank line before execution messages */
+ if (execute_program) printf("\n");
+ }
+ }
+
+ if (execute_program)
+ {
+ /*
+ * Execute the Jam STAPL ByteCode program
+ */
+ time(&start_time);
+ exec_result = jbi_execute(file_buffer, file_length, workspace,
+ workspace_size, action, init_list, reset_jtag,
+ &error_address, &exit_code, &format_version);
+ time(&end_time);
+
+ if (exec_result == JBIC_SUCCESS)
+ {
+ if (format_version == 2)
+ {
+ switch (exit_code)
+ {
+ case 0: exit_string = "Success"; break;
+ case 1: exit_string = "Checking chain failure"; break;
+ case 2: exit_string = "Reading IDCODE failure"; break;
+ case 3: exit_string = "Reading USERCODE failure"; break;
+ case 4: exit_string = "Reading UESCODE failure"; break;
+ case 5: exit_string = "Entering ISP failure"; break;
+ case 6: exit_string = "Unrecognized device"; break;
+ case 7: exit_string = "Device revision is not supported"; break;
+ case 8: exit_string = "Erase failure"; break;
+ case 9: exit_string = "Device is not blank"; break;
+ case 10: exit_string = "Device programming failure"; break;
+ case 11: exit_string = "Device verify failure"; break;
+ case 12: exit_string = "Read failure"; break;
+ case 13: exit_string = "Calculating checksum failure"; break;
+ case 14: exit_string = "Setting security bit failure"; break;
+ case 15: exit_string = "Querying security bit failure"; break;
+ case 16: exit_string = "Exiting ISP failure"; break;
+ case 17: exit_string = "Performing system test failure"; break;
+ default: exit_string = "Unknown exit code"; break;
+ }
+ }
+ else
+ {
+ switch (exit_code)
+ {
+ case 0: exit_string = "Success"; break;
+ case 1: exit_string = "Illegal initialization values"; break;
+ case 2: exit_string = "Unrecognized device"; break;
+ case 3: exit_string = "Device revision is not supported"; break;
+ case 4: exit_string = "Device programming failure"; break;
+ case 5: exit_string = "Device is not blank"; break;
+ case 6: exit_string = "Device verify failure"; break;
+ case 7: exit_string = "SRAM configuration failure"; break;
+ default: exit_string = "Unknown exit code"; break;
+ }
+ }
+
+ printf("Exit code = %d... %s\n", exit_code, exit_string);
+ }
+ else if ((format_version == 2) &&
+ (exec_result == JBIC_ACTION_NOT_FOUND))
+ {
+ if ((action == NULL) || (*action == '\0'))
+ {
+ printf("Error: no action specified for Jam STAPL file.\nProgram terminated.\n");
+ }
+ else
+ {
+ printf("Error: action \"%s\" is not supported for this Jam STAPL file.\nProgram terminated.\n", action);
+ }
+ }
+ else if (exec_result < MAX_ERROR_CODE)
+ {
+ printf("Error at address %ld: %s.\nProgram terminated.\n",
+ error_address, error_text[exec_result]);
+ }
+ else
+ {
+ printf("Unknown error code %ld\n", exec_result);
+ }
+
+ /*
+ * Print out elapsed time
+ */
+ if (verbose)
+ {
+ time_delta = (int) (end_time - start_time);
+ printf("Elapsed time = %02u:%02u:%02u\n",
+ time_delta / 3600, /* hours */
+ (time_delta % 3600) / 60, /* minutes */
+ time_delta % 60); /* seconds */
+ }
+ }
+ }
+ }
+
+ if (jtag_hardware_initialized) close_jtag_hardware();
+
+ if (workspace != NULL) jbi_free(workspace);
+ if (file_buffer != NULL) jbi_free(file_buffer);
+
+#if defined(MEM_TRACKER)
+ if (verbose)
+ {
+#if defined(USE_STATIC_MEMORY)
+ fprintf(stdout, "Memory Usage Info: static memory size = %ud (%dKB)\n", N_STATIC_MEMORY_BYTES, N_STATIC_MEMORY_KBYTES);
+#endif /* USE_STATIC_MEMORY */
+ fprintf(stdout, "Memory Usage Info: peak memory usage = %ud (%dKB)\n", peak_memory_usage, (peak_memory_usage + 1023) / 1024);
+ fprintf(stdout, "Memory Usage Info: peak allocations = %d\n", peak_allocations);
+#if defined(USE_STATIC_MEMORY)
+ if ((n_bytes_allocated - n_bytes_not_recovered) != 0)
+ {
+ fprintf(stdout, "Memory Usage Info: bytes still allocated = %d (%dKB)\n", (n_bytes_allocated - n_bytes_not_recovered), ((n_bytes_allocated - n_bytes_not_recovered) + 1023) / 1024);
+ }
+#else /* USE_STATIC_MEMORY */
+ if (n_bytes_allocated != 0)
+ {
+ fprintf(stdout, "Memory Usage Info: bytes still allocated = %d (%dKB)\n", n_bytes_allocated, (n_bytes_allocated + 1023) / 1024);
+ }
+#endif /* USE_STATIC_MEMORY */
+ if (n_allocations != 0)
+ {
+ fprintf(stdout, "Memory Usage Info: allocations not freed = %d\n", n_allocations);
+ }
+ }
+#endif /* MEM_TRACKER */
+
+ return (exit_status);
+}
+
+#if PORT==WINDOWS
+#ifndef __BORLANDC__
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* SEARCH_DYN_DATA
+*
+* Searches recursively in Windows 95/98 Registry for parallel port info
+* under HKEY_DYN_DATA registry key. Called by search_local_machine().
+*/
+void search_dyn_data
+(
+ char *dd_path,
+ char *hardware_key,
+ int lpt
+)
+{
+ DWORD index;
+ DWORD size;
+ DWORD type;
+ LONG result;
+ HKEY key;
+ int length;
+ WORD address;
+ char buffer[1024];
+ FILETIME last_write = {0};
+ WORD *word_ptr;
+ int i;
+
+ length = strlen(dd_path);
+
+ if (RegOpenKeyEx(
+ HKEY_DYN_DATA,
+ dd_path,
+ 0L,
+ KEY_READ,
+ &key)
+ == ERROR_SUCCESS)
+ {
+ size = 1023;
+
+ if (RegQueryValueEx(
+ key,
+ "HardWareKey",
+ NULL,
+ &type,
+ (unsigned char *) buffer,
+ &size)
+ == ERROR_SUCCESS)
+ {
+ if ((type == REG_SZ) && (stricmp(buffer, hardware_key) == 0))
+ {
+ size = 1023;
+
+ if (RegQueryValueEx(
+ key,
+ "Allocation",
+ NULL,
+ &type,
+ (unsigned char *) buffer,
+ &size)
+ == ERROR_SUCCESS)
+ {
+ /*
+ * By "inspection", I have found five cases: size 32, 48,
+ * 56, 60, and 80 bytes. The port address seems to be
+ * located at different offsets in the buffer for these
+ * five cases, as shown below. If a valid port address
+ * is not found, or the size is not one of these known
+ * sizes, then I search through the entire buffer and
+ * look for a value which is a valid port address.
+ */
+
+ word_ptr = (WORD *) buffer;
+
+ if ((type == REG_BINARY) && (size == 32))
+ {
+ address = word_ptr[10];
+ }
+ else if ((type == REG_BINARY) && (size == 48))
+ {
+ address = word_ptr[18];
+ }
+ else if ((type == REG_BINARY) && (size == 56))
+ {
+ address = word_ptr[22];
+ }
+ else if ((type == REG_BINARY) && (size == 60))
+ {
+ address = word_ptr[24];
+ }
+ else if ((type == REG_BINARY) && (size == 80))
+ {
+ address = word_ptr[24];
+ }
+ else address = 0;
+
+ /* if not found, search through entire buffer */
+ i = 0;
+ while ((i < (int) (size / 2)) &&
+ (address != 0x278) &&
+ (address != 0x27C) &&
+ (address != 0x378) &&
+ (address != 0x37C) &&
+ (address != 0x3B8) &&
+ (address != 0x3BC))
+ {
+ if ((word_ptr[i] == 0x278) ||
+ (word_ptr[i] == 0x27C) ||
+ (word_ptr[i] == 0x378) ||
+ (word_ptr[i] == 0x37C) ||
+ (word_ptr[i] == 0x3B8) ||
+ (word_ptr[i] == 0x3BC))
+ {
+ address = word_ptr[i];
+ }
+ ++i;
+ }
+
+ if ((address == 0x278) ||
+ (address == 0x27C) ||
+ (address == 0x378) ||
+ (address == 0x37C) ||
+ (address == 0x3B8) ||
+ (address == 0x3BC))
+ {
+ lpt_addresses_from_registry[lpt] = address;
+ }
+ }
+ }
+ }
+
+ index = 0;
+
+ do
+ {
+ size = 1023;
+
+ result = RegEnumKeyEx(
+ key,
+ index++,
+ buffer,
+ &size,
+ NULL,
+ NULL,
+ NULL,
+ &last_write);
+
+ if (result == ERROR_SUCCESS)
+ {
+ dd_path[length] = '\\';
+ dd_path[length + 1] = '\0';
+ strcpy(&dd_path[length + 1], buffer);
+
+ search_dyn_data(dd_path, hardware_key, lpt);
+
+ dd_path[length] = '\0';
+ }
+ }
+ while (result == ERROR_SUCCESS);
+
+ RegCloseKey(key);
+ }
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* SEARCH_LOCAL_MACHINE
+*
+* Searches recursively in Windows 95/98 Registry for parallel port info
+* under HKEY_LOCAL_MACHINE\Enum. When parallel port is found, calls
+* search_dyn_data() to get the port address.
+*/
+void search_local_machine
+(
+ char *lm_path,
+ char *dd_path
+)
+{
+ DWORD index;
+ DWORD size;
+ DWORD type;
+ LONG result;
+ HKEY key;
+ int length;
+ char buffer[1024];
+ FILETIME last_write = {0};
+
+ length = strlen(lm_path);
+
+ if (RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ lm_path,
+ 0L,
+ KEY_READ,
+ &key)
+ == ERROR_SUCCESS)
+ {
+ size = 1023;
+
+ if (RegQueryValueEx(
+ key,
+ "PortName",
+ NULL,
+ &type,
+ (unsigned char *) buffer,
+ &size)
+ == ERROR_SUCCESS)
+ {
+ if ((type == REG_SZ) &&
+ (size == 5) &&
+ (buffer[0] == 'L') &&
+ (buffer[1] == 'P') &&
+ (buffer[2] == 'T') &&
+ (buffer[3] >= '1') &&
+ (buffer[3] <= '4') &&
+ (buffer[4] == '\0'))
+ {
+ /* we found the entry in HKEY_LOCAL_MACHINE, now we need to */
+ /* find the corresponding entry under HKEY_DYN_DATA. */
+ /* add 5 to lm_path to skip over "Enum" and backslash */
+ search_dyn_data(dd_path, &lm_path[5], (buffer[3] - '1'));
+ }
+ }
+
+ index = 0;
+
+ do
+ {
+ size = 1023;
+
+ result = RegEnumKeyEx(
+ key,
+ index++,
+ buffer,
+ &size,
+ NULL,
+ NULL,
+ NULL,
+ &last_write);
+
+ if (result == ERROR_SUCCESS)
+ {
+ lm_path[length] = '\\';
+ lm_path[length + 1] = '\0';
+ strcpy(&lm_path[length + 1], buffer);
+
+ search_local_machine(lm_path, dd_path);
+
+ lm_path[length] = '\0';
+ }
+ }
+ while (result == ERROR_SUCCESS);
+
+ RegCloseKey(key);
+ }
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* GET_LPT_ADDRESSES_FROM_REGISTRY
+*
+* Searches Win95/98 registry recursively to get I/O port addresses for
+* parallel ports.
+*/
+void get_lpt_addresses_from_registry()
+{
+ char lm_path[1024];
+ char dd_path[1024];
+
+ strcpy(lm_path, "Enum");
+ strcpy(dd_path, "Config Manager");
+ search_local_machine(lm_path, dd_path);
+}
+#endif
+#endif
+
+void initialize_jtag_hardware()
+{
+ if (specified_com_port)
+ {
+ com_port = open(serial_port_name, O_RDWR);
+ if (com_port == -1)
+ {
+ fprintf(stderr, "Error: can't open serial port \"%s\"\n",
+ serial_port_name);
+ }
+ else
+ {
+ int i = 0, result = 0;
+ char data = 0;
+
+ data = 0x7e;
+ write(com_port, &data, 1);
+
+ for (i = 0; (i < 100) && (result != 1); ++i)
+ {
+ result = read(com_port, &data, 1);
+ }
+
+ if (result == 1)
+ {
+ data = 0x70; write(com_port, &data, 1); /* TDO echo off */
+ data = 0x72; write(com_port, &data, 1); /* auto LEDs off */
+ data = 0x74; write(com_port, &data, 1); /* ERROR LED off */
+ data = 0x76; write(com_port, &data, 1); /* DONE LED off */
+ data = 0x60; write(com_port, &data, 1); /* signals low */
+ }
+ else
+ {
+ fprintf(stderr, "Error: BitBlaster is not responding on %s\n",
+ serial_port_name);
+ close(com_port);
+ com_port = -1;
+ }
+ }
+ }
+ else
+ {
+#if PORT == WINDOWS || PORT == DOS
+
+#if PORT == WINDOWS
+ if (windows_nt)
+ {
+ initialize_nt_driver();
+ }
+ else
+ {
+#ifdef __BORLANDC__
+ fprintf(stderr, "Error: parallel port access is not available\n");
+#else
+ if (!specified_lpt_addr)
+ {
+ get_lpt_addresses_from_registry();
+
+ lpt_addr = 0;
+
+ if (specified_lpt_port)
+ {
+ lpt_addr = lpt_addresses_from_registry[lpt_port - 1];
+ }
+
+ if (lpt_addr == 0)
+ {
+ if (lpt_addresses_from_registry[3] != 0)
+ lpt_addr = lpt_addresses_from_registry[3];
+ if (lpt_addresses_from_registry[2] != 0)
+ lpt_addr = lpt_addresses_from_registry[2];
+ if (lpt_addresses_from_registry[1] != 0)
+ lpt_addr = lpt_addresses_from_registry[1];
+ if (lpt_addresses_from_registry[0] != 0)
+ lpt_addr = lpt_addresses_from_registry[0];
+ }
+
+ if (lpt_addr == 0)
+ {
+ if (specified_lpt_port)
+ {
+ lpt_addr = lpt_addr_table[lpt_port - 1];
+ }
+ else
+ {
+ lpt_addr = lpt_addr_table[0];
+ }
+ }
+ }
+ initial_lpt_ctrl = windows_nt ? 0x0c : read_byteblaster(2);
+#endif
+ }
+#endif
+
+#if PORT == DOS
+ /*
+ * Read word at specific memory address to get the LPT port address
+ */
+ WORD *bios_address = (WORD *) 0x00400008;
+
+ if (!specified_lpt_addr)
+ {
+ lpt_addr = bios_address[lpt_port - 1];
+
+ if ((lpt_addr != 0x278) &&
+ (lpt_addr != 0x27c) &&
+ (lpt_addr != 0x378) &&
+ (lpt_addr != 0x37c) &&
+ (lpt_addr != 0x3b8) &&
+ (lpt_addr != 0x3bc))
+ {
+ lpt_addr = lpt_addr_table[lpt_port - 1];
+ }
+ }
+ initial_lpt_ctrl = read_byteblaster(2);
+#endif
+
+ /* set AUTO-FEED low to enable ByteBlaster (value to port inverted) */
+ /* set DIRECTION low for data output from parallel port */
+ write_byteblaster(2, (initial_lpt_ctrl | 0x02) & 0xDF);
+#endif
+ }
+}
+
+void close_jtag_hardware()
+{
+ if (specified_com_port)
+ {
+ if (com_port != -1) close(com_port);
+ }
+ else
+ {
+#if PORT == WINDOWS || PORT == DOS
+ /* set AUTO-FEED high to disable ByteBlaster */
+ write_byteblaster(2, initial_lpt_ctrl & 0xfd);
+
+#if PORT == WINDOWS
+ if (windows_nt && (nt_device_handle != INVALID_HANDLE_VALUE))
+ {
+ if (port_io_count > 0) flush_ports();
+
+ CloseHandle(nt_device_handle);
+ }
+#endif
+#endif
+ }
+}
+
+#if PORT == WINDOWS
+/**************************************************************************/
+/* */
+
+BOOL initialize_nt_driver()
+
+/* */
+/* Uses CreateFile() to open a connection to the Windows NT device */
+/* driver. */
+/* */
+/**************************************************************************/
+{
+ BOOL status = FALSE;
+
+ ULONG buffer[1];
+ ULONG returned_length = 0;
+ char nt_lpt_str[] = { '\\', '\\', '.', '\\',
+ 'A', 'L', 'T', 'L', 'P', 'T', '1', '\0' };
+
+
+ nt_lpt_str[10] = (char) ('1' + (lpt_port - 1));
+
+ nt_device_handle = CreateFile(
+ nt_lpt_str,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (nt_device_handle == INVALID_HANDLE_VALUE)
+ {
+ fprintf(stderr,
+ "I/O error: cannot open device %s\nCheck port number and device driver installation",
+ nt_lpt_str);
+ }
+ else
+ {
+ if (DeviceIoControl(
+ nt_device_handle, /* Handle to device */
+ PGDC_IOCTL_GET_DEVICE_INFO_PP, /* IO Control code */
+ (ULONG *)NULL, /* Buffer to driver. */
+ 0, /* Length of buffer in bytes. */
+ &buffer, /* Buffer from driver. */
+ sizeof(ULONG), /* Length of buffer in bytes. */
+ &returned_length, /* Bytes placed in data_buffer. */
+ NULL)) /* Wait for operation to complete */
+ {
+ if (returned_length == sizeof(ULONG))
+ {
+ if (buffer[0] == PGDC_HDLC_NTDRIVER_VERSION)
+ {
+ status = TRUE;
+ }
+ else
+ {
+ fprintf(stderr,
+ "I/O error: device driver %s is not compatible\n(Driver version is %lu, expected version %lu.\n",
+ nt_lpt_str,
+ (unsigned long) buffer[0],
+ (unsigned long) PGDC_HDLC_NTDRIVER_VERSION);
+ }
+ }
+ else
+ {
+ fprintf(stderr, "I/O error: device driver %s is not compatible.\n",
+ nt_lpt_str);
+ }
+ }
+
+ if (!status)
+ {
+ CloseHandle(nt_device_handle);
+ nt_device_handle = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ if (!status)
+ {
+ /* error message already given */
+ exit(1);
+ }
+
+ return (status);
+}
+#endif
+
+#if PORT == WINDOWS || PORT == DOS
+/**************************************************************************/
+/* */
+
+void write_byteblaster
+(
+ int port,
+ int data
+)
+
+/* */
+/**************************************************************************/
+{
+#if PORT == WINDOWS
+ BOOL status = FALSE;
+
+ int returned_length = 0;
+ int buffer[2];
+
+
+ if (windows_nt)
+ {
+ /*
+ * On Windows NT, access hardware through device driver
+ */
+ if (port == 0)
+ {
+ port_io_buffer[port_io_count].data = (USHORT) data;
+ port_io_buffer[port_io_count].command = PGDC_WRITE_PORT;
+ ++port_io_count;
+
+ if (port_io_count >= PORT_IO_BUFFER_SIZE) flush_ports();
+ }
+ else
+ {
+ if (port_io_count > 0) flush_ports();
+
+ buffer[0] = port;
+ buffer[1] = data;
+
+ status = DeviceIoControl(
+ nt_device_handle, /* Handle to device */
+ PGDC_IOCTL_WRITE_PORT_PP, /* IO Control code for write */
+ (ULONG *)&buffer, /* Buffer to driver. */
+ 2 * sizeof(int), /* Length of buffer in bytes. */
+ (ULONG *)NULL, /* Buffer from driver. Not used. */
+ 0, /* Length of buffer in bytes. */
+ (ULONG *)&returned_length, /* Bytes returned. Should be zero. */
+ NULL); /* Wait for operation to complete */
+
+ if ((!status) || (returned_length != 0))
+ {
+ fprintf(stderr, "I/O error: Cannot access ByteBlaster hardware\n");
+ CloseHandle(nt_device_handle);
+ exit(1);
+ }
+ }
+ }
+ else
+#endif
+ {
+ /*
+ * On Windows 95, access hardware directly
+ */
+ outp((WORD)(port + lpt_addr), (WORD)data);
+ }
+}
+
+/**************************************************************************/
+/* */
+
+int read_byteblaster
+(
+ int port
+)
+
+/* */
+/**************************************************************************/
+{
+ int data = 0;
+
+#if PORT == WINDOWS
+
+ BOOL status = FALSE;
+
+ int returned_length = 0;
+
+
+ if (windows_nt)
+ {
+ /* flush output cache buffer before reading from device */
+ if (port_io_count > 0) flush_ports();
+
+ /*
+ * On Windows NT, access hardware through device driver
+ */
+ status = DeviceIoControl(
+ nt_device_handle, /* Handle to device */
+ PGDC_IOCTL_READ_PORT_PP, /* IO Control code for Read */
+ (ULONG *)&port, /* Buffer to driver. */
+ sizeof(int), /* Length of buffer in bytes. */
+ (ULONG *)&data, /* Buffer from driver. */
+ sizeof(int), /* Length of buffer in bytes. */
+ (ULONG *)&returned_length, /* Bytes placed in data_buffer. */
+ NULL); /* Wait for operation to complete */
+
+ if ((!status) || (returned_length != sizeof(int)))
+ {
+ fprintf(stderr, "I/O error: Cannot access ByteBlaster hardware\n");
+ CloseHandle(nt_device_handle);
+ exit(1);
+ }
+ }
+ else
+#endif
+ {
+ /*
+ * On Windows 95, access hardware directly
+ */
+ data = inp((WORD)(port + lpt_addr));
+ }
+
+ return (data & 0xff);
+}
+
+#if PORT == WINDOWS
+void flush_ports(void)
+{
+ ULONG n_writes = 0L;
+ BOOL status;
+
+ status = DeviceIoControl(
+ nt_device_handle, /* handle to device */
+ PGDC_IOCTL_PROCESS_LIST_PP, /* IO control code */
+ (LPVOID)port_io_buffer, /* IN buffer (list buffer) */
+ port_io_count * sizeof(struct PORT_IO_LIST_STRUCT),/* length of IN buffer in bytes */
+ (LPVOID)port_io_buffer, /* OUT buffer (list buffer) */
+ port_io_count * sizeof(struct PORT_IO_LIST_STRUCT),/* length of OUT buffer in bytes */
+ &n_writes, /* number of writes performed */
+ 0); /* wait for operation to complete */
+
+ if ((!status) || ((port_io_count * sizeof(struct PORT_IO_LIST_STRUCT)) != n_writes))
+ {
+ fprintf(stderr, "I/O error: Cannot access ByteBlaster hardware\n");
+ CloseHandle(nt_device_handle);
+ exit(1);
+ }
+
+ port_io_count = 0;
+}
+#endif /* PORT == WINDOWS */
+#endif /* PORT == WINDOWS || PORT == DOS */
+
+#if !defined (DEBUG)
+#pragma optimize ("ceglt", off)
+#endif
+
+void delay_loop(long count)
+{
+ while (count != 0L) count--;
+}
OpenPOWER on IntegriCloud