summaryrefslogtreecommitdiff
path: root/usrp2/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'usrp2/firmware')
-rw-r--r--usrp2/firmware/AUTHORS2
-rw-r--r--usrp2/firmware/COPYING674
-rw-r--r--usrp2/firmware/ChangeLog22
-rw-r--r--usrp2/firmware/INSTALL234
-rw-r--r--usrp2/firmware/Makefile.am21
-rw-r--r--usrp2/firmware/Makefile.common59
-rw-r--r--usrp2/firmware/NEWS0
-rw-r--r--usrp2/firmware/README5
-rw-r--r--usrp2/firmware/apps/Makefile.am63
-rw-r--r--usrp2/firmware/apps/app_common_v2.c477
-rw-r--r--usrp2/firmware/apps/app_common_v2.h62
-rw-r--r--usrp2/firmware/apps/app_passthru_v2.c244
-rw-r--r--usrp2/firmware/apps/app_passthru_v2.h54
-rw-r--r--usrp2/firmware/apps/bitrot/tx_drop.c261
-rw-r--r--usrp2/firmware/apps/bitrot/tx_drop2.c292
-rw-r--r--usrp2/firmware/apps/bitrot/tx_drop_rate_limited.c233
-rw-r--r--usrp2/firmware/apps/blink_leds.c40
-rw-r--r--usrp2/firmware/apps/blink_leds2.c53
-rw-r--r--usrp2/firmware/apps/buf_ram_test.c89
-rw-r--r--usrp2/firmware/apps/can_i_sub.c25
-rw-r--r--usrp2/firmware/apps/double_buffer_fragment.c138
-rw-r--r--usrp2/firmware/apps/echo.c34
-rw-r--r--usrp2/firmware/apps/eth_serdes.c230
-rw-r--r--usrp2/firmware/apps/gen_eth_packets.c181
-rw-r--r--usrp2/firmware/apps/gen_pause_frames.c207
-rw-r--r--usrp2/firmware/apps/hello.c30
-rw-r--r--usrp2/firmware/apps/ibs_rx_test.c82
-rw-r--r--usrp2/firmware/apps/ibs_tx_test.c160
-rw-r--r--usrp2/firmware/apps/rcv_eth_packets.c233
-rw-r--r--usrp2/firmware/apps/read_dbids.c59
-rw-r--r--usrp2/firmware/apps/rx_only_v2.c263
-rw-r--r--usrp2/firmware/apps/sd_bounce.c153
-rw-r--r--usrp2/firmware/apps/sd_gentest.c269
-rw-r--r--usrp2/firmware/apps/serdes_to_dsp.c188
-rw-r--r--usrp2/firmware/apps/serdes_txrx.c346
-rw-r--r--usrp2/firmware/apps/test1.c282
-rw-r--r--usrp2/firmware/apps/test_db_spi.c35
-rw-r--r--usrp2/firmware/apps/test_i2c.c108
-rw-r--r--usrp2/firmware/apps/test_lsadc.c57
-rw-r--r--usrp2/firmware/apps/test_lsdac.c51
-rw-r--r--usrp2/firmware/apps/test_phy_comm.c113
-rw-r--r--usrp2/firmware/apps/test_serdes.c192
-rw-r--r--usrp2/firmware/apps/timer_test.c59
-rw-r--r--usrp2/firmware/apps/tx_only_v2.c171
-rw-r--r--usrp2/firmware/apps/tx_standalone.c338
-rw-r--r--usrp2/firmware/apps/txrx.c344
-rwxr-xr-xusrp2/firmware/bootstrap30
-rw-r--r--usrp2/firmware/config.guess1516
-rw-r--r--usrp2/firmware/config.sub1626
-rw-r--r--usrp2/firmware/configure.ac46
-rwxr-xr-xusrp2/firmware/divisors.py34
-rw-r--r--usrp2/firmware/include/Makefile.am27
-rw-r--r--usrp2/firmware/include/usrp2_cdefs.h34
-rw-r--r--usrp2/firmware/include/usrp2_eth_packet.h374
-rw-r--r--usrp2/firmware/include/usrp2_fpga_regs.h80
-rw-r--r--usrp2/firmware/include/usrp2_i2c_addr.h82
-rw-r--r--usrp2/firmware/include/usrp2_mac_addr.h28
-rw-r--r--usrp2/firmware/include/usrp2_mimo_config.h46
-rw-r--r--usrp2/firmware/include/usrp2_types.h106
-rw-r--r--usrp2/firmware/lib/Makefile.am90
-rw-r--r--usrp2/firmware/lib/ad9510.c42
-rw-r--r--usrp2/firmware/lib/ad9510.h30
-rw-r--r--usrp2/firmware/lib/ad9777.c47
-rw-r--r--usrp2/firmware/lib/ad9777.h31
-rw-r--r--usrp2/firmware/lib/ad9777_regs.h71
-rw-r--r--usrp2/firmware/lib/bool.h26
-rw-r--r--usrp2/firmware/lib/buffer_pool.c72
-rw-r--r--usrp2/firmware/lib/buffer_pool.h75
-rw-r--r--usrp2/firmware/lib/clocks.c182
-rw-r--r--usrp2/firmware/lib/clocks.h63
-rw-r--r--usrp2/firmware/lib/db.h94
-rw-r--r--usrp2/firmware/lib/db_base.h68
-rw-r--r--usrp2/firmware/lib/db_basic.c161
-rw-r--r--usrp2/firmware/lib/db_init.c340
-rw-r--r--usrp2/firmware/lib/db_rfx.c609
-rw-r--r--usrp2/firmware/lib/db_tvrx.c240
-rw-r--r--usrp2/firmware/lib/dbsm.c298
-rw-r--r--usrp2/firmware/lib/dbsm.h90
-rw-r--r--usrp2/firmware/lib/eeprom.c69
-rw-r--r--usrp2/firmware/lib/eth_mac.c134
-rw-r--r--usrp2/firmware/lib/eth_mac.h32
-rw-r--r--usrp2/firmware/lib/eth_mac_regs.h97
-rw-r--r--usrp2/firmware/lib/eth_phy.h219
-rw-r--r--usrp2/firmware/lib/ethernet.c281
-rw-r--r--usrp2/firmware/lib/ethernet.h75
-rw-r--r--usrp2/firmware/lib/hal_io.c312
-rw-r--r--usrp2/firmware/lib/hal_io.h174
-rw-r--r--usrp2/firmware/lib/hal_uart.c67
-rw-r--r--usrp2/firmware/lib/hal_uart.h63
-rw-r--r--usrp2/firmware/lib/i2c.c127
-rw-r--r--usrp2/firmware/lib/i2c.h39
-rw-r--r--usrp2/firmware/lib/lsadc.c73
-rw-r--r--usrp2/firmware/lib/lsadc.h45
-rw-r--r--usrp2/firmware/lib/lsdac.c68
-rw-r--r--usrp2/firmware/lib/lsdac.h47
-rw-r--r--usrp2/firmware/lib/mdelay.c73
-rw-r--r--usrp2/firmware/lib/mdelay.h29
-rw-r--r--usrp2/firmware/lib/memcpy_wa.c42
-rw-r--r--usrp2/firmware/lib/memcpy_wa.h32
-rw-r--r--usrp2/firmware/lib/memory_map.h583
-rw-r--r--usrp2/firmware/lib/memset_wa.c45
-rw-r--r--usrp2/firmware/lib/memset_wa.h27
-rw-r--r--usrp2/firmware/lib/microblaze.ld163
-rw-r--r--usrp2/firmware/lib/nonstdio.c80
-rw-r--r--usrp2/firmware/lib/nonstdio.h46
-rw-r--r--usrp2/firmware/lib/pic.c94
-rw-r--r--usrp2/firmware/lib/pic.h35
-rw-r--r--usrp2/firmware/lib/print_buffer.c36
-rw-r--r--usrp2/firmware/lib/print_fxpt.c83
-rw-r--r--usrp2/firmware/lib/print_mac_addr.c30
-rw-r--r--usrp2/firmware/lib/print_rmon_regs.c44
-rw-r--r--usrp2/firmware/lib/print_rmon_regs.h24
-rw-r--r--usrp2/firmware/lib/printf.c134
-rw-r--r--usrp2/firmware/lib/printf.c.smaller134
-rw-r--r--usrp2/firmware/lib/spi.c61
-rw-r--r--usrp2/firmware/lib/spi.h52
-rw-r--r--usrp2/firmware/lib/stdint.h34
-rw-r--r--usrp2/firmware/lib/stdio.h38
-rw-r--r--usrp2/firmware/lib/u2_init.c111
-rw-r--r--usrp2/firmware/lib/u2_init.h26
-rw-r--r--usrp2/firmware/lib/usrp2_bytesex.h66
-rw-r--r--usrp2/firmware/lib/wb16550.h98
-rwxr-xr-xusrp2/firmware/u2_flash_tool116
123 files changed, 18149 insertions, 0 deletions
diff --git a/usrp2/firmware/AUTHORS b/usrp2/firmware/AUTHORS
new file mode 100644
index 000000000..6bd41174b
--- /dev/null
+++ b/usrp2/firmware/AUTHORS
@@ -0,0 +1,2 @@
+Eric Blossom <eb@comsec.com>
+Matt Ettus <matt@ettus.com>
diff --git a/usrp2/firmware/COPYING b/usrp2/firmware/COPYING
new file mode 100644
index 000000000..94a9ed024
--- /dev/null
+++ b/usrp2/firmware/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state 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 3 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, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU 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 Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/usrp2/firmware/ChangeLog b/usrp2/firmware/ChangeLog
new file mode 100644
index 000000000..3154fc43a
--- /dev/null
+++ b/usrp2/firmware/ChangeLog
@@ -0,0 +1,22 @@
+#
+# Copyright 2007 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+Please use the trac interface to see what's changed.
+http://gnuradio.org/trac/timeline
diff --git a/usrp2/firmware/INSTALL b/usrp2/firmware/INSTALL
new file mode 100644
index 000000000..5458714e1
--- /dev/null
+++ b/usrp2/firmware/INSTALL
@@ -0,0 +1,234 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006 Free Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about. Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/usrp2/firmware/Makefile.am b/usrp2/firmware/Makefile.am
new file mode 100644
index 000000000..437f23226
--- /dev/null
+++ b/usrp2/firmware/Makefile.am
@@ -0,0 +1,21 @@
+#
+# Copyright 2007 Free Software Foundation, Inc.
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+include $(top_srcdir)/Makefile.common
+
+SUBDIRS = include lib apps
+
diff --git a/usrp2/firmware/Makefile.common b/usrp2/firmware/Makefile.common
new file mode 100644
index 000000000..f2f8f7d63
--- /dev/null
+++ b/usrp2/firmware/Makefile.common
@@ -0,0 +1,59 @@
+# -*- Makefile -*-
+#
+# Copyright 2007 Free Software Foundation, Inc.
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+STD_INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/lib
+
+#HAL_IO = -DHAL_IO_USES_DBOARD_PINS
+HAL_IO = -DHAL_IO_USES_UART
+
+AM_CPPFLAGS = $(HAL_IO) $(STD_INCLUDES)
+
+STD_CFLAGS = -O2 -g -Wall -Werror-implicit-function-declaration -mxl-soft-div -msoft-float
+
+#AM_CFLAGS = $(STD_CFLAGS) -mxl-soft-mul
+AM_CFLAGS = $(STD_CFLAGS) -mxl-soft-mul -mxl-barrel-shift
+#AM_CFLAGS = $(STD_CFLAGS) -mno-xl-soft-mul
+#AM_CFLAGS = $(STD_CFLAGS) -mno-xl-soft-mul -mxl-barrel-shift
+
+
+LINKER_SCRIPT = $(top_srcdir)/lib/microblaze.ld
+#AM_LDFLAGS = -Wl,-T$(LINKER_SCRIPT) -Wl,-defsym -Wl,_STACK_SIZE=1024
+#AM_LDFLAGS = -Wl,-T$(LINKER_SCRIPT) -Wl,-Map -Wl,$@.map
+AM_LDFLAGS = -Wl,-T$(LINKER_SCRIPT)
+
+
+%.bin : %
+ mb-objcopy -O binary $< $@
+
+%.dump : %
+ mb-objdump -DSC $< > $@
+
+%.rom : %.bin
+ hexdump -v -e'1/1 "%.2X\n"' $< > $@
+
+
+.PRECIOUS : %.bin
+
+
+BINS = $(noinst_PROGRAMS:=.bin)
+ROMS = $(noinst_PROGRAMS:=.rom)
+DUMPS = $(noinst_PROGRAMS:=.dump)
+
+noinst_DATA = $(BINS) $(ROMS) $(DUMPS)
+
+CLEANFILES = $(ROMS) $(DUMPS) $(BINS)
diff --git a/usrp2/firmware/NEWS b/usrp2/firmware/NEWS
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/usrp2/firmware/NEWS
diff --git a/usrp2/firmware/README b/usrp2/firmware/README
new file mode 100644
index 000000000..8b72bf9cf
--- /dev/null
+++ b/usrp2/firmware/README
@@ -0,0 +1,5 @@
+Stay tuned for additional info as it becomes available ...
+
+ $ ./bootstrap
+ $ ./configure
+ $ make
diff --git a/usrp2/firmware/apps/Makefile.am b/usrp2/firmware/apps/Makefile.am
new file mode 100644
index 000000000..092dd9441
--- /dev/null
+++ b/usrp2/firmware/apps/Makefile.am
@@ -0,0 +1,63 @@
+#
+# Copyright 2007,2008 Free Software Foundation, Inc.
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+include $(top_srcdir)/Makefile.common
+
+LDADD = ../lib/libu2fw.a
+
+noinst_PROGRAMS = \
+ blink_leds \
+ blink_leds2 \
+ buf_ram_test \
+ can_i_sub \
+ echo \
+ eth_serdes \
+ gen_eth_packets \
+ hello \
+ ibs_rx_test \
+ ibs_tx_test \
+ rcv_eth_packets \
+ rx_only_v2 \
+ read_dbids \
+ test1 \
+ test_db_spi \
+ test_i2c \
+ test_phy_comm \
+ test_lsadc \
+ test_lsdac \
+ test_serdes \
+ timer_test \
+ tx_only_v2 \
+ tx_standalone \
+ txrx \
+ serdes_txrx \
+ sd_gentest \
+ sd_bounce
+
+
+# tx_drop_SOURCES = tx_drop.c app_common.c
+# tx_drop_rate_limited_SOURCES = tx_drop_rate_limited.c app_common.c
+# tx_drop2_SOURCES = tx_drop2.c app_common.c
+rx_only_v2_SOURCES = rx_only_v2.c app_common_v2.c
+tx_only_v2_SOURCES = tx_only_v2.c app_common_v2.c
+txrx_SOURCES = txrx.c app_common_v2.c
+eth_serdes_SOURCES = eth_serdes.c app_passthru_v2.c
+serdes_txrx_SOURCES = serdes_txrx.c app_common_v2.c
+
+noinst_HEADERS = \
+ app_common_v2.h \
+ app_passthru_v2.h
diff --git a/usrp2/firmware/apps/app_common_v2.c b/usrp2/firmware/apps/app_common_v2.c
new file mode 100644
index 000000000..4dc254f85
--- /dev/null
+++ b/usrp2/firmware/apps/app_common_v2.c
@@ -0,0 +1,477 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "app_common_v2.h"
+#include "buffer_pool.h"
+#include "memcpy_wa.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "print_rmon_regs.h"
+#include "db.h"
+#include "clocks.h"
+#include <string.h>
+
+volatile bool link_is_up = false; // eth handler sets this
+int cpu_tx_buf_dest_port = PORT_ETH;
+
+// If this is non-zero, this dbsm could be writing to the ethernet
+dbsm_t *ac_could_be_sending_to_eth;
+
+static unsigned char exp_seqno __attribute__((unused)) = 0;
+
+
+static bool
+burn_mac_addr(const op_burn_mac_addr_t *p)
+{
+ return ethernet_set_mac_addr(&p->addr);
+}
+
+static bool
+config_mimo_cmd(const op_config_mimo_t *p)
+{
+ clocks_mimo_config(p->flags);
+ return true;
+}
+
+void
+set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt)
+{
+ reply_pkt->ehdr.dst = cmd_pkt->ehdr.src;
+ reply_pkt->ehdr.ethertype = U2_ETHERTYPE;
+ reply_pkt->thdr.flags = 0;
+ reply_pkt->thdr.fifo_status = 0; // written by protocol engine
+ reply_pkt->thdr.seqno = 0; // written by protocol engine
+ reply_pkt->thdr.ack = 0; // written by protocol engine
+ u2p_set_word0(&reply_pkt->fixed, 0, CONTROL_CHAN);
+ reply_pkt->fixed.timestamp = timer_regs->time;
+}
+
+static void
+send_reply(unsigned char *reply, size_t reply_len)
+{
+ if (reply_len < 64)
+ reply_len = 64;
+
+ // wait for buffer to become idle
+ hal_set_leds(0x4, 0x4);
+ while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0)
+ ;
+ hal_set_leds(0x0, 0x4);
+
+ // copy reply into CPU_TX_BUF
+ memcpy_wa(buffer_ram(CPU_TX_BUF), reply, reply_len);
+
+ // wait until nobody else is sending to the ethernet
+ if (ac_could_be_sending_to_eth){
+ hal_set_leds(0x8, 0x8);
+ dbsm_wait_for_opening(ac_could_be_sending_to_eth);
+ hal_set_leds(0x0, 0x8);
+ }
+
+ if (0){
+ printf("sending_reply to port %d, len = %d\n", cpu_tx_buf_dest_port, reply_len);
+ print_buffer(buffer_ram(CPU_TX_BUF), reply_len/4);
+ }
+
+ // fire it off
+ bp_send_from_buf(CPU_TX_BUF, cpu_tx_buf_dest_port, 1, 0, reply_len/4);
+
+ // wait for it to complete (not long, it's a small pkt)
+ while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))) == 0)
+ ;
+
+ bp_clear_buf(CPU_TX_BUF);
+}
+
+
+static size_t
+op_id_cmd(const op_generic_t *p,
+ void *reply_payload, size_t reply_payload_space)
+{
+ op_id_reply_t *r = (op_id_reply_t *) reply_payload;
+ if (reply_payload_space < sizeof(*r)) // no room
+ return 0;
+
+ // Build reply subpacket
+
+ r->opcode = OP_ID_REPLY;
+ r->len = sizeof(op_id_reply_t);
+ r->rid = p->rid;
+ r->addr = *ethernet_mac_addr();
+ r->hw_rev = 0x0000; // FIXME
+ // r->fpga_md5sum = ; // FIXME
+ // r->sw_md5sum = ; // FIXME
+
+ // FIXME Add d'board info, including dbid, min/max gain, min/max freq
+
+ return r->len;
+}
+
+
+static size_t
+config_tx_v2_cmd(const op_config_tx_v2_t *p,
+ void *reply_payload, size_t reply_payload_space)
+{
+ op_config_tx_reply_v2_t *r = (op_config_tx_reply_v2_t *) reply_payload;
+ if (reply_payload_space < sizeof(*r))
+ return 0; // no room
+
+ struct tune_result tune_result;
+ memset(&tune_result, 0, sizeof(tune_result));
+
+ bool ok = true;
+
+ if (p->valid & CFGV_GAIN){
+ ok &= db_set_gain(tx_dboard, p->gain);
+ }
+
+ if (p->valid & CFGV_FREQ){
+ u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
+ bool tune_ok = db_tune(tx_dboard, f, &tune_result);
+ ok &= tune_ok;
+ print_tune_result("Tx", tune_ok, f, &tune_result);
+ }
+
+ if (p->valid & CFGV_INTERP_DECIM){
+ int interp = p->interp;
+ int hb1 = 0;
+ int hb2 = 0;
+
+ if (!(interp & 1)){
+ hb2 = 1;
+ interp = interp >> 1;
+ }
+
+ if (!(interp & 1)){
+ hb1 = 1;
+ interp = interp >> 1;
+ }
+
+ if (p->interp < MIN_INTERP || p->interp > MAX_INTERP)
+ ok = false;
+ else {
+ dsp_tx_regs->interp_rate = (hb1<<9) | (hb2<<8) | interp;
+ // printf("Interp: %d, register %d\n", p->interp, (hb1<<9) | (hb2<<8) | interp);
+ }
+ }
+
+ if (p->valid & CFGV_SCALE_IQ){
+ dsp_tx_regs->scale_iq = p->scale_iq;
+ }
+
+ // Build reply subpacket
+
+ r->opcode = OP_CONFIG_TX_REPLY_V2;
+ r->len = sizeof(*r);
+ r->rid = p->rid;
+ r->ok = ok;
+ r->inverted = tune_result.inverted;
+ r->baseband_freq_hi = u2_fxpt_freq_hi(tune_result.baseband_freq);
+ r->baseband_freq_lo = u2_fxpt_freq_lo(tune_result.baseband_freq);
+ r->duc_freq_hi = u2_fxpt_freq_hi(tune_result.dxc_freq);
+ r->duc_freq_lo = u2_fxpt_freq_lo(tune_result.dxc_freq);
+ r->residual_freq_hi = u2_fxpt_freq_hi(tune_result.residual_freq);
+ r->residual_freq_lo = u2_fxpt_freq_lo(tune_result.residual_freq);
+ return r->len;
+}
+
+static size_t
+config_rx_v2_cmd(const op_config_rx_v2_t *p,
+ void *reply_payload, size_t reply_payload_space)
+{
+ op_config_rx_reply_v2_t *r = (op_config_rx_reply_v2_t *) reply_payload;
+ if (reply_payload_space < sizeof(*r))
+ return 0; // no room
+
+ struct tune_result tune_result;
+ memset(&tune_result, 0, sizeof(tune_result));
+
+ bool ok = true;
+
+ if (p->valid & CFGV_GAIN){
+ ok &= db_set_gain(rx_dboard, p->gain);
+ }
+
+ if (p->valid & CFGV_FREQ){
+ u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
+ bool tune_ok = db_tune(rx_dboard, f, &tune_result);
+ ok &= tune_ok;
+ print_tune_result("Rx", tune_ok, f, &tune_result);
+ }
+
+ if (p->valid & CFGV_INTERP_DECIM){
+ int decim = p->decim;
+ int hb1 = 0;
+ int hb2 = 0;
+
+ if(!(decim & 1)) {
+ hb2 = 1;
+ decim = decim >> 1;
+ }
+
+ if(!(decim & 1)) {
+ hb1 = 1;
+ decim = decim >> 1;
+ }
+
+ if (decim < MIN_DECIM || decim > MAX_DECIM)
+ ok = false;
+ else {
+ dsp_rx_regs->decim_rate = (hb1<<9) | (hb2<<8) | decim;
+ // printf("Decim: %d, register %d\n", p->decim, (hb1<<9) | (hb2<<8) | decim);
+ }
+ }
+
+ if (p->valid & CFGV_SCALE_IQ){
+ dsp_rx_regs->scale_iq = p->scale_iq;
+ }
+
+ // Build reply subpacket
+
+ r->opcode = OP_CONFIG_RX_REPLY_V2;
+ r->len = sizeof(*r);
+ r->rid = p->rid;
+ r->ok = ok;
+ r->inverted = tune_result.inverted;
+ r->baseband_freq_hi = u2_fxpt_freq_hi(tune_result.baseband_freq);
+ r->baseband_freq_lo = u2_fxpt_freq_lo(tune_result.baseband_freq);
+ r->ddc_freq_hi = u2_fxpt_freq_hi(tune_result.dxc_freq);
+ r->ddc_freq_lo = u2_fxpt_freq_lo(tune_result.dxc_freq);
+ r->residual_freq_hi = u2_fxpt_freq_hi(tune_result.residual_freq);
+ r->residual_freq_lo = u2_fxpt_freq_lo(tune_result.residual_freq);
+
+ return r->len;
+}
+
+static size_t
+read_time_cmd(const op_generic_t *p,
+ void *reply_payload, size_t reply_payload_space)
+{
+ op_read_time_reply_t *r = (op_read_time_reply_t *) reply_payload;
+ if (reply_payload_space < sizeof(*r))
+ return 0; // no room
+
+ r->opcode = OP_READ_TIME_REPLY;
+ r->len = sizeof(*r);
+ r->rid = p->rid;
+ r->time = timer_regs->time;
+
+ return r->len;
+}
+
+static size_t
+generic_reply(const op_generic_t *p,
+ void *reply_payload, size_t reply_payload_space,
+ bool ok)
+{
+ op_generic_t *r = (op_generic_t *) reply_payload;
+ if (reply_payload_space < sizeof(*r))
+ return 0; // no room
+
+ r->opcode = p->opcode | OP_REPLY_BIT;
+ r->len = sizeof(*r);
+ r->rid = p->rid;
+ r->ok = ok;
+
+ return r->len;
+}
+
+static size_t
+add_eop(void *reply_payload, size_t reply_payload_space)
+{
+ op_generic_t *r = (op_generic_t *) reply_payload;
+ if (reply_payload_space < sizeof(*r))
+ return 0; // no room
+
+ r->opcode = OP_EOP;
+ r->len = sizeof(*r);
+ r->rid = 0;
+ r->ok = 0;
+
+ return r->len;
+}
+
+void
+handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
+{
+ unsigned char reply[sizeof(u2_eth_packet_t) + 4 * sizeof(u2_subpkt_t)] _AL4;
+ unsigned char *reply_payload = &reply[sizeof(u2_eth_packet_t)];
+ int reply_payload_space = sizeof(reply) - sizeof(u2_eth_packet_t);
+
+ // initialize reply
+ memset(reply, 0, sizeof(reply));
+ set_reply_hdr((u2_eth_packet_t *) reply, pkt);
+
+ // point to beginning of payload (subpackets)
+ unsigned char *payload = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t);
+ int payload_len = len - sizeof(u2_eth_packet_t);
+
+ size_t subpktlen = 0;
+
+ while (payload_len >= sizeof(op_generic_t)){
+ const op_generic_t *gp = (const op_generic_t *) payload;
+ subpktlen = 0;
+
+ switch(gp->opcode){
+ case OP_EOP: // end of subpackets
+ goto end_of_subpackets;
+
+ case OP_ID:
+ subpktlen = op_id_cmd(gp, reply_payload, reply_payload_space);
+ break;
+
+ case OP_CONFIG_TX_V2:
+ subpktlen = config_tx_v2_cmd((op_config_tx_v2_t *) payload,
+ reply_payload, reply_payload_space);
+ break;
+
+ case OP_CONFIG_RX_V2:
+ subpktlen = config_rx_v2_cmd((op_config_rx_v2_t *) payload,
+ reply_payload, reply_payload_space);
+ break;
+
+ case OP_START_RX_STREAMING:
+ start_rx_streaming_cmd(&pkt->ehdr.src, (op_start_rx_streaming_t *) payload);
+ subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true);
+ break;
+
+ case OP_STOP_RX:
+ stop_rx_cmd();
+ subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true);
+ break;
+
+ case OP_BURN_MAC_ADDR:
+ subpktlen = generic_reply(gp, reply_payload, reply_payload_space,
+ burn_mac_addr((op_burn_mac_addr_t *) payload));
+ break;
+
+ case OP_CONFIG_MIMO:
+ subpktlen = generic_reply(gp, reply_payload, reply_payload_space,
+ config_mimo_cmd((op_config_mimo_t *) payload));
+ break;
+
+ case OP_READ_TIME:
+ subpktlen = read_time_cmd(gp, reply_payload, reply_payload_space);
+ break;
+
+ default:
+ printf("app_common_v2: unhandled opcode = %d\n", gp->opcode);
+ break;
+ }
+
+ int t = (gp->len + 3) & ~3; // bump to a multiple of 4
+ payload += t;
+ payload_len -= t;
+
+ subpktlen = (subpktlen + 3) & ~3; // bump to a multiple of 4
+ reply_payload += subpktlen;
+ reply_payload_space -= subpktlen;
+ }
+
+ end_of_subpackets:
+
+ // add the EOP marker
+ subpktlen = add_eop(reply_payload, reply_payload_space);
+ subpktlen = (subpktlen + 3) & ~3; // bump to a multiple of 4
+ reply_payload += subpktlen;
+ reply_payload_space -= subpktlen;
+
+ send_reply(reply, reply_payload - reply);
+}
+
+
+/*
+ * Called when an ethernet packet is received.
+ * Return true if we handled it here, otherwise
+ * it'll be passed on to the DSP Tx pipe
+ */
+bool
+eth_pkt_inspector(dbsm_t *sm, int bufno)
+{
+ u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno);
+ size_t byte_len = (buffer_pool_status->last_line[bufno] - 3) * 4;
+
+ //static size_t last_len = 0;
+
+ // hal_toggle_leds(0x1);
+
+ // inspect rcvd frame and figure out what do do.
+
+ if (pkt->ehdr.ethertype != U2_ETHERTYPE)
+ return true; // ignore, probably bogus PAUSE frame from MAC
+
+ int chan = u2p_chan(&pkt->fixed);
+
+ switch (chan){
+ case CONTROL_CHAN:
+ handle_control_chan_frame(pkt, byte_len);
+ return true; // we handled the packet
+ break;
+
+ case 0:
+ default:
+#if 0
+ if (last_len != 0){
+ if (byte_len != last_len){
+ printf("Len: %d last: %d\n", byte_len, last_len);
+ }
+ }
+ last_len = byte_len;
+
+ if((pkt->thdr.seqno) == exp_seqno){
+ exp_seqno++;
+ //putchar('.');
+ }
+ else {
+ // putchar('S');
+ //printf("S%d %d ",exp_seqno,pkt->thdr.seqno);
+ exp_seqno = pkt->thdr.seqno + 1;
+ }
+#endif
+ return false; // pass it on to Tx DSP
+ break;
+ }
+}
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+ link_is_up = speed != 0;
+ hal_set_leds(link_is_up ? 0x20 : 0x0, 0x20);
+ printf("\neth link changed: speed = %d\n", speed);
+}
+
+
+void
+print_tune_result(char *msg, bool tune_ok,
+ u2_fxpt_freq_t target_freq, struct tune_result *r)
+{
+ printf("db_tune %s %s\n", msg, tune_ok ? "true" : "false");
+ putstr(" target_freq "); print_fxpt_freq(target_freq); newline();
+ putstr(" baseband_freq "); print_fxpt_freq(r->baseband_freq); newline();
+ putstr(" dxc_freq "); print_fxpt_freq(r->dxc_freq); newline();
+ putstr(" residual_freq "); print_fxpt_freq(r->residual_freq); newline();
+ printf(" inverted %s\n", r->inverted ? "true" : "false");
+}
diff --git a/usrp2/firmware/apps/app_common_v2.h b/usrp2/firmware/apps/app_common_v2.h
new file mode 100644
index 000000000..30f54876c
--- /dev/null
+++ b/usrp2/firmware/apps/app_common_v2.h
@@ -0,0 +1,62 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_APP_COMMON_H
+#define INCLUDED_APP_COMMON_H
+
+#include "bool.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include <stddef.h>
+#include <db.h>
+
+#define CPU_TX_BUF 1 // cpu -> eth
+
+#define _AL4 __attribute__((aligned (4)))
+
+extern volatile bool link_is_up; // eth handler sets this
+
+// If there's a dbsm that sends to the ethernet, put it's address here
+extern dbsm_t *ac_could_be_sending_to_eth;
+
+extern int cpu_tx_buf_dest_port;
+
+void set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt);
+
+/*
+ * Called when an ethernet packet is received.
+ * Return true if we handled it here, otherwise
+ * it'll be passed on to the DSP Tx pipe
+ */
+bool eth_pkt_inspector(dbsm_t *sm, int bufno);
+
+void link_changed_callback(int speed);
+
+void
+print_tune_result(char *msg, bool tune_ok,
+ u2_fxpt_freq_t target_freq, struct tune_result *r);
+
+
+void start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p);
+void stop_rx_cmd(void);
+
+void handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len);
+
+#endif /* INCLUDED_APP_COMMON_H */
diff --git a/usrp2/firmware/apps/app_passthru_v2.c b/usrp2/firmware/apps/app_passthru_v2.c
new file mode 100644
index 000000000..1689e8b77
--- /dev/null
+++ b/usrp2/firmware/apps/app_passthru_v2.c
@@ -0,0 +1,244 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "app_passthru_v2.h"
+#include "buffer_pool.h"
+#include "memcpy_wa.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "print_rmon_regs.h"
+#include "db.h"
+#include "clocks.h"
+#include <string.h>
+
+volatile bool link_is_up = false; // eth handler sets this
+
+
+// If this is non-zero, this dbsm could be writing to the ethernet
+dbsm_t *ac_could_be_sending_to_eth;
+
+//static unsigned char exp_seqno = 0;
+
+void
+set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt)
+{
+ reply_pkt->ehdr.dst = cmd_pkt->ehdr.src;
+ reply_pkt->ehdr.ethertype = U2_ETHERTYPE;
+ reply_pkt->thdr.flags = 0;
+ reply_pkt->thdr.fifo_status = 0; // written by protocol engine
+ reply_pkt->thdr.seqno = 0; // written by protocol engine
+ reply_pkt->thdr.ack = 0; // written by protocol engine
+ u2p_set_word0(&reply_pkt->fixed, 0, CONTROL_CHAN);
+ reply_pkt->fixed.timestamp = timer_regs->time;
+}
+
+static void
+send_reply(unsigned char *reply, size_t reply_len)
+{
+ if (reply_len < 64)
+ reply_len = 64;
+
+ // wait for buffer to become idle
+ hal_set_leds(0x4, 0x4);
+ while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0)
+ ;
+ hal_set_leds(0x0, 0x4);
+
+ // copy reply into CPU_TX_BUF
+ memcpy_wa(buffer_ram(CPU_TX_BUF), reply, reply_len);
+
+ // wait until nobody else is sending to the ethernet
+ if (ac_could_be_sending_to_eth){
+ hal_set_leds(0x8, 0x8);
+ dbsm_wait_for_opening(ac_could_be_sending_to_eth);
+ hal_set_leds(0x0, 0x8);
+ }
+
+ // fire it off
+ bp_send_from_buf(CPU_TX_BUF, PORT_ETH, 1, 0, reply_len/4);
+
+ // wait for it to complete (not long, it's a small pkt)
+ while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))) == 0)
+ ;
+
+ bp_clear_buf(CPU_TX_BUF);
+}
+
+
+static size_t
+op_id_cmd(const op_generic_t *p,
+ void *reply_payload, size_t reply_payload_space)
+{
+ op_id_reply_t *r = (op_id_reply_t *) reply_payload;
+ if (reply_payload_space < sizeof(*r)) // no room
+ return 0;
+
+ // Build reply subpacket
+
+ r->opcode = OP_ID_REPLY;
+ r->len = sizeof(op_id_reply_t);
+ r->rid = p->rid;
+ r->addr = *ethernet_mac_addr();
+ r->hw_rev = 0x0000; // FIXME
+ // r->fpga_md5sum = ; // FIXME
+ // r->sw_md5sum = ; // FIXME
+
+ // FIXME Add d'board info, including dbid, min/max gain, min/max freq
+
+ return r->len;
+}
+
+static size_t
+add_eop(void *reply_payload, size_t reply_payload_space)
+{
+ op_generic_t *r = (op_generic_t *) reply_payload;
+ if (reply_payload_space < sizeof(*r))
+ return 0; // no room
+
+ r->opcode = OP_EOP;
+ r->len = sizeof(*r);
+ r->rid = 0;
+ r->ok = 0;
+
+ return r->len;
+}
+
+bool
+handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
+{
+ unsigned char reply[sizeof(u2_eth_packet_t) + 4 * sizeof(u2_subpkt_t)] _AL4;
+ unsigned char *reply_payload = &reply[sizeof(u2_eth_packet_t)];
+ int reply_payload_space = sizeof(reply) - sizeof(u2_eth_packet_t);
+
+ bool handled_it = false;
+
+ // initialize reply
+ memset(reply, 0, sizeof(reply));
+ set_reply_hdr((u2_eth_packet_t *) reply, pkt);
+
+ // point to beginning of payload (subpackets)
+ unsigned char *payload = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t);
+ int payload_len = len - sizeof(u2_eth_packet_t);
+
+ size_t subpktlen = 0;
+
+ while (payload_len >= sizeof(op_generic_t)){
+ const op_generic_t *gp = (const op_generic_t *) payload;
+ subpktlen = 0;
+
+ switch(gp->opcode){
+ case OP_EOP: // end of subpackets
+ goto end_of_subpackets;
+
+ case OP_ID:
+ subpktlen = op_id_cmd(gp, reply_payload, reply_payload_space);
+ handled_it = true;
+ break;
+ }
+
+ int t = (gp->len + 3) & ~3; // bump to a multiple of 4
+ payload += t;
+ payload_len -= t;
+
+ subpktlen = (subpktlen + 3) & ~3; // bump to a multiple of 4
+ reply_payload += subpktlen;
+ reply_payload_space -= subpktlen;
+ }
+
+ end_of_subpackets:
+
+ if (handled_it){
+ // add the EOP marker
+ subpktlen = add_eop(reply_payload, reply_payload_space);
+ subpktlen = (subpktlen + 3) & ~3; // bump to a multiple of 4
+ reply_payload += subpktlen;
+ reply_payload_space -= subpktlen;
+
+ send_reply(reply, reply_payload - reply);
+ }
+
+ return handled_it;
+}
+
+
+/*
+ * Called when an ethernet packet is received.
+ * Return true if we handled it here, otherwise
+ * it'll be passed on to the DSP Tx pipe
+ */
+bool
+eth_pkt_inspector(dbsm_t *sm, int bufno)
+{
+ u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno);
+ size_t byte_len = (buffer_pool_status->last_line[bufno] - 3) * 4;
+
+ //static size_t last_len = 0;
+
+ // hal_toggle_leds(0x1);
+
+ // inspect rcvd frame and figure out what do do.
+
+ if (pkt->ehdr.ethertype != U2_ETHERTYPE)
+ return true; // ignore, probably bogus PAUSE frame from MAC
+
+ int chan = u2p_chan(&pkt->fixed);
+
+ switch (chan){
+ case CONTROL_CHAN:
+ return handle_control_chan_frame(pkt, byte_len);
+ break;
+
+ case 0:
+ default:
+#if 0
+ if (last_len != 0){
+ if (byte_len != last_len){
+ printf("Len: %d last: %d\n", byte_len, last_len);
+ }
+ }
+ last_len = byte_len;
+
+ if((pkt->thdr.seqno) == exp_seqno){
+ exp_seqno++;
+ //putchar('.');
+ }
+ else {
+ // putchar('S');
+ //printf("S%d %d ",exp_seqno,pkt->thdr.seqno);
+ exp_seqno = pkt->thdr.seqno + 1;
+ }
+#endif
+ return false; // pass it on to Tx DSP
+ break;
+ }
+}
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+ link_is_up = speed != 0;
+ hal_set_leds(link_is_up ? 0x10 : 0x0, 0x10);
+ printf("\neth link changed: speed = %d\n", speed);
+}
diff --git a/usrp2/firmware/apps/app_passthru_v2.h b/usrp2/firmware/apps/app_passthru_v2.h
new file mode 100644
index 000000000..102243644
--- /dev/null
+++ b/usrp2/firmware/apps/app_passthru_v2.h
@@ -0,0 +1,54 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_APP_COMMON_H
+#define INCLUDED_APP_COMMON_H
+
+#include "bool.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include <stddef.h>
+#include <db.h>
+
+#define CPU_TX_BUF 1 // cpu -> eth
+
+#define _AL4 __attribute__((aligned (4)))
+
+extern volatile bool link_is_up; // eth handler sets this
+
+
+// If there's a dbsm that sends to the ethernet, put it's address here
+extern dbsm_t *ac_could_be_sending_to_eth;
+
+
+void set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt);
+
+/*
+ * Called when an ethernet packet is received.
+ * Return true if we handled it here, otherwise
+ * it'll be passed on to the DSP Tx pipe
+ */
+bool eth_pkt_inspector(dbsm_t *sm, int bufno);
+
+void link_changed_callback(int speed);
+
+bool handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len);
+
+#endif /* INCLUDED_APP_COMMON_H */
diff --git a/usrp2/firmware/apps/bitrot/tx_drop.c b/usrp2/firmware/apps/bitrot/tx_drop.c
new file mode 100644
index 000000000..d5d6557de
--- /dev/null
+++ b/usrp2/firmware/apps/bitrot/tx_drop.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common.h"
+#include "print_rmon_regs.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*
+ * Like tx_only.c, but we discard data packets instead of sending them to the
+ * DSP TX pipeline.
+ */
+
+int total_rx_pkts = 0;
+int total_rx_bytes = 0;
+
+
+static int timer_delta = MASTER_CLK_RATE/1000; // tick at 1kHz
+
+/*
+ * This program can respond to queries from the host
+ * and stream rx samples.
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow
+ */
+//#define CPU_RX_BUF 0 // eth -> cpu
+//#define CPU_TX_BUF 1 // cpu -> eth
+
+#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer)
+#define DSP_RX_BUF_1 3 // dsp rx -> eth
+#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer)
+#define DSP_TX_BUF_1 5 // eth -> dsp tx
+
+
+/*
+ * ================================================================
+ * configure DSP TX double buffering state machine
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE 4
+#define DSP_TX_SAMPLES_PER_FRAME 250 // not used except w/ debugging
+#define DSP_TX_EXTRA_LINES 2 // reads word0 + timestamp
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+ PORT_ETH,
+ 0,
+ BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+ PORT_DSP,
+ DSP_TX_FIRST_LINE, // starts just past ethernet header
+ 0 // filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm; // the state machine
+
+
+// ----------------------------------------------------------------
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+void
+timer_irq_handler(unsigned irq)
+{
+ hal_set_timeout(timer_delta); // schedule next timeout
+}
+
+// Tx DSP underrun
+void
+underrun_irq_handler(unsigned irq)
+{
+ putchar('U');
+
+ dbsm_stop(&dsp_tx_sm);
+ dsp_tx_regs->clear_state = 1;
+ dbsm_start(&dsp_tx_sm); // restart sm so we're listening to ethernet again
+
+ // putstr("\nirq: underrun\n");
+}
+
+
+void
+start_rx_cmd(const u2_mac_addr_t *host, op_start_rx_t *p)
+{
+}
+
+void
+stop_rx_cmd(void)
+{
+}
+
+static void
+setup_tx()
+{
+ dsp_tx_regs->clear_state = 1;
+ bp_clear_buf(DSP_TX_BUF_0);
+ bp_clear_buf(DSP_TX_BUF_1);
+
+ int tx_scale = 256;
+ int interp = 32;
+
+ op_config_tx_t def_config;
+ memset(&def_config, 0, sizeof(def_config));
+ def_config.phase_inc = 408021893; // 9.5 MHz [2**32 * fc/fsample]
+ def_config.scale_iq = (tx_scale << 16) | tx_scale;
+ def_config.interp = interp;
+
+ // setup Tx DSP regs
+ config_tx_cmd(&def_config);
+}
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+ uint32_t status = buffer_pool_status->status;
+
+ if (status & BPS_ERROR_ALL){
+ // FIXME rare path, handle error conditions
+ putstr("Errors! status = ");
+ puthex32_nl(status);
+
+ printf("total_rx_pkts = %d\n", total_rx_pkts);
+ printf("total_rx_bytes = %d\n", total_rx_bytes);
+
+ print_rmon_regs();
+
+ if (status & (BPS_ERROR(DSP_TX_BUF_0) | BPS_ERROR(DSP_TX_BUF_1))){
+ dbsm_stop(&dsp_tx_sm);
+ dsp_tx_regs->clear_state = 1; // try to restart
+ dbsm_start(&dsp_tx_sm);
+ return;
+ }
+ }
+
+ dbsm_process_status(&dsp_tx_sm, status);
+
+ if (status & BPS_DONE(CPU_TX_BUF)){
+ bp_clear_buf(CPU_TX_BUF);
+ }
+}
+
+
+/*
+ * Called when an ethernet packet is received.
+ *
+ * Claim that we handled all the packets,
+ * dropping those destined for the TX DSP chain
+ * on the ground.
+ */
+bool
+nop_eth_pkt_inspector(dbsm_t *sm, int bufno)
+{
+ hal_toggle_leds(0x1);
+
+ u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno);
+ size_t byte_len = (buffer_pool_status->last_line[bufno] - 1) * 4;
+
+ total_rx_pkts++;
+ total_rx_bytes += byte_len;
+
+ // inspect rcvd frame and figure out what do do.
+
+ if (pkt->ehdr.ethertype != U2_ETHERTYPE)
+ return true; // ignore, probably bogus PAUSE frame from MAC
+
+ int chan = u2p_chan(&pkt->fixed);
+
+ switch (chan){
+ case CONTROL_CHAN:
+ handle_control_chan_frame(pkt, byte_len);
+ return true; // we handled the packet
+ break;
+
+ case 0:
+ default:
+ return true; // We handled the data by dropping it :)
+ break;
+ }
+}
+
+
+int
+main(void)
+{
+ u2_init();
+
+ // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+ hal_gpio_set_tx_mode(15, 0, GPIOM_FPGA_1);
+ hal_gpio_set_rx_mode(15, 0, GPIOM_FPGA_1);
+
+ putstr("\ntx_drop\n");
+
+ // Control LEDs
+ hal_set_leds(0x0, 0x3);
+
+ pic_register_handler(IRQ_UNDERRUN, underrun_irq_handler);
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+ ethernet_init();
+
+ // initialize double buffering state machine for ethernet -> DSP Tx
+
+ dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+ &dsp_tx_recv_args, &dsp_tx_send_args,
+ nop_eth_pkt_inspector);
+
+ // program tx registers
+ setup_tx();
+
+ // kick off the state machine
+ dbsm_start(&dsp_tx_sm);
+
+ while(1){
+ buffer_irq_handler(0);
+ }
+}
+
diff --git a/usrp2/firmware/apps/bitrot/tx_drop2.c b/usrp2/firmware/apps/bitrot/tx_drop2.c
new file mode 100644
index 000000000..7f9b7a563
--- /dev/null
+++ b/usrp2/firmware/apps/bitrot/tx_drop2.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common.h"
+#include "print_rmon_regs.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*
+ * Like tx_only.c, but we discard data packets instead of sending them to the
+ * DSP TX pipeline.
+ */
+
+int total_rx_pkts = 0;
+int total_rx_bytes = 0;
+
+
+static int timer_delta = MASTER_CLK_RATE/1000; // tick at 1kHz
+
+/*
+ * This program can respond to queries from the host
+ * and stream rx samples.
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow
+ */
+//#define CPU_RX_BUF 0 // eth -> cpu
+//#define CPU_TX_BUF 1 // cpu -> eth
+
+#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer)
+#define DSP_RX_BUF_1 3 // dsp rx -> eth
+#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer)
+#define DSP_TX_BUF_1 5 // eth -> dsp tx
+
+
+/*
+ * ================================================================
+ * configure DSP RX double buffering state machine
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line (word0)
+// DSP Rx writes timestamp followed by nlines_per_frame of samples
+#define DSP_RX_FIRST_LINE 5
+#define DSP_RX_SAMPLES_PER_FRAME 128
+#define DSP_RX_EXTRA_LINES 1 // writes timestamp
+
+// Receive from DSP Rx
+buf_cmd_args_t dsp_rx_recv_args = {
+ PORT_DSP,
+ DSP_RX_FIRST_LINE,
+ BP_LAST_LINE
+};
+
+// send to ethernet
+buf_cmd_args_t dsp_rx_send_args = {
+ PORT_ETH,
+ 0, // starts with ethernet header in line 0
+ 0, // filled in from last_line register
+};
+
+dbsm_t dsp_rx_sm; // the state machine
+
+/*
+ * ================================================================
+ * configure DSP TX double buffering state machine
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE 4
+#define DSP_TX_SAMPLES_PER_FRAME 250 // not used except w/ debugging
+#define DSP_TX_EXTRA_LINES 2 // reads word0 + timestamp
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+ PORT_ETH,
+ 0,
+ BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+ PORT_DSP,
+ DSP_TX_FIRST_LINE, // starts just past ethernet header
+ 0 // filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm; // the state machine
+
+
+// ----------------------------------------------------------------
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+void
+timer_irq_handler(unsigned irq)
+{
+ hal_set_timeout(timer_delta); // schedule next timeout
+}
+
+// Tx DSP underrun
+void
+underrun_irq_handler(unsigned irq)
+{
+ putchar('U');
+
+ dbsm_stop(&dsp_tx_sm);
+ dsp_tx_regs->clear_state = 1;
+ dbsm_start(&dsp_tx_sm); // restart sm so we're listening to ethernet again
+
+ // putstr("\nirq: underrun\n");
+}
+
+
+void
+start_rx_cmd(const u2_mac_addr_t *host, op_start_rx_t *p)
+{
+}
+
+void
+stop_rx_cmd(void)
+{
+}
+
+static void
+setup_tx()
+{
+ dsp_tx_regs->clear_state = 1;
+ bp_clear_buf(DSP_TX_BUF_0);
+ bp_clear_buf(DSP_TX_BUF_1);
+
+#if 1
+ int tx_scale = 256;
+ int interp = 32;
+
+ op_config_tx_t def_config;
+ memset(&def_config, 0, sizeof(def_config));
+ def_config.phase_inc = 408021893; // 9.5 MHz [2**32 * fc/fsample]
+ def_config.scale_iq = (tx_scale << 16) | tx_scale;
+ def_config.interp = interp;
+
+ // setup Tx DSP regs
+ config_tx_cmd(&def_config);
+#endif
+}
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+ uint32_t status = buffer_pool_status->status;
+
+ if (status & BPS_ERROR_ALL){
+ // FIXME rare path, handle error conditions
+ putstr("Errors! status = ");
+ puthex32_nl(status);
+
+ printf("total_rx_pkts = %d\n", total_rx_pkts);
+ printf("total_rx_bytes = %d\n", total_rx_bytes);
+
+ print_rmon_regs();
+
+ if (status & (BPS_ERROR(DSP_TX_BUF_0) | BPS_ERROR(DSP_TX_BUF_1))){
+ dbsm_stop(&dsp_tx_sm);
+ dsp_tx_regs->clear_state = 1; // try to restart
+ dbsm_start(&dsp_tx_sm);
+ return;
+ }
+ }
+
+ dbsm_process_status(&dsp_tx_sm, status);
+
+ if (status & BPS_DONE(CPU_TX_BUF)){
+ bp_clear_buf(CPU_TX_BUF);
+ }
+}
+
+/*
+ * Called when an ethernet packet is received.
+ * Return true if we handled it here (always!)
+ */
+bool
+nop_eth_pkt_inspector(dbsm_t *sm, int bufno)
+{
+ hal_toggle_leds(0x1);
+
+ u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno);
+ size_t byte_len = (buffer_pool_status->last_line[bufno] - 1) * 4;
+
+ total_rx_pkts++;
+ total_rx_bytes += byte_len;
+
+ // inspect rcvd frame and figure out what do do.
+
+ if (pkt->ehdr.ethertype != U2_ETHERTYPE)
+ return true; // ignore, probably bogus PAUSE frame from MAC
+
+ int chan = u2p_chan(&pkt->fixed);
+
+ switch (chan){
+ case CONTROL_CHAN:
+ handle_control_chan_frame(pkt, byte_len);
+ return true; // we handled the packet
+ break;
+
+ case 0:
+ default:
+ return true; // say we handled it
+ break;
+ }
+}
+
+
+int
+main(void)
+{
+ u2_init();
+
+ // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+ hal_gpio_set_tx_mode(15, 0, GPIOM_FPGA_1);
+ hal_gpio_set_rx_mode(15, 0, GPIOM_FPGA_1); // no printing...
+
+ putstr("\ntx_drop2\n");
+
+ // Control LEDs
+ hal_set_leds(0x0, 0x3);
+
+ // pic_register_handler(IRQ_OVERRUN, overrun_irq_handler);
+ pic_register_handler(IRQ_UNDERRUN, underrun_irq_handler);
+
+ //pic_register_handler(IRQ_TIMER, timer_irq_handler);
+ //hal_set_timeout(timer_delta);
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+
+ ethernet_init();
+
+ // initialize double buffering state machine for ethernet -> DSP Tx
+
+ dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+ &dsp_tx_recv_args, &dsp_tx_send_args,
+ nop_eth_pkt_inspector);
+
+ // program tx registers
+ setup_tx();
+
+ // kick off the state machine
+ dbsm_start(&dsp_tx_sm);
+
+ while(1){
+ buffer_irq_handler(0);
+ }
+}
+
diff --git a/usrp2/firmware/apps/bitrot/tx_drop_rate_limited.c b/usrp2/firmware/apps/bitrot/tx_drop_rate_limited.c
new file mode 100644
index 000000000..0eab25b34
--- /dev/null
+++ b/usrp2/firmware/apps/bitrot/tx_drop_rate_limited.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common.h"
+#include "print_rmon_regs.h"
+#include "eth_mac.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*
+ * receive packets from ethernet at a fixed rate and discard them
+ */
+
+int total_rx_pkts = 0;
+int total_rx_bytes = 0;
+
+
+static int timer_delta = (int)(MASTER_CLK_RATE * 10e-6); // 10us / tick
+
+
+/*
+ * This program can respond to queries from the host
+ * and stream rx samples.
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow
+ */
+//#define CPU_RX_BUF 0 // eth -> cpu
+//#define CPU_TX_BUF 1 // cpu -> eth
+
+#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer)
+#define DSP_RX_BUF_1 3 // dsp rx -> eth
+#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer)
+#define DSP_TX_BUF_1 5 // eth -> dsp tx
+
+
+
+// ----------------------------------------------------------------
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+static volatile bool receive_packet_now = false;
+
+void
+timer_irq_handler(unsigned irq)
+{
+ hal_set_timeout(timer_delta); // schedule next timeout
+ receive_packet_now = true;
+}
+
+
+// Tx DSP underrun
+void
+underrun_irq_handler(unsigned irq)
+{
+ putchar('U');
+}
+
+
+void
+start_rx_cmd(const u2_mac_addr_t *host, op_start_rx_t *p)
+{
+}
+
+void
+stop_rx_cmd(void)
+{
+}
+
+static void
+setup_tx()
+{
+ dsp_tx_regs->clear_state = 1;
+ bp_clear_buf(DSP_TX_BUF_0);
+ bp_clear_buf(DSP_TX_BUF_1);
+
+ int tx_scale = 256;
+ int interp = 32;
+
+ op_config_tx_t def_config;
+ memset(&def_config, 0, sizeof(def_config));
+ def_config.phase_inc = 408021893; // 9.5 MHz [2**32 * fc/fsample]
+ def_config.scale_iq = (tx_scale << 16) | tx_scale;
+ def_config.interp = interp;
+
+ // setup Tx DSP regs
+ config_tx_cmd(&def_config);
+}
+
+
+/*
+ * Called when an ethernet packet is received.
+ *
+ * Claim that we handled all the packets,
+ * dropping those destined for the TX DSP chain
+ * on the ground.
+ */
+bool
+nop_eth_pkt_inspector(dbsm_t *sm, int bufno)
+{
+ hal_toggle_leds(0x1);
+
+ u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno);
+ size_t byte_len = (buffer_pool_status->last_line[bufno] - 1) * 4;
+
+ total_rx_pkts++;
+ total_rx_bytes += byte_len;
+
+ // inspect rcvd frame and figure out what do do.
+
+ if (pkt->ehdr.ethertype != U2_ETHERTYPE)
+ return true; // ignore, probably bogus PAUSE frame from MAC
+
+ int chan = u2p_chan(&pkt->fixed);
+
+ switch (chan){
+ case CONTROL_CHAN:
+ handle_control_chan_frame(pkt, byte_len);
+ return true; // we handled the packet
+ break;
+
+ case 0:
+ default:
+ return true; // We handled the data by dropping it :)
+ break;
+ }
+}
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+ uint32_t status = buffer_pool_status->status;
+
+ if (status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF)))
+ bp_clear_buf(CPU_TX_BUF);
+
+ if (status & (BPS_DONE(DSP_TX_BUF_0) | BPS_ERROR(DSP_TX_BUF_0))){
+ bp_clear_buf(DSP_TX_BUF_0);
+
+ if (status & BPS_ERROR(DSP_TX_BUF_0)){
+ int crc = eth_mac_read_rmon(0x05);
+ int fifo_full = eth_mac_read_rmon(0x06);
+ int too_short_too_long = eth_mac_read_rmon(0x07);
+ putstr("Errors! status = ");
+ puthex32_nl(status);
+
+ printf("crc_err\t\t= %d\n", crc);
+ printf("fifo_full\t\t= %d\n", fifo_full);
+ printf("too_short_too_long\t= %d\n", too_short_too_long);
+
+ printf("total_rx_pkts = %d\n", total_rx_pkts);
+ printf("total_rx_bytes = %d\n", total_rx_bytes);
+ }
+ else
+ nop_eth_pkt_inspector(0, DSP_TX_BUF_0);
+ }
+
+ if (receive_packet_now && (status & BPS_IDLE(DSP_TX_BUF_0))){
+ receive_packet_now = false;
+ bp_receive_to_buf(DSP_TX_BUF_0, PORT_ETH, 1, 0, BP_LAST_LINE);
+ }
+}
+
+
+int
+main(void)
+{
+ u2_init();
+
+ // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+ hal_gpio_set_tx_mode(15, 0, GPIOM_FPGA_1);
+ hal_gpio_set_rx_mode(15, 0, GPIOM_FPGA_1);
+
+ putstr("\ntx_drop_rate_limited\n");
+
+ // Control LEDs
+ hal_set_leds(0x0, 0x3);
+
+ pic_register_handler(IRQ_UNDERRUN, underrun_irq_handler);
+
+ pic_register_handler(IRQ_TIMER, timer_irq_handler);
+ hal_set_timeout(timer_delta);
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+ ethernet_init();
+
+ // program tx registers
+ setup_tx();
+
+ // start a receive from ethernet
+ bp_receive_to_buf(DSP_TX_BUF_0, PORT_ETH, 1, 0, BP_LAST_LINE);
+
+ while(1){
+ buffer_irq_handler(0);
+ }
+}
+
diff --git a/usrp2/firmware/apps/blink_leds.c b/usrp2/firmware/apps/blink_leds.c
new file mode 100644
index 000000000..682ca8db2
--- /dev/null
+++ b/usrp2/firmware/apps/blink_leds.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include "nonstdio.h"
+
+int
+main(void)
+{
+ int counter = 0;
+
+ u2_init();
+
+ putstr("blink_leds\n");
+ while(1){
+ output_regs->leds = (counter++ & 0x3);
+ }
+
+ return 0;
+}
diff --git a/usrp2/firmware/apps/blink_leds2.c b/usrp2/firmware/apps/blink_leds2.c
new file mode 100644
index 000000000..d4bd89a19
--- /dev/null
+++ b/usrp2/firmware/apps/blink_leds2.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include "pic.h"
+#include "nonstdio.h"
+
+//#define DELTA_T (MASTER_CLK_RATE/2) // 0.5s (10ns per tick)
+#define DELTA_T 5000 // 5 us (10ns per tick)
+
+
+void
+timer_handler(unsigned irq)
+{
+ hal_set_timeout(DELTA_T); // schedule next timeout
+ hal_toggle_leds(0x2);
+}
+
+int
+main(void)
+{
+ u2_init();
+
+ putstr("blink_leds2\n");
+ pic_register_handler(IRQ_TIMER, timer_handler);
+ hal_set_timeout(DELTA_T); // schedule next timeout
+
+ while(1){
+ hal_toggle_leds(0x1);
+ }
+
+ return 0;
+}
diff --git a/usrp2/firmware/apps/buf_ram_test.c b/usrp2/firmware/apps/buf_ram_test.c
new file mode 100644
index 000000000..e639166a1
--- /dev/null
+++ b/usrp2/firmware/apps/buf_ram_test.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "bool.h"
+#include "nonstdio.h"
+#include "hal_io.h"
+#include "mdelay.h"
+
+
+static void
+write_bufs(void)
+{
+ int i, n;
+ int counter = 0;
+
+ for (n = 0; n < NBUFFERS; n++){
+ volatile int *p = buffer_ram(n);
+ for (i = 0; i < BP_NLINES; i++)
+ p[i] = counter++;
+ }
+}
+
+// return number of errors detected
+static int
+check_bufs(void)
+{
+ int i, n;
+ int counter = 0;
+ int nerrors = 0;
+
+ for (n = 0; n < NBUFFERS; n++){
+ volatile int *p = buffer_ram(n);
+ for (i = 0; i < BP_NLINES; i++, counter++){
+ int rd = p[i];
+ if (rd != counter){
+ putchar('b');
+ putchar(n + '0');
+ putchar('[');
+ puthex16(i);
+ putstr("] exp: ");
+ puthex32(counter);
+ putstr(" got: ");
+ puthex32_nl(rd);
+ nerrors++;
+ }
+ }
+ }
+ return nerrors;
+}
+
+
+int
+main(void)
+{
+ u2_init();
+
+ output_regs->leds = 0;
+
+ write_bufs();
+ int nerrors = check_bufs();
+
+ if (nerrors == 0){
+ output_regs->leds = 0x3; // leds on -> PASS
+ putstr("PASS\n");
+ }
+ else {
+ output_regs->leds = 0x0; // leds off -> FAIL
+ putstr("FAIL\n");
+ }
+
+ hal_finish();
+ return 0;
+}
diff --git a/usrp2/firmware/apps/can_i_sub.c b/usrp2/firmware/apps/can_i_sub.c
new file mode 100644
index 000000000..ed49791f0
--- /dev/null
+++ b/usrp2/firmware/apps/can_i_sub.c
@@ -0,0 +1,25 @@
+#include <u2_init.h>
+#include <nonstdio.h>
+
+//typedef long long int64_t;
+
+
+int64_t sub(int64_t a, int64_t b);
+void print(int64_t d);
+
+int main(void)
+{
+ u2_init();
+
+ int64_t d = sub(462550990848000LL, 462028800000000LL);
+ print_uint64(d);
+ newline();
+ return 0;
+}
+
+int64_t sub(int64_t a, int64_t b)
+{
+ return a - b;
+}
+
+
diff --git a/usrp2/firmware/apps/double_buffer_fragment.c b/usrp2/firmware/apps/double_buffer_fragment.c
new file mode 100644
index 000000000..cfc061247
--- /dev/null
+++ b/usrp2/firmware/apps/double_buffer_fragment.c
@@ -0,0 +1,138 @@
+#if 0
+void
+double_buffering(int port) {
+ unsigned int localstatus = buffer_pool_status->status;
+
+ if(localstatus & BPS_DONE_0) {
+ bp_clear_buf(0);
+ if(buffer_state[0] == FILLING) {
+ buffer_state[0] = FULL;
+ if(buffer_state[1] == EMPTY) {
+ bp_receive_to_buf(1, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines
+ buffer_state[1] = FILLING;
+ }
+ else
+ dsp_rx_idle = 1;
+ if(serdes_tx_idle) {
+ serdes_tx_idle = 0;
+ bp_send_from_buf(0, port, 1, 10, 509); // SERDES_TX from buffer 0
+ buffer_state[0] = EMPTYING;
+ }
+ }
+ else { // buffer was emptying
+ buffer_state[0] = EMPTY;
+ if(dsp_rx_idle) {
+ dsp_rx_idle = 0;
+ bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 0, use 500 lines
+ buffer_state[0] = FILLING;
+ }
+ if(buffer_state[1] == FULL) {
+ bp_send_from_buf(1, port, 1, 10, 509); // SERDES_TX from buffer 1
+ buffer_state[1] = EMPTYING;
+ }
+ else
+ serdes_tx_idle = 1;
+ }
+ putstr("Int Proc'ed 0\n");
+ }
+
+ if(localstatus & BPS_DONE_1) {
+ bp_clear_buf(1);
+ if(buffer_state[1] == FILLING) {
+ buffer_state[1] = FULL;
+ if(buffer_state[0] == EMPTY) {
+ bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines
+ buffer_state[0] = FILLING;
+ }
+ else
+ dsp_rx_idle = 1;
+ if(serdes_tx_idle) {
+ serdes_tx_idle = 0;
+ bp_send_from_buf(1, port, 1, 10, 509); // SERDES_TX from buffer 1
+ buffer_state[1] = EMPTYING;
+ }
+ }
+ else { // buffer was emptying
+ buffer_state[1] = EMPTY;
+ if(dsp_rx_idle) {
+ dsp_rx_idle = 0;
+ bp_receive_to_buf(1, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines
+ buffer_state[1] = FILLING;
+ }
+ if(buffer_state[0] == FULL) {
+ bp_send_from_buf(0, port, 1, 10, 509); // SERDES_TX from buffer 0
+ buffer_state[0] = EMPTYING;
+ }
+ else
+ serdes_tx_idle = 1;
+ }
+ putstr("Int Proc'ed 1\n");
+ }
+
+ if(localstatus & BPS_DONE_2) {
+ bp_clear_buf(2);
+ if(buffer_state[2] == FILLING) {
+ buffer_state[2] = FULL;
+ if(buffer_state[3] == EMPTY) {
+ bp_receive_to_buf(3, port, 1, 5, 504); // SERDES_RX to buffer 3, use 500 lines
+ buffer_state[3] = FILLING;
+ }
+ else
+ serdes_rx_idle = 1;
+ if(dsp_tx_idle) {
+ dsp_tx_idle = 0;
+ bp_send_from_buf(2, 1, 1, 5, 504); // DSP_TX from buffer 2
+ buffer_state[2] = EMPTYING;
+ }
+ }
+ else { // buffer was emptying
+ buffer_state[2] = EMPTY;
+ if(serdes_rx_idle) {
+ serdes_rx_idle = 0;
+ bp_receive_to_buf(2, port, 1, 5, 504); // SERDES_RX to buffer 2
+ buffer_state[2] = FILLING;
+ }
+ if(buffer_state[3] == FULL) {
+ bp_send_from_buf(3, 1, 1, 5, 504); // DSP_TX from buffer 3
+ buffer_state[3] = EMPTYING;
+ }
+ else
+ dsp_tx_idle = 1;
+ }
+ putstr("Int Proc'ed 2\n");
+ }
+
+ if(localstatus & BPS_DONE_3) {
+ bp_clear_buf(3);
+ if(buffer_state[3] == FILLING) {
+ buffer_state[3] = FULL;
+ if(buffer_state[2] == EMPTY) {
+ bp_receive_to_buf(2, port, 1, 5, 504); // SERDES_RX to buffer 2, use 500 lines
+ buffer_state[2] = FILLING;
+ }
+ else
+ serdes_rx_idle = 1;
+ if(dsp_tx_idle) {
+ dsp_tx_idle = 0;
+ bp_send_from_buf(3, 1, 1, 5, 504); // DSP_TX from buffer 3
+ buffer_state[3] = EMPTYING;
+ }
+ }
+ else { // buffer was emptying
+ buffer_state[3] = EMPTY;
+ if(serdes_rx_idle) {
+ serdes_rx_idle = 0;
+ bp_receive_to_buf(3, port, 1, 5, 504); // SERDES_RX to buffer 3
+ buffer_state[3] = FILLING;
+ }
+ if(buffer_state[2] == FULL) {
+ bp_send_from_buf(2, 1, 1, 5, 504); // DSP_TX from buffer 2
+ buffer_state[2] = EMPTYING;
+ }
+ else
+ dsp_tx_idle = 1;
+ }
+ putstr("Int Proc'ed 3\n");
+ }
+}
+#endif
diff --git a/usrp2/firmware/apps/echo.c b/usrp2/firmware/apps/echo.c
new file mode 100644
index 000000000..89108ee80
--- /dev/null
+++ b/usrp2/firmware/apps/echo.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "u2_init.h"
+#include "stdio.h"
+
+int
+main(void)
+{
+ u2_init();
+
+ puts("\n>>> echo <<<");
+
+ while (1){
+ int ch = getchar();
+ putchar(ch);
+ }
+
+ return 0;
+}
diff --git a/usrp2/firmware/apps/eth_serdes.c b/usrp2/firmware/apps/eth_serdes.c
new file mode 100644
index 000000000..c47b8ebd0
--- /dev/null
+++ b/usrp2/firmware/apps/eth_serdes.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_passthru_v2.h"
+#include "memcpy_wa.h"
+#include "clocks.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now)
+
+#if (FW_SETS_SEQNO)
+static int fw_seqno __attribute__((unused)); // used when f/w is filling in sequence numbers
+#endif
+
+
+/*
+ * Full duplex Tx and Rx between ethernet and serdes
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow
+ */
+//#define CPU_RX_BUF 0 // eth -> cpu
+
+#define DSP_RX_BUF_0 2 // serdes -> eth (double buffer)
+#define DSP_RX_BUF_1 3 // serdes -> eth
+#define DSP_TX_BUF_0 4 // eth -> serdes (double buffer)
+#define DSP_TX_BUF_1 5 // eth -> serdes
+
+/*
+ * ================================================================
+ * configure serdes double buffering state machine (eth -> serdes)
+ * ================================================================
+ */
+
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+ PORT_ETH,
+ 0,
+ BP_LAST_LINE
+};
+
+// send to serdes
+buf_cmd_args_t dsp_tx_send_args = {
+ PORT_SERDES,
+ 0,
+ 0 // filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm; // the state machine
+
+/*
+ * ====================================================================
+ * configure serdes RX double buffering state machine (serdes -> eth)
+ * ====================================================================
+ */
+
+// receive from serdes
+buf_cmd_args_t dsp_rx_recv_args = {
+ PORT_SERDES,
+ 0,
+ BP_LAST_LINE
+};
+
+// send to ETH
+buf_cmd_args_t dsp_rx_send_args = {
+ PORT_ETH,
+ 0, // starts with ethernet header in line 0
+ 0, // filled in from list_line register
+};
+
+dbsm_t dsp_rx_sm; // the state machine
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+// ----------------------------------------------------------------
+
+
+#if (FW_SETS_SEQNO)
+/*
+ * Debugging ONLY. This will be handled by the tx_protocol_engine.
+ *
+ * This is called when the DSP Rx chain has filled in a packet.
+ * We set and increment the seqno, then return false, indicating
+ * that we didn't handle the packet. A bit of a kludge
+ * but it should work.
+ */
+
+bool
+fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false
+{
+#if 0
+ uint32_t *p = buffer_ram(buf_this);
+ uint32_t last_line = buffer_pool_status->last_line[buf_this] - sm->last_line_adj;
+ printf("fw_sets_seqno_inspector: buf_this = %d, last_line = %d\n",
+ buf_this, last_line);
+
+ print_buffer(p, (last_line + 1));
+#endif
+
+#if 0
+ uint32_t *p = buffer_ram(buf_this);
+ uint32_t seqno = fw_seqno++;
+
+ // KLUDGE all kinds of nasty magic numbers and embedded knowledge
+ uint32_t t = p[4];
+ t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
+ p[4] = t;
+#endif
+
+ return false; // we didn't handle the packet
+}
+#endif
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+ uint32_t status = buffer_pool_status->status;
+
+ if (0 && (status & ~BPS_IDLE_ALL)){
+ putstr("status = ");
+ puthex32_nl(status);
+ }
+
+ dbsm_process_status(&dsp_tx_sm, status);
+ dbsm_process_status(&dsp_rx_sm, status);
+}
+
+int
+main(void)
+{
+ u2_init();
+
+ putstr("\neth <-> serdes\n");
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+ ethernet_init();
+
+ // clocks_mimo_config(MC_WE_LOCK_TO_SMA | MC_PROVIDE_CLK_TO_MIMO);
+ clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO);
+
+#if 0
+ // make bit 15 of Tx gpio's be a s/w output
+ hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
+ hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
+#endif
+
+#if 1
+ output_regs->debug_mux_ctrl = 1;
+ hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+ hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+ hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
+ hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
+#endif
+
+
+ // initialize double buffering state machine for ethernet -> serdes
+
+ dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+ &dsp_tx_recv_args, &dsp_tx_send_args,
+ eth_pkt_inspector);
+
+
+ // initialize double buffering state machine for serdes -> ethernet
+
+ if (FW_SETS_SEQNO){
+ dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+ &dsp_rx_recv_args, &dsp_rx_send_args,
+ fw_sets_seqno_inspector);
+ }
+ else {
+ dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+ &dsp_rx_recv_args, &dsp_rx_send_args,
+ dbsm_nop_inspector);
+ }
+
+ // tell app_common that this dbsm could be sending to the ethernet
+ ac_could_be_sending_to_eth = &dsp_rx_sm;
+
+
+ // kick off the state machines
+ dbsm_start(&dsp_tx_sm);
+ dbsm_start(&dsp_rx_sm);
+
+ //int which = 0;
+
+ while(1){
+ // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
+ // which ^= 0x8000;
+
+ buffer_irq_handler(0);
+ }
+}
diff --git a/usrp2/firmware/apps/gen_eth_packets.c b/usrp2/firmware/apps/gen_eth_packets.c
new file mode 100644
index 000000000..ce1e8160b
--- /dev/null
+++ b/usrp2/firmware/apps/gen_eth_packets.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "memcpy_wa.h"
+#include "print_rmon_regs.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+// ----------------------------------------------------------------
+
+static u2_mac_addr_t dst_mac_addr =
+ {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
+
+// ----------------------------------------------------------------
+
+// #define PACKET_SIZE 1500 // bytes
+// #define ETH_DATA_RATE 1000000 // 1MB/s
+// #define ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE) // 13,3333 pkts/s
+
+// static int timer_delta = MASTER_CLK_RATE/ETH_PACKET_RATE; // ticks between interrupts
+
+static int timer_delta = (int)(MASTER_CLK_RATE * 1e-3); // tick at 1 kHz
+static int sim_timer_delta = (int)(MASTER_CLK_RATE * 100e-6); // tick at 10 kHz
+
+static volatile bool send_packet_now = false; // timer handler sets this
+static volatile bool link_is_up = false; // eth handler sets this
+
+int packet_number = 0;
+
+
+#define CPU_TX_BUF 0 // cpu xmits ethernet frames from here
+#define CPU_RX_BUF 1 // receive ethernet frames here
+
+// ----------------------------------------------------------------
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+ link_is_up = speed == 0 ? false : true;
+ hal_set_leds(link_is_up ? 0x2 : 0x0, 0x2);
+ printf("\neth link changed: speed = %d\n", speed);
+}
+
+void
+timer_irq_handler(unsigned irq)
+{
+ hal_set_timeout(timer_delta); // schedule next timeout
+ send_packet_now = 1;
+}
+
+
+static void
+init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum)
+{
+ int i = 0;
+ int mark = ((bufnum & 0xff) << 24) | 0x005A0000;
+
+ for (i = 0; i < BP_NLINES; i++){
+ buf[i] = mark | i;
+ mark ^= 0x00FF0000;
+ }
+
+ // copy header into buffer
+ memcpy_wa(buf, pkt, sizeof(*pkt));
+}
+
+static void
+init_packets(void)
+{
+ u2_eth_packet_t pkt __attribute__((aligned (4)));
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ehdr.dst = dst_mac_addr;
+ // src address filled in by mac
+
+ pkt.ehdr.ethertype = U2_ETHERTYPE;
+ pkt.fixed.word0 = 0x01234567;
+ pkt.fixed.timestamp = 0xffffffff;
+
+ // init just the one we're using
+ init_packet((void *)buffer_ram(CPU_TX_BUF), &pkt, CPU_TX_BUF);
+}
+
+int
+main(void)
+{
+ int npackets_sent = 0;
+
+ u2_init();
+
+ // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+ //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+ //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+ putstr("\ngen_eth_packets\n");
+
+ hal_set_leds(0x0, 0x3);
+
+ init_packets();
+
+ pic_register_handler(IRQ_TIMER, timer_irq_handler);
+
+ if (hwconfig_simulation_p())
+ timer_delta = sim_timer_delta;
+
+ hal_set_timeout(timer_delta);
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+ ethernet_init();
+
+ if (hwconfig_simulation_p()){
+ eth_mac->speed = 4; // hardcode mac speed to 1000
+ link_is_up = true;
+ }
+
+ // fire off a receive from the ethernet
+ bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+
+ while(1){
+ uint32_t status = buffer_pool_status->status;
+
+ if (status & (BPS_DONE(CPU_RX_BUF) | BPS_ERROR(CPU_RX_BUF))){
+ bp_clear_buf(CPU_RX_BUF);
+ // ignore incoming ethernet packets; they were looped back in sim
+ bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+ }
+
+ if (status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))){
+ bp_clear_buf(CPU_TX_BUF);
+ npackets_sent++;
+ if ((npackets_sent & 0xF) == 0) // print after every 16 packets
+ print_rmon_regs();
+ }
+
+ if (link_is_up && send_packet_now && (status & BPS_IDLE(CPU_TX_BUF))){
+ send_packet_now = false;
+
+ // kick off the next packet
+ // FIXME set packet number in packet
+
+ bp_send_from_buf(CPU_TX_BUF, PORT_ETH, 1, 0, 255); // 1KB total
+ hal_toggle_leds(0x1);
+ }
+ }
+
+ hal_finish();
+ return 1;
+}
diff --git a/usrp2/firmware/apps/gen_pause_frames.c b/usrp2/firmware/apps/gen_pause_frames.c
new file mode 100644
index 000000000..4eaebcc4a
--- /dev/null
+++ b/usrp2/firmware/apps/gen_pause_frames.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "u2_eth_packet.h"
+#include "memcpy_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+
+
+// ----------------------------------------------------------------
+
+unsigned char dst_mac_addr[6] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+// ----------------------------------------------------------------
+
+// #define PACKET_SIZE 1500 // bytes
+// #define ETH_DATA_RATE 1000000 // 1MB/s
+// #define ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE) // 13,3333 pkts/s
+
+// static int timer_delta = MASTER_CLK_RATE/ETH_PACKET_RATE; // ticks between interrupts
+
+static int timer_delta = MASTER_CLK_RATE/1000; // tick at 1kHz
+
+static volatile bool send_packet_now = false; // timer handler sets this
+static volatile bool link_is_up = false; // eth handler sets this
+
+int packet_number = 0;
+
+// ----------------------------------------------------------------
+
+// debugging output on tx pins
+#define LS_MASK 0xE0000
+#define LS_1000 0x80000
+#define LS_100 0x40000
+#define LS_10 0x20000
+
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+ int v = 0;
+ switch(speed){
+ case 10:
+ v = LS_10;
+ link_is_up = true;
+ break;
+
+ case 100:
+ v = LS_100;
+ link_is_up = true;
+ break;
+
+ case 1000:
+ v = LS_100;
+ link_is_up = true;
+ break;
+
+ default:
+ v = 0;
+ link_is_up = false;
+ break;
+ }
+
+ hal_gpio_set_tx(v, LS_MASK); /* set debug bits on d'board */
+
+ putstr("\neth link changed: speed = ");
+ puthex16_nl(speed);
+}
+
+void
+timer_irq_handler(unsigned irq)
+{
+ hal_set_timeout(timer_delta); // schedule next timeout
+ send_packet_now = 1;
+}
+
+
+void
+buffer_irq_handler(unsigned irq)
+{
+ // FIXME
+}
+
+static void
+init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum)
+{
+ int i = 0;
+ int mark = ((bufnum & 0xff) << 24) | 0x005A0000;
+
+ for (i = 0; i < BP_NLINES; i++){
+ buf[i] = mark | i;
+ mark ^= 0x00FF0000;
+ }
+
+ // copy header into buffer
+ memcpy_wa(buf, pkt, sizeof(*pkt));
+}
+
+static void
+init_packets(void)
+{
+ int i;
+
+ u2_eth_packet_t pkt __attribute__((aligned (4)));
+
+ for (i = 0; i < 6; i++){
+ pkt.ehdr.dst_addr[i] = dst_mac_addr[i];
+ pkt.ehdr.src_addr[i] = 0; // filled in by mac
+ }
+ pkt.ehdr.ethertype = U2_ETHERTYPE;
+
+ // fill ALL buffers for debugging
+ for (i = 0; i < 8; i++)
+ init_packet((void *)buffer_ram(i), &pkt, i);
+}
+
+static int led_counter = 0;
+
+int
+main(void)
+{
+ int send_pause = 1;
+
+ u2_init();
+
+ // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+ //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+ //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+ putstr("\ngen_eth_packets\n");
+
+ // Control LEDs
+ output_regs->leds = 0x00;
+
+ init_packets();
+
+ // pic_register_handler(IRQ_BUFFER, buffer_irq_handler); // poll for now
+ pic_register_handler(IRQ_TIMER, timer_irq_handler);
+ hal_set_timeout(timer_delta);
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+
+ ethernet_init();
+
+ eth_mac->pause_frame_send_en = 1;
+ eth_mac->pause_quanta_set = 16384 / 512;
+
+ // eth_mac->speed = 4; // FIXME hardcode mac speed to 1000
+
+ while(1){
+ if (link_is_up && send_packet_now){
+ send_packet_now = false;
+
+
+ if (send_pause)
+ eth_mac->xon_cpu = 1;
+ else
+ eth_mac->xon_cpu = 0;
+
+ send_pause ^= 1;
+
+ // kick off the next packet
+ // FIXME set packet number in packet
+
+#if 0
+ bp_send_from_buf(0, PORT_ETH, 1, 0, 255); // 1KB total
+
+ while ((buffer_pool_status->status & (BPS_DONE_0|BPS_ERROR_0)) == 0)
+ ;
+ bp_clear_buf(0);
+#endif
+
+ output_regs->leds = ((++led_counter) & 0x1) | (link_is_up ? 0x2 : 0x0);
+ }
+ }
+
+ hal_finish();
+ return 1;
+}
diff --git a/usrp2/firmware/apps/hello.c b/usrp2/firmware/apps/hello.c
new file mode 100644
index 000000000..bce843093
--- /dev/null
+++ b/usrp2/firmware/apps/hello.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "u2_init.h"
+#include "stdio.h"
+
+int
+main(void)
+{
+ u2_init();
+
+ puts("Hello World");
+ puts("Goodbye World");
+
+ return 0;
+}
diff --git a/usrp2/firmware/apps/ibs_rx_test.c b/usrp2/firmware/apps/ibs_rx_test.c
new file mode 100644
index 000000000..bdc04747e
--- /dev/null
+++ b/usrp2/firmware/apps/ibs_rx_test.c
@@ -0,0 +1,82 @@
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "nonstdio.h"
+
+#define PORT 2 // ethernet = 2, serdes = 0
+int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf;
+int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle;
+
+int buffer_state[4];
+
+static void __attribute__((unused))
+wait_until_status_nonzero(void)
+{
+ while (buffer_pool_status->status == 0)
+ ;
+}
+
+int
+main(void)
+{
+ int i;
+
+ u2_init();
+
+ output_regs->adc_ctrl = 0x0A;
+
+ dsp_rx_regs->freq = 0;
+ dsp_rx_regs->scale_iq = (1 << 16) | 1;
+ dsp_rx_regs->decim_rate = 8;
+
+ volatile unsigned int *buffer0 = buffer_ram(0);
+ volatile unsigned int *buffer1 = buffer_ram(1);
+ volatile unsigned int *buffer2 = buffer_ram(2);
+
+ putstr("Starting RX\n");
+ bp_clear_buf(0);
+ bp_receive_to_buf(0, 1, 1, 0, 99);
+
+ dsp_rx_regs->rx_command = (50 << 9) | 100; // Numlines, lines per frame
+ dsp_rx_regs->rx_time = 0x2000;
+
+ dsp_rx_regs->rx_command = (137 << 9) | 50; // Numlines, lines per frame
+ dsp_rx_regs->rx_time = 0x2200;
+
+ while (buffer_pool_status->status == 0)
+ ;
+ bp_clear_buf(0);
+ bp_clear_buf(1);
+ bp_receive_to_buf(1, 1, 1, 0, 99);
+ while (buffer_pool_status->status == 0)
+ ;
+ bp_clear_buf(2);
+ bp_receive_to_buf(2, 1, 1, 0, 99);
+ while (buffer_pool_status->status == 0)
+ ;
+
+ for(i=0;i<100;i++) {
+ puthex(i);
+ putstr(" ");
+ puthex_nl(buffer0[i]);
+ }
+ for(i=0;i<60;i++) {
+ puthex(i);
+ putstr(" ");
+ puthex_nl(buffer1[i]);
+ }
+ for(i=0;i<60;i++) {
+ puthex(i);
+ putstr(" ");
+ puthex_nl(buffer2[i]);
+ }
+ //while(timer_regs -> time < 0x6000)
+ // {}
+
+ putstr("Done\n");
+ hal_finish();
+
+ return 1;
+}
diff --git a/usrp2/firmware/apps/ibs_tx_test.c b/usrp2/firmware/apps/ibs_tx_test.c
new file mode 100644
index 000000000..ff9446d92
--- /dev/null
+++ b/usrp2/firmware/apps/ibs_tx_test.c
@@ -0,0 +1,160 @@
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "nonstdio.h"
+
+// Globals
+#define EMPTY 0
+#define FILLING 1
+#define FULL 2
+#define EMPTYING 3
+
+#define PORT 2 // ethernet = 2, serdes = 0
+int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf;
+int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle;
+
+int buffer_state[4];
+
+static void
+wait_until_status_nonzero(void)
+{
+ while (buffer_pool_status->status == 0)
+ ;
+}
+
+int
+main(void)
+{
+ int i;
+
+ u2_init();
+
+ dsp_tx_regs->freq = 0;
+ dsp_tx_regs->scale_iq = (1 << 16) | 1;
+ dsp_tx_regs->interp_rate = 8;
+
+ // Write data to be sent into the first buffer
+ volatile unsigned int *buffer0 = buffer_ram(0);
+ volatile unsigned int *buffer1 = buffer_ram(1);
+
+
+ putstr("Starting to fill in RAM\n");
+ for(i=0;i<512;i++)
+ buffer0[i] = i;
+ putstr("Filled in RAM\n");
+
+ buffer0[0] = 7; // start and end of buffer, send immediately
+ buffer0[1] = 0x0000; // start time
+ bp_clear_buf(0);
+ bp_send_from_buf(0, 1, 1, 0, 9);
+ while (buffer_pool_status->status == 0)
+ ;
+ while(timer_regs -> time < 0x6000)
+ {}
+
+ buffer0[0] = 3; // start and end of buffer
+ buffer0[1] = 0x8000; // start time
+ bp_clear_buf(0);
+ bp_send_from_buf(0, 1, 1, 0, 9);
+ while (buffer_pool_status->status == 0)
+ ;
+ while(timer_regs -> time < 0x8400)
+ {}
+
+ buffer0[0] = 3; // start and end of buffer
+ buffer0[1] = 0x8800; // start time
+ bp_clear_buf(0);
+ bp_send_from_buf(0, 1, 1, 0, 9);
+ while (buffer_pool_status->status == 0)
+ ;
+ while(timer_regs -> time < 0x9000)
+ {}
+
+ buffer0[0] = 0x2; // not last
+ buffer0[1] = 0x9100; // start time
+ bp_clear_buf(0);
+ bp_send_from_buf(0, 1, 1, 0, 9);
+ while (buffer_pool_status->status == 0)
+ ;
+ buffer0[0] = 0x1; // last
+ buffer0[1] = 0x0000; // start time
+ bp_clear_buf(0);
+ bp_send_from_buf(0, 1, 1, 0, 9);
+ while (buffer_pool_status->status == 0)
+ ;
+
+
+ buffer0[0] = 0x3; // first and last
+ buffer0[1] = 0x8000; // Time in the past
+ bp_clear_buf(0);
+ bp_send_from_buf(0, 1, 1, 0, 9);
+ while (buffer_pool_status->status == 0)
+ ;
+
+ /*
+ buffer0[0] = 0x2; // not last
+ buffer0[1] = 0x9600; // start time
+ bp_clear_buf(0);
+ bp_send_from_buf(0, 1, 1, 0, 9);
+ while (buffer_pool_status->status == 0)
+ ;
+ */
+
+ while(timer_regs -> time < 0xa000)
+ {}
+
+ putstr("Done\n");
+
+ while(1)
+ {}
+ hal_finish();
+
+ // Send a bunch, let them pile up in FIFO
+ bp_send_from_buf(0, 2, 1, 21, 80); wait_until_status_nonzero();
+ bp_clear_buf(0);
+ putstr("First add'l TX done\n");
+ bp_send_from_buf(0, 2, 1, 81, 288); wait_until_status_nonzero();
+ bp_clear_buf(0);
+ bp_send_from_buf(0, 2, 1, 289, 292); wait_until_status_nonzero();
+ bp_clear_buf(0);
+ bp_send_from_buf(0, 2, 1, 293, 326); wait_until_status_nonzero();
+ bp_clear_buf(0);
+ bp_send_from_buf(0, 2, 1, 327, 399); wait_until_status_nonzero();
+ bp_clear_buf(0);
+ bp_send_from_buf(0, 2, 1, 400, 511); wait_until_status_nonzero();
+ bp_clear_buf(0);
+ putstr("All add'l TX done\n");
+
+ bp_receive_to_buf(1, 2, 1, 21, 80); wait_until_status_nonzero();
+ bp_clear_buf(1);
+ putstr("First add'l RX done\n");
+ bp_receive_to_buf(1, 2, 1, 81, 288); wait_until_status_nonzero();
+ bp_clear_buf(1);
+ bp_receive_to_buf(1, 2, 1, 289, 292); wait_until_status_nonzero();
+ bp_clear_buf(1);
+ bp_receive_to_buf(1, 2, 1, 293, 326); wait_until_status_nonzero();
+ bp_clear_buf(1);
+ bp_receive_to_buf(1, 2, 1, 327, 399); wait_until_status_nonzero();
+ bp_clear_buf(1);
+ bp_receive_to_buf(1, 2, 1, 400, 511); wait_until_status_nonzero();
+ bp_clear_buf(1);
+ putstr("All add'l RX done\n");
+
+ for(i=0;i<512;i++)
+ if(buffer0[i] != buffer1[i]) {
+ putstr("ERROR at location: ");
+ puthex_nl(i);
+ putstr("Value sent: ");
+ puthex_nl(buffer0[i]);
+ putstr("Value rcvd: ");
+ puthex_nl(buffer1[i]);
+ //break;
+ }
+
+ putstr("Done Testing\n");
+
+ hal_finish();
+ return 1;
+}
diff --git a/usrp2/firmware/apps/rcv_eth_packets.c b/usrp2/firmware/apps/rcv_eth_packets.c
new file mode 100644
index 000000000..92e41d92b
--- /dev/null
+++ b/usrp2/firmware/apps/rcv_eth_packets.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "memcpy_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+
+
+// ----------------------------------------------------------------
+
+static u2_mac_addr_t dst_mac_addr =
+ {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
+
+
+// ----------------------------------------------------------------
+
+#define PACKET_SIZE 1500 // bytes
+#define ETH_DATA_RATE 1000000 // 1MB/s
+#define ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE) // 13,3333 pkts/s
+
+#define TIMER_RATE 100000000 // 100 MHz clock
+
+static int timer_delta = TIMER_RATE/ETH_PACKET_RATE; // ticks between interrupts
+
+static volatile bool send_packet_now = false; // timer handler sets this
+static volatile bool link_is_up = false; // eth handler sets this
+
+int packet_number = 0;
+
+// ----------------------------------------------------------------
+
+// debugging output on tx pins
+#define LS_MASK 0xE0000
+#define LS_1000 0x80000
+#define LS_100 0x40000
+#define LS_10 0x20000
+
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+ int v = 0;
+ switch(speed){
+ case 10:
+ v = LS_10;
+ link_is_up = true;
+ break;
+
+ case 100:
+ v = LS_100;
+ link_is_up = true;
+ break;
+
+ case 1000:
+ v = LS_100;
+ link_is_up = true;
+ break;
+
+ default:
+ v = 0;
+ link_is_up = false;
+ break;
+ }
+
+ //hal_gpio_set_tx(v, LS_MASK); /* set debug bits on d'board */
+
+ putstr("\neth link changed: speed = ");
+ puthex16_nl(speed);
+}
+
+void
+timer_irq_handler(unsigned irq)
+{
+ hal_set_timeout(timer_delta); // schedule next timeout
+ send_packet_now = 1;
+}
+
+
+void
+buffer_irq_handler(unsigned irq)
+{
+ // FIXME
+}
+
+static void
+init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum)
+{
+ int i = 0;
+ int mark = ((bufnum & 0xff) << 24) | 0x005A0000;
+
+ for (i = 0; i < BP_NLINES; i++){
+ buf[i] = mark | i;
+ mark ^= 0x00FF0000;
+ }
+
+ // copy header into buffer
+ memcpy_wa(buf, pkt, sizeof(*pkt));
+}
+
+static void
+init_packets(void)
+{
+ int i;
+
+ u2_eth_packet_t pkt __attribute__((aligned (4)));
+
+ pkt.ehdr.dst = dst_mac_addr;
+ // src filled in by mac
+ pkt.ehdr.ethertype = U2_ETHERTYPE;
+
+ // fill ALL buffers for debugging
+ for (i = 0; i < 8; i++)
+ init_packet((void *)buffer_ram(i), &pkt, i);
+}
+
+int
+main(void)
+{
+ u2_init();
+
+ int prev_leds = -1;
+ int new_leds = 0x00;
+ output_regs->leds = 0x00;
+
+ int peak_hold_count = 0;
+
+ // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+ //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+ //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+ putstr("\nrcv_eth_packets\n");
+
+ init_packets();
+
+ // pic_register_handler(IRQ_BUFFER, buffer_irq_handler); // poll for now
+
+ // FIXME turn off timer since I don't think MTS and MFS instructions are implemented
+ // pic_register_handler(IRQ_TIMER, timer_irq_handler);
+ // hal_set_timeout(timer_delta);
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+
+ ethernet_init();
+
+ //eth_mac->speed = 4; // FIXME hardcode mac speed to 1000
+
+ // kick off a receive
+ bp_receive_to_buf(2, PORT_ETH, 1, 0, 511);
+
+ while(1){
+ // u2_eth_packet_t pkt;
+
+ new_leds = 0;
+ if (link_is_up)
+ new_leds = 0x2;
+
+ if ((buffer_pool_status->status & (BPS_DONE_2|BPS_ERROR_2)) != 0){
+ // we've got a packet!
+
+#if 0
+ // copy to stack buffer so we can byte address it
+ memcpy_wa(&pkt, (void *)buffer_ram(2), sizeof(pkt));
+
+ putstr("Rx: src: ");
+ print_mac_addr(pkt.ehdr.dst_addr);
+ putstr(" dst: ");
+ print_mac_addr(pkt.ehdr.src_addr);
+ putstr(" ethtype: ");
+ puthex16(pkt.ehdr.ethertype);
+ putstr(" len: ");
+ int len = (buffer_pool_status->last_line[2] + 1) * 4;
+ puthex16_nl(len);
+#else
+ volatile int *bp = buffer_ram(2);
+ int i;
+ for (i = 0; i < 16; i++){
+ puthex8(i);
+ putchar(':');
+ puthex32_nl(bp[i]);
+ }
+#endif
+
+ // kick off next receive
+ bp_clear_buf(2);
+ bp_receive_to_buf(2, PORT_ETH, 1, 0, 511);
+
+ peak_hold_count = 2048 * 10;
+ }
+
+ if (peak_hold_count > 0){
+ peak_hold_count--;
+ new_leds |= 0x1;
+ }
+
+ if (new_leds != prev_leds){
+ prev_leds = new_leds;
+ output_regs->leds = new_leds;
+ }
+ }
+
+ hal_finish();
+ return 1;
+}
diff --git a/usrp2/firmware/apps/read_dbids.c b/usrp2/firmware/apps/read_dbids.c
new file mode 100644
index 000000000..4caabd885
--- /dev/null
+++ b/usrp2/firmware/apps/read_dbids.c
@@ -0,0 +1,59 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nonstdio.h>
+#include <u2_init.h>
+#include <bool.h>
+#include <usrp2_i2c_addr.h>
+#include <i2c.h>
+
+
+int main(void)
+{
+ u2_init();
+
+ puts("\nread_dbids");
+
+ unsigned char dbid_tx[2];
+ unsigned char dbid_rx[2];
+ bool ok;
+
+ ok = eeprom_read(I2C_ADDR_TX_A, 1, dbid_tx, 2);
+ if (!ok){
+ puts("failed to read Tx Daugherboard EEPROM");
+ }
+ else {
+ putstr("Tx Daugherboard ID: ");
+ puthex8(dbid_tx[1]); // MSB
+ puthex8(dbid_tx[0]); // LSB
+ newline();
+ }
+
+ ok = eeprom_read(I2C_ADDR_RX_A, 1, dbid_rx, 2);
+ if (!ok){
+ puts("failed to read Rx Daugherboard EEPROM");
+ }
+ else {
+ putstr("Rx Daugherboard ID: ");
+ puthex8(dbid_rx[1]); // MSB
+ puthex8(dbid_rx[0]); // LSB
+ newline();
+ }
+
+ return 0;
+}
diff --git a/usrp2/firmware/apps/rx_only_v2.c b/usrp2/firmware/apps/rx_only_v2.c
new file mode 100644
index 000000000..fc5907415
--- /dev/null
+++ b/usrp2/firmware/apps/rx_only_v2.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "memcpy_wa.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <db.h>
+#include <db_base.h>
+
+
+#define FW_SETS_SEQNO 1 // define to 0 or 1
+
+#if (FW_SETS_SEQNO)
+static int fw_seqno; // used when f/w is filling in sequence numbers
+#endif
+
+/*
+ * This program can respond to queries from the host
+ * and stream rx samples.
+ *
+ * Buffer 0 is used for rcvd frames from ethernet
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ */
+#define CPU_RX_BUF 0 // eth -> cpu
+//#define CPU_TX_BUF 1 // cpu -> eth
+#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer)
+#define DSP_RX_BUF_1 3 // dsp rx -> eth
+
+
+// variables for streaming mode
+
+static bool streaming_p = false;
+static int streaming_frame_count = 0;
+#define FRAMES_PER_CMD 1000
+
+
+/*
+ * ================================================================
+ * configure DSP RX double buffering state machine
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
+// DSP Rx writes timestamp followed by nlines_per_frame of samples
+#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1)
+
+// receive from DSP
+buf_cmd_args_t dsp_rx_recv_args = {
+ PORT_DSP,
+ DSP_RX_FIRST_LINE,
+ BP_LAST_LINE
+};
+
+// send to ETH
+buf_cmd_args_t dsp_rx_send_args = {
+ PORT_ETH,
+ 0, // starts with ethernet header in line 0
+ 0, // filled in from list_line register
+};
+
+dbsm_t dsp_rx_sm; // the state machine
+
+// ----------------------------------------------------------------
+
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+void link_changed_callback(int speed);
+static volatile bool link_is_up = false; // eth handler sets this
+
+
+void
+start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+ host_mac_addr = *host; // remember who we're sending to
+
+ /*
+ * Construct ethernet header and word0 and preload into two buffers
+ */
+ u2_eth_packet_t pkt;
+ memset(&pkt, 0, sizeof(pkt));
+ pkt.ehdr.dst = *host;
+ pkt.ehdr.ethertype = U2_ETHERTYPE;
+ u2p_set_word0(&pkt.fixed, 0, 0);
+ // DSP RX will fill in timestamp
+
+ memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
+ memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
+
+
+ if (FW_SETS_SEQNO)
+ fw_seqno = 0;
+
+ // setup RX DSP regs
+ dsp_rx_regs->clear_state = 1; // reset
+
+ if (1){ // we're streaming
+ streaming_p = true;
+ streaming_frame_count = FRAMES_PER_CMD;
+ dsp_rx_regs->rx_command =
+ MK_RX_CMD(FRAMES_PER_CMD * p->items_per_frame, p->items_per_frame,
+ 1, 1); // set "chain" bit
+
+ // kick off the state machine
+ dbsm_start(&dsp_rx_sm);
+ dsp_rx_regs->rx_time = 0; // enqueue first of two commands
+
+ // make sure this one and the rest have the "now" and "chain" bits set.
+ dsp_rx_regs->rx_command =
+ MK_RX_CMD(FRAMES_PER_CMD * p->items_per_frame, p->items_per_frame,
+ 1, 1);
+ dsp_rx_regs->rx_time = 0; // enqueue second command
+ }
+#if 0
+ else {
+ streaming_p = false;
+ dsp_rx_regs->rx_command =
+ MK_RX_CMD(p->total_samples, p->items_per_frame, p->rx_now, 0);
+
+ // kick off the state machine
+ dbsm_start(&dsp_rx_sm);
+ dsp_rx_regs->rx_time = p->rx_time;
+ }
+#endif
+}
+
+
+void
+stop_rx_cmd(void)
+{
+ streaming_p = false;
+ dsp_rx_regs->clear_state = 1; // flush cmd queue
+ bp_clear_buf(DSP_RX_BUF_0);
+ bp_clear_buf(DSP_RX_BUF_1);
+}
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+ uint32_t status = buffer_pool_status->status;
+
+ if (status & BPS_DONE(CPU_RX_BUF)){ // we've rcvd a frame from ethernet
+ bp_clear_buf(CPU_RX_BUF);
+ eth_pkt_inspector(0, CPU_RX_BUF);
+ bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+ }
+ if (status & BPS_ERROR(CPU_RX_BUF)){ // error from ethernet
+ bp_clear_buf(CPU_RX_BUF);
+ bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+ }
+
+ dbsm_process_status(&dsp_rx_sm, status);
+
+ if (status & BPS_DONE(CPU_TX_BUF)){
+ bp_clear_buf(CPU_TX_BUF);
+ }
+}
+
+#if (FW_SETS_SEQNO)
+/*
+ * Debugging ONLY. This will be handled by the tx_protocol_engine.
+ *
+ * This is called when the DSP Rx chain has filled in a packet.
+ * We set and increment the seqno, then return false, indicating
+ * that we didn't handle the packet. A bit of a kludge
+ * but it should work.
+ */
+bool
+fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false
+{
+ uint32_t *p = buffer_ram(buf_this);
+ uint32_t seqno = fw_seqno++;
+
+ // KLUDGE all kinds of nasty magic numbers and embedded knowledge
+ uint32_t t = p[4];
+ t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
+ p[4] = t;
+
+ // queue up another rx command when required
+ if (streaming_p && --streaming_frame_count == 0){
+ streaming_frame_count = FRAMES_PER_CMD;
+ dsp_rx_regs->rx_time = 0;
+ }
+
+ return false; // we didn't handle the packet
+}
+#endif
+
+
+int
+main(void)
+{
+ u2_init();
+
+ putstr("\nrx_only_v2\n");
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+ ethernet_init();
+
+ // initialize double buffering state machine for DSP RX -> Ethernet
+
+ if (FW_SETS_SEQNO){
+ dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+ &dsp_rx_recv_args, &dsp_rx_send_args,
+ fw_sets_seqno_inspector);
+ }
+ else {
+ dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+ &dsp_rx_recv_args, &dsp_rx_send_args,
+ dbsm_nop_inspector);
+ }
+
+ // setup receive from ETH
+ bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+
+
+ while(1){
+ buffer_irq_handler(0);
+
+ int pending = pic_regs->pending; // poll for under or overrun
+
+ if (pending & PIC_OVERRUN_INT){
+ dbsm_handle_rx_overrun(&dsp_rx_sm);
+ pic_regs->pending = PIC_OVERRUN_INT; // clear pending interrupt
+ putchar('O');
+ }
+ }
+}
diff --git a/usrp2/firmware/apps/sd_bounce.c b/usrp2/firmware/apps/sd_bounce.c
new file mode 100644
index 000000000..30e3e3fc5
--- /dev/null
+++ b/usrp2/firmware/apps/sd_bounce.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Loopback SERDES to SERDES
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "nonstdio.h"
+#include "memset_wa.h"
+#include <dbsm.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <clocks.h>
+
+
+
+// ----------------------------------------------------------------
+
+#define SERDES_RX_BUF_0 0
+#define SERDES_RX_BUF_1 1
+
+/*
+ * ================================================================
+ * configure SD RX double buffering state machine
+ * ================================================================
+ */
+
+// receive from SERDES
+buf_cmd_args_t sd_recv_args = {
+ PORT_SERDES,
+ 0,
+ BP_LAST_LINE
+};
+
+// send to SERDES
+buf_cmd_args_t sd_send_args = {
+ PORT_SERDES,
+ 0, // starts with packet in line 0
+ 0, // filled in from list_line register
+};
+
+dbsm_t sd_sm; // the state machine
+
+
+
+
+// ----------------------------------------------------------------
+
+#if 0
+static bool
+check_packet(int *buf, int nlines)
+{
+ bool ok = true;
+ int i = 0;
+ for (i = 0; i < nlines; i++){
+ int expected = ((2*i + 0) << 16) | (2*i+1);
+ if (buf[i] != expected){
+ ok = false;
+ printf("buf[%d] = 0x%x expected = 0x%x\n", i, buf[i], expected);
+ }
+ }
+ return ok;
+}
+
+static void
+zero_buffer(int bufno)
+{
+ memset_wa(buffer_ram(bufno), 0, BP_NLINES * 4);
+}
+#endif
+
+
+bool
+sd_rx_inspector(dbsm_t *sm, int buf_this)
+{
+ hal_toggle_leds(0x2);
+
+#if 0
+ int last_line = buffer_pool_status->last_line[buf_this];
+ bool ok = check_packet(buffer_ram(buf_this), last_line);
+ static int good = 0;
+ static int bad = 0;
+
+ if (ok)
+ good++;
+ else
+ bad++;
+
+ if(good+bad == 10000) {
+ printf("Good %d\tBad %d\n",good,bad);
+ good = 0;
+ bad = 0;
+ }
+#endif
+
+ return false;
+}
+
+
+inline static void
+buffer_irq_handler(void)
+{
+ uint32_t status = buffer_pool_status->status;
+ dbsm_process_status(&sd_sm, status);
+}
+
+
+int
+main(void)
+{
+ u2_init();
+
+ putstr("\nsd_bounce\n");
+
+ // Get our clock from the mimo interface
+ clocks_mimo_config(MC_WE_LOCK_TO_MIMO);
+
+ dbsm_init(&sd_sm, SERDES_RX_BUF_0,
+ &sd_recv_args, &sd_send_args,
+ sd_rx_inspector);
+
+ // kick off the state machine
+ dbsm_start(&sd_sm);
+
+ while(1){
+ buffer_irq_handler();
+ }
+}
diff --git a/usrp2/firmware/apps/sd_gentest.c b/usrp2/firmware/apps/sd_gentest.c
new file mode 100644
index 000000000..4824f03f5
--- /dev/null
+++ b/usrp2/firmware/apps/sd_gentest.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "nonstdio.h"
+#include "memset_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <clocks.h>
+#include <mdelay.h>
+
+// ----------------------------------------------------------------
+
+int packet_number = 0;
+volatile bool send_packet_now = 0;
+
+#define SERDES_TX_BUF 0
+#define SERDES_RX_BUF 1
+
+
+#define NLINES_PER_PKT 380
+
+
+// ----------------------------------------------------------------
+
+//static int timer_delta = (int)(MASTER_CLK_RATE * 100e-6);
+static int timer_delta = 1000000; // .01 second
+
+void
+timer_irq_handler(unsigned irq)
+{
+ hal_set_timeout(timer_delta); // schedule next timeout
+ send_packet_now = true;
+}
+
+
+static void
+init_packet(int *buf)
+{
+ int i = 0;
+ for (i = 0; i < BP_NLINES; i++){
+ buf[i] = ((2*i + 0) << 16) | (2*i+1);
+ }
+}
+
+static bool
+check_packet(int *buf, int nlines)
+{
+ bool ok = true;
+ int i = 0;
+ for (i = 0; i < nlines; i++){
+ int expected = ((2*i + 0) << 16) | (2*i+1);
+ if (buf[i] != expected){
+ ok = false;
+ printf("buf[%d] = 0x%x expected = 0x%x\n", i, buf[i], expected);
+ }
+ }
+ return ok;
+}
+
+static void
+zero_buffer(int bufno)
+{
+ memset_wa(buffer_ram(bufno), 0, BP_NLINES * 4);
+}
+
+static void
+init_packets(void)
+{
+ // init just the one we're using
+ init_packet(buffer_ram(SERDES_TX_BUF));
+}
+
+int
+main(void)
+{
+ u2_init();
+
+ // We're free running and provide clock to the MIMO interface
+ clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO);
+
+
+ // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+ // output_regs->debug_mux_ctrl = 1;
+ // hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+ // hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+ putstr("\nsd_gentest\n");
+
+ // Set up serdes (already enabled)
+ //output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN | SERDES_LOOPEN);
+ //output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN);
+
+ init_packets();
+
+ // pic_register_handler(IRQ_TIMER, timer_irq_handler);
+
+ //if (hwconfig_simulation_p())
+ // timer_delta = sim_timer_delta;
+
+ // start a receive from sd
+ zero_buffer(SERDES_RX_BUF);
+ bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE);
+
+ // fire off the first packet
+ bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT);
+ hal_set_timeout(timer_delta);
+ int ready_to_send = 0;
+
+ int counter __attribute__((unused)) = 0;
+ int sent = 1;
+ int txerr = 0;
+ int rxerr = 0;
+ int rcvd = 0;
+ int rxcrc = 0;
+ int sent_acc = 0;
+ int txerr_acc = 0;
+ int rxerr_acc = 0;
+ int rcvd_acc = 0;
+ int rxcrc_acc = 0;
+
+#define EXPECTING_PKT() ((counter & 0x1) == 0)
+#define SEND_PKT() ((counter & 0x1) != 0)
+
+ bool got_packet = false;
+
+ while(1){
+ uint32_t status = buffer_pool_status->status;
+
+ if (status & (BPS_DONE(SERDES_RX_BUF))){
+ bp_clear_buf(SERDES_RX_BUF);
+ got_packet = true;
+
+ //hal_toggle_leds(0x2);
+
+ // check packet
+ int last_line = buffer_pool_status->last_line[SERDES_RX_BUF]-1;
+ bool ok = check_packet(buffer_ram(SERDES_RX_BUF), last_line);
+
+ if (ok) {
+ rcvd++;
+ //putchar('r');
+ }
+ else {
+ rcvd++;
+ rxcrc++;
+ //putchar('P');
+ }
+ // start a receive from sd
+ zero_buffer(SERDES_RX_BUF);
+ bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE);
+ }
+
+ if (status & (BPS_ERROR(SERDES_RX_BUF))){
+ bp_clear_buf(SERDES_RX_BUF);
+ got_packet = true;
+ rcvd++;
+ rxerr++;
+ //putchar('E');
+
+ // start a receive from sd
+ zero_buffer(SERDES_RX_BUF);
+ bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE);
+ }
+
+ if (status & (BPS_DONE(SERDES_TX_BUF))){
+ bp_clear_buf(SERDES_TX_BUF);
+ //putchar('t');
+ bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT);
+ //mdelay(1);
+ int i;
+ for (i = 0; i < 50; i++){
+ asm volatile ("or r0, r0, r0\n\
+ or r0, r0, r0\n \
+ or r0, r0, r0\n \
+ or r0, r0, r0\n \
+ or r0, r0, r0\n \
+ or r0, r0, r0\n \
+ or r0, r0, r0\n");
+ }
+ sent ++;
+ ready_to_send = 1;
+ //hal_toggle_leds(0x1);
+ }
+
+ if (status & BPS_ERROR(SERDES_TX_BUF)){
+ bp_clear_buf(SERDES_TX_BUF);
+ sent++;
+ txerr++;
+ ready_to_send = 1;
+ //putchar('X');
+ }
+
+ if(sent >=1000) {
+ printf("Status\tSENT %d\tTXERR %d\t",sent,txerr);
+ printf("RX %d\tERR %d\tCRC %d\tMISSED %d\n",rcvd, rxerr, rxcrc, sent-rcvd);
+ sent_acc += sent; sent = 0;
+ txerr_acc += txerr; txerr = 0;
+ rcvd_acc += rcvd; rcvd = 0;
+ rxerr_acc += rxerr; rxerr = 0;
+ rxcrc_acc += rxcrc; rxcrc = 0;
+ }
+
+ if(sent_acc >=10000) {
+ printf("\nOverall\tSENT %d\tTXERR %d\t",sent_acc,txerr_acc);
+ printf("RX %d\tERR %d\tCRC %d\tMISSED %d\n\n",rcvd_acc, rxerr_acc, rxcrc_acc, sent_acc-rcvd_acc);
+ sent_acc = 0;
+ txerr_acc = 0;
+ rcvd_acc = 0;
+ rxerr_acc = 0;
+ rxcrc_acc = 0;
+ }
+#if 0
+ int pending = pic_regs->pending;
+ if (pending & PIC_TIMER_INT){
+ hal_set_timeout(timer_delta);
+
+ /*
+ if (EXPECTING_PKT()){
+ if (!got_packet)
+ putchar('T');
+ got_packet = false;
+ }
+
+ if (SEND_PKT()){
+ if (status & BPS_IDLE(SERDES_TX_BUF))
+ bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT);
+ }
+ counter++;
+ */
+
+ putchar('T');
+ if(ready_to_send) {
+ bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT);
+ counter++;
+ ready_to_send = 0;
+ }
+
+ pic_regs->pending = PIC_TIMER_INT; // clear pending interrupt
+ }
+#endif
+ }
+
+ return 0;
+}
diff --git a/usrp2/firmware/apps/serdes_to_dsp.c b/usrp2/firmware/apps/serdes_to_dsp.c
new file mode 100644
index 000000000..ff226bd9f
--- /dev/null
+++ b/usrp2/firmware/apps/serdes_to_dsp.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common.h"
+#include <ad9510.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*
+ * This program can respond to queries from the host
+ * and stream rx samples.
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow
+ */
+//#define CPU_RX_BUF 0 // eth -> cpu
+//#define CPU_TX_BUF 1 // cpu -> eth
+
+#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer)
+#define DSP_RX_BUF_1 3 // dsp rx -> eth
+#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer)
+#define DSP_TX_BUF_1 5 // eth -> dsp tx
+
+/*
+ * ================================================================
+ * configure DSP TX double buffering state machine
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+ PORT_SERDES,
+ 0,
+ BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+ PORT_DSP,
+ DSP_TX_FIRST_LINE, // starts just past transport header
+ 0 // filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm; // the state machine
+
+
+// ----------------------------------------------------------------
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+void
+start_rx_cmd(const u2_mac_addr_t *host, op_start_rx_t *p)
+{
+}
+
+void
+stop_rx_cmd(void)
+{
+}
+
+static void
+setup_tx()
+{
+ dsp_tx_regs->clear_state = 1;
+ bp_clear_buf(DSP_TX_BUF_0);
+ bp_clear_buf(DSP_TX_BUF_1);
+
+ int tx_scale = 256;
+ int interp = 32;
+
+ op_config_tx_t def_config;
+ memset(&def_config, 0, sizeof(def_config));
+ def_config.phase_inc = 408021893; // 9.5 MHz [2**32 * fc/fsample]
+ def_config.scale_iq = (tx_scale << 16) | tx_scale;
+ def_config.interp = interp;
+
+ // setup Tx DSP regs
+ config_tx_cmd(&def_config);
+}
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+ //hal_toggle_leds(0x2);
+
+ uint32_t status = buffer_pool_status->status;
+
+ dbsm_process_status(&dsp_tx_sm, status);
+
+ if (status & BPS_DONE(CPU_TX_BUF)){
+ bp_clear_buf(CPU_TX_BUF);
+ }
+}
+
+int
+main(void)
+{
+ u2_init();
+
+ // Get our clock from the mimo interface
+
+ // if(I WANT TO LOCK TO A REFERENCE CLOCK)
+ // Reg 8, Charge pump on, dig lock det, positive PFD, 47
+ ad9510_write_reg(0x08, 0x47);
+ ad9510_write_reg(0x5A, 0x01); // Update Regs
+ // if (LOCK_TO_MIMO_REF)
+
+ // Turn on ref output and choose the MIMO connector
+ output_regs->clk_ctrl = 0x15;
+ // Turn on ref output and choose the SMA connector
+ //output_regs->clk_ctrl = 0x14;
+
+ // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+ //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+ //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+ putstr("\nserdes_to_dsp\n");
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+ ethernet_init();
+
+
+ // initialize double buffering state machine for ethernet -> DSP Tx
+
+ dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+ &dsp_tx_recv_args, &dsp_tx_send_args,
+ eth_pkt_inspector);
+
+ // program tx registers
+ setup_tx();
+
+ // kick off the state machine
+ dbsm_start(&dsp_tx_sm);
+
+ while(1){
+ buffer_irq_handler(0);
+
+ int pending = pic_regs->pending; // poll for under or overrun
+
+ if (pending & PIC_UNDERRUN_INT){
+ dbsm_handle_tx_underrun(&dsp_tx_sm);
+ pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt
+ putchar('U');
+ }
+ }
+}
+
diff --git a/usrp2/firmware/apps/serdes_txrx.c b/usrp2/firmware/apps/serdes_txrx.c
new file mode 100644
index 000000000..8f28a84f1
--- /dev/null
+++ b/usrp2/firmware/apps/serdes_txrx.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include "memcpy_wa.h"
+#include "clocks.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now)
+
+#if (FW_SETS_SEQNO)
+static int fw_seqno; // used when f/w is filling in sequence numbers
+#endif
+
+
+/*
+ * Full duplex Tx and Rx between serdes and DSP pipelines
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to serdes flow
+ * Buffers 4 and 5 are used to double-buffer the serdes to DSP Tx flow
+ */
+//#define CPU_RX_BUF 0 // eth -> cpu
+
+#define DSP_RX_BUF_0 2 // dsp rx -> serdes (double buffer)
+#define DSP_RX_BUF_1 3 // dsp rx -> serdes
+#define DSP_TX_BUF_0 4 // serdes -> dsp tx (double buffer)
+#define DSP_TX_BUF_1 5 // serdes -> dsp tx
+
+/*
+ * ==================================================================
+ * configure DSP TX double buffering state machine (serdes -> dsp)
+ * ==================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
+
+// Receive from serdes
+buf_cmd_args_t dsp_tx_recv_args = {
+ PORT_SERDES,
+ 0,
+ BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+ PORT_DSP,
+ DSP_TX_FIRST_LINE, // starts just past transport header
+ 0 // filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm; // the state machine
+
+/*
+ * =================================================================
+ * configure DSP RX double buffering state machine (dsp -> serdes)
+ * =================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
+// DSP Rx writes timestamp followed by nlines_per_frame of samples
+#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1)
+
+// receive from DSP
+buf_cmd_args_t dsp_rx_recv_args = {
+ PORT_DSP,
+ DSP_RX_FIRST_LINE,
+ BP_LAST_LINE
+};
+
+// send to serdes
+buf_cmd_args_t dsp_rx_send_args = {
+ PORT_SERDES,
+ 0, // starts with ethernet header in line 0
+ 0, // filled in from list_line register
+};
+
+dbsm_t dsp_rx_sm; // the state machine
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+// variables for streaming mode
+
+static bool streaming_p = false;
+static unsigned int streaming_items_per_frame = 0;
+static int streaming_frame_count = 0;
+#define FRAMES_PER_CMD 1000
+
+
+// ----------------------------------------------------------------
+
+
+static void
+restart_streaming(void)
+{
+ // setup RX DSP regs
+ dsp_rx_regs->clear_state = 1; // reset
+
+ streaming_p = true;
+ streaming_frame_count = FRAMES_PER_CMD;
+
+ dsp_rx_regs->rx_command =
+ MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+ streaming_items_per_frame,
+ 1, 1); // set "chain" bit
+
+ // kick off the state machine
+ dbsm_start(&dsp_rx_sm);
+
+ dsp_rx_regs->rx_time = 0; // enqueue first of two commands
+
+ // make sure this one and the rest have the "now" and "chain" bits set.
+ dsp_rx_regs->rx_command =
+ MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+ streaming_items_per_frame,
+ 1, 1);
+
+ dsp_rx_regs->rx_time = 0; // enqueue second command
+}
+
+void
+start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+ host_mac_addr = *host; // remember who we're sending to
+
+ /*
+ * Construct ethernet header and word0 and preload into two buffers
+ */
+ u2_eth_packet_t pkt;
+ memset(&pkt, 0, sizeof(pkt));
+ pkt.ehdr.dst = *host;
+ pkt.ehdr.ethertype = U2_ETHERTYPE;
+ u2p_set_word0(&pkt.fixed, 0, 0);
+ // DSP RX will fill in timestamp
+
+ memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
+ memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
+
+
+ if (FW_SETS_SEQNO)
+ fw_seqno = 0;
+
+ streaming_items_per_frame = p->items_per_frame;
+ restart_streaming();
+}
+
+
+void
+stop_rx_cmd(void)
+{
+ streaming_p = false;
+ dsp_rx_regs->clear_state = 1; // flush cmd queue
+ bp_clear_buf(DSP_RX_BUF_0);
+ bp_clear_buf(DSP_RX_BUF_1);
+}
+
+
+static void
+setup_tx()
+{
+ dsp_tx_regs->clear_state = 1;
+ bp_clear_buf(DSP_TX_BUF_0);
+ bp_clear_buf(DSP_TX_BUF_1);
+
+ int tx_scale = 256;
+ int interp = 32;
+
+ // setup some defaults
+
+ dsp_tx_regs->freq = 0;
+ dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+ dsp_tx_regs->interp_rate = interp;
+}
+
+
+#if (FW_SETS_SEQNO)
+/*
+ * Debugging ONLY. This will be handled by the tx_protocol_engine.
+ *
+ * This is called when the DSP Rx chain has filled in a packet.
+ * We set and increment the seqno, then return false, indicating
+ * that we didn't handle the packet. A bit of a kludge
+ * but it should work.
+ */
+bool
+fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false
+{
+ uint32_t *p = buffer_ram(buf_this);
+ uint32_t seqno = fw_seqno++;
+
+ // KLUDGE all kinds of nasty magic numbers and embedded knowledge
+ uint32_t t = p[4];
+ t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
+ p[4] = t;
+
+ // queue up another rx command when required
+ if (streaming_p && --streaming_frame_count == 0){
+ streaming_frame_count = FRAMES_PER_CMD;
+ dsp_rx_regs->rx_time = 0;
+ }
+
+ return false; // we didn't handle the packet
+}
+#endif
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+ uint32_t status = buffer_pool_status->status;
+
+ dbsm_process_status(&dsp_tx_sm, status);
+ dbsm_process_status(&dsp_rx_sm, status);
+}
+
+int
+main(void)
+{
+ u2_init();
+
+ putstr("\nSERDES TxRx\n");
+
+ cpu_tx_buf_dest_port = PORT_SERDES;
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+ ethernet_init();
+
+ clocks_mimo_config(MC_WE_LOCK_TO_MIMO);
+
+#if 0
+ // make bit 15 of Tx gpio's be a s/w output
+ hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
+ hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
+#endif
+
+#if 1
+ output_regs->debug_mux_ctrl = 1;
+ hal_gpio_set_sels(GPIO_TX_BANK, "0000000000000000");
+ hal_gpio_set_sels(GPIO_RX_BANK, "0000000000000000");
+ hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
+ hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
+#endif
+
+
+ // initialize double buffering state machine for ethernet -> DSP Tx
+
+ dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+ &dsp_tx_recv_args, &dsp_tx_send_args,
+ eth_pkt_inspector);
+
+
+ // initialize double buffering state machine for DSP RX -> Ethernet
+
+ if (FW_SETS_SEQNO){
+ dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+ &dsp_rx_recv_args, &dsp_rx_send_args,
+ fw_sets_seqno_inspector);
+ }
+ else {
+ dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+ &dsp_rx_recv_args, &dsp_rx_send_args,
+ dbsm_nop_inspector);
+ }
+
+ // tell app_common that this dbsm could be sending to the ethernet
+ ac_could_be_sending_to_eth = &dsp_rx_sm;
+
+
+ // program tx registers
+ setup_tx();
+
+ // kick off the state machine
+ dbsm_start(&dsp_tx_sm);
+
+ //int which = 0;
+
+ while(1){
+ // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
+ // which ^= 0x8000;
+
+ buffer_irq_handler(0);
+
+ int pending = pic_regs->pending; // poll for under or overrun
+
+ if (pending & PIC_UNDERRUN_INT){
+ dbsm_handle_tx_underrun(&dsp_tx_sm);
+ pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt
+ putchar('U');
+ }
+
+ if (pending & PIC_OVERRUN_INT){
+ dbsm_handle_rx_overrun(&dsp_rx_sm);
+ pic_regs->pending = PIC_OVERRUN_INT; // clear pending interrupt
+
+ // FIXME Figure out how to handle this robustly.
+ // Any buffers that are emptying should be allowed to drain...
+
+ if (streaming_p){
+ // restart_streaming();
+ // FIXME report error
+ }
+ else {
+ // FIXME report error
+ }
+ putchar('O');
+ }
+ }
+}
diff --git a/usrp2/firmware/apps/test1.c b/usrp2/firmware/apps/test1.c
new file mode 100644
index 000000000..c3cc3be56
--- /dev/null
+++ b/usrp2/firmware/apps/test1.c
@@ -0,0 +1,282 @@
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "nonstdio.h"
+
+// Globals
+#define EMPTY 0
+#define FILLING 1
+#define FULL 2
+#define EMPTYING 3
+
+#define PORT 2 // ethernet = 2, serdes = 0
+int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf;
+int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle;
+
+int buffer_state[4];
+
+
+void double_buffering(int port);
+
+//
+// We register this in the secondary interrupt vector.
+// It's called on buffer manager interrupts
+//
+void
+buffer_irq_handler(unsigned irq)
+{
+ double_buffering(PORT);
+}
+
+int
+main(void)
+{
+ int i;
+
+ u2_init();
+
+ // Control LEDs
+ output_regs->leds = 0x02;
+
+ // Turn on ADCs
+ output_regs->adc_ctrl = 0x0A;
+
+ // Set up TX Chain
+ dsp_tx_regs->freq = 0;
+ dsp_tx_regs->scale_iq = (1 << 16) | 1;
+ dsp_tx_regs->interp_rate = 8;
+
+ // Set up RX Chain
+ dsp_rx_regs->freq = 0;
+ dsp_rx_regs->scale_iq = (1 << 16) | 1;
+ dsp_rx_regs->decim_rate = 8;
+
+ // Set up buffer control, using only 4 for now
+ for(i=0;i<4;i++)
+ buffer_state[i] = EMPTY;
+
+ // Set up DSP RX
+ buffer_state[0] = FILLING;
+ serdes_tx_idle = 1;
+ bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 0, use 500 lines
+
+ //dsp_rx_regs->run_rx = 1; // Start DSP_RX
+ putstr("Done DSP RX setup\n");
+
+ // Set up serdes RX
+ buffer_state[2] = FILLING;
+ dsp_tx_idle = 1;
+ bp_receive_to_buf(2, PORT, 1, 5, 504);
+
+ while (buffer_pool_status->status == 0) // wait for completion of DSP RX
+ ;
+
+ putstr("Done DSP TX setup\n");
+ //dsp_tx_regs->run_tx = 1;
+
+ // register interrupt handler
+ pic_register_handler(IRQ_BUFFER, buffer_irq_handler);
+
+ while (1)
+ ;
+
+ hal_finish();
+ return 1;
+}
+
+void
+double_buffering(int port) {
+ unsigned int localstatus = buffer_pool_status->status;
+
+ if(localstatus & BPS_DONE_0) {
+ bp_clear_buf(0);
+ if(buffer_state[0] == FILLING) {
+ buffer_state[0] = FULL;
+ if(buffer_state[1] == EMPTY) {
+ bp_receive_to_buf(1, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines
+ buffer_state[1] = FILLING;
+ }
+ else
+ dsp_rx_idle = 1;
+ if(serdes_tx_idle) {
+ serdes_tx_idle = 0;
+ bp_send_from_buf(0, port, 1, 10, 509); // SERDES_TX from buffer 0
+ buffer_state[0] = EMPTYING;
+ }
+ }
+ else { // buffer was emptying
+ buffer_state[0] = EMPTY;
+ if(dsp_rx_idle) {
+ dsp_rx_idle = 0;
+ bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 0, use 500 lines
+ buffer_state[0] = FILLING;
+ }
+ if(buffer_state[1] == FULL) {
+ bp_send_from_buf(1, port, 1, 10, 509); // SERDES_TX from buffer 1
+ buffer_state[1] = EMPTYING;
+ }
+ else
+ serdes_tx_idle = 1;
+ }
+ putstr("Int Proc'ed 0\n");
+ }
+ if(localstatus & BPS_DONE_1) {
+ bp_clear_buf(1);
+ if(buffer_state[1] == FILLING) {
+ buffer_state[1] = FULL;
+ if(buffer_state[0] == EMPTY) {
+ bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines
+ buffer_state[0] = FILLING;
+ }
+ else
+ dsp_rx_idle = 1;
+ if(serdes_tx_idle) {
+ serdes_tx_idle = 0;
+ bp_send_from_buf(1, port, 1, 10, 509); // SERDES_TX from buffer 1
+ buffer_state[1] = EMPTYING;
+ }
+ }
+ else { // buffer was emptying
+ buffer_state[1] = EMPTY;
+ if(dsp_rx_idle) {
+ dsp_rx_idle = 0;
+ bp_receive_to_buf(1, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines
+ buffer_state[1] = FILLING;
+ }
+ if(buffer_state[0] == FULL) {
+ bp_send_from_buf(0, port, 1, 10, 509); // SERDES_TX from buffer 0
+ buffer_state[0] = EMPTYING;
+ }
+ else
+ serdes_tx_idle = 1;
+ }
+ putstr("Int Proc'ed 1\n");
+ }
+ if(localstatus & BPS_DONE_2) {
+ bp_clear_buf(2);
+ if(buffer_state[2] == FILLING) {
+ buffer_state[2] = FULL;
+ if(buffer_state[3] == EMPTY) {
+ bp_receive_to_buf(3, port, 1, 5, 504); // SERDES_RX to buffer 3, use 500 lines
+ buffer_state[3] = FILLING;
+ }
+ else
+ serdes_rx_idle = 1;
+ if(dsp_tx_idle) {
+ dsp_tx_idle = 0;
+ bp_send_from_buf(2, 1, 1, 5, 504); // DSP_TX from buffer 2
+ buffer_state[2] = EMPTYING;
+ }
+ }
+ else { // buffer was emptying
+ buffer_state[2] = EMPTY;
+ if(serdes_rx_idle) {
+ serdes_rx_idle = 0;
+ bp_receive_to_buf(2, port, 1, 5, 504); // SERDES_RX to buffer 2
+ buffer_state[2] = FILLING;
+ }
+ if(buffer_state[3] == FULL) {
+ bp_send_from_buf(3, 1, 1, 5, 504); // DSP_TX from buffer 3
+ buffer_state[3] = EMPTYING;
+ }
+ else
+ dsp_tx_idle = 1;
+ }
+ putstr("Int Proc'ed 2\n");
+ }
+ if(localstatus & BPS_DONE_3) {
+ bp_clear_buf(3);
+ if(buffer_state[3] == FILLING) {
+ buffer_state[3] = FULL;
+ if(buffer_state[2] == EMPTY) {
+ bp_receive_to_buf(2, port, 1, 5, 504); // SERDES_RX to buffer 2, use 500 lines
+ buffer_state[2] = FILLING;
+ }
+ else
+ serdes_rx_idle = 1;
+ if(dsp_tx_idle) {
+ dsp_tx_idle = 0;
+ bp_send_from_buf(3, 1, 1, 5, 504); // DSP_TX from buffer 3
+ buffer_state[3] = EMPTYING;
+ }
+ }
+ else { // buffer was emptying
+ buffer_state[3] = EMPTY;
+ if(serdes_rx_idle) {
+ serdes_rx_idle = 0;
+ bp_receive_to_buf(3, port, 1, 5, 504); // SERDES_RX to buffer 3
+ buffer_state[3] = FILLING;
+ }
+ if(buffer_state[2] == FULL) {
+ bp_send_from_buf(2, 1, 1, 5, 504); // DSP_TX from buffer 2
+ buffer_state[2] = EMPTYING;
+ }
+ else
+ dsp_tx_idle = 1;
+ }
+ putstr("Int Proc'ed 3\n");
+ }
+}
+
+// Spare Code
+
+#if 0
+ // Set up LSDAC
+ int i = 0;
+ while(1) {
+ int command = (3 << 19) | (0 << 16) | (i & 0xffff);
+ spi_transact(SPI_TXONLY, SPI_SS_TX_DAC, command, 24, 1); // negate TX phase
+ i++;
+ }
+#endif
+
+#if 0
+ // Write to buffer 0
+ int *buf = (int *)(BUFFER_BASE + BUFFER_0);
+ puthex_nl((int)buf);
+
+ for(i=0;i<BUFFER_SIZE;i++)
+ buf[i] = i;
+
+ putstr("Filled buffer 0\n");
+
+ // Write to buffer 1
+ buf = (int *)(BUFFER_BASE + BUFFER_1);
+ puthex_nl((int)buf);
+ for(i=0;i<BUFFER_SIZE;i++)
+ buf[i] = i + ((i^0xFFFF) << 16);
+
+ putstr("Filled buffer 1\n");
+
+#endif
+
+#if 0
+ // rx SERDES into buffer #2 (buf,port,step,fl,ll)
+ bp_receive_to_buf(2, 0, 1, 10, 300);
+ putstr("SERDES RX buffer setup\n");
+
+ // send SERDES from buffer #0 (buf,port,step,fl,ll)
+ bp_send_from_buf(0, 0, 1, 20, 200);
+ putstr("SERDES TX buffer setup\n");
+
+#endif
+
+#if 0
+ // send to DACs from buffer #1
+ bp_send_from_buf(1 /*buf#*/, 1 /*port*/, 1 /*step*/, 20 /*fl*/, 250 /*ll*/);
+ putstr("DAC Buffer setup\n");
+#endif
+
+#if 0
+ //putstr("ENTER INT\n");
+ for(i=0;i<8;i++)
+ if(*status & (1<<i)) {
+ //putstr("Clearing buf ");
+ puthex_nl(i);
+ bp_clear_buf(i);
+ }
+ //putstr("EXIT INT\n");
+#endif
diff --git a/usrp2/firmware/apps/test_db_spi.c b/usrp2/firmware/apps/test_db_spi.c
new file mode 100644
index 000000000..f4fa98ef1
--- /dev/null
+++ b/usrp2/firmware/apps/test_db_spi.c
@@ -0,0 +1,35 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <u2_init.h>
+#include <nonstdio.h>
+#include <hal_io.h>
+#include <spi.h>
+
+int
+main(void)
+{
+ u2_init();
+
+ puts("\ntest_db_spi");
+
+ while(1){
+ spi_transact(SPI_TXONLY, SPI_SS_RX_DB, 0xCC33, 16, SPIF_PUSH_FALL);
+ spi_transact(SPI_TXONLY, SPI_SS_TX_DB, 0x33CC, 16, SPIF_PUSH_FALL);
+ }
+}
diff --git a/usrp2/firmware/apps/test_i2c.c b/usrp2/firmware/apps/test_i2c.c
new file mode 100644
index 000000000..f349ead88
--- /dev/null
+++ b/usrp2/firmware/apps/test_i2c.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <u2_init.h> /* FIXME */
+#include <i2c.h>
+#include <usrp2_i2c_addr.h>
+#include <string.h>
+#include <hal_io.h>
+
+
+
+#define ASSERT_TRUE(x) \
+ do { \
+ if (!(x)){ \
+ printf("ASSERT_TRUE failed on line %d\n", __LINE__); \
+ nerrors++; \
+ } \
+ } while(0)
+
+#define ASSERT_FALSE(x) \
+ do { \
+ if (x){ \
+ printf("ASSERT_FALSE failed on line %d\n", __LINE__); \
+ nerrors++; \
+ } \
+ } while(0)
+
+
+#define BUFSIZE 128
+
+int
+main(void)
+{
+ int i;
+ bool ok;
+ int nerrors = 0;
+ uint8_t buf[BUFSIZE];
+ int not_dev_addr = 0x35; // no device with this address on the i2c bus.
+ int offset;
+ int len;
+
+ u2_init();
+
+ puts("test_i2c\n");
+
+ // try writing a non-existent device
+ buf[0] = 0xA5;
+ ok = i2c_write(not_dev_addr, buf, 1);
+ ASSERT_FALSE(ok);
+
+ // try read from non-existent device
+ buf[0] = 0;
+ ok = i2c_read(not_dev_addr, buf, 1);
+ ASSERT_FALSE(ok);
+
+ // try writing eeprom
+ offset = 31;
+ len = 8;
+ memset(buf, 0, sizeof(buf));
+ for (i = 0; i < len; i++)
+ buf[i] = i;
+ ok = eeprom_write(I2C_ADDR_MBOARD, offset, buf, len);
+ ASSERT_TRUE(ok);
+
+ // now try to read it back
+ offset = 31;
+ len = 8;
+ memset(buf, 0, sizeof(buf));
+ ok = eeprom_read(I2C_ADDR_MBOARD, offset, buf, len);
+ ASSERT_TRUE(ok);
+
+ // check result
+ for (i = 0; i < len; i++){
+ if (buf[i] != i){
+ printf("buf[%d] = %d, should be %d\n", i, buf[i], i);
+ nerrors++;
+ }
+ }
+
+ if (nerrors == 0){
+ output_regs->leds = 0x3;
+ puts("PASSED\n");
+ }
+ else {
+ output_regs->leds = 0x0;
+ puts("FAILED\n");
+ }
+
+ hal_finish();
+ return 0;
+}
+
diff --git a/usrp2/firmware/apps/test_lsadc.c b/usrp2/firmware/apps/test_lsadc.c
new file mode 100644
index 000000000..5fda29cd7
--- /dev/null
+++ b/usrp2/firmware/apps/test_lsadc.c
@@ -0,0 +1,57 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <lsadc.h>
+#include <lsdac.h>
+#include <u2_init.h>
+#include <nonstdio.h>
+#include <hal_io.h>
+
+int
+main(void)
+{
+ u2_init();
+
+ puts("\ntest_lsadc");
+
+ uint32_t r;
+
+ unsigned int up_counter = 0;
+
+ while (1){
+ unsigned int v;
+ v = up_counter;
+
+ lsdac_write_rx(0, v << 0);
+ lsdac_write_rx(2, v << 1);
+
+#if 1
+ r = lsadc_read_rx(0);
+ lsdac_write_rx(1, r & 0x0fff);
+ //puthex32_nl(r);
+#endif
+
+#if 1
+ r = lsadc_read_rx(1);
+ lsdac_write_rx(3, r & 0x0fff);
+ //puthex32_nl(r);
+#endif
+
+ up_counter++;
+ }
+}
diff --git a/usrp2/firmware/apps/test_lsdac.c b/usrp2/firmware/apps/test_lsdac.c
new file mode 100644
index 000000000..8c1bf333b
--- /dev/null
+++ b/usrp2/firmware/apps/test_lsdac.c
@@ -0,0 +1,51 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <lsdac.h>
+#include <u2_init.h>
+#include <nonstdio.h>
+#include <hal_io.h>
+
+int
+main(void)
+{
+ u2_init();
+
+ puts("\ntest_lsdac");
+
+ unsigned int up_counter = 0;
+ unsigned int dn_counter = 0;
+
+ while(1){
+ unsigned int v;
+ v = up_counter;
+ lsdac_write_rx(0, v << 0);
+ lsdac_write_rx(1, v << 1);
+ lsdac_write_rx(2, v << 2);
+ lsdac_write_rx(3, v << 3);
+
+ v = up_counter;
+ lsdac_write_tx(0, v << 0);
+ lsdac_write_tx(1, v << 1);
+ lsdac_write_tx(2, v << 2);
+ lsdac_write_tx(3, v << 3);
+
+ up_counter++;
+ dn_counter--;
+ }
+}
diff --git a/usrp2/firmware/apps/test_phy_comm.c b/usrp2/firmware/apps/test_phy_comm.c
new file mode 100644
index 000000000..7242c6fc8
--- /dev/null
+++ b/usrp2/firmware/apps/test_phy_comm.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+// check communication with ethernet PHY chip
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include "ethernet.h"
+#include "pic.h"
+#include "nonstdio.h"
+
+
+#define DELTA_T 12500000 // .125s (10ns per tick)
+//#define DELTA_T 10000
+
+// debugging output on tx pins
+#define LS_MASK 0xE0000
+#define LS_1000 0x80000
+#define LS_100 0x40000
+#define LS_10 0x20000
+
+
+
+#define U2_ETHERTYPE 0xBEEF
+
+
+static volatile int led_link_up_flag = 0;
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+ int v = 0;
+ switch(speed){
+ case 10:
+ v = LS_10;
+ led_link_up_flag = 0x2;
+ break;
+
+ case 100:
+ v = LS_100;
+ led_link_up_flag = 0x2;
+ break;
+
+ case 1000:
+ v = LS_100;
+ led_link_up_flag = 0x2;
+ break;
+
+ default:
+ v = 0;
+ led_link_up_flag = 0;
+ break;
+ }
+
+ //hal_gpio_set_tx(v, LS_MASK); /* set debug bits on d'board */
+
+ putstr("\neth link changed: speed = ");
+ puthex_nl(speed);
+}
+
+void
+timer_handler(unsigned irq)
+{
+ static int led_counter = 0;
+
+ hal_set_timeout(DELTA_T); // schedule next timeout
+ output_regs->leds = (led_counter++ & 0x1) | led_link_up_flag;
+}
+
+int
+main(void)
+{
+ u2_init();
+
+ putstr("\n test_phy_comm\n");
+
+ pic_register_handler(IRQ_TIMER, timer_handler);
+ hal_set_timeout(DELTA_T); // schedule timeout
+
+ // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+ //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+ //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+
+ output_regs->phy_ctrl = 1; /* reset the eth PHY */
+ output_regs->phy_ctrl = 0;
+
+ ethernet_init();
+
+ while(1)
+ ;
+
+ return 0;
+}
diff --git a/usrp2/firmware/apps/test_serdes.c b/usrp2/firmware/apps/test_serdes.c
new file mode 100644
index 000000000..fadf4d86c
--- /dev/null
+++ b/usrp2/firmware/apps/test_serdes.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "memcpy_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+
+
+// ----------------------------------------------------------------
+
+static u2_mac_addr_t dst_mac_addr =
+ {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
+
+// ----------------------------------------------------------------
+
+// #define PACKET_SIZE 1500 // bytes
+// #define ETH_DATA_RATE 1000000 // 1MB/s
+// #define ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE) // 13,3333 pkts/s
+
+// static int timer_delta = MASTER_CLK_RATE/ETH_PACKET_RATE; // ticks between interrupts
+
+static int timer_delta = MASTER_CLK_RATE/1000; // tick at 1kHz
+
+static volatile bool send_packet_now = false; // timer handler sets this
+static volatile bool link_is_up = false; // eth handler sets this
+
+int packet_number = 0;
+
+// ----------------------------------------------------------------
+
+// debugging output on tx pins
+#define LS_MASK 0xE0000
+#define LS_1000 0x80000
+#define LS_100 0x40000
+#define LS_10 0x20000
+
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+ int v = 0;
+ switch(speed){
+ case 10:
+ v = LS_10;
+ link_is_up = true;
+ break;
+
+ case 100:
+ v = LS_100;
+ link_is_up = true;
+ break;
+
+ case 1000:
+ v = LS_100;
+ link_is_up = true;
+ break;
+
+ default:
+ v = 0;
+ link_is_up = false;
+ break;
+ }
+
+ //hal_gpio_set_tx(v, LS_MASK); /* set debug bits on d'board */
+
+ putstr("\neth link changed: speed = ");
+ puthex16_nl(speed);
+}
+
+void
+timer_irq_handler(unsigned irq)
+{
+ hal_set_timeout(timer_delta); // schedule next timeout
+ send_packet_now = 1;
+}
+
+
+void
+buffer_irq_handler(unsigned irq)
+{
+ // FIXME
+}
+
+static void
+init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum)
+{
+ int i = 0;
+ int mark = ((bufnum & 0xff) << 24) | 0x005A0000;
+
+ for (i = 0; i < BP_NLINES; i++){
+ buf[i] = mark | i;
+ mark ^= 0x00FF0000;
+ }
+
+ // copy header into buffer
+ memcpy_wa(buf, pkt, sizeof(*pkt));
+}
+
+static void
+init_packets(void)
+{
+ int i;
+
+ u2_eth_packet_t pkt __attribute__((aligned (4)));
+
+ pkt.ehdr.dst = dst_mac_addr;
+ // pkt.ehdr.src filled in by mac
+ pkt.ehdr.ethertype = U2_ETHERTYPE;
+
+ // fill ALL buffers for debugging
+ for (i = 0; i < 8; i++)
+ init_packet((void *)buffer_ram(i), &pkt, i);
+}
+
+static int led_counter = 0;
+
+int
+main(void)
+{
+ u2_init();
+
+ // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+ //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+ //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+ putstr("\ngen_eth_packets\n");
+
+ // Control LEDs
+ output_regs->leds = 0x00;
+
+ init_packets();
+
+ // pic_register_handler(IRQ_BUFFER, buffer_irq_handler); // poll for now
+ pic_register_handler(IRQ_TIMER, timer_irq_handler);
+ hal_set_timeout(timer_delta);
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+
+ ethernet_init();
+
+ // eth_mac->speed = 4; // FIXME hardcode mac speed to 1000
+ int i = 0;
+ while(1){
+ if (link_is_up && send_packet_now){
+ send_packet_now = false;
+
+ // kick off the next packet
+ // FIXME set packet number in packet
+
+ bp_send_from_buf(i, PORT_SERDES, 1, 0, 255); // 1KB total
+
+ //while ((buffer_pool_status->status & (BPS_DONE_0|BPS_ERROR_0)) == 0)
+ while ((buffer_pool_status->status ) == 0)
+ ;
+ bp_clear_buf(i);
+ i++;
+ if(i==8)
+ i=0;
+ output_regs->leds = ((++led_counter) & 0x1) | (link_is_up ? 0x2 : 0x0);
+ }
+ }
+
+ hal_finish();
+ return 1;
+}
diff --git a/usrp2/firmware/apps/timer_test.c b/usrp2/firmware/apps/timer_test.c
new file mode 100644
index 000000000..7c1e46440
--- /dev/null
+++ b/usrp2/firmware/apps/timer_test.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "nonstdio.h"
+
+
+#define DELTA_T 500 // 5 us (10ns per tick)
+
+
+void
+timer_handler(unsigned irq)
+{
+ int t = timer_regs->time;
+ timer_regs->time = t + DELTA_T;
+
+ putstr("Tick: ");
+ puthex_nl(t);
+}
+
+int
+main(void)
+{
+ u2_init();
+
+ // setup timer
+
+ putstr("Setting up timer\n");
+ pic_register_handler(IRQ_TIMER, timer_handler);
+
+ int t = timer_regs->time;
+ timer_regs->time = t + DELTA_T;
+
+ while (1)
+ ;
+
+ putstr("Done Testing\n");
+
+ hal_finish();
+ return 1;
+}
diff --git a/usrp2/firmware/apps/tx_only_v2.c b/usrp2/firmware/apps/tx_only_v2.c
new file mode 100644
index 000000000..f1e788db6
--- /dev/null
+++ b/usrp2/firmware/apps/tx_only_v2.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <db.h>
+#include <db_base.h>
+
+
+/*
+ * This program can respond to queries from the host
+ * and stream rx samples.
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow
+ */
+//#define CPU_RX_BUF 0 // eth -> cpu
+//#define CPU_TX_BUF 1 // cpu -> eth
+
+#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer)
+#define DSP_RX_BUF_1 3 // dsp rx -> eth
+#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer)
+#define DSP_TX_BUF_1 5 // eth -> dsp tx
+
+/*
+ * ================================================================
+ * configure DSP TX double buffering state machine
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+ PORT_ETH,
+ 0,
+ BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+ PORT_DSP,
+ DSP_TX_FIRST_LINE, // starts just past transport header
+ 0 // filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm; // the state machine
+
+
+// ----------------------------------------------------------------
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+void
+start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+ // FIXME nop
+}
+
+
+void
+stop_rx_cmd(void)
+{
+ // FIXME nop
+}
+
+
+static void
+setup_tx()
+{
+ dsp_tx_regs->clear_state = 1;
+ bp_clear_buf(DSP_TX_BUF_0);
+ bp_clear_buf(DSP_TX_BUF_1);
+
+ int tx_scale = 256;
+ int interp = 32;
+
+ // setup some defaults
+
+ dsp_tx_regs->freq = 0;
+ dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+ dsp_tx_regs->interp_rate = interp;
+}
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+ //hal_toggle_leds(0x2);
+
+ uint32_t status = buffer_pool_status->status;
+
+ dbsm_process_status(&dsp_tx_sm, status);
+
+ if (status & BPS_DONE(CPU_TX_BUF)){
+ bp_clear_buf(CPU_TX_BUF);
+ }
+}
+
+int
+main(void)
+{
+ u2_init();
+
+ putstr("\ntx_only_v2\n");
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+ ethernet_init();
+
+ // initialize double buffering state machine for ethernet -> DSP Tx
+
+ dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+ &dsp_tx_recv_args, &dsp_tx_send_args,
+ eth_pkt_inspector);
+
+ // program tx registers
+ setup_tx();
+
+ // kick off the state machine
+ dbsm_start(&dsp_tx_sm);
+
+ while(1){
+ buffer_irq_handler(0);
+
+ int pending = pic_regs->pending; // poll for under or overrun
+
+ if (pending & PIC_UNDERRUN_INT){
+ dbsm_handle_tx_underrun(&dsp_tx_sm);
+ pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt
+ putchar('U');
+ }
+ }
+}
diff --git a/usrp2/firmware/apps/tx_standalone.c b/usrp2/firmware/apps/tx_standalone.c
new file mode 100644
index 000000000..25ba8fd40
--- /dev/null
+++ b/usrp2/firmware/apps/tx_standalone.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "memcpy_wa.h"
+#include "dbsm.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define _AL4 __attribute__((aligned (4)))
+
+#define USE_BUFFER_INTERRUPT 0 // 0 or 1
+
+
+static int timer_delta = MASTER_CLK_RATE/1000; // tick at 1kHz
+
+/*
+ * This program can respond to queries from the host
+ * and stream rx samples.
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow
+ */
+//#define CPU_RX_BUF 0 // eth -> cpu
+#define CPU_TX_BUF 1 // cpu -> eth
+
+#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer)
+#define DSP_RX_BUF_1 3 // dsp rx -> eth
+#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer)
+#define DSP_TX_BUF_1 5 // eth -> dsp tx
+
+
+/*
+ * ================================================================
+ * configure DSP RX double buffering state machine
+ * ================================================================
+ */
+
+
+// 4 lines of ethernet hdr + 1 line (word0)
+// DSP Rx writes timestamp followed by nlines_per_frame of samples
+#define DSP_RX_FIRST_LINE 5
+#define DSP_RX_SAMPLES_PER_FRAME 128
+#define DSP_RX_EXTRA_LINES 1 // writes timestamp
+
+// Receive from DSP Rx
+buf_cmd_args_t dsp_rx_recv_args = {
+ PORT_DSP,
+ DSP_RX_FIRST_LINE,
+ BP_LAST_LINE
+};
+
+// send to ethernet
+buf_cmd_args_t dsp_rx_send_args = {
+ PORT_ETH,
+ 0, // starts with ethernet header in line 0
+ 0, // filled in from last_line register
+};
+
+dbsm_t dsp_rx_sm; // the state machine
+
+/*
+ * ================================================================
+ * configure DSP TX double buffering state machine
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE 4
+#define DSP_TX_SAMPLES_PER_FRAME 250 // not used except w/ debugging
+#define DSP_TX_EXTRA_LINES 2 // reads word0 + timestamp
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+ PORT_ETH,
+ 0,
+ BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+ PORT_DSP,
+ DSP_TX_FIRST_LINE, // starts just past ethernet header
+ 0 // filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm; // the state machine
+
+/*
+ * send constant buffer to DSP TX
+ */
+static inline void
+SEND_CONST_TO_DSP_TX(void)
+{
+ bp_send_from_buf(DSP_TX_BUF_0, PORT_DSP, 1,
+ DSP_TX_FIRST_LINE,
+ DSP_TX_FIRST_LINE + DSP_TX_EXTRA_LINES + DSP_TX_SAMPLES_PER_FRAME - 1);
+}
+
+// ----------------------------------------------------------------
+
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+void link_changed_callback(int speed);
+static volatile bool link_is_up = false; // eth handler sets this
+
+
+void
+timer_irq_handler(unsigned irq)
+{
+ hal_set_timeout(timer_delta); // schedule next timeout
+}
+
+// Tx DSP underrun
+void
+underrun_irq_handler(unsigned irq)
+{
+ dsp_tx_regs->clear_state = 1;
+ bp_clear_buf(DSP_TX_BUF_0);
+ bp_clear_buf(DSP_TX_BUF_1);
+ dbsm_stop(&dsp_tx_sm);
+
+ // FIXME anything else?
+
+ putstr("\nirq: underrun\n");
+}
+
+// Rx DSP overrun
+void
+overrun_irq_handler(unsigned irq)
+{
+ dsp_rx_regs->clear_state = 1;
+ bp_clear_buf(DSP_RX_BUF_0);
+ bp_clear_buf(DSP_RX_BUF_1);
+ dbsm_stop(&dsp_rx_sm);
+
+ // FIXME anything else?
+
+ putstr("\nirq: overrun\n");
+}
+
+static void
+start_tx_transfers(void)
+{
+ bp_clear_buf(DSP_TX_BUF_0); // FIXME, really goes in state machine
+ bp_clear_buf(DSP_TX_BUF_1);
+
+ // fill everything with a constant 32k + 0j
+
+ uint32_t const_sample = (32000 << 16) | 0;
+ int i;
+ for (i = 0; i < BP_NLINES; i++){
+ buffer_ram(DSP_TX_BUF_0)[i] = const_sample;
+ buffer_ram(DSP_TX_BUF_1)[i] = const_sample;
+ }
+
+ /*
+ * Construct ethernet header and word0 and preload into two buffers
+ */
+ u2_eth_packet_t pkt;
+ memset(&pkt, 0, sizeof(pkt));
+ //pkt.ehdr.dst = *host;
+ pkt.ehdr.ethertype = U2_ETHERTYPE;
+ u2p_set_word0(&pkt.fixed,
+ U2P_TX_IMMEDIATE | U2P_TX_START_OF_BURST, 0);
+ u2p_set_timestamp(&pkt.fixed, T_NOW);
+
+ memcpy_wa(buffer_ram(DSP_TX_BUF_0), &pkt, sizeof(pkt));
+ memcpy_wa(buffer_ram(DSP_TX_BUF_1), &pkt, sizeof(pkt));
+
+
+ int tx_scale = 256;
+
+ // setup Tx DSP regs
+ dsp_tx_regs->clear_state = 1; // reset
+ dsp_tx_regs->freq = 408021893; // 9.5 MHz [2**32 * fc/fsample]
+ dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+ dsp_tx_regs->interp_rate = 32;
+
+ // kick off the state machine
+ // dbsm_start(&dsp_rx_sm);
+
+ SEND_CONST_TO_DSP_TX(); // send constant buffer to DSP TX
+}
+
+
+void
+buffer_irq_handler(unsigned irq)
+{
+ uint32_t status = buffer_pool_status->status;
+
+ if (0){
+ putstr("irq: ");
+ puthex32(status);
+ putchar('\n');
+ }
+
+ if (status & BPS_ERROR_ALL){
+ // FIXME rare path, handle error conditions
+ }
+
+ if (status & BPS_DONE(DSP_TX_BUF_0)){
+ bp_clear_buf(DSP_TX_BUF_0);
+ SEND_CONST_TO_DSP_TX();
+ hal_toggle_leds(0x1);
+ }
+
+}
+
+int
+main(void)
+{
+ u2_init();
+
+ // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+ //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+ //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+ putstr("\ntx_only\n");
+
+ // Control LEDs
+ hal_set_leds(0x0, 0x3);
+
+ if (USE_BUFFER_INTERRUPT)
+ pic_register_handler(IRQ_BUFFER, buffer_irq_handler);
+
+ pic_register_handler(IRQ_OVERRUN, overrun_irq_handler);
+ pic_register_handler(IRQ_UNDERRUN, underrun_irq_handler);
+
+ //pic_register_handler(IRQ_TIMER, timer_irq_handler);
+ //hal_set_timeout(timer_delta);
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+
+ ethernet_init();
+
+ // initialize double buffering state machine for DSP RX -> Ethernet
+ dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+ &dsp_rx_recv_args, &dsp_rx_send_args,
+ dbsm_nop_inspector);
+
+ // setup receive from ETH
+ // bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+
+#if 0
+ if (hwconfig_simulation_p()){
+ // If we're simulating, pretend that we got a start command from the host
+ u2_mac_addr_t host = {{ 0x00, 0x0A, 0xE4, 0x3E, 0xD2, 0xD5 }};
+ start_rx_cmd(&host);
+ }
+#endif
+
+ start_tx_transfers(); // send constant buffers to DSP TX
+
+ while(1){
+ if (!USE_BUFFER_INTERRUPT)
+ buffer_irq_handler(0);
+ }
+}
+
+// ----------------------------------------------------------------
+
+// debugging output on tx pins
+#define LS_MASK 0xE0000
+#define LS_1000 0x80000
+#define LS_100 0x40000
+#define LS_10 0x20000
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+ int v = 0;
+ switch(speed){
+ case 10:
+ v = LS_10;
+ link_is_up = true;
+ break;
+
+ case 100:
+ v = LS_100;
+ link_is_up = true;
+ break;
+
+ case 1000:
+ v = LS_100;
+ link_is_up = true;
+ break;
+
+ default:
+ v = 0;
+ link_is_up = false;
+ break;
+ }
+
+ //hal_gpio_set_tx(v, LS_MASK); /* set debug bits on d'board */
+
+ // hal_set_leds(link_is_up ? 0x2 : 0x0, 0x2);
+
+ printf("\neth link changed: speed = %d\n", speed);
+}
diff --git a/usrp2/firmware/apps/txrx.c b/usrp2/firmware/apps/txrx.c
new file mode 100644
index 000000000..13aa8ba2b
--- /dev/null
+++ b/usrp2/firmware/apps/txrx.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include "memcpy_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now)
+
+#if (FW_SETS_SEQNO)
+static int fw_seqno; // used when f/w is filling in sequence numbers
+#endif
+
+
+/*
+ * Full duplex Tx and Rx between ethernet and DSP pipelines
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow
+ */
+//#define CPU_RX_BUF 0 // eth -> cpu
+
+#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer)
+#define DSP_RX_BUF_1 3 // dsp rx -> eth
+#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer)
+#define DSP_TX_BUF_1 5 // eth -> dsp tx
+
+/*
+ * ================================================================
+ * configure DSP TX double buffering state machine (eth -> dsp)
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+ PORT_ETH,
+ 0,
+ BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+ PORT_DSP,
+ DSP_TX_FIRST_LINE, // starts just past transport header
+ 0 // filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm; // the state machine
+
+/*
+ * ================================================================
+ * configure DSP RX double buffering state machine (dsp -> eth)
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
+// DSP Rx writes timestamp followed by nlines_per_frame of samples
+#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1)
+
+// receive from DSP
+buf_cmd_args_t dsp_rx_recv_args = {
+ PORT_DSP,
+ DSP_RX_FIRST_LINE,
+ BP_LAST_LINE
+};
+
+// send to ETH
+buf_cmd_args_t dsp_rx_send_args = {
+ PORT_ETH,
+ 0, // starts with ethernet header in line 0
+ 0, // filled in from list_line register
+};
+
+dbsm_t dsp_rx_sm; // the state machine
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+// variables for streaming mode
+
+static bool streaming_p = false;
+static unsigned int streaming_items_per_frame = 0;
+static int streaming_frame_count = 0;
+#define FRAMES_PER_CMD 1000
+
+
+// ----------------------------------------------------------------
+
+
+static void
+restart_streaming(void)
+{
+ // setup RX DSP regs
+ dsp_rx_regs->clear_state = 1; // reset
+
+ streaming_p = true;
+ streaming_frame_count = FRAMES_PER_CMD;
+
+ dsp_rx_regs->rx_command =
+ MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+ streaming_items_per_frame,
+ 1, 1); // set "chain" bit
+
+ // kick off the state machine
+ dbsm_start(&dsp_rx_sm);
+
+ dsp_rx_regs->rx_time = 0; // enqueue first of two commands
+
+ // make sure this one and the rest have the "now" and "chain" bits set.
+ dsp_rx_regs->rx_command =
+ MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+ streaming_items_per_frame,
+ 1, 1);
+
+ dsp_rx_regs->rx_time = 0; // enqueue second command
+}
+
+void
+start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+ host_mac_addr = *host; // remember who we're sending to
+
+ /*
+ * Construct ethernet header and word0 and preload into two buffers
+ */
+ u2_eth_packet_t pkt;
+ memset(&pkt, 0, sizeof(pkt));
+ pkt.ehdr.dst = *host;
+ pkt.ehdr.ethertype = U2_ETHERTYPE;
+ u2p_set_word0(&pkt.fixed, 0, 0);
+ // DSP RX will fill in timestamp
+
+ memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
+ memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
+
+
+ if (FW_SETS_SEQNO)
+ fw_seqno = 0;
+
+ streaming_items_per_frame = p->items_per_frame;
+ restart_streaming();
+}
+
+
+void
+stop_rx_cmd(void)
+{
+ streaming_p = false;
+ dsp_rx_regs->clear_state = 1; // flush cmd queue
+ bp_clear_buf(DSP_RX_BUF_0);
+ bp_clear_buf(DSP_RX_BUF_1);
+}
+
+
+static void
+setup_tx()
+{
+ dsp_tx_regs->clear_state = 1;
+ bp_clear_buf(DSP_TX_BUF_0);
+ bp_clear_buf(DSP_TX_BUF_1);
+
+ int tx_scale = 256;
+ int interp = 32;
+
+ // setup some defaults
+
+ dsp_tx_regs->freq = 0;
+ dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+ dsp_tx_regs->interp_rate = interp;
+}
+
+
+#if (FW_SETS_SEQNO)
+/*
+ * Debugging ONLY. This will be handled by the tx_protocol_engine.
+ *
+ * This is called when the DSP Rx chain has filled in a packet.
+ * We set and increment the seqno, then return false, indicating
+ * that we didn't handle the packet. A bit of a kludge
+ * but it should work.
+ */
+bool
+fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false
+{
+ uint32_t *p = buffer_ram(buf_this);
+ uint32_t seqno = fw_seqno++;
+
+ // KLUDGE all kinds of nasty magic numbers and embedded knowledge
+ uint32_t t = p[4];
+ t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
+ p[4] = t;
+
+ // queue up another rx command when required
+ if (streaming_p && --streaming_frame_count == 0){
+ streaming_frame_count = FRAMES_PER_CMD;
+ dsp_rx_regs->rx_time = 0;
+ }
+
+ return false; // we didn't handle the packet
+}
+#endif
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+ uint32_t status = buffer_pool_status->status;
+
+ dbsm_process_status(&dsp_tx_sm, status);
+ dbsm_process_status(&dsp_rx_sm, status);
+}
+
+int
+main(void)
+{
+ u2_init();
+
+ putstr("\nTxRx\n");
+ print_mac_addr(ethernet_mac_addr()->addr);
+ newline();
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+ ethernet_init();
+
+
+#if 0
+ // make bit 15 of Tx gpio's be a s/w output
+ hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
+ hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
+#endif
+
+ output_regs->debug_mux_ctrl = 1;
+#if 0
+ hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+ hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+ hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
+ hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
+#endif
+
+
+ // initialize double buffering state machine for ethernet -> DSP Tx
+
+ dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+ &dsp_tx_recv_args, &dsp_tx_send_args,
+ eth_pkt_inspector);
+
+
+ // initialize double buffering state machine for DSP RX -> Ethernet
+
+ if (FW_SETS_SEQNO){
+ dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+ &dsp_rx_recv_args, &dsp_rx_send_args,
+ fw_sets_seqno_inspector);
+ }
+ else {
+ dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+ &dsp_rx_recv_args, &dsp_rx_send_args,
+ dbsm_nop_inspector);
+ }
+
+ // tell app_common that this dbsm could be sending to the ethernet
+ ac_could_be_sending_to_eth = &dsp_rx_sm;
+
+
+ // program tx registers
+ setup_tx();
+
+ // kick off the state machine
+ dbsm_start(&dsp_tx_sm);
+
+ //int which = 0;
+
+ while(1){
+ // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
+ // which ^= 0x8000;
+
+ buffer_irq_handler(0);
+
+ int pending = pic_regs->pending; // poll for under or overrun
+
+ if (pending & PIC_UNDERRUN_INT){
+ dbsm_handle_tx_underrun(&dsp_tx_sm);
+ pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt
+ putchar('U');
+ }
+
+ if (pending & PIC_OVERRUN_INT){
+ dbsm_handle_rx_overrun(&dsp_rx_sm);
+ pic_regs->pending = PIC_OVERRUN_INT; // clear pending interrupt
+
+ // FIXME Figure out how to handle this robustly.
+ // Any buffers that are emptying should be allowed to drain...
+
+ if (streaming_p){
+ // restart_streaming();
+ // FIXME report error
+ }
+ else {
+ // FIXME report error
+ }
+ putchar('O');
+ }
+ }
+}
diff --git a/usrp2/firmware/bootstrap b/usrp2/firmware/bootstrap
new file mode 100755
index 000000000..5b4ab09ae
--- /dev/null
+++ b/usrp2/firmware/bootstrap
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# Copyright 2001,2005 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+
+rm -fr config.cache autom4te*.cache
+
+aclocal
+autoconf
+autoheader
+# libtoolize --automake
+automake --add-missing -Wno-portability
+
diff --git a/usrp2/firmware/config.guess b/usrp2/firmware/config.guess
new file mode 100644
index 000000000..278f9e9e0
--- /dev/null
+++ b/usrp2/firmware/config.guess
@@ -0,0 +1,1516 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+# Inc.
+
+timestamp='2007-07-22'
+
+# This 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; 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 Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ case ${UNAME_MACHINE} in
+ pc98)
+ echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:[3456]*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ EM64T | authenticamd)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ xtensa:Linux:*:*)
+ echo xtensa-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^LIBC/{
+ s: ::g
+ p
+ }'`"
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/usrp2/firmware/config.sub b/usrp2/firmware/config.sub
new file mode 100644
index 000000000..1761d8bdf
--- /dev/null
+++ b/usrp2/firmware/config.sub
@@ -0,0 +1,1626 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+# Inc.
+
+timestamp='2007-06-28'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This 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; 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 Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fido | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | mcore | mep \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | mt \
+ | msp430 \
+ | nios | nios2 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nios-* | nios2-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/usrp2/firmware/configure.ac b/usrp2/firmware/configure.ac
new file mode 100644
index 000000000..bbb223c06
--- /dev/null
+++ b/usrp2/firmware/configure.ac
@@ -0,0 +1,46 @@
+dnl
+dnl Copyright 2007 Free Software Foundation, Inc.
+dnl
+dnl This program is free software: you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation, either version 3 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
+dnl
+
+AC_INIT
+AC_PREREQ(2.57)
+AM_CONFIG_HEADER(config.h)
+AC_CONFIG_AUX_DIR([.])
+AC_CONFIG_SRCDIR([lib/u2_init.c])
+
+AM_INIT_AUTOMAKE(u2f,0.0svn)
+
+cross_compiling=yes
+
+AC_PROG_CC([mb-gcc])
+dnl AC_PROG_LD([mb-ld])
+
+RANLIB=mb-ranlib
+AC_SUBST(RANLIB)
+
+dnl AC_PROG_RANLIB([mb-ranlib])
+
+AC_CHECK_HEADERS(arpa/inet.h netinet/in.h byteswap.h)
+AC_C_BIGENDIAN
+
+AC_CONFIG_FILES([\
+ Makefile \
+ apps/Makefile \
+ include/Makefile \
+ lib/Makefile \
+])
+
+AC_OUTPUT
diff --git a/usrp2/firmware/divisors.py b/usrp2/firmware/divisors.py
new file mode 100755
index 000000000..d31bd4dad
--- /dev/null
+++ b/usrp2/firmware/divisors.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+
+speeds = (9600, 19200, 38400, 57600, 115200, 230400)
+
+master_clk = 100e6
+wb_clk = master_clk / 2
+
+def divisor(speed):
+ div0 = wb_clk // (speed * 16)
+ div1 = div0 + 1
+ actual0 = actual_speed(div0)
+ actual1 = actual_speed(div1)
+ if abs(actual0 - speed) < abs(actual1 - speed):
+ return div0
+ else:
+ return div1
+
+def actual_speed(divisor):
+ return (wb_clk // divisor) / 16
+
+def doit(speed):
+ div = divisor(speed)
+ actual = actual_speed(div)
+ rel_error = (actual - speed) / speed
+ print "target: %6d divisor: %6d actual: %11.4f %6.3f%%" % (speed, div, actual, rel_error*100)
+
+def main():
+ print "wb_clk = %f" % (wb_clk,)
+ for s in speeds:
+ doit(s)
+
+if __name__ == '__main__':
+ main()
+
diff --git a/usrp2/firmware/include/Makefile.am b/usrp2/firmware/include/Makefile.am
new file mode 100644
index 000000000..a5e339191
--- /dev/null
+++ b/usrp2/firmware/include/Makefile.am
@@ -0,0 +1,27 @@
+#
+# Copyright 2008 Free Software Foundation, Inc.
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+include $(top_srcdir)/Makefile.common
+
+noinst_HEADERS = \
+ usrp2_cdefs.h \
+ usrp2_eth_packet.h \
+ usrp2_fpga_regs.h \
+ usrp2_i2c_addr.h \
+ usrp2_mac_addr.h \
+ usrp2_mimo_config.h \
+ usrp2_types.h
diff --git a/usrp2/firmware/include/usrp2_cdefs.h b/usrp2/firmware/include/usrp2_cdefs.h
new file mode 100644
index 000000000..71395cda8
--- /dev/null
+++ b/usrp2/firmware/include/usrp2_cdefs.h
@@ -0,0 +1,34 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef INCLUDED_USRP2_CDEFS_H
+#define INCLUDED_USRP2_CDEFS_H
+
+/* C++ needs to know that types and declarations are C, not C++. */
+#ifdef __cplusplus
+# define __U2_BEGIN_DECLS extern "C" {
+# define __U2_END_DECLS }
+#else
+# define __U2_BEGIN_DECLS
+# define __U2_END_DECLS
+#endif
+
+#endif /* INCLUDED_USRP2_CDEFS_H */
diff --git a/usrp2/firmware/include/usrp2_eth_packet.h b/usrp2/firmware/include/usrp2_eth_packet.h
new file mode 100644
index 000000000..ca13d61ad
--- /dev/null
+++ b/usrp2/firmware/include/usrp2_eth_packet.h
@@ -0,0 +1,374 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_USRP2_ETH_PACKET_H
+#define INCLUDED_USRP2_ETH_PACKET_H
+
+#include "usrp2_cdefs.h"
+#include "usrp2_bytesex.h"
+#include "usrp2_mac_addr.h"
+#include "usrp2_mimo_config.h"
+
+__U2_BEGIN_DECLS
+
+#define U2_ETHERTYPE 0xBEEF // used in our frames
+#define MAC_CTRL_ETHERTYPE 0x8808 // used in PAUSE frames
+
+/*
+ * All these data structures are BIG-ENDIAN on the wire
+ */
+
+// FIXME gcc specific. Really ought to come from compiler.h
+#define _AL4 __attribute__((aligned (4)))
+
+/*
+ * \brief The classic 14-byte ethernet header
+ */
+typedef struct {
+ u2_mac_addr_t dst;
+ u2_mac_addr_t src;
+ uint16_t ethertype;
+} __attribute__((packed)) u2_eth_hdr_t;
+
+/*!
+ * \brief USRP2 transport header
+ *
+ * This enables host->usrp2 flow control and dropped packet detection.
+ */
+typedef struct {
+ uint16_t flags; // MBZ, may be used for channel in future
+ uint16_t fifo_status; // free space in Rx fifo in 32-bit lines
+ uint8_t seqno; // sequence number of this packet
+ uint8_t ack; // sequence number of next packet expected
+} __attribute__((packed)) u2_transport_hdr_t;
+
+
+/*
+ * The fixed payload header of a USRP2 ethernet packet...
+ *
+ * Basically there's 1 word of flags and routing info, and 1 word
+ * of timestamp that specifies when the data was received, or
+ * when it should be transmitted. The data samples follow immediately.
+ *
+ * Transmit packets (from host to U2)
+ *
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Chan | mbz |I|S|E|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Timestamp |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ *
+ * Received packets (from U2 to host)
+ *
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Chan | mbz |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Timestamp |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * mbz == must be zero
+ */
+
+typedef struct {
+ uint32_t word0; // flags etc
+ uint32_t timestamp; // time of rx or tx (100 MHz)
+} u2_fixed_hdr_t;
+
+
+#define U2P_CHAN_MASK 0x1f
+#define U2P_CHAN_SHIFT 27
+
+#define U2P_TX_IMMEDIATE 0x00000004 // send samples NOW, else at timestamp
+#define U2P_TX_START_OF_BURST 0x00000002 // this frame is the start of a burst
+#define U2P_TX_END_OF_BURST 0x00000001 // this frame is the end of a burst
+
+#define U2P_ALL_FLAGS 0x00000007
+
+#define CONTROL_CHAN 0x1f
+
+static inline int
+u2p_chan(u2_fixed_hdr_t *p)
+{
+ return (ntohl(p->word0) >> U2P_CHAN_SHIFT) & U2P_CHAN_MASK;
+}
+
+inline static uint32_t
+u2p_word0(u2_fixed_hdr_t *p)
+{
+ return ntohl(p->word0);
+}
+
+inline static uint32_t
+u2p_timestamp(u2_fixed_hdr_t *p)
+{
+ return ntohl(p->timestamp);
+}
+
+inline static void
+u2p_set_word0(u2_fixed_hdr_t *p, int flags, int chan)
+{
+ p->word0 = htonl((flags & U2P_ALL_FLAGS)
+ | ((chan & U2P_CHAN_MASK) << U2P_CHAN_SHIFT));
+}
+
+inline static void
+u2p_set_timestamp(u2_fixed_hdr_t *p, uint32_t ts)
+{
+ p->timestamp = htonl(ts);
+}
+
+/*!
+ * \brief consolidated packet: ethernet header + transport header + fixed header
+ */
+typedef struct {
+ u2_eth_hdr_t ehdr;
+ u2_transport_hdr_t thdr;
+ u2_fixed_hdr_t fixed;
+} u2_eth_packet_t;
+
+/*
+ * full load of samples:
+ * ethernet header + transport header + fixed header + maximum number of samples.
+ * sizeof(u2_eth_samples_t) == 1512
+ * (payload is 1498 bytes, two bytes shorter than 1500 byte MTU)
+ */
+
+#define U2_MAX_SAMPLES 371
+
+typedef struct {
+ u2_eth_packet_t hdrs;
+ uint32_t samples[U2_MAX_SAMPLES];
+} u2_eth_samples_t;
+
+/*
+ * Opcodes for control channel
+ *
+ * Reply opcodes are the same as the request opcode with the OP_REPLY_BIT set (0x80).
+ */
+#define OP_REPLY_BIT 0x80
+
+#define OP_EOP 0 // marks last subpacket in packet
+
+#define OP_ID 1
+#define OP_ID_REPLY (OP_ID | OP_REPLY_BIT)
+#define OP_BURN_MAC_ADDR 2
+#define OP_BURN_MAC_ADDR_REPLY (OP_BURN_MAC_ADDR | OP_REPLY_BIT)
+#define OP_READ_TIME 3 // What time is it? (100 MHz counter)
+#define OP_READ_TIME_REPLY (OP_READ_TIME | OP_REPLY_BIT)
+#define OP_CONFIG_RX_V2 4
+#define OP_CONFIG_RX_REPLY_V2 (OP_CONFIG_RX_V2 | OP_REPLY_BIT)
+#define OP_CONFIG_TX_V2 5
+#define OP_CONFIG_TX_REPLY_V2 (OP_CONFIG_TX_V2 | OP_REPLY_BIT)
+#define OP_START_RX_STREAMING 6
+#define OP_START_RX_STREAMING_REPLY (OP_START_RX_STREAMING | OP_REPLY_BIT)
+#define OP_STOP_RX 7
+#define OP_STOP_RX_REPLY (OP_STOP_RX | OP_REPLY_BIT)
+#define OP_CONFIG_MIMO 8
+#define OP_CONFIG_MIMO_REPLY (OP_CONFIG_MIMO | OP_REPLY_BIT)
+
+
+//#define OP_WRITE_REG xx // not implemented
+//#define OP_WRITE_REG_MASKED xx
+//#define OP_READ_REG xx
+//#define OP_READ_REG_REPLY xx
+
+/*
+ * All subpackets are a multiple of 4 bytes long.
+ * All subpackets start with an 8-bit opcode, an 8-bit len and an 8-bit rid.
+ */
+
+
+/*!
+ * \brief Generic request and reply packet
+ *
+ * Used by:
+ * OP_EOP, OP_BURN_MAC_ADDR_REPLY, OP_START_RX_STREAMING_REPLY,
+ * OP_STOP_RX_REPLY
+ */
+typedef struct {
+ uint8_t opcode;
+ uint8_t len;
+ uint8_t rid;
+ uint8_t ok; // bool
+} _AL4 op_generic_t;
+
+/*!
+ * \brief Reply info from a USRP2
+ */
+typedef struct {
+ uint8_t opcode;
+ uint8_t len;
+ uint8_t rid;
+ uint8_t mbz;
+ u2_mac_addr_t addr;
+ uint16_t hw_rev;
+ uint8_t fpga_md5sum[16];
+ uint8_t sw_md5sum[16];
+} _AL4 op_id_reply_t;
+
+typedef struct {
+ uint8_t opcode;
+ uint8_t len;
+ uint8_t rid;
+ uint8_t mbz;
+ uint32_t items_per_frame; // # of 32-bit data items; MTU=1500: [9,371]
+} _AL4 op_start_rx_streaming_t;
+
+typedef struct {
+ uint8_t opcode;
+ uint8_t len;
+ uint8_t rid;
+ u2_mac_addr_t addr;
+} _AL4 op_burn_mac_addr_t;
+
+typedef struct {
+ uint8_t opcode;
+ uint8_t len;
+ uint8_t rid;
+ uint8_t mbz;
+ uint32_t time;
+} _AL4 op_read_time_reply_t;
+
+
+/*!
+ * \brief Configure receiver
+ */
+typedef struct {
+ uint8_t opcode;
+ uint8_t len;
+ uint8_t rid;
+ uint8_t mbz;
+ // bitmask indicating which of the following fields are valid
+ uint16_t valid;
+ uint16_t gain; // fxpt_db (Q9.7)
+ uint32_t freq_hi; // high 32-bits of 64-bit fxpt_freq (Q44.20)
+ uint32_t freq_lo; // low 32-bits of 64-bit fxpt_freq (Q44.20)
+ uint32_t decim; // desired decimation factor (NOT -1)
+ uint32_t scale_iq; // (scale_i << 16) | scale_q [16.0 format]
+} _AL4 op_config_rx_v2_t;
+
+// bitmask for "valid" field. If the bit is set, there's
+// meaningful data in the corresonding field.
+
+#define CFGV_GAIN 0x0001 // gain field is valid
+#define CFGV_FREQ 0x0002 // target_freq field is valid
+#define CFGV_INTERP_DECIM 0x0004 // interp or decim is valid
+#define CFGV_SCALE_IQ 0x0008 // scale_iq is valid
+
+/*!
+ * \brief Reply to receiver configuration
+ */
+typedef struct {
+ uint8_t opcode;
+ uint8_t len;
+ uint8_t rid;
+ uint8_t mbz;
+
+ uint16_t ok; // config was successful (bool)
+ uint16_t inverted; // spectrum is inverted (bool)
+
+ // RF frequency that corresponds to DC in the IF (fxpt_freq)
+ uint32_t baseband_freq_hi;
+ uint32_t baseband_freq_lo;
+ // DDC frequency (fxpt_freq)
+ uint32_t ddc_freq_hi;
+ uint32_t ddc_freq_lo;
+ // residual frequency (fxpt_freq)
+ uint32_t residual_freq_hi;
+ uint32_t residual_freq_lo;
+
+} _AL4 op_config_rx_reply_v2_t;
+
+/*!
+ * \brief Configure transmitter
+ */
+typedef struct {
+ uint8_t opcode;
+ uint8_t len;
+ uint8_t rid;
+ uint8_t mbz;
+
+ // bitmask indicating which of the following fields are valid
+ uint16_t valid;
+ uint16_t gain; // fxpt_db (Q9.7)
+ uint32_t freq_hi; // high 32-bits of 64-bit fxpt_freq (Q44.20)
+ uint32_t freq_lo; // low 32-bits of 64-bit fxpt_freq (Q44.20)
+ uint32_t interp; // desired interpolation factor (NOT -1)
+ uint32_t scale_iq; // (scale_i << 16) | scale_q [16.0 format]
+} _AL4 op_config_tx_v2_t;
+
+/*!
+ * \brief Reply to configure transmitter
+ */
+typedef struct {
+ uint8_t opcode;
+ uint8_t len;
+ uint8_t rid;
+ uint8_t mbz;
+
+ uint16_t ok; // config was successful (bool)
+ uint16_t inverted; // spectrum is inverted (bool)
+
+ // RF frequency that corresponds to DC in the IF (fxpt_freq)
+ uint32_t baseband_freq_hi;
+ uint32_t baseband_freq_lo;
+ // DUC frequency (fxpt_freq)
+ uint32_t duc_freq_hi;
+ uint32_t duc_freq_lo;
+ // residual frequency (fxpt_freq)
+ uint32_t residual_freq_hi;
+ uint32_t residual_freq_lo;
+
+} _AL4 op_config_tx_reply_v2_t;
+
+/*!
+ * \brief Configure MIMO clocking, etc (uses generic reply)
+ */
+typedef struct {
+ uint8_t opcode;
+ uint8_t len;
+ uint8_t rid;
+ uint8_t flags; // from usrp_mimo_config.h
+} op_config_mimo_t;
+
+
+/*
+ * ================================================================
+ * union of all of subpacket types
+ * ================================================================
+ */
+typedef union {
+
+ op_generic_t op_generic;
+ op_id_reply_t op_id_reply;
+ op_start_rx_streaming_t op_start_rx_streaming;
+ op_burn_mac_addr_t op_burn_mac_addr;
+ op_read_time_reply_t op_read_time_reply;
+ op_config_rx_v2_t op_config_rx_v2;
+ op_config_rx_reply_v2_t op_config_rx_reply_v2;
+ op_config_tx_v2_t op_config_tx_v2;
+ op_config_tx_reply_v2_t op_config_tx_reply_v2;
+ op_config_mimo_t op_config_mimo;
+
+} u2_subpkt_t;
+
+
+__U2_END_DECLS
+
+#endif /* INCLUDED_USRP2_ETH_PACKET_H */
diff --git a/usrp2/firmware/include/usrp2_fpga_regs.h b/usrp2/firmware/include/usrp2_fpga_regs.h
new file mode 100644
index 000000000..b0f83df60
--- /dev/null
+++ b/usrp2/firmware/include/usrp2_fpga_regs.h
@@ -0,0 +1,80 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_USRP2_FPGA_REGS_H
+#define INCLUDED_USSRP2_FPGA_REGS_H
+
+#include "usrp2_cdefs.h"
+
+__U2_BEGIN_DECLS
+
+// ----------------------------------------------------------------
+
+#define DSP_CORE_TX_BASE 128
+
+// DUC center frequency tuning word (phase increment)
+#define FR_TX_FREQ_0 (0 + DSP_CORE_TX_BASE)
+
+// I & Q output scaling, 16.0 format ((I_SCALE << 16) | Q_SCALE)
+#define FR_TX_SCALE_0 (1 + DSP_CORE_TX_BASE)
+
+// Tx interpolation rate (set to 1 less than desired rate)
+#define FR_TX_INTERP_RATE_0 (2 + DSP_CORE_TX_BASE)
+
+// Write 1 (actually anything) to clear tx state
+#define FR_TX_CLEAR_STATE_0 (3 + DSP_CORE_TX_BASE)
+
+// ----------------------------------------------------------------
+
+#define DSP_CORE_RX_BASE 160
+
+// DDC center frequency tuning word (phase increment)
+#define FR_RX_FREQ_0 (0 + DSP_CORE_RX_BASE)
+
+// I & Q input scaling, 16.0 format ((I_SCALE << 16) | Q_SCALE)
+#define FR_RX_SCALE_0 (1 + DSP_CORE_RX_BASE)
+
+// Rx decimation rate (set to 1 less than desired rate)
+#define FR_RX_DECIM_RATE_0 (2 + DSP_CORE_RX_BASE)
+
+// The next two registers concatenated are the Rx command register.
+//
+// Writing FR_RX_TIME_TO_RX_0 writes the concatenated value into the
+// cmd queue. Thus, if you're writing both, be sure to write
+// FR_RX_QTY_0 first.
+//
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Timestamp |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+#define FR_RX_TIME_TO_RX (3 + DSP_CORE_RX_BASE)
+
+// 23-bits 9-bits
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | number_of_lines | lines_per_frame |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+#define FR_RX_QTY_0 (4 + DSP_CORE_RX_BASE)
+
+// write a 1 (anything actually) to clear the overrun
+#define FR_RX_CLR_OVERRUN_0 (5 + DSP_CORE_RX_BASE)
+
+
+__U2_END_DECLS
+
+#endif /* INCLUDED_USRP2_FPGA_REGS_H */
diff --git a/usrp2/firmware/include/usrp2_i2c_addr.h b/usrp2/firmware/include/usrp2_i2c_addr.h
new file mode 100644
index 000000000..f25996903
--- /dev/null
+++ b/usrp2/firmware/include/usrp2_i2c_addr.h
@@ -0,0 +1,82 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_USRP2_I2C_ADDR_H
+#define INCLUDED_USRP2_I2C_ADDR_H
+
+#include "usrp2_cdefs.h"
+
+__U2_BEGIN_DECLS
+
+// I2C addresses
+
+#define I2C_DEV_EEPROM 0x50 // 24LC02[45]: 7-bits 1010xxx
+
+#define I2C_ADDR_MBOARD (I2C_DEV_EEPROM | 0x0)
+#define I2C_ADDR_TX_A (I2C_DEV_EEPROM | 0x4)
+#define I2C_ADDR_RX_A (I2C_DEV_EEPROM | 0x5)
+
+
+// format of USRP2 motherboard rom
+// 00: 0x00 h/w rev (LSB)
+// 01: 0x00 h/w rev (MSB)
+// 02: 0x00 MAC addr 0
+// 03: 0x50 MAC addr 1
+// 04: 0xC2 MAC addr 2
+// 05: 0x85 MAC addr 3
+// 06: 0x3. MAC addr 4
+// 07: 0x.. MAC addr 5
+
+#define MBOARD_REV_LSB 0x00
+#define MBOARD_REV_MSB 0x01
+#define MBOARD_MAC_ADDR 0x02
+
+
+// format of daughterboard EEPROM
+// 00: 0xDB code for ``I'm a daughterboard''
+// 01: .. Daughterboard ID (LSB)
+// 02: .. Daughterboard ID (MSB)
+// 03: .. io bits 7-0 direction (bit set if it's an output from m'board)
+// 04: .. io bits 15-8 direction (bit set if it's an output from m'board)
+// 05: .. ADC0 DC offset correction (LSB)
+// 06: .. ADC0 DC offset correction (MSB)
+// 07: .. ADC1 DC offset correction (LSB)
+// 08: .. ADC1 DC offset correction (MSB)
+// ...
+// 1f: .. negative of the sum of bytes [0x00, 0x1e]
+
+#define DB_EEPROM_MAGIC 0x00
+#define DB_EEPROM_MAGIC_VALUE 0xDB
+#define DB_EEPROM_ID_LSB 0x01
+#define DB_EEPROM_ID_MSB 0x02
+#define DB_EEPROM_OE_LSB 0x03
+#define DB_EEPROM_OE_MSB 0x04
+#define DB_EEPROM_OFFSET_0_LSB 0x05 // offset correction for ADC or DAC 0
+#define DB_EEPROM_OFFSET_0_MSB 0x06
+#define DB_EEPROM_OFFSET_1_LSB 0x07 // offset correction for ADC or DAC 1
+#define DB_EEPROM_OFFSET_1_MSB 0x08
+#define DB_EEPROM_CHKSUM 0x1f
+
+#define DB_EEPROM_CLEN 0x20 // length of common portion of eeprom
+
+#define DB_EEPROM_CUSTOM_BASE DB_EEPROM_CLEN // first avail offset for
+ // daughterboard specific use
+__U2_END_DECLS
+
+#endif /* INCLUDED_USRP2_I2C_ADDR_H */
+
diff --git a/usrp2/firmware/include/usrp2_mac_addr.h b/usrp2/firmware/include/usrp2_mac_addr.h
new file mode 100644
index 000000000..da5a69f58
--- /dev/null
+++ b/usrp2/firmware/include/usrp2_mac_addr.h
@@ -0,0 +1,28 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_USRP2_MAC_ADDR_H
+#define INCLUDED_USRP2_MAC_ADDR_H
+
+#include <stdint.h>
+
+typedef struct {
+ uint8_t addr[6];
+} u2_mac_addr_t;
+
+#endif /* INCLUDED_USRP2_MAC_ADDR_H */
diff --git a/usrp2/firmware/include/usrp2_mimo_config.h b/usrp2/firmware/include/usrp2_mimo_config.h
new file mode 100644
index 000000000..129675198
--- /dev/null
+++ b/usrp2/firmware/include/usrp2_mimo_config.h
@@ -0,0 +1,46 @@
+/* -*- c -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_USRP2_MIMO_CONFIG_H
+#define INCLUDED_USRP2_MIMO_CONFIG_H
+
+#define _MC_WE_LOCK 0x0001
+#define _MC_MIMO_CLK_INPUT 0x0002 // else SMA input
+
+/*
+ * Derived masks (use these):
+ *
+ * We get our input from 1 of three places:
+ * Our free running oscilator, our SMA connector, or from the MIMO connector
+ */
+#define MC_WE_DONT_LOCK 0x0000
+#define MC_WE_LOCK_TO_SMA (_MC_WE_LOCK | 0)
+#define MC_WE_LOCK_TO_MIMO (_MC_WE_LOCK | _MC_MIMO_CLK_INPUT)
+
+/*
+ * Independent of the source of the clock, we may or may not drive our
+ * clock onto the mimo connector. Note that there are dedicated clock
+ * signals in each direction, so disaster doesn't occurs if we're
+ * unnecessarily providing clock.
+ */
+#define MC_PROVIDE_CLK_TO_MIMO 0x0004
+
+
+#endif /* INCLUDED_USRP2_MIMO_CONFIG_H */
diff --git a/usrp2/firmware/include/usrp2_types.h b/usrp2/firmware/include/usrp2_types.h
new file mode 100644
index 000000000..83d9f26c7
--- /dev/null
+++ b/usrp2/firmware/include/usrp2_types.h
@@ -0,0 +1,106 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef INCLUDED_USRP2_TYPES_H
+#define INCLUDED_USRP2_TYPES_H
+
+#include <usrp2_cdefs.h>
+#include <stdint.h>
+
+__U2_BEGIN_DECLS
+
+/*!
+ * \brief Fixed point representation of a frequency in Hertz (VITA-49 compatible)
+ *
+ * 64-bit two's complement, with the radix point 20 bits up from the bottom.
+ * Q44.20 format (20 bits to the right of the radix point)
+ *
+ * Values range from +/- 8.79 terahertz with a resolution of 0.95 microhertz.
+ */
+typedef int64_t u2_fxpt_freq_t;
+
+#define U2_FPF_RP 20 // location of radix point in u2_fxpt_freq_t
+
+// macro so we can init structs at compile time
+#define U2_DOUBLE_TO_FXPT_FREQ(f) (int64_t)((f) * (1LL << U2_FPF_RP))
+
+static inline u2_fxpt_freq_t
+u2_double_to_fxpt_freq(double f)
+{
+ return U2_DOUBLE_TO_FXPT_FREQ(f);
+}
+
+static inline int
+u2_fxpt_freq_round_to_int(u2_fxpt_freq_t fx)
+{
+ return (int)((fx+(1<<(U2_FPF_RP-1)))>>U2_FPF_RP);
+}
+
+static inline double
+u2_fxpt_freq_to_double(u2_fxpt_freq_t fx)
+{
+ return ((double) fx) * 1.0/(1 << U2_FPF_RP);
+}
+
+static inline uint32_t
+u2_fxpt_freq_hi(u2_fxpt_freq_t f)
+{
+ return ((f >> 32) & 0xffffffff);
+}
+
+static inline uint32_t
+u2_fxpt_freq_lo(u2_fxpt_freq_t f)
+{
+ return (f & 0xffffffff);
+}
+
+static inline u2_fxpt_freq_t
+u2_fxpt_freq_from_hilo(uint32_t hi, uint32_t lo)
+{
+ return (((u2_fxpt_freq_t) hi) << 32) | lo;
+}
+
+/*!
+ * \brief Fixed point representation of a gain in dB (VITA-49 compatible)
+ *
+ * 16-bit two's complement, with the radix point 7 bits up from the bottom.
+ * Q9.7 format (7 bits to the right of the radix point)
+ */
+typedef int16_t u2_fxpt_gain_t;
+
+#define U2_FPG_RP 7 // location of radix point in u2_fxpt_gain_t
+
+// macro so we can init structs at compile time
+#define U2_DOUBLE_TO_FXPT_GAIN(g) (int16_t)((g) * (1 << U2_FPG_RP))
+
+static inline u2_fxpt_gain_t
+u2_double_to_fxpt_gain(double g)
+{
+ return U2_DOUBLE_TO_FXPT_GAIN(g);
+}
+
+static inline float
+u2_fxpt_gain_to_double(u2_fxpt_gain_t fx)
+{
+ return ((double) fx) * 1.0/(1 << U2_FPG_RP);
+}
+
+
+__U2_END_DECLS
+
+
+#endif /* INCLUDED_USRP2_TYPES_H */
diff --git a/usrp2/firmware/lib/Makefile.am b/usrp2/firmware/lib/Makefile.am
new file mode 100644
index 000000000..83dd915c9
--- /dev/null
+++ b/usrp2/firmware/lib/Makefile.am
@@ -0,0 +1,90 @@
+#
+# Copyright 2007 Free Software Foundation, Inc.
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+include $(top_srcdir)/Makefile.common
+
+noinst_LIBRARIES = \
+ libu2fw.a
+
+
+libu2fw_a_SOURCES = \
+ ad9510.c \
+ ad9777.c \
+ buffer_pool.c \
+ clocks.c \
+ db_basic.c \
+ db_init.c \
+ db_rfx.c \
+ db_tvrx.c \
+ dbsm.c \
+ eeprom.c \
+ ethernet.c \
+ eth_mac.c \
+ hal_io.c \
+ hal_uart.c \
+ i2c.c \
+ lsadc.c \
+ lsdac.c \
+ mdelay.c \
+ memcpy_wa.c \
+ memset_wa.c \
+ nonstdio.c \
+ pic.c \
+ print_mac_addr.c \
+ print_rmon_regs.c \
+ print_fxpt.c \
+ print_buffer.c \
+ printf.c \
+ spi.c \
+ u2_init.c
+
+
+noinst_HEADERS = \
+ ad9510.h \
+ ad9777.h \
+ ad9777_regs.h \
+ bool.h \
+ buffer_pool.h \
+ clocks.h \
+ db.h \
+ db_base.h \
+ dbsm.h \
+ eth_mac.h \
+ eth_mac_regs.h \
+ eth_phy.h \
+ ethernet.h \
+ hal_io.h \
+ hal_uart.h \
+ i2c.h \
+ lsadc.h \
+ lsdac.h \
+ mdelay.h \
+ memcpy_wa.h \
+ memory_map.h \
+ memset_wa.h \
+ nonstdio.h \
+ pic.h \
+ print_rmon_regs.h \
+ spi.h \
+ stdint.h \
+ stdio.h \
+ u2_init.h \
+ usrp2_bytesex.h \
+ wb16550.h
+
+EXTRA_DIST = \
+ microblaze.ld
diff --git a/usrp2/firmware/lib/ad9510.c b/usrp2/firmware/lib/ad9510.c
new file mode 100644
index 000000000..4d3acb65d
--- /dev/null
+++ b/usrp2/firmware/lib/ad9510.c
@@ -0,0 +1,42 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ad9510.h"
+#include "spi.h"
+#include <memory_map.h>
+
+#define RD (1 << 15)
+#define WR (0 << 15)
+
+void
+ad9510_write_reg(int regno, uint8_t value)
+{
+ uint32_t inst = WR | (regno & 0xff);
+ uint32_t v = (inst << 8) | (value & 0xff);
+ spi_transact(SPI_TXONLY, SPI_SS_AD9510, v, 24, SPIF_PUSH_FALL);
+}
+
+int
+ad9510_read_reg(int regno)
+{
+ uint32_t inst = RD | (regno & 0xff);
+ uint32_t v = (inst << 8) | 0;
+ uint32_t r = spi_transact(SPI_TXRX, SPI_SS_AD9510, v, 24,
+ SPIF_PUSH_FALL | SPIF_LATCH_FALL);
+ return r & 0xff;
+}
diff --git a/usrp2/firmware/lib/ad9510.h b/usrp2/firmware/lib/ad9510.h
new file mode 100644
index 000000000..a395e5223
--- /dev/null
+++ b/usrp2/firmware/lib/ad9510.h
@@ -0,0 +1,30 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef INCLUDED_AD9510_H
+#define INCLUDED_AD9510_H
+
+#include <stdint.h>
+
+/*
+ * Analog Device AD9510 1.2 GHz Clock Distribution IC w/ PLL
+ */
+
+void ad9510_write_reg(int regno, uint8_t value);
+int ad9510_read_reg(int regno);
+
+#endif /* INCLUDED_AD9510_H */
diff --git a/usrp2/firmware/lib/ad9777.c b/usrp2/firmware/lib/ad9777.c
new file mode 100644
index 000000000..734ccd7e5
--- /dev/null
+++ b/usrp2/firmware/lib/ad9777.c
@@ -0,0 +1,47 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ad9777.h"
+#include "memory_map.h"
+#include "spi.h"
+
+#define IB_RD 0x80
+#define IB_WR 0x00
+#define IB_XFER_1 0x00
+#define IB_XFER_2 0x20
+#define IB_XFER_3 0x40
+#define IB_XFER_4 0x60
+#define IB_ADDR_MASK 0x1f
+
+void
+ad9777_write_reg(int regno, uint8_t value)
+{
+ uint8_t instr = IB_WR | IB_XFER_1 | (regno & IB_ADDR_MASK);
+ spi_transact(SPI_TXONLY, SPI_SS_AD9777,
+ (instr << 8) | (value & 0xff), 16, SPIF_PUSH_FALL);
+}
+
+int
+ad9777_read_reg(int regno)
+{
+ uint8_t instr = IB_RD | IB_XFER_1 | (regno & IB_ADDR_MASK);
+ uint32_t r = spi_transact(SPI_TXRX, SPI_SS_AD9777,
+ (instr << 8) | 0, 16,
+ SPIF_PUSH_FALL | SPIF_LATCH_RISE);
+ return r & 0xff;
+}
diff --git a/usrp2/firmware/lib/ad9777.h b/usrp2/firmware/lib/ad9777.h
new file mode 100644
index 000000000..d4d104910
--- /dev/null
+++ b/usrp2/firmware/lib/ad9777.h
@@ -0,0 +1,31 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef INCLUDED_AD9777_H
+#define INCLUDED_AD9777_H
+
+#include <stdint.h>
+#include "ad9777_regs.h"
+
+/*
+ * Analog Devices AD9777 16-bit, 160 MS/s, Dual Interpolating TxDAC
+ */
+
+void ad9777_write_reg(int regno, uint8_t value);
+int ad9777_read_reg(int regno);
+
+#endif /* INCLUDED_AD9777_H */
diff --git a/usrp2/firmware/lib/ad9777_regs.h b/usrp2/firmware/lib/ad9777_regs.h
new file mode 100644
index 000000000..de2936c15
--- /dev/null
+++ b/usrp2/firmware/lib/ad9777_regs.h
@@ -0,0 +1,71 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef INCLUDED_AD9777_REGS_H
+#define INCLUDED_AD9777_REGS_H
+
+#define R0_SW_RESET (1 << 5)
+#define R0_SLEEP (1 << 4)
+#define R0_POWER_DN (1 << 3)
+#define R0_1R (1 << 2)
+#define R0_2R (0 << 2)
+#define R0_PLL_LOCKED (1 << 1)
+
+#define R1_INTERP_1X 0x00
+#define R1_INTERP_2X 0x40
+#define R1_INTERP_4X 0x80
+#define R1_INTERP_8X 0xC0
+#define R1_MOD_NONE 0x00
+#define R1_MOD_FS_2 0x10 // Fs/2
+#define R1_MOD_FS_4 0x20 // Fs/4
+#define R1_MOD_FS_8 0x30 // Fs/8
+#define R1_ZERO_STUFF (1 << 3) // N.B., doubles output rate
+#define R1_REAL_MIX (1 << 2)
+#define R1_CMPLX_MIX (0 << 2)
+#define R1_POS_EXP (1 << 1) // exp(+jwt)
+#define R1_NEG_EXP (0 << 1) // exp(-jwt)
+#define R1_DATACLK_OUT (1 << 0)
+
+#define R2_2S_COMP (0 << 7)
+#define R2_2PORT_MODE (0 << 6)
+#define R2_1PORT_MODE (1 << 6)
+
+#define R3_PLL_DIV_1 0x00
+#define R3_PLL_DIV_2 0x01
+#define R3_PLL_DIV_4 0x02
+#define R3_PLL_DIV_8 0x03
+
+#define R4_PLL_ON (1 << 7)
+#define R4_CP_MANUAL (1 << 6)
+#define R4_CP_AUTO (0 << 6)
+#define R4_CP_50uA (0x00 | R4_CP_MANUAL)
+#define R4_CP_100uA (0x01 | R4_CP_MANUAL)
+#define R4_CP_200uA (0x02 | R4_CP_MANUAL)
+#define R4_CP_400uA (0x03 | R4_CP_MANUAL)
+#define R4_CP_800uA (0x07 | R4_CP_MANUAL)
+
+#define R5_I_FINE_GAIN(g) (g) // 8-bits
+#define R6_I_COARSE_GAIN(g) ((g) & 0xf) // low 4-bits
+
+#define R9_Q_FINE_GAIN(g) (g) // 8-bits
+#define R10_Q_COARSE_GAIN(g) ((g) & 0xf) // low 4-bits
+
+
+// FIXME more registers for offset and gain control...
+
+
+#endif /* INCLUDED_AD9777_REGS_H */
diff --git a/usrp2/firmware/lib/bool.h b/usrp2/firmware/lib/bool.h
new file mode 100644
index 000000000..36f472d40
--- /dev/null
+++ b/usrp2/firmware/lib/bool.h
@@ -0,0 +1,26 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_BOOL_H
+#define INCLUDED_BOOL_H
+
+typedef int bool;
+#define true 1
+#define false 0
+
+#endif /* INCLUDED_BOOL_H */
diff --git a/usrp2/firmware/lib/buffer_pool.c b/usrp2/firmware/lib/buffer_pool.c
new file mode 100644
index 000000000..77e7c5213
--- /dev/null
+++ b/usrp2/firmware/lib/buffer_pool.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "memory_map.h"
+#include "buffer_pool.h"
+#include "hal_io.h"
+
+void
+bp_init(void)
+{
+ int i;
+ bp_disable_port(PORT_SERDES);
+ bp_disable_port(PORT_DSP);
+ bp_disable_port(PORT_ETH);
+ bp_disable_port(PORT_RAM);
+
+ for (i = 0; i < NBUFFERS; i++)
+ bp_clear_buf(i);
+}
+
+#ifndef INLINE_BUFFER_POOL
+
+void
+bp_clear_buf(int bufnum)
+{
+ buffer_pool_ctrl->ctrl = BPC_BUFFER(bufnum) | BPC_PORT_NIL | BPC_CLR;
+}
+
+void
+bp_disable_port(int portnum)
+{
+ // disable buffer connections to this port
+ buffer_pool_ctrl->ctrl = BPC_BUFFER_NIL | BPC_PORT(portnum);
+}
+
+void
+bp_receive_to_buf(int bufnum, int port, int step, int fl, int ll)
+{
+ buffer_pool_ctrl->ctrl = (BPC_READ
+ | BPC_BUFFER(bufnum)
+ | BPC_PORT(port)
+ | BPC_STEP(step)
+ | BPC_FIRST_LINE(fl)
+ | BPC_LAST_LINE(ll));
+}
+
+void
+bp_send_from_buf(int bufnum, int port, int step, int fl, int ll)
+{
+ buffer_pool_ctrl->ctrl = (BPC_WRITE
+ | BPC_BUFFER(bufnum)
+ | BPC_PORT(port)
+ | BPC_STEP(step)
+ | BPC_FIRST_LINE(fl)
+ | BPC_LAST_LINE(ll));
+}
+
+#endif
diff --git a/usrp2/firmware/lib/buffer_pool.h b/usrp2/firmware/lib/buffer_pool.h
new file mode 100644
index 000000000..145b20f8d
--- /dev/null
+++ b/usrp2/firmware/lib/buffer_pool.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_BUFFER_POOL_H
+#define INCLUDED_BUFFER_POOL_H
+
+#include "memory_map.h"
+
+// Buffer Pool Management
+
+
+// define to have common buffer operations inlined
+#define INLINE_BUFFER_POOL 1
+
+void bp_init(void);
+
+#ifndef INLINE_BUFFER_POOL
+
+void bp_clear_buf(int bufnum);
+void bp_disable_port(int portnum);
+void bp_receive_to_buf(int bufnum, int port, int step, int fl, int ll);
+void bp_send_from_buf(int bufnum, int port, int step, int fl, int ll);
+
+#else
+
+static inline void
+bp_clear_buf(int bufnum)
+{
+ buffer_pool_ctrl->ctrl = BPC_BUFFER(bufnum) | BPC_PORT_NIL | BPC_CLR;
+}
+
+static inline void
+bp_disable_port(int portnum)
+{
+ // disable buffer connections to this port
+ buffer_pool_ctrl->ctrl = BPC_BUFFER_NIL | BPC_PORT(portnum);
+}
+
+static inline void
+bp_receive_to_buf(int bufnum, int port, int step, int fl, int ll)
+{
+ buffer_pool_ctrl->ctrl = (BPC_READ
+ | BPC_BUFFER(bufnum)
+ | BPC_PORT(port)
+ | BPC_STEP(step)
+ | BPC_FIRST_LINE(fl)
+ | BPC_LAST_LINE(ll));
+}
+
+static inline void
+bp_send_from_buf(int bufnum, int port, int step, int fl, int ll)
+{
+ buffer_pool_ctrl->ctrl = (BPC_WRITE
+ | BPC_BUFFER(bufnum)
+ | BPC_PORT(port)
+ | BPC_STEP(step)
+ | BPC_FIRST_LINE(fl)
+ | BPC_LAST_LINE(ll));
+}
+#endif
+#endif
diff --git a/usrp2/firmware/lib/clocks.c b/usrp2/firmware/lib/clocks.c
new file mode 100644
index 000000000..bfcaa7347
--- /dev/null
+++ b/usrp2/firmware/lib/clocks.c
@@ -0,0 +1,182 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <clocks.h>
+
+#include "memory_map.h"
+#include "ad9510.h"
+#include "spi.h"
+
+void
+clocks_init(void)
+{
+ // Set up basic clocking functions in AD9510
+ ad9510_write_reg(0x45, 0x00); // CLK2 drives distribution
+ ad9510_write_reg(0x3D, 0x00); // Turn on output 1 (FPGA CLK), normal levels
+ ad9510_write_reg(0x4B, 0x80); // Bypass divider 1
+ ad9510_write_reg(0x5A, 0x01); // Update Regs
+
+ spi_wait();
+
+ // Set up PLL for 10 MHz reference
+ // Reg 4, A counter, Don't Care
+ ad9510_write_reg(0x05, 0x00); // Reg 5, B counter MSBs, 0
+ ad9510_write_reg(0x06, 0x05); // Reg 6, B counter LSBs, 5
+ // Reg 7, Loss of reference detect, doesn't work yet, 0
+ ad9510_write_reg(0x5A, 0x01); // Update Regs
+
+
+ // FIXME, probably need interface to this...
+ timesync_regs->tick_control = 4;
+
+ // Primary clock configuration
+ clocks_mimo_config(MC_WE_DONT_LOCK);
+
+ // Set up other clocks
+
+ clocks_enable_test_clk(false);
+ clocks_enable_tx_dboard(false, 0);
+ clocks_enable_rx_dboard(false, 0);
+
+ // ETH phy clock
+ ad9510_write_reg(0x41, 0x01); // Turn off output 5 (phy_clk)
+ ad9510_write_reg(0x53, 0x80); // Bypass divider
+ ad9510_write_reg(0x5A, 0x01); // Update Regs
+
+ // Enable clock to ADCs and DACs
+ ad9510_write_reg(0x3F, 0x00); // Turn on output 3 (DAC CLK), normal levels
+ ad9510_write_reg(0x4F, 0x80); // Bypass Div #3
+
+ ad9510_write_reg(0x40, 0x02); // Turn on out 4 (ADC clk), LVDS
+ ad9510_write_reg(0x51, 0x80); // Bypass Div #4
+
+ ad9510_write_reg(0x5A, 0x01); // Update Regs
+}
+
+
+void
+clocks_mimo_config(int flags)
+{
+ if (flags & _MC_WE_LOCK){
+ // Reg 8, Charge pump on, dig lock det, positive PFD, 47
+ ad9510_write_reg(0x08, 0x47);
+ }
+ else {
+ // Reg 8, Charge pump off, dig lock det, positive PFD
+ ad9510_write_reg(0x08, 0x00);
+ }
+
+ // Reg 9, Charge pump current, 0x40=3mA, 0x00=650uA
+ ad9510_write_reg(0x09, 0x00);
+ // Reg A, Prescaler of 2, everything normal 04
+ ad9510_write_reg(0x0A, 0x04);
+ // Reg B, R Div MSBs, 0
+ ad9510_write_reg(0x0B, 0x00);
+ // Reg C, R Div LSBs, 1
+ ad9510_write_reg(0x0C, 0x01);
+ // Reg D, Antibacklash, Digital lock det, 0
+
+ ad9510_write_reg(0x5A, 0x01); // Update Regs
+
+ spi_wait();
+
+ // Allow for clock switchover
+
+ if (flags & _MC_WE_LOCK){ // WE LOCK
+ if (flags & _MC_MIMO_CLK_INPUT) {
+ // Turn on ref output and choose the MIMO connector
+ output_regs->clk_ctrl = 0x15;
+ }
+ else {
+ // turn on ref output and choose the SMA
+ output_regs->clk_ctrl = 0x1C;
+ }
+ }
+ else { // WE DONT LOCK
+ // Disable both ext clk inputs
+ output_regs->clk_ctrl = 0x10;
+ }
+
+ // Do we drive a clock onto the MIMO connector?
+
+ if (flags & MC_PROVIDE_CLK_TO_MIMO) {
+ ad9510_write_reg(0x3E, 0x00); // Turn on output 2 (clk_exp_out), normal levels
+ ad9510_write_reg(0x4D, 0x00); // Turn on Div2
+ ad9510_write_reg(0x4C, 0x44); // Set Div2 = 10, output a 10 MHz clock
+ }
+ else {
+ ad9510_write_reg(0x3E, 0x02); // Turn off output 2 (clk_exp_out)
+ ad9510_write_reg(0x4D, 0x80); // Bypass divider 2
+ }
+ ad9510_write_reg(0x5A, 0x01); // Update Regs
+}
+
+void
+clocks_enable_test_clk(bool enable)
+{
+ if (enable){
+ ad9510_write_reg(0x3C, 0x08); // Turn on output 0 -- Test output
+ ad9510_write_reg(0x49, 0x80); // Bypass divider 0
+ }
+ else {
+ ad9510_write_reg(0x3C, 0x02); // Turn off output 0
+ }
+ ad9510_write_reg(0x5A, 0x01); // Update Regs
+}
+
+
+void
+clocks_enable_rx_dboard(bool enable, int divisor)
+{
+ if (enable){
+ ad9510_write_reg(0x43, 0x08); // enable output 7 (db_rx_clk), CMOS
+
+ if (divisor == 0){
+ ad9510_write_reg(0x57, 0x80); // Bypass Div #7, 100 MHz clock
+ }
+ else {
+ // FIXME Matt, do something with divisor...
+ }
+ }
+ else {
+ ad9510_write_reg(0x43, 0x01); // Turn off output 7 (db_rx_clk)
+ }
+ ad9510_write_reg(0x5A, 0x01); // Update Regs
+}
+
+
+void
+clocks_enable_tx_dboard(bool enable, int divisor)
+{
+ if (enable){
+ ad9510_write_reg(0x42, 0x08); // enable output 6 (db_tx_clk), CMOS
+ if (divisor == 0) {
+ ad9510_write_reg(0x55, 0x80); // Bypass Div #6, 100 MHz clock
+ }
+ else {
+ // FIXME Matt, do something with divisor
+ }
+ }
+ else {
+ ad9510_write_reg(0x42, 0x01); // Turn off output 6 (db_tx_clk)
+ }
+ ad9510_write_reg(0x5A, 0x01); // Update Regs
+}
diff --git a/usrp2/firmware/lib/clocks.h b/usrp2/firmware/lib/clocks.h
new file mode 100644
index 000000000..c43cfcb14
--- /dev/null
+++ b/usrp2/firmware/lib/clocks.h
@@ -0,0 +1,63 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_CLOCKS_H
+#define INCLUDED_CLOCKS_H
+
+/*
+ * Routines to configure our multitude of clocks
+ */
+
+#include <bool.h>
+#include <usrp2_mimo_config.h>
+
+
+/*!
+ * One time call to initialize all clocks to a reasonable state. We
+ * come out of here using our free running 100MHz oscilator and not
+ * providing a clock to the MIMO connector (CMC_WE_DONT_LOCK)
+ */
+void clocks_init(void);
+
+
+/*!
+ * \brief MIMO clock configuration.
+ *
+ * Configure our master clock source, and whether or not we drive a
+ * clock onto the mimo connector. See MC_flags in usrp2_mimo_config.h.
+ */
+void clocks_mimo_config(int flags);
+
+/*!
+ * \brief Enable or disable test clock (extra clock signal)
+ */
+void clocks_enable_test_clk(bool enable);
+
+/*!
+ * \brief Enable or disable clock to Rx daughterboard
+ */
+void clocks_enable_rx_dboard(bool enable, int divisor);
+
+
+/*!
+ * \brief Enable or disable clock to Tx daughterboard
+ */
+void clocks_enable_tx_dboard(bool enable, int divisor);
+
+
+#endif /* INCLUDED_CLOCKS_H */
diff --git a/usrp2/firmware/lib/db.h b/usrp2/firmware/lib/db.h
new file mode 100644
index 000000000..5828fb00d
--- /dev/null
+++ b/usrp2/firmware/lib/db.h
@@ -0,0 +1,94 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Interface to daughterboard code
+ */
+
+#ifndef INCLUDED_DB_H
+#define INCLUDED_DB_H
+
+#include <usrp2_types.h>
+
+
+struct db_base;
+
+/* pointers to daughterboard structures */
+extern struct db_base *tx_dboard;
+extern struct db_base *rx_dboard;
+
+
+//! Intermediate tuning information
+
+struct tune_result
+{
+ //! The RF frequency that corresponds to DC in the IF from the daughterboard
+ u2_fxpt_freq_t baseband_freq;
+
+ //! The DDC/DUC frequency used to down/up convert to/from the target frequency
+ u2_fxpt_freq_t dxc_freq;
+
+ //! Any differerence btwn target and actual (typically < 0.01 Hz)
+ u2_fxpt_freq_t residual_freq;
+
+ //! Is the complex baseband spectrum inverted
+ bool inverted;
+};
+
+
+/*!
+ * \brief One-time init at powerup
+ *
+ * Sets rx_dboard, tx_dboard and initializes daughterboards.
+ */
+void
+db_init(void);
+
+/*!
+ * \brief Two stage tuning. Given target_freq, tune LO and DDC/DUC
+ *
+ * \param[in] db is the daughterboard instance
+ * \param[in] target_freq is the freq to translate the complex baseband to/from.
+ * \param[out] result provides details of the resulting configuration.
+ *
+ */
+bool
+db_tune(struct db_base *db, u2_fxpt_freq_t target_freq, struct tune_result *result);
+
+
+/*
+ * Set only the DDC frequency
+ */
+bool
+db_set_ddc_freq(u2_fxpt_freq_t dxc_freq, u2_fxpt_freq_t *actual_dxc_freq);
+
+/*
+ * Set only the DUC frequency
+ */
+bool
+db_set_duc_freq(u2_fxpt_freq_t dxc_freq, u2_fxpt_freq_t *actual_dxc_freq);
+
+
+/*!
+ * \brief Set gain
+ */
+bool
+db_set_gain(struct db_base *db, u2_fxpt_gain_t gain);
+
+
+#endif /* INCLUDED_DB_H */
diff --git a/usrp2/firmware/lib/db_base.h b/usrp2/firmware/lib/db_base.h
new file mode 100644
index 000000000..9b5ce051f
--- /dev/null
+++ b/usrp2/firmware/lib/db_base.h
@@ -0,0 +1,68 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_DB_BASE_H
+#define INCLUDED_DB_BASE_H
+
+#include <usrp2_types.h>
+#include <bool.h>
+
+/*!
+ * \brief "base class" for firmware version of daughterboard code
+ */
+struct db_base {
+ uint16_t dbid; //< daughterboard ID
+
+ uint16_t is_tx : 1; //< is this a transmit db?
+ uint16_t is_quadrature : 1;
+ uint16_t i_and_q_swapped : 1;
+ uint16_t spectrum_inverted : 1;
+
+ uint16_t output_enables; //< bitmask of which pins should be outputs from FPGA
+ uint16_t used_pins; //< bitmask of pins used by the daughterboard
+
+ u2_fxpt_freq_t freq_min; //< min freq that can be set (Hz)
+ u2_fxpt_freq_t freq_max; //< max freq that can be set (Hz)
+
+ u2_fxpt_gain_t gain_min; //< min gain that can be set (dB)
+ u2_fxpt_gain_t gain_max; //< max gain that can be set (dB)
+ u2_fxpt_gain_t gain_step_size; //< (dB)
+
+ // u2_fxpt_freq_t lo_offset;
+
+ /*
+ * Auto T/R control values
+ */
+ uint32_t atr_mask; //< which bits to control
+ uint32_t atr_txval; //< value to use when transmitting
+ uint32_t atr_rxval; //< value to use when receiving
+
+ //! delay in clk ticks from when Tx fifo gets data to when T/R switches
+ // uint32_t atr_tx_delay;
+
+ //! delay in clk ticks from when Tx fifo goes empty to when T/R switches
+ // uint32_t atr_rx_delay;
+
+ bool (*init)(struct db_base *);
+ bool (*set_freq)(struct db_base *, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc);
+ bool (*set_gain)(struct db_base *, u2_fxpt_gain_t gain);
+ bool (*set_tx_enable)(struct db_base *, bool on);
+};
+
+
+#endif /* INCLUDED_DB_BASE_H */
diff --git a/usrp2/firmware/lib/db_basic.c b/usrp2/firmware/lib/db_basic.c
new file mode 100644
index 000000000..0f1ad6504
--- /dev/null
+++ b/usrp2/firmware/lib/db_basic.c
@@ -0,0 +1,161 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <db_base.h>
+
+bool db_basic_init(struct db_base *db);
+bool db_basic_set_freq(struct db_base *db, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc);
+bool db_basic_set_gain(struct db_base *db, u2_fxpt_gain_t gain);
+bool db_basic_set_tx_enable(struct db_base *, bool on);
+
+struct db_basic {
+ struct db_base base;
+};
+
+
+struct db_basic db_basic_tx = {
+ .base.dbid = 0x0000,
+ .base.is_tx = true,
+ .base.output_enables = 0x0000,
+ .base.used_pins = 0x0000,
+ .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(-90e9),
+ .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(90e9),
+ .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
+ .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(0),
+ .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0),
+ .base.is_quadrature = true,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(0),
+ .base.atr_mask = 0,
+ .base.atr_txval = 0,
+ .base.atr_rxval = 0,
+ //.base.atr_tx_delay = 0,
+ //.base.atr_rx_delay = 0,
+
+ .base.init = db_basic_init,
+ .base.set_freq = db_basic_set_freq,
+ .base.set_gain = db_basic_set_gain,
+ .base.set_tx_enable = db_basic_set_tx_enable,
+};
+
+struct db_basic db_basic_rx = {
+ .base.dbid = 0x0001,
+ .base.is_tx = false,
+ .base.output_enables = 0x0000,
+ .base.used_pins = 0x0000,
+ .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(-90e9),
+ .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(90e9),
+ .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
+ .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(0),
+ .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0),
+ .base.is_quadrature = false,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(0),
+ .base.atr_mask = 0,
+ .base.atr_txval = 0,
+ .base.atr_rxval = 0,
+ //.base.atr_tx_delay = 0,
+ //.base.atr_rx_delay = 0,
+
+ .base.init = db_basic_init,
+ .base.set_freq = db_basic_set_freq,
+ .base.set_gain = db_basic_set_gain,
+ .base.set_tx_enable = db_basic_set_tx_enable,
+};
+
+struct db_basic db_lf_tx = {
+ .base.dbid = 0x000e,
+ .base.is_tx = true,
+ .base.output_enables = 0x0000,
+ .base.used_pins = 0x0000,
+ .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(-32e6),
+ .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(32e6),
+ .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
+ .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(0),
+ .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0),
+ .base.is_quadrature = true,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(0),
+ .base.atr_mask = 0,
+ .base.atr_txval = 0,
+ .base.atr_rxval = 0,
+ //.base.atr_tx_delay = 0,
+ //.base.atr_rx_delay = 0,
+
+ .base.init = db_basic_init,
+ .base.set_freq = db_basic_set_freq,
+ .base.set_gain = db_basic_set_gain,
+ .base.set_tx_enable = db_basic_set_tx_enable,
+};
+
+struct db_basic db_lf_rx = {
+ .base.dbid = 0x000f,
+ .base.is_tx = false,
+ .base.output_enables = 0x0000,
+ .base.used_pins = 0x0000,
+ .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(0),
+ .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(32e6),
+ .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
+ .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(0),
+ .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0),
+ .base.is_quadrature = false,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(0),
+ .base.atr_mask = 0,
+ .base.atr_txval = 0,
+ .base.atr_rxval = 0,
+ //.base.atr_tx_delay = 0,
+ //.base.atr_rx_delay = 0,
+
+ .base.init = db_basic_init,
+ .base.set_freq = db_basic_set_freq,
+ .base.set_gain = db_basic_set_gain,
+ .base.set_tx_enable = db_basic_set_tx_enable,
+};
+
+
+bool
+db_basic_init(struct db_base *db)
+{
+ return true;
+}
+
+bool
+db_basic_set_freq(struct db_base *db, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc)
+{
+ *dc = 0;
+ return true;
+}
+
+bool
+db_basic_set_gain(struct db_base *db, u2_fxpt_gain_t gain)
+{
+ return true;
+}
+
+bool
+db_basic_set_tx_enable(struct db_base *db, bool on)
+{
+ return true;
+}
+
diff --git a/usrp2/firmware/lib/db_init.c b/usrp2/firmware/lib/db_init.c
new file mode 100644
index 000000000..d47beb11d
--- /dev/null
+++ b/usrp2/firmware/lib/db_init.c
@@ -0,0 +1,340 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <memory_map.h>
+#include <i2c.h>
+#include <usrp2_i2c_addr.h>
+#include <string.h>
+#include <stdio.h>
+#include <db.h>
+#include <db_base.h>
+#include <hal_io.h>
+#include <nonstdio.h>
+
+
+struct db_base *tx_dboard; // the tx daughterboard that's installed
+struct db_base *rx_dboard; // the rx daughterboard that's installed
+
+extern struct db_base db_basic_tx;
+extern struct db_base db_basic_rx;
+extern struct db_base db_lf_tx;
+extern struct db_base db_lf_rx;
+extern struct db_base db_rfx_400_tx;
+extern struct db_base db_rfx_400_rx;
+extern struct db_base db_tvrx1;
+extern struct db_base db_tvrx2;
+extern struct db_base db_tvrx3;
+
+struct db_base *all_dboards[] = {
+ &db_basic_tx,
+ &db_basic_rx,
+ &db_lf_tx,
+ &db_lf_rx,
+ &db_rfx_400_tx,
+ &db_rfx_400_rx,
+ &db_tvrx1,
+ &db_tvrx2,
+ &db_tvrx3,
+ 0
+};
+
+
+typedef enum { UDBE_OK, UDBE_NO_EEPROM, UDBE_INVALID_EEPROM } usrp_dbeeprom_status_t;
+
+static usrp_dbeeprom_status_t
+read_raw_dboard_eeprom (unsigned char *buf, int i2c_addr)
+{
+ if (!eeprom_read (i2c_addr, 0, buf, DB_EEPROM_CLEN))
+ return UDBE_NO_EEPROM;
+
+ if (buf[DB_EEPROM_MAGIC] != DB_EEPROM_MAGIC_VALUE)
+ return UDBE_INVALID_EEPROM;
+
+ int sum = 0;
+ unsigned int i;
+ for (i = 0; i < DB_EEPROM_CLEN; i++)
+ sum += buf[i];
+
+ if ((sum & 0xff) != 0)
+ return UDBE_INVALID_EEPROM;
+
+ return UDBE_OK;
+}
+
+
+/*
+ * Return DBID, -1 <none> or -2 <invalid eeprom contents>
+ */
+static int
+read_dboard_eeprom(int i2c_addr)
+{
+ unsigned char buf[DB_EEPROM_CLEN];
+
+ usrp_dbeeprom_status_t s = read_raw_dboard_eeprom (buf, i2c_addr);
+
+ //printf("\nread_raw_dboard_eeprom: %d\n", s);
+
+ switch (s){
+ case UDBE_OK:
+ return (buf[DB_EEPROM_ID_MSB] << 8) | buf[DB_EEPROM_ID_LSB];
+
+ case UDBE_NO_EEPROM:
+ default:
+ return -1;
+
+ case UDBE_INVALID_EEPROM:
+ return -2;
+ }
+}
+
+
+static struct db_base *
+lookup_dbid(int dbid)
+{
+ if (dbid < 0)
+ return 0;
+
+ int i;
+ for (i = 0; all_dboards[i]; i++)
+ if (all_dboards[i]->dbid == dbid)
+ return all_dboards[i];
+
+ return 0;
+}
+
+static struct db_base *
+lookup_dboard(int i2c_addr, struct db_base *default_db, char *msg)
+{
+ struct db_base *db;
+ int dbid = read_dboard_eeprom(i2c_addr);
+ printf("%s dbid: 0x%x\n", msg, dbid);
+
+ if (dbid < 0){ // there was some kind of problem. Treat as Basic Tx
+ return default_db;
+ }
+ else if ((db = lookup_dbid(dbid)) == 0){
+ return default_db;
+ printf("No daugherboard code for dbid = 0x%x\n", dbid);
+ }
+ return db;
+}
+
+static void
+set_atr_regs(int bank, struct db_base *db)
+{
+ uint32_t val[4];
+ int shift;
+ int mask;
+ int i;
+
+ val[ATR_IDLE] = db->atr_rxval;
+ val[ATR_RX] = db->atr_rxval;
+ val[ATR_TX] = db->atr_txval;
+ val[ATR_FULL] = db->atr_txval;
+
+ if (bank == GPIO_TX_BANK){
+ mask = 0xffff0000;
+ shift = 16;
+ }
+ else {
+ mask = 0x0000ffff;
+ shift = 0;
+ }
+
+ for (i = 0; i < 4; i++){
+ int t = (atr_regs->v[i] & ~mask) | ((val[i] << shift) & mask);
+ //printf("atr_regs[%d] = 0x%x\n", i, t);
+ atr_regs->v[i] = t;
+ }
+}
+
+static void
+set_gpio_mode(int bank, struct db_base *db)
+{
+ int i;
+
+ hal_gpio_set_ddr(bank, db->output_enables, 0xffff);
+ set_atr_regs(bank, db);
+
+ for (i = 0; i < 16; i++){
+ if (db->used_pins & (1 << i)){
+ // set to either GPIO_SEL_SW or GPIO_SEL_ATR
+ hal_gpio_set_sel(bank, i, (db->atr_mask & (1 << i)) ? 'a' : 's');
+ }
+ }
+}
+
+void
+db_init(void)
+{
+
+ tx_dboard = lookup_dboard(I2C_ADDR_TX_A, &db_basic_tx, "Tx");
+ //printf("db_init: tx dbid = 0x%x\n", tx_dboard->dbid);
+ set_gpio_mode(GPIO_TX_BANK, tx_dboard);
+ tx_dboard->init(tx_dboard);
+
+ rx_dboard = lookup_dboard(I2C_ADDR_RX_A, &db_basic_rx, "Rx");
+ //printf("db_init: rx dbid = 0x%x\n", rx_dboard->dbid);
+ set_gpio_mode(GPIO_RX_BANK, rx_dboard);
+ rx_dboard->init(rx_dboard);
+}
+
+/*!
+ * Calculate the frequency to use for setting the digital down converter.
+ *
+ * \param[in] target_freq desired RF frequency (Hz)
+ * \param[in] baseband_freq the RF frequency that corresponds to DC in the IF.
+ *
+ * \param[out] dxc_freq is the value for the ddc
+ * \param[out] inverted is true if we're operating in an inverted Nyquist zone.
+*/
+void
+calc_dxc_freq(u2_fxpt_freq_t target_freq, u2_fxpt_freq_t baseband_freq,
+ u2_fxpt_freq_t *dxc_freq, bool *inverted)
+{
+ u2_fxpt_freq_t fs = U2_DOUBLE_TO_FXPT_FREQ(100e6); // converter sample rate
+ u2_fxpt_freq_t delta = target_freq - baseband_freq;
+
+ printf("calc_dxc_freq\n");
+ printf(" fs = "); print_fxpt_freq(fs); newline();
+ printf(" target = "); print_fxpt_freq(target_freq); newline();
+ printf(" baseband = "); print_fxpt_freq(baseband_freq); newline();
+ printf(" delta = "); print_fxpt_freq(delta); newline();
+
+#if 0
+ printf("--- printed as uint64_t ---\n");
+ printf(" fs = "); print_uint64(fs); newline();
+ printf(" target = "); print_uint64(target_freq); newline();
+ printf(" baseband = "); print_uint64(baseband_freq); newline();
+ printf(" delta = "); print_uint64(delta); newline();
+#endif
+
+ if (delta >= 0){
+ while (delta > fs)
+ delta -= fs;
+ if (delta <= fs/2){ // non-inverted region
+ *dxc_freq = -delta;
+ *inverted = false;
+ }
+ else { // inverted region
+ *dxc_freq = delta - fs;
+ *inverted = true;
+ }
+ }
+ else {
+ while (delta < -fs){
+ delta += fs;
+ if (delta >= -fs/2){ // non-inverted region
+ *dxc_freq = -delta;
+ *inverted = false;
+ }
+ else { // inverted region
+ *dxc_freq = delta + fs;
+ *inverted = true;
+ }
+ }
+ }
+}
+
+
+bool
+db_tune(struct db_base *db, u2_fxpt_freq_t target_freq, struct tune_result *result)
+{
+ memset(result, 0, sizeof(*result));
+ bool inverted = false;
+ u2_fxpt_freq_t dxc_freq;
+ u2_fxpt_freq_t actual_dxc_freq;
+
+ // Ask the d'board to tune as closely as it can to target_freq
+ bool ok = db->set_freq(db, target_freq, &result->baseband_freq);
+
+ // Calculate the DDC setting that will downconvert the baseband from the
+ // daughterboard to our target frequency.
+ calc_dxc_freq(target_freq, result->baseband_freq, &dxc_freq, &inverted);
+
+ // If the spectrum is inverted, and the daughterboard doesn't do
+ // quadrature downconversion, we can fix the inversion by flipping the
+ // sign of the dxc_freq... (This only happens using the basic_rx board)
+
+ if (db->spectrum_inverted)
+ inverted = !inverted;
+
+ if (inverted && !db->is_quadrature){
+ dxc_freq = -dxc_freq;
+ inverted = !inverted;
+ }
+
+ if (db->is_tx){
+ dxc_freq = -dxc_freq; // down conversion versus up conversion
+ ok &= db_set_duc_freq(dxc_freq, &actual_dxc_freq);
+ }
+ else {
+ ok &= db_set_ddc_freq(dxc_freq, &actual_dxc_freq);
+ }
+
+ result->dxc_freq = dxc_freq;
+ result->residual_freq = dxc_freq - actual_dxc_freq;
+ result->inverted = inverted;
+ return ok;
+}
+
+static int32_t
+compute_freq_control_word(u2_fxpt_freq_t target_freq, u2_fxpt_freq_t *actual_freq)
+{
+ // If we were using floating point, we'd calculate
+ // master = 100e6;
+ // v = (int) rint(target_freq / master_freq) * pow(2.0, 32.0);
+
+ printf("compute_freq_control_word\n");
+ printf(" target_freq = "); print_fxpt_freq(target_freq); newline();
+
+ int32_t master_freq = 100000000; // 100M
+
+ int32_t v = ((target_freq << 12)) / master_freq;
+ printf(" fcw = %d\n", v);
+
+ *actual_freq = (v * (int64_t) master_freq) >> 12;
+
+ printf(" actual = "); print_fxpt_freq(*actual_freq); newline();
+
+ return v;
+}
+
+
+bool
+db_set_ddc_freq(u2_fxpt_freq_t dxc_freq, u2_fxpt_freq_t *actual_dxc_freq)
+{
+ int32_t v = compute_freq_control_word(dxc_freq, actual_dxc_freq);
+ dsp_rx_regs->freq = v;
+ return true;
+}
+
+bool
+db_set_duc_freq(u2_fxpt_freq_t dxc_freq, u2_fxpt_freq_t *actual_dxc_freq)
+{
+ int32_t v = compute_freq_control_word(dxc_freq, actual_dxc_freq);
+ dsp_tx_regs->freq = v;
+ return true;
+}
+
+bool
+db_set_gain(struct db_base *db, u2_fxpt_gain_t gain)
+{
+ return db->set_gain(db, gain);
+}
diff --git a/usrp2/firmware/lib/db_rfx.c b/usrp2/firmware/lib/db_rfx.c
new file mode 100644
index 000000000..d56112929
--- /dev/null
+++ b/usrp2/firmware/lib/db_rfx.c
@@ -0,0 +1,609 @@
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <spi.h>
+#include <memory_map.h>
+#include <db_base.h>
+#include <hal_io.h>
+#include <ad9510.h>
+#include <stdio.h>
+#include <mdelay.h>
+#include <lsdac.h>
+#include <clocks.h>
+
+
+bool rfx_init_rx(struct db_base *db);
+bool rfx_init_tx(struct db_base *db);
+bool rfx_set_freq(struct db_base *db, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc);
+bool rfx_set_gain_rx(struct db_base *db, u2_fxpt_gain_t gain);
+bool rfx_set_gain_tx(struct db_base *db, u2_fxpt_gain_t gain);
+bool rfx_set_tx_enable(struct db_base *, bool on);
+
+// Control Latch Defines
+#define P 0 // Prescalar value for setting in regs, must match the next line...
+#define PRESCALER 8 // Presacalar value for computations
+#define PD 0 // Power down, 0 = normal operation
+#define PL 0 // PLL power output
+#define MTLD 1 // Mute till lock detect
+#define CPGAIN 0 // Charge pump gain, use setting 1, also in N-reg
+#define CP3S 0 // Charge pump tri-state, 0 = normal operation
+#define PDP 1 // Phase detector polarity
+#define MUXOUT 1 // Digital lock detect, active high
+#define CR 0 // normal operation
+#define PC 1 // core power
+
+// N Latch Defines
+#define DIVSEL 0 // N Counter always operates on full rate
+#define N_RSV 0
+
+// R Latch Defines
+#define R_RSV 0
+#define R_BSC 3
+#define R_TMB 0
+#define R_LDP 1
+#define R_ABP 0
+#define R_DIV 16
+
+#define phdet_freq (U2_DOUBLE_TO_FXPT_FREQ(100e6/R_DIV))
+
+// IO Pin functions
+#define POWER_UP (1 << 7) // Low enables power supply
+#define ANT_SW (1 << 6) // On TX DB, 0 = TX, 1 = RX, on RX DB 0 = main ant, 1 = RX2
+#define MIX_EN (1 << 5) // Enable appropriate mixer
+#define LOCKDET_MASK (1 << 2) // Input pin
+
+struct db_rfx_common {
+ // RFX common stuff
+ unsigned char DIV2;
+ unsigned char CP1;
+ unsigned char CP2;
+ int freq_mult;
+ int spi_mask;
+};
+
+struct db_rfx_dummy {
+ struct db_base base;
+ struct db_rfx_common common;
+};
+
+
+struct db_rfx_400_rx {
+ struct db_base base;
+ struct db_rfx_common common;
+};
+
+struct db_rfx_400_tx {
+ struct db_base base;
+ struct db_rfx_common common;
+};
+
+struct db_rfx_900_rx {
+ struct db_base base;
+ struct db_rfx_common common;
+};
+
+struct db_rfx_900_tx {
+ struct db_base base;
+ struct db_rfx_common common;
+};
+
+struct db_rfx_1200_rx {
+ struct db_base base;
+ struct db_rfx_common common;
+};
+
+struct db_rfx_1200_tx {
+ struct db_base base;
+ struct db_rfx_common common;
+};
+
+struct db_rfx_1800_rx {
+ struct db_base base;
+ struct db_rfx_common common;
+};
+
+struct db_rfx_1800_tx {
+ struct db_base base;
+ struct db_rfx_common common;
+};
+
+struct db_rfx_2400_rx {
+ struct db_base base;
+ struct db_rfx_common common;
+};
+
+struct db_rfx_2400_tx {
+ struct db_base base;
+ struct db_rfx_common common;
+};
+
+
+/*
+ * The class instances
+ */
+struct db_rfx_400_rx db_rfx_400_rx = {
+ .base.dbid = 0x0024,
+ .base.is_tx = false,
+ .base.output_enables = 0x00E0,
+ .base.used_pins = 0x00FF,
+ //.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = true,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = rfx_init_rx,
+ .base.set_freq = rfx_set_freq,
+ .base.set_gain = rfx_set_gain_rx,
+ .base.set_tx_enable = 0,
+ .base.atr_mask = 0x00E0,
+ .base.atr_txval = POWER_UP,
+ .base.atr_rxval = POWER_UP|MIX_EN,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.DIV2 = 0,
+ .common.CP1 = 7,
+ .common.CP2 = 7,
+ .common.spi_mask = SPI_SS_RX_DB,
+ .common.freq_mult = 2
+};
+
+
+struct db_rfx_400_tx db_rfx_400_tx = {
+ .base.dbid = 0x0028,
+ .base.is_tx = true,
+ .base.output_enables = 0x00E0,
+ .base.used_pins = 0x00FF,
+ //.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = true,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = rfx_init_tx,
+ .base.set_freq = rfx_set_freq,
+ .base.set_gain = rfx_set_gain_tx,
+ .base.set_tx_enable = rfx_set_tx_enable,
+ .base.atr_mask = 0x00E0,
+ .base.atr_txval = POWER_UP|MIX_EN,
+ .base.atr_rxval = POWER_UP|ANT_SW,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.DIV2 = 1,
+ .common.CP1 = 7,
+ .common.CP2 = 7,
+ .common.spi_mask = SPI_SS_TX_DB,
+ .common.freq_mult = 2
+};
+
+struct db_rfx_900_rx db_rfx_900_rx = {
+ .base.dbid = 0x0025,
+ .base.is_tx = false,
+ .base.output_enables = 0x00E0,
+ .base.used_pins = 0x00FF,
+ //.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = true,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = rfx_init_rx,
+ .base.set_freq = rfx_set_freq,
+ .base.set_gain = rfx_set_gain_rx,
+ .base.set_tx_enable = 0,
+ .base.atr_mask = 0x00E0,
+ .base.atr_txval = 0,
+ .base.atr_rxval = MIX_EN,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.DIV2 = 1,
+ .common.CP1 = 7,
+ .common.CP2 = 7,
+ .common.spi_mask = SPI_SS_RX_DB,
+ .common.freq_mult = 2
+};
+
+
+struct db_rfx_900_tx db_rfx_900_tx = {
+ .base.dbid = 0x0029,
+ .base.is_tx = true,
+ .base.output_enables = 0x00E0,
+ .base.used_pins = 0x00FF,
+ //.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = true,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = rfx_init_tx,
+ .base.set_freq = rfx_set_freq,
+ .base.set_gain = rfx_set_gain_tx,
+ .base.set_tx_enable = rfx_set_tx_enable,
+ .base.atr_mask = 0x00E0,
+ .base.atr_txval = MIX_EN,
+ .base.atr_rxval = ANT_SW,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.DIV2 = 1,
+ .common.CP1 = 7,
+ .common.CP2 = 7,
+ .common.spi_mask = SPI_SS_TX_DB,
+ .common.freq_mult = 2
+};
+
+struct db_rfx_1200_rx db_rfx_1200_rx = {
+ .base.dbid = 0x0026,
+ .base.is_tx = false,
+ .base.output_enables = 0x00E0,
+ .base.used_pins = 0x00FF,
+ //.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = true,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = rfx_init_rx,
+ .base.set_freq = rfx_set_freq,
+ .base.set_gain = rfx_set_gain_rx,
+ .base.set_tx_enable = 0,
+ .base.atr_mask = 0x00E0,
+ .base.atr_txval = 0,
+ .base.atr_rxval = MIX_EN,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.DIV2 = 1,
+ .common.CP1 = 7,
+ .common.CP2 = 7,
+ .common.spi_mask = SPI_SS_RX_DB,
+ .common.freq_mult = 2
+};
+
+
+struct db_rfx_1200_tx db_rfx_1200_tx = {
+ .base.dbid = 0x002a,
+ .base.is_tx = true,
+ .base.output_enables = 0x00E0,
+ .base.used_pins = 0x00FF,
+ //.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = true,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = rfx_init_tx,
+ .base.set_freq = rfx_set_freq,
+ .base.set_gain = rfx_set_gain_tx,
+ .base.set_tx_enable = rfx_set_tx_enable,
+ .base.atr_mask = 0x00E0,
+ .base.atr_txval = MIX_EN,
+ .base.atr_rxval = ANT_SW,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.DIV2 = 1,
+ .common.CP1 = 7,
+ .common.CP2 = 7,
+ .common.spi_mask = SPI_SS_TX_DB,
+ .common.freq_mult = 2
+};
+
+struct db_rfx_1800_rx db_rfx_1800_rx = {
+ .base.dbid = 0x0034,
+ .base.is_tx = false,
+ .base.output_enables = 0x00E0,
+ .base.used_pins = 0x00FF,
+ //.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = true,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = rfx_init_rx,
+ .base.set_freq = rfx_set_freq,
+ .base.set_gain = rfx_set_gain_rx,
+ .base.set_tx_enable = 0,
+ .base.atr_mask = 0x00E0,
+ .base.atr_txval = 0,
+ .base.atr_rxval = MIX_EN,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.DIV2 = 0,
+ .common.CP1 = 7,
+ .common.CP2 = 7,
+ .common.spi_mask = SPI_SS_RX_DB,
+ .common.freq_mult = 1
+};
+
+
+struct db_rfx_1800_tx db_rfx_1800_tx = {
+ .base.dbid = 0x0035,
+ .base.is_tx = true,
+ .base.output_enables = 0x00E0,
+ .base.used_pins = 0x00FF,
+ //.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = true,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = rfx_init_tx,
+ .base.set_freq = rfx_set_freq,
+ .base.set_gain = rfx_set_gain_tx,
+ .base.set_tx_enable = rfx_set_tx_enable,
+ .base.atr_mask = 0x00E0,
+ .base.atr_txval = MIX_EN,
+ .base.atr_rxval = ANT_SW,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.DIV2 = 0,
+ .common.CP1 = 7,
+ .common.CP2 = 7,
+ .common.spi_mask = SPI_SS_TX_DB,
+ .common.freq_mult = 1
+};
+
+
+struct db_rfx_2400_rx db_rfx_2400_rx = {
+ .base.dbid = 0x0027,
+ .base.is_tx = false,
+ .base.output_enables = 0x00E0,
+ .base.used_pins = 0x00FF,
+ //.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = true,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = rfx_init_rx,
+ .base.set_freq = rfx_set_freq,
+ .base.set_gain = rfx_set_gain_rx,
+ .base.set_tx_enable = 0,
+ .base.atr_mask = 0x00E0,
+ .base.atr_txval = 0,
+ .base.atr_rxval = MIX_EN,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.DIV2 = 0,
+ .common.CP1 = 7,
+ .common.CP2 = 7,
+ .common.spi_mask = SPI_SS_RX_DB,
+ .common.freq_mult = 1
+};
+
+
+struct db_rfx_2400_tx db_rfx_2400_tx = {
+ .base.dbid = 0x002b,
+ .base.is_tx = true,
+ .base.output_enables = 0x00E0,
+ .base.used_pins = 0x00FF,
+ //.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = true,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = rfx_init_tx,
+ .base.set_freq = rfx_set_freq,
+ .base.set_gain = rfx_set_gain_tx,
+ .base.set_tx_enable = rfx_set_tx_enable,
+ .base.atr_mask = 0x00E0,
+ .base.atr_txval = MIX_EN,
+ .base.atr_rxval = ANT_SW,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.DIV2 = 0,
+ .common.CP1 = 7,
+ .common.CP2 = 7,
+ .common.spi_mask = SPI_SS_TX_DB,
+ .common.freq_mult = 1
+};
+
+
+bool
+rfx_init_tx(struct db_base *dbb)
+{
+ //struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
+ clocks_enable_tx_dboard(true, 0);
+ return true;
+}
+
+bool
+rfx_init_rx(struct db_base *dbb)
+{
+ //struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
+ clocks_enable_rx_dboard(true, 0);
+
+ // test gain
+ dbb->set_gain(dbb,U2_DOUBLE_TO_FXPT_GAIN(45.0));
+ printf("set the gain\n");
+ return true;
+}
+
+bool
+rfx_set_freq(struct db_base *dbb, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc)
+{
+ *dc = 0;
+ struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
+ //u2_fxpt_freq_t desired_n = db->common.freq_mult*freq/phdet_freq;
+ //int N_DIV = u2_fxpt_freq_round_to_int(desired_n);
+ u2_fxpt_freq_t desired_n = ((1LL<<20) * db->common.freq_mult*freq)/phdet_freq;
+ int N_DIV = u2_fxpt_freq_round_to_int(desired_n);
+ int B = N_DIV/PRESCALER;
+ int A = N_DIV - PRESCALER*B;
+
+ if(B<A)
+ return false;
+
+ int R = (R_RSV<<22)|(R_BSC<<20)|(R_TMB<<19)|(R_LDP<<18)|(R_ABP<<16)|(R_DIV<<2)|1;
+ int N = (DIVSEL<<23)|(db->common.DIV2<<22)|(CPGAIN<<21)|(B<<8)|(N_RSV<<7)|(A<<2)|2;
+ int C = (P<<22)|(PD<<20)|(db->common.CP2<<17)|(db->common.CP1<<14)|(PL<<12)|
+ (MTLD<<11)|(CPGAIN<<10)|(CP3S<<9)|(PDP<<8)|(MUXOUT<<5)|(CR<<4)|(PC<<2)|0;
+
+ spi_transact(SPI_TXONLY,db->common.spi_mask,R,24,SPIF_PUSH_FALL);
+ spi_transact(SPI_TXONLY,db->common.spi_mask,C,24,SPIF_PUSH_FALL);
+ mdelay(10);
+ spi_transact(SPI_TXONLY,db->common.spi_mask,N,24,SPIF_PUSH_FALL);
+
+ printf("A = %d, B = %d, N_DIV = %d\n",A, B, N_DIV);
+ *dc = (N_DIV * phdet_freq) / db->common.freq_mult;
+ return true;
+}
+
+bool
+rfx_set_gain_tx(struct db_base *dbb, u2_fxpt_gain_t gain)
+{
+ // There is no analog gain control on TX
+ return true;
+}
+
+bool
+rfx_set_gain_rx(struct db_base *dbb, u2_fxpt_gain_t gain)
+{
+ struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
+
+ u2_fxpt_gain_t MAXGAIN = U2_DOUBLE_TO_FXPT_GAIN(70.0);
+
+ int offset_q8 = (int)(1.2/3.3*4096*(1<<15));
+ int slope_q8 = (int)(-1.0/45.0*4096/3.3*256);
+ int dacword = ((slope_q8 * gain) + offset_q8)>>15;
+ printf("DACWORD %d\n",dacword);
+ lsdac_write_rx(1,dacword);
+ return true;
+ /*
+ def set_gain(self, gain):
+ """
+ Set the gain.
+
+ @param gain: gain in decibels
+ @returns True/False
+ """
+ maxgain = self.gain_range()[1] - self._u.pga_max()
+ mingain = self.gain_range()[0]
+ if gain > maxgain:
+ pga_gain = gain-maxgain
+ assert pga_gain <= self._u.pga_max()
+ agc_gain = maxgain
+ else:
+ pga_gain = 0
+ agc_gain = gain
+ V_maxgain = .2
+ V_mingain = 1.2
+ V_fullscale = 3.3
+ dac_value = (agc_gain*(V_maxgain-V_mingain)/(maxgain-mingain) + V_mingain)*4096/V_fullscale
+ assert dac_value>=0 and dac_value<4096
+ return self._u.write_aux_dac(self._which, 0, int(dac_value)) and \
+ self._set_pga(int(pga_gain))
+
+ def gain_range(self):
+ return (self._u.pga_min(), self._u.pga_max() + 70, 0.05) -- For 900-2400
+ return (self._u.pga_min(), self._u.pga_max() + 45, 0.035) -- For 400
+ */
+}
+
+
+bool
+rfx_set_tx_enable(struct db_base *dbb, bool on)
+{
+ struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
+
+ // FIXME
+
+ return false;
+}
+
+bool
+rfx_lock_detect(struct db_base *dbb)
+{
+ struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
+ int pins;
+ pins = hal_gpio_read( db->base.is_tx ? GPIO_TX_BANK : GPIO_RX_BANK );
+ if(pins & LOCKDET_MASK)
+ return true;
+ return false;
+}
+
+/*
+ def select_rx_antenna(self, which_antenna):
+ """
+ Specify which antenna port to use for reception.
+ @param which_antenna: either 'TX/RX' or 'RX2'
+ """
+ if which_antenna in (0, 'TX/RX'):
+ self._u.write_io(self._which, 0, RX2_RX1N)
+ elif which_antenna in (1, 'RX2'):
+ self._u.write_io(self._which, RX2_RX1N, RX2_RX1N)
+ else:
+ raise ValueError, "which_antenna must be either 'TX/RX' or 'RX2'"
+
+ def set_gain(self, gain):
+ """
+ Set the gain.
+
+ @param gain: gain in decibels
+ @returns True/False
+ """
+ maxgain = self.gain_range()[1] - self._u.pga_max()
+ mingain = self.gain_range()[0]
+ if gain > maxgain:
+ pga_gain = gain-maxgain
+ assert pga_gain <= self._u.pga_max()
+ agc_gain = maxgain
+ else:
+ pga_gain = 0
+ agc_gain = gain
+ V_maxgain = .2
+ V_mingain = 1.2
+ V_fullscale = 3.3
+ dac_value = (agc_gain*(V_maxgain-V_mingain)/(maxgain-mingain) + V_mingain)*4096/V_fullscale
+ assert dac_value>=0 and dac_value<4096
+ return self._u.write_aux_dac(self._which, 0, int(dac_value)) and \
+ self._set_pga(int(pga_gain))
+
+ def gain_range(self):
+ return (self._u.pga_min(), self._u.pga_max() + 70, 0.05) -- For 900-2400
+ return (self._u.pga_min(), self._u.pga_max() + 45, 0.035) -- For 400
+
+*/
diff --git a/usrp2/firmware/lib/db_tvrx.c b/usrp2/firmware/lib/db_tvrx.c
new file mode 100644
index 000000000..062d71895
--- /dev/null
+++ b/usrp2/firmware/lib/db_tvrx.c
@@ -0,0 +1,240 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <i2c.h>
+#include <lsdac.h>
+#include <memory_map.h>
+#include <db_base.h>
+#include <hal_io.h>
+#include <ad9510.h>
+#include <stdio.h>
+#include <mdelay.h>
+
+bool tvrx_init(struct db_base *db);
+bool tvrx_set_freq(struct db_base *db, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc);
+bool tvrx_set_gain(struct db_base *db, u2_fxpt_gain_t gain);
+
+#define I2C_ADDR 0x60
+#define ref_freq (U2_DOUBLE_TO_FXPT_FREQ(4e6)/640*8)
+
+#define ref_div 640 /* choices are 640, 512, 1024 */
+
+#if (ref_div == 640)
+#define ref_div_byte 0
+#else
+#if (ref_div == 512)
+#define ref_div_byte 0x6
+#else
+#define ref_div_byte 0x2
+#endif
+#endif
+
+#define fast_tuning 0x40
+
+#define control_byte_1 (0x88|fast_tuning|ref_div_byte)
+
+
+struct db_tvrx_common {
+ // TVRX common stuff
+ u2_fxpt_freq_t first_if;
+ u2_fxpt_freq_t second_if;
+};
+
+struct db_tvrx_dummy {
+ struct db_base base;
+ struct db_tvrx_common common;
+};
+
+struct db_tvrx1 {
+ struct db_base base;
+ struct db_tvrx_common common;
+};
+
+struct db_tvrx2 {
+ struct db_base base;
+ struct db_tvrx_common common;
+};
+
+struct db_tvrx3 {
+ struct db_base base;
+ struct db_tvrx_common common;
+};
+
+/* The class instances */
+struct db_tvrx1 db_tvrx1 = {
+ .base.dbid = 0x0003,
+ .base.is_tx = false,
+ .base.output_enables = 0x0000,
+ .base.used_pins = 0x0000,
+ .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(50e6),
+ .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(860e6),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = false,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = tvrx_init,
+ .base.set_freq = tvrx_set_freq,
+ .base.set_gain = tvrx_set_gain,
+ .base.set_tx_enable = 0,
+ .base.atr_mask = 0x0000,
+ .base.atr_txval = 0,
+ .base.atr_rxval = 0,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.first_if = U2_DOUBLE_TO_FXPT_FREQ(43.75e6),
+ .common.second_if = U2_DOUBLE_TO_FXPT_FREQ(5.75e6),
+};
+
+struct db_tvrx2 db_tvrx2 = {
+ .base.dbid = 0x000c,
+ .base.is_tx = false,
+ .base.output_enables = 0x0000,
+ .base.used_pins = 0x0000,
+ .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(50e6),
+ .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(860e6),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = false,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = tvrx_init,
+ .base.set_freq = tvrx_set_freq,
+ .base.set_gain = tvrx_set_gain,
+ .base.set_tx_enable = 0,
+ .base.atr_mask = 0x0000,
+ .base.atr_txval = 0,
+ .base.atr_rxval = 0,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.first_if = U2_DOUBLE_TO_FXPT_FREQ(44e6),
+ .common.second_if = U2_DOUBLE_TO_FXPT_FREQ(44e6),
+};
+
+struct db_tvrx3 db_tvrx3 = {
+ .base.dbid = 0x0040,
+ .base.is_tx = false,
+ .base.output_enables = 0x0000,
+ .base.used_pins = 0x0000,
+ .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(50e6),
+ .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(860e6),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = false,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = tvrx_init,
+ .base.set_freq = tvrx_set_freq,
+ .base.set_gain = tvrx_set_gain,
+ .base.set_tx_enable = 0,
+ .base.atr_mask = 0x0000,
+ .base.atr_txval = 0,
+ .base.atr_rxval = 0,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.first_if = U2_DOUBLE_TO_FXPT_FREQ(44e6),
+ .common.second_if = U2_DOUBLE_TO_FXPT_FREQ(44e6),
+};
+
+bool
+tvrx_init(struct db_base *dbb)
+{
+ struct db_tvrx_dummy *db = (struct db_tvrx_dummy *) dbb;
+ db->base.set_gain(dbb,U2_DOUBLE_TO_FXPT_GAIN(94.0));
+ return true;
+}
+
+bool
+tvrx_set_freq(struct db_base *dbb, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc)
+{
+ *dc = 0;
+ if (freq < dbb->freq_min || freq > dbb->freq_max)
+ return false;
+
+ struct db_tvrx_dummy *db = (struct db_tvrx_dummy *) dbb;
+
+ u2_fxpt_freq_t target_lo_freq = freq + db->common.first_if;
+ int N_DIV = u2_fxpt_freq_round_to_int(((1LL<<20) * target_lo_freq)/ref_freq);
+
+ u2_fxpt_freq_t actual_lo_freq = ref_freq * N_DIV;
+ u2_fxpt_freq_t actual_freq = actual_lo_freq - db->common.first_if;
+ if(N_DIV > 32767)
+ return false;
+
+ printf("N_DIV = %d, actual_freq = %d, actual_lo_freq = %d\n",
+ N_DIV, u2_fxpt_freq_round_to_int(actual_freq),u2_fxpt_freq_round_to_int(actual_freq));
+
+ char buf[4];
+ buf[0] = (N_DIV>>8) & 0xff;
+ buf[1] = N_DIV & 0xff;
+ buf[2] = control_byte_1;
+ buf[3] = (freq < U2_DOUBLE_TO_FXPT_FREQ(158e6)) ? 0xa8 : // VHF LOW
+ (freq < U2_DOUBLE_TO_FXPT_FREQ(464e6)) ? 0x98 : // VHF HIGH
+ 0x38; // UHF
+
+ *dc = actual_freq - db->common.second_if;
+ return i2c_write(I2C_ADDR,buf,4);
+}
+
+bool
+tvrx_set_gain(struct db_base *dbb, u2_fxpt_gain_t gain)
+{
+ struct db_tvrx_dummy *db = (struct db_tvrx_dummy *) dbb;
+ int rfgain;
+ int ifgain;
+ if(gain>U2_DOUBLE_TO_FXPT_GAIN(95.0))
+ return false;
+ if(gain<0)
+ return false;
+
+ if(gain>U2_DOUBLE_TO_FXPT_GAIN(60.0)) {
+ rfgain = U2_DOUBLE_TO_FXPT_GAIN(60.0);
+ ifgain = gain-U2_DOUBLE_TO_FXPT_GAIN(60.0);
+ } else {
+ rfgain = gain;
+ ifgain = 0;
+ }
+
+ int rf_slope_q8 = 256 * 4096 * 2.5 / 60.0 / 1.22 / 3.3;
+ int rf_offset_q8 = 128 * 256 * 4096 * 1.25 / 1.22 / 3.3;
+ int if_slope_q8 = 256 * 4096 * 2.25 / 35.0 / 1.22 / 3.3;
+ int if_offset_q8 = 128 * 256 * 4096 * 1.4 / 1.22 / 3.3;
+
+
+ int rfdac = (rfgain*rf_slope_q8 + rf_offset_q8)>>15;
+ int ifdac = (ifgain*if_slope_q8 + if_offset_q8)>>15;
+ lsdac_write_rx(0,rfdac);
+ lsdac_write_rx(1,ifdac);
+
+ printf("Setting gain %d, rf %d, if %d\n",gain,rfdac,ifdac);
+ return true;
+}
+
+
+bool
+tvrx_lock_detect(struct db_base *dbb)
+{
+ struct db_tvrx_dummy *db = (struct db_tvrx_dummy *) dbb;
+ return true;
+}
diff --git a/usrp2/firmware/lib/dbsm.c b/usrp2/firmware/lib/dbsm.c
new file mode 100644
index 000000000..5e2042bed
--- /dev/null
+++ b/usrp2/firmware/lib/dbsm.c
@@ -0,0 +1,298 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Double Buffering State Machine
+ */
+
+#include "dbsm.h"
+#include "memory_map.h"
+#include "buffer_pool.h"
+#include "bool.h"
+#include "nonstdio.h"
+#include <stdlib.h>
+
+typedef enum {
+ BS_EMPTY,
+ BS_FILLING,
+ BS_FULL,
+ BS_EMPTYING,
+} buffer_state_t;
+
+buffer_state_t buffer_state[NBUFFERS];
+
+bool
+dbsm_nop_inspector(dbsm_t *sm, int buf_this)
+{
+ return false;
+}
+
+void
+dbsm_init(dbsm_t *sm, int buf0,
+ const buf_cmd_args_t *recv, const buf_cmd_args_t *send,
+ inspector_t inspect)
+{
+ if (buf0 & 0x1) // must be even
+ abort();
+
+ sm->buf0 = buf0;
+ sm->running = false;
+ sm->recv_args = *recv;
+ sm->send_args = *send;
+
+ sm->rx_idle = true;
+ sm->tx_idle = true;
+
+ sm->inspect = inspect;
+
+ // How much to adjust the last_line register.
+ // It's 1 for everything but the ethernet.
+ sm->last_line_adj = recv->port == PORT_ETH ? 3 : 1;
+
+ buffer_state[sm->buf0] = BS_EMPTY;
+ buffer_state[sm->buf0 ^ 1] = BS_EMPTY;
+
+ sm->precomputed_receive_to_buf_ctrl_word[0] =
+ (BPC_READ
+ | BPC_BUFFER(sm->buf0)
+ | BPC_PORT(sm->recv_args.port)
+ | BPC_STEP(1)
+ | BPC_FIRST_LINE(sm->recv_args.first_line)
+ | BPC_LAST_LINE(sm->recv_args.last_line));
+
+ sm->precomputed_receive_to_buf_ctrl_word[1] =
+ (BPC_READ
+ | BPC_BUFFER(sm->buf0 ^ 1)
+ | BPC_PORT(sm->recv_args.port)
+ | BPC_STEP(1)
+ | BPC_FIRST_LINE(sm->recv_args.first_line)
+ | BPC_LAST_LINE(sm->recv_args.last_line));
+
+ sm->precomputed_send_from_buf_ctrl_word[0] =
+ (BPC_WRITE
+ | BPC_BUFFER(sm->buf0)
+ | BPC_PORT(sm->send_args.port)
+ | BPC_STEP(1)
+ | BPC_FIRST_LINE(sm->send_args.first_line)
+ | BPC_LAST_LINE(0)); // last line filled in at runtime
+
+ sm->precomputed_send_from_buf_ctrl_word[1] =
+ (BPC_WRITE
+ | BPC_BUFFER(sm->buf0 ^ 1)
+ | BPC_PORT(sm->send_args.port)
+ | BPC_STEP(1)
+ | BPC_FIRST_LINE(sm->send_args.first_line)
+ | BPC_LAST_LINE(0)); // last line filled in at runtime
+
+}
+
+static inline void
+dbsm_receive_to_buf(dbsm_t *sm, int bufno)
+{
+ buffer_pool_ctrl->ctrl = sm->precomputed_receive_to_buf_ctrl_word[bufno & 1];
+}
+
+static inline void
+dbsm_send_from_buf(dbsm_t *sm, int bufno)
+{
+ buffer_pool_ctrl->ctrl =
+ (sm->precomputed_send_from_buf_ctrl_word[bufno & 1]
+ | BPC_LAST_LINE(buffer_pool_status->last_line[bufno] - sm->last_line_adj));
+}
+
+void
+dbsm_start(dbsm_t *sm)
+{
+ // printf("dbsm_start: buf0 = %d, recv_port = %d\n", sm->buf0, sm->recv_args.port);
+
+ sm->running = true;
+
+ buffer_state[sm->buf0] = BS_EMPTY;
+ buffer_state[sm->buf0 ^ 1] = BS_EMPTY;
+
+ bp_clear_buf(sm->buf0);
+ bp_clear_buf(sm->buf0 ^ 1);
+
+ sm->tx_idle = true;
+ sm->rx_idle = false;
+ dbsm_receive_to_buf(sm, sm->buf0);
+ buffer_state[sm->buf0] = BS_FILLING;
+
+}
+
+
+void
+dbsm_stop(dbsm_t *sm)
+{
+ sm->running = false;
+ bp_clear_buf(sm->buf0);
+ bp_clear_buf(sm->buf0 ^ 1);
+ buffer_state[sm->buf0] = BS_EMPTY;
+ buffer_state[sm->buf0 ^ 1] = BS_EMPTY;
+}
+
+static void dbsm_process_helper(dbsm_t *sm, int buf_this);
+static void dbsm_error_helper(dbsm_t *sm, int buf_this);
+
+void
+dbsm_process_status(dbsm_t *sm, uint32_t status)
+{
+ if (!sm->running)
+ return;
+
+ if (status & (BPS_ERROR(sm->buf0) | BPS_ERROR(sm->buf0 ^ 1))){
+ putchar('E');
+ // Most likely an ethernet Rx error. We just restart the transfer.
+ if (status & (BPS_ERROR(sm->buf0)))
+ dbsm_error_helper(sm, sm->buf0);
+
+ if (status & (BPS_ERROR(sm->buf0 ^ 1)))
+ dbsm_error_helper(sm, sm->buf0 ^ 1);
+ }
+
+ if (status & BPS_DONE(sm->buf0))
+ dbsm_process_helper(sm, sm->buf0);
+
+ if (status & BPS_DONE(sm->buf0 ^ 1))
+ dbsm_process_helper(sm, sm->buf0 ^ 1);
+}
+
+static void
+dbsm_process_helper(dbsm_t *sm, int buf_this)
+{
+ int buf_other = buf_this ^ 1;
+
+ if (1){
+ bp_clear_buf(buf_this);
+
+ if (buffer_state[buf_this] == BS_FILLING){
+ buffer_state[buf_this] = BS_FULL;
+ //
+ // does s/w handle this packet?
+ //
+ if (sm->inspect(sm, buf_this)){
+ // s/w handled the packet; refill the buffer
+ dbsm_receive_to_buf(sm, buf_this);
+ buffer_state[buf_this] = BS_FILLING;
+ }
+
+ else { // s/w didn't handle this; pass it on
+
+ if(buffer_state[buf_other] == BS_EMPTY){
+ dbsm_receive_to_buf(sm, buf_other);
+ buffer_state[buf_other] = BS_FILLING;
+ }
+ else
+ sm->rx_idle = true;
+
+ if (sm->tx_idle){
+ sm->tx_idle = false;
+ dbsm_send_from_buf(sm, buf_this);
+ buffer_state[buf_this] = BS_EMPTYING;
+ }
+ }
+ }
+ else { // buffer was emptying
+ buffer_state[buf_this] = BS_EMPTY;
+ if (sm->rx_idle){
+ sm->rx_idle = false;
+ dbsm_receive_to_buf(sm, buf_this);
+ buffer_state[buf_this] = BS_FILLING;
+ }
+ if (buffer_state[buf_other] == BS_FULL){
+ dbsm_send_from_buf(sm, buf_other);
+ buffer_state[buf_other] = BS_EMPTYING;
+ }
+ else
+ sm->tx_idle = true;
+ }
+ }
+}
+
+static void
+dbsm_error_helper(dbsm_t *sm, int buf_this)
+{
+ bp_clear_buf(buf_this); // clears ERROR flag
+
+ if (buffer_state[buf_this] == BS_FILLING){
+ dbsm_receive_to_buf(sm, buf_this); // restart the xfer
+ }
+ else { // buffer was emptying
+ dbsm_send_from_buf(sm, buf_this); // restart the xfer
+ }
+}
+
+/*
+ * Handle DSP Tx underrun
+ */
+void
+dbsm_handle_tx_underrun(dbsm_t *sm)
+{
+ // clear the DSP Tx state machine
+ dsp_tx_regs->clear_state = 1;
+
+ // If there's a buffer that's empyting, clear it & flush xfer
+
+ if (buffer_state[sm->buf0] == BS_EMPTYING){
+ bp_clear_buf(sm->buf0);
+ dsp_tx_regs->clear_state = 1; // flush partial packet
+ // drop frame in progress on ground. Pretend it finished
+ dbsm_process_helper(sm, sm->buf0);
+ }
+ else if (buffer_state[sm->buf0 ^ 1] == BS_EMPTYING){
+ bp_clear_buf(sm->buf0 ^ 1);
+ dsp_tx_regs->clear_state = 1; // flush partial packet
+ // drop frame in progress on ground. Pretend it finished
+ dbsm_process_helper(sm, sm->buf0 ^ 1);
+ }
+}
+
+/*
+ * Handle DSP Rx overrun
+ */
+void
+dbsm_handle_rx_overrun(dbsm_t *sm)
+{
+ dsp_rx_regs->clear_state = 1;
+
+ // If there's a buffer that's filling, clear it.
+ // Any restart will be the job of the caller.
+
+ if (buffer_state[sm->buf0] == BS_FILLING)
+ bp_clear_buf(sm->buf0);
+
+ if (buffer_state[sm->buf0 ^1] == BS_FILLING)
+ bp_clear_buf(sm->buf0 ^ 1);
+}
+
+void
+dbsm_wait_for_opening(dbsm_t *sm)
+{
+ if (buffer_state[sm->buf0] == BS_EMPTYING){
+ // wait for xfer to complete
+ int mask = BPS_DONE(sm->buf0) | BPS_ERROR(sm->buf0) | BPS_IDLE(sm->buf0);
+ while ((buffer_pool_status->status & mask) == 0)
+ ;
+ }
+ else if (buffer_state[sm->buf0 ^ 1] == BS_EMPTYING){
+ // wait for xfer to complete
+ int mask = BPS_DONE(sm->buf0 ^ 1) | BPS_ERROR(sm->buf0 ^ 1) | BPS_IDLE(sm->buf0 ^ 1);
+ while ((buffer_pool_status->status & mask) == 0)
+ ;
+ }
+}
diff --git a/usrp2/firmware/lib/dbsm.h b/usrp2/firmware/lib/dbsm.h
new file mode 100644
index 000000000..3a64bf0dc
--- /dev/null
+++ b/usrp2/firmware/lib/dbsm.h
@@ -0,0 +1,90 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef INCLUDED_DBSM_H
+#define INCLUDED_DBSM_H
+
+/*
+ * Double Buffering State Machine
+ */
+
+#include <stdint.h>
+#include "bool.h"
+
+struct _dbsm;
+typedef struct _dbsm dbsm_t;
+
+/*
+ * pointer to function that does packet inspection.
+ *
+ * If one of these returns true, it means that the s/w
+ * handled that packet, and that it should NOT be passed
+ * on to the normal destination port.
+ */
+typedef bool (*inspector_t)(dbsm_t *sm, int buf_this);
+
+bool dbsm_nop_inspector(dbsm_t *sm, int buf_this); // returns false
+
+
+typedef struct
+{
+ uint16_t port;
+ uint16_t first_line;
+ uint16_t last_line;
+} buf_cmd_args_t;
+
+/*!
+ * double buffer state machine
+ */
+struct _dbsm
+{
+ uint8_t buf0; // Must be even. This machine uses buf0 and buf0+1
+ uint8_t running;
+ uint8_t rx_idle;
+ uint8_t tx_idle;
+ buf_cmd_args_t recv_args;
+ buf_cmd_args_t send_args;
+ inspector_t inspect;
+ uint32_t precomputed_receive_to_buf_ctrl_word[2];
+ uint32_t precomputed_send_from_buf_ctrl_word[2];
+ int last_line_adj;
+};
+
+void dbsm_init(dbsm_t *sm, int buf0,
+ const buf_cmd_args_t *recv, const buf_cmd_args_t *send,
+ inspector_t inspect);
+
+void dbsm_start(dbsm_t *sm);
+void dbsm_stop(dbsm_t *sm);
+void dbsm_process_status(dbsm_t *sm, uint32_t status);
+void dbsm_handle_tx_underrun(dbsm_t *sm);
+void dbsm_handle_rx_overrun(dbsm_t *sm);
+
+/*
+ * The cpu calls this when it want to ensure that it can send a buffer
+ * to the same destination being used by this state machine.
+ *
+ * If neither buffer is EMPTYING it returns immediately. If a buffer
+ * is EMPYTING, it waits for the h/w to transition to the DONE or
+ * ERROR state.
+ *
+ * When this function returns, the caller queues it's buffer and busy
+ * waits for it to complete.
+ */
+void dbsm_wait_for_opening(dbsm_t *sm);
+
+#endif /* INCLUDED_DBSM_H */
diff --git a/usrp2/firmware/lib/eeprom.c b/usrp2/firmware/lib/eeprom.c
new file mode 100644
index 000000000..b12ffe082
--- /dev/null
+++ b/usrp2/firmware/lib/eeprom.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "i2c.h"
+#include "mdelay.h"
+
+static const int EEPROM_PAGESIZE = 16;
+
+bool
+eeprom_write (int i2c_addr, int eeprom_offset, const void *buf, int len)
+{
+ unsigned char cmd[2];
+ const unsigned char *p = (unsigned char *) buf;
+
+ // The simplest thing that could possibly work:
+ // all writes are single byte writes.
+ //
+ // We could speed this up using the page write feature,
+ // but we write so infrequently, why bother...
+
+ while (len-- > 0){
+ cmd[0] = eeprom_offset++;
+ cmd[1] = *p++;
+ bool r = i2c_write (i2c_addr, cmd, sizeof (cmd));
+ mdelay (10); // delay 10ms worst case write time
+ if (!r)
+ return false;
+ }
+ return true;
+}
+
+bool
+eeprom_read (int i2c_addr, int eeprom_offset, void *buf, int len)
+{
+ unsigned char *p = (unsigned char *) buf;
+
+ // We setup a random read by first doing a "zero byte write".
+ // Writes carry an address. Reads use an implicit address.
+
+ unsigned char cmd[1];
+ cmd[0] = eeprom_offset;
+ if (!i2c_write (i2c_addr, cmd, sizeof (cmd)))
+ return false;
+
+ while (len > 0){
+ // int n = std::min (len, MAX_EP0_PKTSIZE);
+ int n = len;
+ if (!i2c_read (i2c_addr, p, n))
+ return false;
+ len -= n;
+ p += n;
+ }
+ return true;
+}
+
diff --git a/usrp2/firmware/lib/eth_mac.c b/usrp2/firmware/lib/eth_mac.c
new file mode 100644
index 000000000..f0b3a57ba
--- /dev/null
+++ b/usrp2/firmware/lib/eth_mac.c
@@ -0,0 +1,134 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "eth_mac.h"
+#include "memory_map.h"
+#include "bool.h"
+#include "eth_phy.h" // for simulation constants
+#include "mdelay.h"
+
+
+#define PHY_ADDR 1
+
+void
+eth_mac_set_addr(const u2_mac_addr_t *src)
+{
+ int i;
+
+ // tell mac our source address and enable automatic insertion on Tx.
+ eth_mac->mac_tx_add_prom_wr = 0; // just in case
+ for (i = 0; i < 6; i++){
+ eth_mac->mac_tx_add_prom_add = i;
+ eth_mac->mac_tx_add_prom_data = src->addr[i];
+ eth_mac->mac_tx_add_prom_wr = 1;
+ mdelay(1);
+ eth_mac->mac_tx_add_prom_wr = 0;
+ mdelay(1);
+ }
+ eth_mac->mac_tx_add_en = 1; // overwrite pkt src addr field with this stuff
+
+ // set up receive destination address filter
+ eth_mac->mac_rx_add_prom_wr = 0; // just in case
+ for (i = 0; i < 6; i++){
+ eth_mac->mac_rx_add_prom_add = i;
+ eth_mac->mac_rx_add_prom_data = src->addr[i];
+ eth_mac->mac_rx_add_prom_wr = 1;
+ mdelay(1);
+ eth_mac->mac_rx_add_prom_wr = 0;
+ mdelay(1);
+ }
+ // eth_mac->mac_rx_add_chk_en = 1; // FIXME enable when everything's working
+}
+
+
+void
+eth_mac_init(const u2_mac_addr_t *src)
+{
+ eth_mac->miimoder = 25; // divider from CPU clock (50MHz/25 = 2MHz)
+
+ eth_mac_set_addr(src);
+
+ // set rx flow control high and low water marks
+ // unsigned int lwmark = (2*2048 + 64)/4; // 2 * 2048-byte frames + 1 * 64-byte pause frame
+ // eth_mac->fc_hwmark = lwmark + 2048/4; // plus a 2048-byte frame
+
+ eth_mac->fc_lwmark = 600; // there are currently 2047 lines in the fifo
+ eth_mac->fc_hwmark = 1200;
+
+ //eth_mac->tx_pause_en = 0; // pay attn to pause frames sent to us
+ //eth_mac->pause_quanta_set = 38; // a bit more than 1 max frame 16kb/512 + fudge
+ //eth_mac->pause_frame_send_en = 0; // enable sending pause frames
+}
+
+int
+eth_mac_read_rmon(int addr)
+{
+ int t;
+
+ eth_mac->rmon_rd_addr = addr;
+ eth_mac->rmon_rd_apply = 1;
+ while(eth_mac->rmon_rd_grant == 0)
+ ;
+
+ t = eth_mac->rmon_rd_dout;
+ eth_mac->rmon_rd_apply = 0;
+ return t;
+}
+
+int
+eth_mac_miim_read(int addr)
+{
+ if (hwconfig_simulation_p()){
+ switch(addr){
+ case PHY_LINK_AN:
+ return LANSR_MASTER | LANSR_LINK_GOOD | LANSR_SPEED_1000;
+ default:
+ return 0;
+ }
+ }
+
+ int phy_addr = PHY_ADDR;
+ eth_mac->miiaddress = ((addr & 0x1f) << 8) | phy_addr;
+ eth_mac->miicommand = MIIC_RSTAT;
+
+ while((eth_mac->miistatus & MIIS_BUSY) != 0)
+ ;
+
+ return eth_mac->miirx_data;
+}
+
+void
+eth_mac_miim_write(int addr, int value)
+{
+ int phy_addr = PHY_ADDR;
+ eth_mac->miiaddress = ((addr & 0x1f) << 8) | phy_addr;
+ eth_mac->miitx_data = value;
+ eth_mac->miicommand = MIIC_WCTRLDATA;
+
+ while((eth_mac->miistatus & MIIS_BUSY) != 0)
+ ;
+}
+
+int
+eth_mac_miim_read_status(void)
+{
+ if (hwconfig_simulation_p())
+ return 0;
+
+ return eth_mac->miistatus;
+}
diff --git a/usrp2/firmware/lib/eth_mac.h b/usrp2/firmware/lib/eth_mac.h
new file mode 100644
index 000000000..291994c5c
--- /dev/null
+++ b/usrp2/firmware/lib/eth_mac.h
@@ -0,0 +1,32 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_ETH_MAC_H
+#define INCLUDED_ETH_MAC_H
+
+#include "usrp2_mac_addr.h"
+
+void eth_mac_init(const u2_mac_addr_t *src);
+
+void eth_mac_set_addr(const u2_mac_addr_t *src);
+int eth_mac_read_rmon(int addr);
+int eth_mac_miim_read(int addr);
+void eth_mac_miim_write(int addr, int value);
+int eth_mac_miim_read_status(void);
+
+#endif /* INCLUDED_ETH_MAC_H */
diff --git a/usrp2/firmware/lib/eth_mac_regs.h b/usrp2/firmware/lib/eth_mac_regs.h
new file mode 100644
index 000000000..bb6d2519b
--- /dev/null
+++ b/usrp2/firmware/lib/eth_mac_regs.h
@@ -0,0 +1,97 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_ETH_MAC_REGS_H
+#define INCLUDED_ETH_MAC_REGS_H
+
+/*
+ * See opencores.org 10_100_1000 Mbps Tri-mode Ethernet MAC Specification
+ *
+ * In reality, these are 16-bit regs, but are assigned
+ * on 32-bit boundaries. Because we're little endian,
+ * declaring them "int" works.
+ */
+typedef struct {
+ volatile int tx_hwmark;
+ volatile int tx_lwmark;
+
+ //! if set, send pause frames automatically
+ volatile int pause_frame_send_en;
+
+ //! quanta value for pause frame in units of 512 bit times.
+ volatile int pause_quanta_set;
+
+ volatile int ifg_set;
+ volatile int full_duplex;
+ volatile int max_retry;
+ volatile int mac_tx_add_en;
+ volatile int mac_tx_add_prom_data;
+ volatile int mac_tx_add_prom_add;
+ volatile int mac_tx_add_prom_wr;
+
+ //! if set, other end can pause us (i.e., we pay attention to pause frames)
+ volatile int tx_pause_en;
+
+ // Flow Control high and low water marks
+ //! when space available (in 32-bit lines) > hwmark, send un-pause frame
+ volatile int fc_hwmark;
+
+ //! when space avail (in 32-bit lines) < lwmark, send pause frame
+ volatile int fc_lwmark;
+
+ volatile int mac_rx_add_chk_en;
+ volatile int mac_rx_add_prom_data;
+ volatile int mac_rx_add_prom_add;
+ volatile int mac_rx_add_prom_wr;
+ volatile int broadcast_filter_en;
+ volatile int broadcast_bucket_depth;
+ volatile int broadcast_bucket_interval;
+ volatile int rx_append_crc;
+ volatile int rx_hwmark;
+ volatile int rx_lwmark;
+ volatile int crc_chk_en;
+ volatile int rx_ifg_set;
+ volatile int rx_max_length;
+ volatile int rx_min_length;
+ volatile int rmon_rd_addr; // performance counter access
+ volatile int rmon_rd_apply;
+ volatile int rmon_rd_grant; // READONLY
+ volatile int rmon_rd_dout; // READONLY
+ volatile int dummy; // READONLY
+ volatile int line_loop_en;
+ volatile int speed;
+ volatile int miimoder;
+ volatile int miicommand;
+ volatile int miiaddress;
+ volatile int miitx_data;
+ volatile int miirx_data;
+ volatile int miistatus;
+} eth_mac_regs_t;
+
+// miicommand register
+#define MIIC_SCANSSTAT (1 << 0) // Scan status
+#define MIIC_RSTAT (1 << 1) // Read status
+#define MIIC_WCTRLDATA (1 << 2) // Write control data
+
+// miistatus register
+#define MIIS_LINKFAIL (1 << 0) // The link failed
+#define MIIS_BUSY (1 << 1) // The MII is busy (operation in progress)
+#define MIIS_NVALID (1 << 2) // The data in the status register is invalid
+ // This it is only valid when the scan status is active.
+
+#endif /* INCLUDED_ETH_MAC_REGS_H */
diff --git a/usrp2/firmware/lib/eth_phy.h b/usrp2/firmware/lib/eth_phy.h
new file mode 100644
index 000000000..6c16f97b7
--- /dev/null
+++ b/usrp2/firmware/lib/eth_phy.h
@@ -0,0 +1,219 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Much of this was extracted from the Linux e1000_hw.h file */
+
+#ifndef INCLUDED_ETH_PHY_H
+#define INCLUDED_ETH_PHY_H
+
+/* PHY 1000 MII Register/Bit Definitions */
+/* PHY Registers defined by IEEE */
+
+#define PHY_CTRL 0x00 /* Control Register */
+#define PHY_STATUS 0x01 /* Status Regiser */
+#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */
+#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */
+#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */
+#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */
+#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */
+#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */
+#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */
+#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */
+#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
+#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */
+
+/* PHY 1000 MII Register additions in DP83856 */
+/* The part implements 0x00 thru 0x1f; we use these. */
+
+#define PHY_LINK_AN 0x11 /* Link and Auto Negotiation Status Reg */
+#define PHY_INT_STATUS 0x14 /* Interupt Status Reg (RO) */
+#define PHY_INT_MASK 0x15 /* Interrupt Mask Reg (RW) */
+#define PHY_INT_CLEAR 0x17 /* Interrupt Clear Reg (RW) */
+
+
+/* Bit definitions for some of the registers above */
+
+/* PHY Control Register (PHY_CTRL) */
+#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
+#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
+#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN 0x0800 /* Power down */
+#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
+
+/* PHY Status Register (PHY_STATUS) */
+#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
+#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
+#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
+
+/* Autoneg Advertisement Register (PHY_AUTONEG_ADV) */
+#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */
+#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
+#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
+#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
+#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
+#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */
+#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */
+#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
+#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
+#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */
+
+/* Link Partner Ability Register (Base Page) (PHY_LP_ABILITY) */
+#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */
+#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP is 10T Half Duplex Capable */
+#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP is 10T Full Duplex Capable */
+#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP is 100TX Half Duplex Capable */
+#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP is 100TX Full Duplex Capable */
+#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */
+#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */
+#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */
+#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP has detected Remote Fault */
+#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP has rx'd link code word */
+#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */
+
+/* Autoneg Expansion Register (PHY_AUTONEG_EXP) */
+#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */
+#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */
+#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */
+#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */
+#define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP is 100TX Full Duplex Capable */
+
+/* Next Page TX Register (PHY_NEXT_PAGE_TX) */
+#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
+#define NPTX_TOGGLE 0x0800 /* Toggles between exchanges
+ * of different NP
+ */
+#define NPTX_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg
+ * 0 = cannot comply with msg
+ */
+#define NPTX_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */
+#define NPTX_NEXT_PAGE 0x8000 /* 1 = addition NP will follow
+ * 0 = sending last NP
+ */
+
+/* Link Partner Next Page Register (PHY_LP_NEXT_PAGE) */
+#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
+#define LP_RNPR_TOGGLE 0x0800 /* Toggles between exchanges
+ * of different NP
+ */
+#define LP_RNPR_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg
+ * 0 = cannot comply with msg
+ */
+#define LP_RNPR_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */
+#define LP_RNPR_ACKNOWLDGE 0x4000 /* 1 = ACK / 0 = NO ACK */
+#define LP_RNPR_NEXT_PAGE 0x8000 /* 1 = addition NP will follow
+ * 0 = sending last NP
+ */
+
+/* 1000BASE-T Control Register (PHY_1000T_CTRL) */
+#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */
+#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
+#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
+#define CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */
+ /* 0=DTE device */
+#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */
+ /* 0=Configure PHY as Slave */
+#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */
+ /* 0=Automatic Master/Slave config */
+#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
+#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
+#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */
+#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */
+#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */
+
+/* 1000BASE-T Status Register (PHY_1000T_STATUS) */
+#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */
+#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */
+#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
+#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
+#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
+#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
+#define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */
+#define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */
+#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12
+#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13
+#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5
+#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20
+#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100
+
+/* Extended Status Register (PHY_EXT_STATUS) */
+#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
+#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
+#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
+#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
+
+#define PHY_TX_POLARITY_MASK 0x0100 /* register 10h bit 8 (polarity bit) */
+#define PHY_TX_NORMAL_POLARITY 0 /* register 10h bit 8 (normal polarity) */
+
+#define AUTO_POLARITY_DISABLE 0x0010 /* register 11h bit 4 */
+ /* (0=enable, 1=disable) */
+
+/* Link and Auto Negotiation Status Reg (PHY_LINK_AN) [READ-ONLY] */
+#define LANSR_MASTER 0x0001 /* 1=PHY is currently in master mode */
+#define LANSR_FULL_DUPLEX 0x0002 /* 1=PHY is currently full duplex */
+#define LANSR_LINK_GOOD 0x0004 /* 1=a good link is established */
+#define LANSR_SPEED_MASK 0x0018
+#define LANSR_SPEED_10 0x0000 /* 10Mb/s */
+#define LANSR_SPEED_100 0x0008 /* 100Mb/s */
+#define LANSR_SPEED_1000 0x0010 /* 1000Mb/s */
+#define LANSR_SPEED_RSRVD 0x0018 /* reserved */
+#define LANSR_NON_COMP_MODE 0x0020 /* 1=detects only in non-compliant mode */
+#define LANSR_DEEP_LOOPBACK 0x0040 /* 1=the PHY operates in deep loopback mode */
+#define LANSR_SHALLOW_LOOPBACK 0x0080 /* 1=the PHY operates in shallow loopback mode */
+#define LANSR_RSRVD_8 0x0100 /* reserved */
+#define LANSR_FIFO_ERR 0x0200 /* 1=FIFO error occurred */
+#define LANSR_MDIX_XOVER 0x0400 /* 1=PHY's MDI is in cross-over mode */
+#define LANSR_RSRVD_11 0x0800 /* resevered */
+#define LANSR_TP_POLARITY_REV 0xf000 /* Twisted pair polarity status A:D([15:12]) 1=reversed */
+
+/* Interrupt status, mask and clear regs (PHY_INT_{STATUS,MASK,CLEAR}) */
+#define PHY_INT_RSRVD_0 0x0001 /* reserved */
+#define PHY_INT_RSRVD_1 0x0002 /* reserved */
+#define PHY_INT_RSRVD_2 0x0004 /* reserved */
+#define PHY_INT_REM_FLT_CNG 0x0008 /* Remote Fault Changed */
+#define PHY_INT_AN_CMPL 0x0010 /* Auto-negotiation completion */
+#define PHY_INT_NXT_PG_RCVD 0x0020 /* Next Page Received */
+#define PHY_INT_JABBER_CNG 0x0040 /* Jabber Changed */
+#define PHY_INT_NO_LINK 0x0080 /* No link after auto-negotiation */
+#define PHY_INT_NO_HCD 0x0100 /* AN couldn't determine highest common denominator */
+#define PHY_INT_MAS_SLA_ERR 0x0200 /* Master / Slave Error: couldn't resolve */
+#define PHY_INT_PRL_DET_FLT 0x0400 /* Parallel detection fault */
+#define PHY_INT_POL_CNG 0x0800 /* Polarity of any channel changed */
+#define PHY_INT_MDIX_CNG 0x1000 /* MDIX changed. A pair swap occurred. */
+#define PHY_INT_DPLX_CNG 0x2000 /* Duplex changed */
+#define PHY_INT_LNK_CNG 0x4000 /* Link changed (asserted when a link is established or broken) */
+#define PHY_INT_SPD_CNG 0x8000 /* Speed changed */
+
+#endif /* INCLUDED_ETH_PHY_H */
diff --git a/usrp2/firmware/lib/ethernet.c b/usrp2/firmware/lib/ethernet.c
new file mode 100644
index 000000000..0e2f46167
--- /dev/null
+++ b/usrp2/firmware/lib/ethernet.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ethernet.h"
+#include "memory_map.h"
+#include "eth_phy.h"
+#include "eth_mac.h"
+#include "eth_mac_regs.h"
+#include "pic.h"
+#include "hal_io.h"
+#include "nonstdio.h"
+#include "bool.h"
+#include "i2c.h"
+#include "usrp2_i2c_addr.h"
+
+
+#define VERBOSE 0
+
+static ethernet_t ed_state;
+static ethernet_link_changed_callback_t ed_callback = 0;
+
+void
+ethernet_register_link_changed_callback(ethernet_link_changed_callback_t new_callback)
+{
+ ed_callback = new_callback;
+}
+
+
+static void
+ed_set_mac_speed(int speed)
+{
+ switch(speed){
+ case 10:
+ eth_mac->speed = 1;
+ break;
+ case 100:
+ eth_mac->speed = 2;
+ break;
+ case 1000:
+ eth_mac->speed = 4;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+ed_link_up(int speed)
+{
+ // putstr("ed_link_up: "); puthex16_nl(speed);
+
+ ed_set_mac_speed(speed);
+
+ if (ed_callback) // fire link changed callback
+ (*ed_callback)(speed);
+}
+
+static void
+ed_link_down(void)
+{
+ // putstr("ed_link_down\n");
+
+ if (ed_callback) // fire link changed callback
+ (*ed_callback)(0);
+}
+
+
+static void
+ed_link_speed_change(int speed)
+{
+ ed_link_down();
+ ed_link_up(speed);
+}
+
+/*
+ * Read the PHY state register to determine link state and speed
+ */
+static void
+ed_check_phy_state(void)
+{
+ int lansr = eth_mac_miim_read(PHY_LINK_AN);
+ eth_link_state_t new_state = LS_UNKNOWN;
+ int new_speed = S_UNKNOWN;
+
+ if (VERBOSE){
+ putstr("LANSR: ");
+ puthex16_nl(lansr);
+ }
+
+ if (lansr & LANSR_LINK_GOOD){ // link's up
+ if (VERBOSE)
+ puts(" LINK_GOOD");
+
+ new_state = LS_UP;
+ switch (lansr & LANSR_SPEED_MASK){
+ case LANSR_SPEED_10:
+ new_speed = 10;
+ break;
+
+ case LANSR_SPEED_100:
+ new_speed = 100;
+ break;
+
+ case LANSR_SPEED_1000:
+ new_speed = 1000;
+ break;
+
+ default:
+ new_speed = S_UNKNOWN;
+ break;
+ }
+ }
+ else { // link's down
+ if (VERBOSE)
+ puts(" NOT LINK_GOOD");
+
+ new_state = LS_DOWN;
+ new_speed = S_UNKNOWN;
+ }
+
+ if (new_state != ed_state.link_state){
+ ed_state.link_state = new_state; // remember new state
+ if (new_state == LS_UP)
+ ed_link_up(new_speed);
+ else if (new_state == LS_DOWN)
+ ed_link_down();
+ }
+ else if (new_state == LS_UP && new_speed != ed_state.link_speed){
+ ed_state.link_speed = new_speed; // remember new speed
+ ed_link_speed_change(new_speed);
+ }
+}
+
+/*
+ * This is fired when the ethernet PHY state changes
+ */
+static void
+eth_phy_irq_handler(unsigned irq)
+{
+ ed_check_phy_state();
+ eth_mac_miim_write(PHY_INT_CLEAR, ~0); // clear all ints
+}
+
+void
+ethernet_init(void)
+{
+ eth_mac_init(ethernet_mac_addr());
+
+ ed_state.link_state = LS_UNKNOWN;
+ ed_state.link_speed = S_UNKNOWN;
+
+ // initialize MAC registers
+ eth_mac->tx_hwmark = 0x1e;
+ eth_mac->tx_lwmark = 0x19;
+
+ eth_mac->crc_chk_en = 1;
+ eth_mac->rx_max_length = 2048;
+
+ // configure PAUSE frame stuff
+ eth_mac->tx_pause_en = 1; // pay attn to pause frames sent to us
+
+ eth_mac->pause_quanta_set = 38; // a bit more than 1 max frame 16kb/512 + fudge
+ eth_mac->pause_frame_send_en = 1; // enable sending pause frames
+
+
+ // setup PHY to interrupt on changes
+
+ unsigned mask =
+ (PHY_INT_AN_CMPL // auto-neg completed
+ | PHY_INT_NO_LINK // no link after auto-neg
+ | PHY_INT_NO_HCD // no highest common denominator
+ | PHY_INT_MAS_SLA_ERR // couldn't resolve master/slave
+ | PHY_INT_PRL_DET_FLT // parallel detection fault
+ | PHY_INT_LNK_CNG // link established or broken
+ | PHY_INT_SPD_CNG // speed changed
+ );
+
+ eth_mac_miim_write(PHY_INT_CLEAR, ~0); // clear all pending interrupts
+ eth_mac_miim_write(PHY_INT_MASK, mask); // enable the ones we want
+
+ pic_register_handler(IRQ_PHY, eth_phy_irq_handler);
+
+ // Advertise that we handle PAUSE frames and asymmetric pause direction.
+ int t = eth_mac_miim_read(PHY_AUTONEG_ADV);
+ eth_mac_miim_write(PHY_AUTONEG_ADV, t | NWAY_AR_PAUSE | NWAY_AR_ASM_DIR);
+
+ // Restart autonegotation.
+ // We want to ensure that we're advertising our PAUSE capabilities.
+ t = eth_mac_miim_read(PHY_CTRL);
+ eth_mac_miim_write(PHY_CTRL, t | MII_CR_RESTART_AUTO_NEG);
+}
+
+static bool
+unprogrammed(const u2_mac_addr_t *t)
+{
+ int i;
+ bool all_zeros = true;
+ bool all_ones = true;
+ for (i = 0; i < 6; i++){
+ all_zeros &= t->addr[i] == 0x00;
+ all_ones &= t->addr[i] == 0xff;
+ }
+ return all_ones | all_zeros;
+}
+
+static int8_t src_addr_initialized = false;
+static u2_mac_addr_t src_addr = {{
+ 0x00, 0x50, 0xC2, 0x85, 0x3f, 0xff
+ }};
+
+const u2_mac_addr_t *
+ethernet_mac_addr(void)
+{
+ if (!src_addr_initialized){ // fetch from eeprom
+ src_addr_initialized = true;
+
+ // if we're simulating, don't read the EEPROM model, it's REALLY slow
+ if (hwconfig_simulation_p())
+ return &src_addr;
+
+ u2_mac_addr_t tmp;
+ bool ok = eeprom_read(I2C_ADDR_MBOARD, MBOARD_MAC_ADDR, &tmp.addr[0], 6);
+ if (!ok || unprogrammed(&tmp)){
+ // use the default
+ }
+ else
+ src_addr = tmp;
+ }
+
+ return &src_addr;
+}
+
+bool
+ethernet_set_mac_addr(const u2_mac_addr_t *t)
+{
+ bool ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_MAC_ADDR, &t->addr[0], 6);
+ if (ok){
+ src_addr = *t;
+ src_addr_initialized = true;
+ eth_mac_set_addr(t);
+ }
+
+ return ok;
+}
+
+int
+ethernet_check_errors(void)
+{
+ // these registers are reset when read
+
+ int r = 0;
+ if (eth_mac_read_rmon(0x05) != 0)
+ r |= RME_RX_CRC;
+ if (eth_mac_read_rmon(0x06) != 0)
+ r |= RME_RX_FIFO_FULL;
+ if (eth_mac_read_rmon(0x07) != 0)
+ r |= RME_RX_2SHORT_2LONG;
+
+ if (eth_mac_read_rmon(0x25) != 0)
+ r |= RME_TX_JAM_DROP;
+ if (eth_mac_read_rmon(0x26) != 0)
+ r |= RME_TX_FIFO_UNDER;
+ if (eth_mac_read_rmon(0x27) != 0)
+ r |= RME_TX_FIFO_OVER;
+
+ return r;
+}
diff --git a/usrp2/firmware/lib/ethernet.h b/usrp2/firmware/lib/ethernet.h
new file mode 100644
index 000000000..4e5490460
--- /dev/null
+++ b/usrp2/firmware/lib/ethernet.h
@@ -0,0 +1,75 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_ETHERNET_H
+#define INCLUDED_ETHERNET_H
+
+#include "usrp2_mac_addr.h"
+#include "bool.h"
+
+typedef void (*ethernet_link_changed_callback_t)(int speed);
+
+
+/*!
+ * \brief one time call to initialize ethernet
+ */
+void ethernet_init(void);
+
+/*!
+ * \brief Specify the function to call on link state changes.
+ *
+ * When the link comes up, speed is the link speed in Mbit/s.
+ * When the link goes down, speed is 0.
+ */
+void ethernet_register_link_changed_callback(ethernet_link_changed_callback_t cb);
+
+/*!
+ * \returns ethernet MAC address
+ */
+const u2_mac_addr_t *ethernet_mac_addr(void);
+
+/*!
+ * \brief write mac address to eeprom and begin using it
+ */
+bool ethernet_set_mac_addr(const u2_mac_addr_t *t);
+
+
+/*
+ * \brief read RMON regs and return error mask
+ */
+int ethernet_check_errors(void);
+
+#define RME_RX_CRC 0x0001
+#define RME_RX_FIFO_FULL 0x0002
+#define RME_RX_2SHORT_2LONG 0x0004
+
+#define RME_TX_JAM_DROP 0x0010
+#define RME_TX_FIFO_UNDER 0x0020
+#define RME_TX_FIFO_OVER 0x0040
+
+
+typedef enum { LS_UNKNOWN, LS_DOWN, LS_UP } eth_link_state_t;
+
+#define S_UNKNOWN (-1) // unknown link speed
+
+typedef struct {
+ eth_link_state_t link_state;
+ int link_speed; // in Mb/s
+} ethernet_t;
+
+#endif /* INCLUDED_ETHERNET_H */
diff --git a/usrp2/firmware/lib/hal_io.c b/usrp2/firmware/lib/hal_io.c
new file mode 100644
index 000000000..541906825
--- /dev/null
+++ b/usrp2/firmware/lib/hal_io.c
@@ -0,0 +1,312 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+// conditionalized on HAL_IO_USES_DBOARD_PINS && HAL_IO_USES_UART
+
+#include "hal_io.h"
+#include "memory_map.h"
+#include "hal_uart.h"
+#include "bool.h"
+#include <stdio.h>
+#include <string.h>
+//#include <assert.h>
+
+/*
+ * ========================================================================
+ * GPIOS
+ * ========================================================================
+ */
+void
+hal_gpio_set_ddr(int bank, int value, int mask)
+{
+ bank &= 0x1;
+
+ if (bank == GPIO_TX_BANK){ // tx in top half
+ value <<= 16;
+ mask <<= 16;
+ }
+ else {
+ value &= 0xffff;
+ mask &= 0xffff;
+ }
+
+ int ei = hal_disable_ints();
+ gpio_base->ddr = (gpio_base->ddr & ~mask) | (value & mask);
+ hal_restore_ints(ei);
+}
+
+static bool
+code_to_int(char code, int *val)
+{
+ switch(code){
+ case 's': *val = GPIO_SEL_SW; return true;
+ case 'a': *val = GPIO_SEL_ATR; return true;
+ case '0': *val = GPIO_SEL_DEBUG_0; return true;
+ case '1': *val = GPIO_SEL_DEBUG_1; return true;
+ case '.':
+ default:
+ return false;
+ }
+}
+
+void
+hal_gpio_set_sel(int bank, int bitno, char code)
+{
+ bank &= 0x1;
+ int t;
+
+ if (!code_to_int(code, &t))
+ return;
+
+ int val = t << (2 * bitno);
+ int mask = 0x3 << (2 * bitno);
+
+ volatile uint32_t *sel = bank == GPIO_TX_BANK ? &gpio_base->tx_sel : &gpio_base->rx_sel;
+ int ei = hal_disable_ints();
+ int v = (*sel & ~mask) | (val & mask);
+ *sel = v;
+ hal_restore_ints(ei);
+
+ if (0)
+ printf("hal_gpio_set_sel(bank=%d, bitno=%d, code=%c) *sel = 0x%x\n",
+ bank, bitno, code, v);
+}
+
+void
+hal_gpio_set_sels(int bank, char *codes)
+{
+ //assert(strlen(codes) == 16);
+
+ int val = 0;
+ int mask = 0;
+ int i;
+
+ for (i = 15; i >= 0; i--){
+ val <<= 2;
+ mask <<= 2;
+ int t;
+ if (code_to_int(codes[i], &t)){
+ val |= t;
+ mask |= 0x3;
+ }
+ }
+
+ volatile uint32_t *sel = bank == GPIO_TX_BANK ? &gpio_base->tx_sel : &gpio_base->rx_sel;
+ int ei = hal_disable_ints();
+ *sel = (*sel & ~mask) | (val & mask);
+ hal_restore_ints(ei);
+}
+
+
+/*!
+ * \brief write \p value to gpio pins specified by \p mask.
+ */
+void
+hal_gpio_write(int bank, int value, int mask)
+{
+ static uint32_t _gpio_io_shadow;
+
+ bank &= 0x1;
+
+ if (bank == GPIO_TX_BANK){ // tx in top half
+ value <<= 16;
+ mask <<= 16;
+ }
+ else {
+ value &= 0xffff;
+ mask &= 0xffff;
+ }
+
+ //int ei = hal_disable_ints();
+ _gpio_io_shadow = (_gpio_io_shadow & ~mask) | (value & mask);
+ gpio_base->io = _gpio_io_shadow;
+ //hal_restore_ints(ei);
+}
+
+
+/*!
+ * \brief read GPIO bits
+ */
+int
+hal_gpio_read(int bank)
+{
+ bank &= 0x1;
+ int r = gpio_base->io;
+ if (bank == GPIO_TX_BANK)
+ r >>= 16;
+
+ return r & 0xffff;
+}
+
+/*
+ * ========================================================================
+ * leds
+ * ========================================================================
+ */
+
+static unsigned long leds_shadow = 0;
+
+void
+hal_set_leds(int value, int mask)
+{
+ int ei = hal_disable_ints();
+ leds_shadow = (leds_shadow & ~mask) | (value & mask);
+ output_regs->leds = leds_shadow;
+ hal_restore_ints(ei);
+}
+
+void
+hal_toggle_leds(int mask)
+{
+ int ei = hal_disable_ints();
+ leds_shadow ^= mask;
+ output_regs->leds = leds_shadow;
+ hal_restore_ints(ei);
+}
+
+
+// ================================================================
+// primitives
+// ================================================================
+
+#if defined(HAL_IO_USES_DBOARD_PINS)
+//
+// Does i/o using high 9-bits of rx daughterboard pins.
+//
+// 1 1 1 1 1 1
+// 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | char |W| |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//
+//
+// Asserts W when writing char
+//
+
+#define W 0x0080
+
+void
+hal_io_init(void)
+{
+ // make high 9 bits of tx daughterboard outputs
+ hal_gpio_set_rx_mode(15, 7, GPIOM_OUTPUT);
+
+ // and set them to zero
+ hal_gpio_set_rx(0x0000, 0xff80);
+}
+
+void
+hal_finish(void)
+{
+ volatile unsigned long *p = (unsigned long *) 0xC2F0;
+ *p = 0;
+}
+
+// %c
+inline int
+putchar(int ch)
+{
+ hal_gpio_set_rx((s << 8) | W, 0xff80);
+ hal_gpio_set_rx(0, 0xff80);
+ return ch;
+}
+
+#elif defined(HAL_IO_USES_UART)
+
+void
+hal_io_init(void)
+{
+ hal_uart_init();
+}
+
+void
+hal_finish(void)
+{
+}
+
+// %c
+inline int
+putchar(int ch)
+{
+ hal_uart_putc(ch);
+ return ch;
+}
+
+int
+getchar(void)
+{
+ return hal_uart_getc();
+}
+
+#else // nop all i/o
+
+void
+hal_io_init(void)
+{
+}
+
+void
+hal_finish(void)
+{
+}
+
+// %c
+inline int
+putchar(int ch)
+{
+ return ch;
+}
+
+int
+getchar(void)
+{
+ return EOF;
+}
+
+#endif
+
+// ================================================================
+// (slightly) higher level functions
+//
+// These are here so we can inline the calls to putchar.
+// The rest of the stuff was moved to nonstdio.c
+// ================================================================
+
+// \n
+inline void
+newline(void)
+{
+ putchar('\n');
+}
+
+int
+putstr(const char *s)
+{
+ while (*s)
+ putchar(*s++);
+
+ return 0;
+}
+
+int
+puts(const char *s)
+{
+ putstr(s);
+ putchar('\n');
+ return 0;
+}
diff --git a/usrp2/firmware/lib/hal_io.h b/usrp2/firmware/lib/hal_io.h
new file mode 100644
index 000000000..5ffebf57b
--- /dev/null
+++ b/usrp2/firmware/lib/hal_io.h
@@ -0,0 +1,174 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_HAL_IO_H
+#define INCLUDED_HAL_IO_H
+
+#include "memory_map.h"
+
+void hal_io_init(void);
+void hal_finish();
+
+
+/*
+ * ------------------------------------------------------------------------
+ * The GPIO pins are organized into two banks of 16-bits.
+ * Bank 0 goes to the Tx daughterboard, Bank 1 goes to the Rx daughterboard.
+ *
+ * Each pin may be configured as an input or an output from the FPGA.
+ * For output pins, there are four signals which may be routed to the
+ * pin. The four signals are the value written by s/w, the output of
+ * the ATR controller, or two different sources of debug info from the
+ * FPGA fabric.
+ * ------------------------------------------------------------------------
+ */
+
+#define GPIO_TX_BANK 0 // pins that connect to the Tx daughterboard
+#define GPIO_RX_BANK 1 // pins that connect to the Rx daughterboard
+
+
+/*!
+ * \brief Set the data direction for GPIO pins
+ *
+ * If the bit is set, it's an output from the FPGA.
+ * \param value is a 16-bit bitmask of values
+ * \param mask is a 16-bit bitmask of which bits to effect.
+ */
+void hal_gpio_set_ddr(int bank, int value, int mask);
+
+/*!
+ * \brief Select the source of the signal for an output pin.
+ *
+ * \param code is is one of 's', 'a', '0', '1'
+ * where 's' selects software output, 'a' selects ATR output, '0' selects
+ * debug 0, '1' selects debug 1.
+ */
+void hal_gpio_set_sel(int bank, int bitno, char code);
+
+/*!
+ * \brief Select the source of the signal for the output pins.
+ *
+ * \param codes is is a string of 16 characters composed of '.', 's',
+ * 'a', '0', or '1' where '.' means "don't change", 's' selects
+ * software output, 'a' selects ATR output, '0' selects debug 0, '1'
+ * selects debug 1.
+ */
+void hal_gpio_set_sels(int bank, char *codes);
+
+
+/*!
+ * \brief write \p value to gpio pins specified by \p mask.
+ */
+void hal_gpio_write(int bank, int value, int mask);
+
+/*!
+ * \brief read GPIO bits
+ */
+int hal_gpio_read(int bank);
+
+
+/*
+ * ------------------------------------------------------------------------
+ * control the leds
+ *
+ * Low 4-bits are the general purpose leds on the board
+ * The next bit is the led on the ethernet connector
+ * ------------------------------------------------------------------------
+ */
+
+#define LED_0 0x0001
+#define LED_1 0x0002
+#define LED_3 0x0004
+#define LED_4 0x0008
+#define LED_ETH_CONN 0x0010
+
+void hal_set_leds(int value, int mask);
+void hal_toggle_leds(int mask);
+
+/*
+ * ------------------------------------------------------------------------
+ * simple timeouts
+ * ------------------------------------------------------------------------
+ */
+
+
+
+static inline void
+hal_set_timeout(int delta_ticks)
+{
+ int t = timer_regs->time + delta_ticks;
+ if (t == 0) // kills timer
+ t = 1;
+ timer_regs->time = t;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * interrupt enable/disable
+ * ------------------------------------------------------------------------
+ */
+
+/*!
+ * \brief Disable interrupts and return previous interrupt enable state.
+ * [Microblaze specific]
+ */
+static inline int
+hal_disable_ints(void)
+{
+ int result, t0;
+
+ asm volatile("mfs %0, rmsr \n\
+ andni %1, %0, 0x2 \n\
+ mts rmsr, %1"
+ : "=r" (result), "=r" (t0));
+ return result;
+}
+
+/*!
+ * \brief Enable interrupts and return previous interrupt enable state.
+ * [Microblaze specific]
+ */
+static inline int
+hal_enable_ints(void)
+{
+ int result, t0;
+
+ asm volatile("mfs %0, rmsr \n\
+ ori %1, %0, 0x2 \n\
+ mts rmsr, %1"
+ : "=r" (result), "=r" (t0));
+ return result;
+}
+
+/*!
+ * \brief Set interrupt enable state to \p prev_state.
+ * [Microblaze specific]
+ */
+static inline void
+hal_restore_ints(int prev_state)
+{
+ int t0, t1;
+ asm volatile("andi %0, %2, 0x2 \n\
+ mfs %1, rmsr \n\
+ andni %1, %1, 0x2 \n\
+ or %1, %1, %0 \n\
+ mts rmsr, %1"
+ : "=r" (t0), "=r"(t1) : "r" (prev_state));
+}
+
+#endif /* INCLUDED_HAL_IO_H */
diff --git a/usrp2/firmware/lib/hal_uart.c b/usrp2/firmware/lib/hal_uart.c
new file mode 100644
index 000000000..f1d46fe84
--- /dev/null
+++ b/usrp2/firmware/lib/hal_uart.c
@@ -0,0 +1,67 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hal_uart.h"
+#include "hal_io.h"
+#include "memory_map.h"
+
+// First pass, no interrupts
+
+// Replaced with divisors.py which generates best divisor
+//#define CALC_DIVISOR(rate) (WISHBONE_CLK_RATE / ((rate) * 16))
+
+#define NSPEEDS 6
+#define MAX_WB_DIV 4
+
+static const uint16_t
+divisor_table[MAX_WB_DIV+1][NSPEEDS] = {
+ { 2, 2, 2, 2, 2, 2}, // 0: can't happen
+ { 651, 326, 163, 109, 54, 27 }, // 1: 100 MHz
+ { 326, 163, 81, 54, 27, 14 }, // 2: 50 MHz
+ { 217, 109, 54, 36, 18, 9 }, // 3: 33.3333 MHz
+ { 163, 81, 41, 27, 14, 7 }, // 4: 25 MHz
+};
+
+#define u uart_regs
+
+void
+hal_uart_init(void)
+{
+ u->clkdiv = 217; // 230400 bps
+}
+
+void
+hal_uart_putc(int ch)
+{
+ if (ch == '\n') // FIXME for now map \n -> \r\n
+ hal_uart_putc('\r');
+
+ while (u->txlevel == 0) // wait for fifo to have space
+ ;
+
+ u->txchar = ch;
+}
+
+int
+hal_uart_getc(void)
+{
+ while ((u->rxlevel) == 0) // wait for data to be ready
+ ;
+
+ return u->rxchar;
+}
diff --git a/usrp2/firmware/lib/hal_uart.h b/usrp2/firmware/lib/hal_uart.h
new file mode 100644
index 000000000..41e78894b
--- /dev/null
+++ b/usrp2/firmware/lib/hal_uart.h
@@ -0,0 +1,63 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_HAL_UART_H
+#define INCLUDED_HAL_UART_H
+
+
+/*!
+ * \brief one-time call to init
+ */
+void hal_uart_init(void);
+
+typedef enum {
+ US_9600,
+ US_19200,
+ US_38400,
+ US_57600,
+ US_115200,
+ US_230400,
+} hal_uart_speed_t;
+
+typedef struct {
+ hal_uart_speed_t speed;
+} hal_uart_config_t;
+
+/*!
+ * \brief Set uart parameters
+ * Default is 115,200 bps, 8N1.
+ */
+void hal_uart_set_config(const hal_uart_config_t *c);
+
+/*!
+ * \brief Get uart configuation.
+ */
+void hal_uart_get_config(hal_uart_config_t *c);
+
+/*!
+ * \brief Enqueue \p ch for output over serial port
+ */
+void hal_uart_putc(int ch);
+
+/*
+ * \brief Blocking read of next char from serial port
+ */
+int hal_uart_getc(void);
+
+
+#endif /* INCLUDED_HAL_UART_H */
diff --git a/usrp2/firmware/lib/i2c.c b/usrp2/firmware/lib/i2c.c
new file mode 100644
index 000000000..3f738733b
--- /dev/null
+++ b/usrp2/firmware/lib/i2c.c
@@ -0,0 +1,127 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "i2c.h"
+#include "memory_map.h"
+#include "stdint.h"
+
+#define MAX_WB_DIV 4 // maximum wishbone divisor (from 100 MHz MASTER_CLK)
+
+// prescaler divisor values for 100 kHz I2C [uses 5 * SCLK internally]
+
+#define PRESCALER(wb_div) (((MASTER_CLK_RATE/(wb_div)) / (5 * 100000)) - 1)
+
+static uint16_t prescaler_values[MAX_WB_DIV+1] = {
+ 0xffff, // 0: can't happen
+ PRESCALER(1), // 1: 100 MHz
+ PRESCALER(2), // 2: 50 MHz
+ PRESCALER(3), // 3: 33.333 MHz
+ PRESCALER(4), // 4: 25 MHz
+};
+
+void
+i2c_init(void)
+{
+ i2c_regs->ctrl = 0; // disable core
+
+ // setup prescaler depending on wishbone divisor
+ int wb_div = hwconfig_wishbone_divisor();
+ if (wb_div > MAX_WB_DIV)
+ wb_div = MAX_WB_DIV;
+
+ i2c_regs->prescaler_lo = prescaler_values[wb_div] & 0xff;
+ i2c_regs->prescaler_hi = (prescaler_values[wb_div] >> 8) & 0xff;
+
+ i2c_regs->ctrl = I2C_CTRL_EN; // enable core
+
+ // FIXME interrupt driven?
+}
+
+static inline void
+wait_for_xfer(void)
+{
+ while (i2c_regs->cmd_status & I2C_ST_TIP) // wait for xfer to complete
+ ;
+}
+
+static inline bool
+wait_chk_ack(void)
+{
+ wait_for_xfer();
+
+ if ((i2c_regs->cmd_status & I2C_ST_RXACK) != 0){ // target NAK'd
+ return false;
+ }
+ return true;
+}
+
+bool
+i2c_read (unsigned char i2c_addr, unsigned char *buf, unsigned int len)
+{
+ if (len == 0) // reading zero bytes always works
+ return true;
+
+ while (i2c_regs->cmd_status & I2C_ST_BUSY)
+ ;
+
+ i2c_regs->data = (i2c_addr << 1) | 1; // 7 bit address and read bit (1)
+ // generate START and write addr
+ i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_START;
+ if (!wait_chk_ack())
+ goto fail;
+
+ for (; len > 0; buf++, len--){
+ i2c_regs->cmd_status = I2C_CMD_RD | (len == 1 ? (I2C_CMD_NACK | I2C_CMD_STOP) : 0);
+ wait_for_xfer();
+ *buf = i2c_regs->data;
+ }
+ return true;
+
+ fail:
+ i2c_regs->cmd_status = I2C_CMD_STOP; // generate STOP
+ return false;
+}
+
+
+bool
+i2c_write(unsigned char i2c_addr, const unsigned char *buf, unsigned int len)
+{
+ while (i2c_regs->cmd_status & I2C_ST_BUSY)
+ ;
+
+ i2c_regs->data = (i2c_addr << 1) | 0; // 7 bit address and write bit (0)
+
+ // generate START and write addr (and maybe STOP)
+ i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_START | (len == 0 ? I2C_CMD_STOP : 0);
+ if (!wait_chk_ack())
+ goto fail;
+
+ for (; len > 0; buf++, len--){
+ i2c_regs->data = *buf;
+ i2c_regs->cmd_status = I2C_CMD_WR | (len == 1 ? I2C_CMD_STOP : 0);
+ if (!wait_chk_ack())
+ goto fail;
+ }
+ return true;
+
+ fail:
+ i2c_regs->cmd_status = I2C_CMD_STOP; // generate STOP
+ return false;
+}
+
+
diff --git a/usrp2/firmware/lib/i2c.h b/usrp2/firmware/lib/i2c.h
new file mode 100644
index 000000000..ad1e4159a
--- /dev/null
+++ b/usrp2/firmware/lib/i2c.h
@@ -0,0 +1,39 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_I2C_H
+#define INCLUDED_I2C_H
+
+#include "bool.h"
+
+void i2c_init(void);
+bool i2c_read (unsigned char i2c_addr, unsigned char *buf, unsigned int len);
+bool i2c_write(unsigned char i2c_addr, const unsigned char *buf, unsigned int len);
+
+
+// Write 24LC024 / 24LC025 EEPROM on motherboard or daughterboard.
+// Which EEPROM is determined by i2c_addr. See i2c_addr.h
+
+bool eeprom_write (int i2c_addr, int eeprom_offset, const void *buf, int len);
+
+// Read 24LC024 / 24LC025 EEPROM on motherboard or daughterboard.
+// Which EEPROM is determined by i2c_addr. See i2c_addr.h
+
+bool eeprom_read (int i2c_addr, int eeprom_offset, void *buf, int len);
+
+#endif /* INCLUDED_I2C_H */
diff --git a/usrp2/firmware/lib/lsadc.c b/usrp2/firmware/lib/lsadc.c
new file mode 100644
index 000000000..7983552e7
--- /dev/null
+++ b/usrp2/firmware/lib/lsadc.c
@@ -0,0 +1,73 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "lsadc.h"
+#include "spi.h"
+#include "memory_map.h"
+
+
+// AD9712 or AD7922 1 MS/s, 10-/12-bit ADCs
+
+//#define SPI_SS_DEBUG SPI_SS_RX_DB
+#define SPI_SS_DEBUG 0
+
+
+void
+lsadc_init(void)
+{
+ // nop
+}
+
+/*
+ * The ADC's are pipelined. That is, you have to tell them
+ * which of the two inputs you want one cycle ahead of time.
+ * We could optimize and keep track of which one we used last
+ * time, but for simplicity we'll always tell it which
+ * one we want. This takes 2 16-bit xfers, one to set the
+ * input and one to read the one we want.
+ */
+
+int
+_lsadc_read(int which_adc, int slave_select)
+{
+ uint32_t r;
+ int channel = which_adc & 0x1;
+
+ // Set CHN and STY equal to channel number. We don't want "daisy chain mode"
+ uint16_t cmd = (channel << 13) | (channel << 12);
+
+ spi_transact(SPI_TXONLY, slave_select | SPI_SS_DEBUG,
+ cmd, 16, SPIF_PUSH_RISE | SPIF_LATCH_RISE);
+
+ r = spi_transact(SPI_TXRX, slave_select | SPI_SS_DEBUG,
+ cmd, 16, SPIF_PUSH_RISE | SPIF_LATCH_RISE);
+
+ return r & 0x0fff;
+}
+
+int
+lsadc_read_rx(int which_adc)
+{
+ return _lsadc_read(which_adc, SPI_SS_RX_ADC);
+}
+
+int
+lsadc_read_tx(int which_adc)
+{
+ return _lsadc_read(which_adc, SPI_SS_TX_ADC);
+}
diff --git a/usrp2/firmware/lib/lsadc.h b/usrp2/firmware/lib/lsadc.h
new file mode 100644
index 000000000..319f34d91
--- /dev/null
+++ b/usrp2/firmware/lib/lsadc.h
@@ -0,0 +1,45 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef INCLUDED_LSADC_H
+#define INCLUDED_LSADC_H
+
+#include "memory_map.h"
+
+/*!
+ * \brief One time call to initialize low-speed ADCs.
+ */
+void lsadc_init(void);
+
+/*!
+ * \brief Read one of the low-speed Rx daughterboard ADCs.
+ * \param which_adc in [0, 1]
+ *
+ * \returns 12-bit value in [0,4095]
+ */
+int lsadc_read_rx(int which_adc);
+
+/*!
+ * \brief Read one of the low-speed Tx daughterboard ADCs.
+ * \param which_adc in [0, 1]
+ *
+ * \returns 12-bit value in [0,4095]
+ */
+int lsadc_read_tx(int which_adc);
+
+
+#endif /* INCLUDED_LSADC_H */
diff --git a/usrp2/firmware/lib/lsdac.c b/usrp2/firmware/lib/lsdac.c
new file mode 100644
index 000000000..6bc2e5cb5
--- /dev/null
+++ b/usrp2/firmware/lib/lsdac.c
@@ -0,0 +1,68 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "lsdac.h"
+#include "spi.h"
+#include "memory_map.h"
+
+// AD5624, AD5623
+
+#define CMD(x) ((x) << 19)
+#define CMD_WR_INPUT_N CMD(0) // write input N
+#define CMD_UP_DAC_N CMD(1) // update DAC N from input reg
+#define CMD_WR_INPUT_N_LDAC CMD(2) // write input N, update all
+#define CMD_WR_UP_DAC_N CMD(3) // write and update N
+#define CMD_WR_PWR_CONFIG CMD(4) // write power up/down config reg
+#define CMD_SW_RESET CMD(5) // force s/w reset
+#define CMD_WR_LDAC_CFG CMD(6) // write LDAC config reg
+#define CMD_WR_INT_REF_CFG CMD(7) // write internal ref cfg reg (AD5623R only)
+
+
+//#define SPI_SS_DEBUG SPI_SS_TX_DB
+#define SPI_SS_DEBUG 0
+
+inline static void
+_write_rx(uint32_t v)
+{
+ spi_transact(SPI_TXONLY, SPI_SS_RX_DAC | SPI_SS_DEBUG, v, 24, SPIF_PUSH_RISE);
+}
+
+inline static void
+_write_tx(uint32_t v)
+{
+ spi_transact(SPI_TXONLY, SPI_SS_TX_DAC | SPI_SS_DEBUG, v, 24, SPIF_PUSH_RISE);
+}
+
+void
+lsdac_init(void)
+{
+ _write_tx(CMD_SW_RESET | 0x1); // power-on reset
+ _write_rx(CMD_SW_RESET | 0x1); // power-on reset
+}
+
+void
+lsdac_write_rx(int which_dac, int value)
+{
+ _write_rx(CMD_WR_UP_DAC_N | ((which_dac & 0x7) << 16) | ((value << 4) & 0xffff));
+}
+
+void
+lsdac_write_tx(int which_dac, int value)
+{
+ _write_tx(CMD_WR_UP_DAC_N | ((which_dac & 0x7) << 16) | ((value << 4) & 0xffff));
+}
diff --git a/usrp2/firmware/lib/lsdac.h b/usrp2/firmware/lib/lsdac.h
new file mode 100644
index 000000000..9cad917e3
--- /dev/null
+++ b/usrp2/firmware/lib/lsdac.h
@@ -0,0 +1,47 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef INCLUDED_LSDAC_H
+#define INCLUDED_LSDAC_H
+
+#include "memory_map.h"
+
+/*!
+ * \brief One time call to initialize low-speed DACs.
+ */
+void lsdac_init(void);
+
+/*!
+ * \brief Write one of the low-speed Rx daughterboard DACs.
+ * \param which_dac in [0, 3]
+ * \param unsigned 12-bit value in [0, 4095]
+ *
+ * value maps linearly to output voltage from 0 to 3.3V
+ */
+void lsdac_write_rx(int which_dac, int value);
+
+/*!
+ * \brief Write one of the low-speed Tx daughterboard DACs.
+ * \param which_dac in [0, 3]
+ * \param unsigned 12-bit value in [0, 4095]
+ *
+ * value maps linearly to output voltage from 0 to 3.3V
+ */
+void lsdac_write_tx(int which_dac, int value);
+
+
+#endif /* INCLUDED_LSDAC_H */
diff --git a/usrp2/firmware/lib/mdelay.c b/usrp2/firmware/lib/mdelay.c
new file mode 100644
index 000000000..c8c119b1a
--- /dev/null
+++ b/usrp2/firmware/lib/mdelay.c
@@ -0,0 +1,73 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mdelay.h"
+#include "memory_map.h"
+
+// Delay about one millisecond.
+//
+// Need 33,333 cycles at 33 MHz.
+// Each time around the loop is 10 cycles
+//
+
+#define LOOPCNT(wb_div) (MASTER_CLK_RATE/(wb_div) / 10000)
+
+inline static void
+delay_1ms(int loop_count)
+{
+ int i;
+ for (i = 0; i < loop_count; i++){
+ asm volatile ("or r0, r0, r0\n\
+ or r0, r0, r0\n\
+ or r0, r0, r0\n\
+ or r0, r0, r0\n\
+ or r0, r0, r0\n\
+ or r0, r0, r0\n\
+ or r0, r0, r0\n");
+ }
+}
+
+// delay about ms milliseconds
+void
+mdelay(int ms)
+{
+ static int loop_count = -1;
+
+ if (hwconfig_simulation_p())
+ return;
+
+ if (loop_count < 0){
+ // set correct loop_count
+ static unsigned short lc[8] = {
+ 0,
+ LOOPCNT(1),
+ LOOPCNT(2),
+ LOOPCNT(3),
+ LOOPCNT(4),
+ LOOPCNT(5),
+ LOOPCNT(6),
+ LOOPCNT(7)
+ };
+
+ loop_count = lc[hwconfig_wishbone_divisor() & 0x7];
+ }
+
+ int i;
+ for (i = 0; i < ms; i++)
+ delay_1ms(loop_count);
+}
diff --git a/usrp2/firmware/lib/mdelay.h b/usrp2/firmware/lib/mdelay.h
new file mode 100644
index 000000000..226bbb3f7
--- /dev/null
+++ b/usrp2/firmware/lib/mdelay.h
@@ -0,0 +1,29 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_MDELAY_H
+#define INCLUDED_MDELAY_H
+
+/*!
+ * \brief Delay about ms milliseconds
+ *
+ * If simulating, _very_ short delay
+ */
+void mdelay(int ms);
+
+#endif /* INCLUDED_MDELAY_H */
diff --git a/usrp2/firmware/lib/memcpy_wa.c b/usrp2/firmware/lib/memcpy_wa.c
new file mode 100644
index 000000000..ef20efaa9
--- /dev/null
+++ b/usrp2/firmware/lib/memcpy_wa.c
@@ -0,0 +1,42 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "memcpy_wa.h"
+#include <stdint.h>
+#include <stdlib.h>
+
+/*
+ * For copying to/from non-byte-adressable memory, such as
+ * the buffers. dst, src, and nbytes must all satisfy (x % 4 == 0)
+ */
+void
+memcpy_wa(void *dst, const void *src, size_t nbytes)
+{
+ if (((intptr_t) dst & 0x3)
+ || ((intptr_t) src & 0x3)
+ || (nbytes & 0x3))
+ exit(1); /* die! */
+
+ int *dp = (int *) dst;
+ int *sp = (int *) src;
+ unsigned nw = nbytes/4;
+
+ unsigned i;
+ for (i = 0; i < nw; i++)
+ dp[i] = sp[i];
+}
diff --git a/usrp2/firmware/lib/memcpy_wa.h b/usrp2/firmware/lib/memcpy_wa.h
new file mode 100644
index 000000000..072fc148f
--- /dev/null
+++ b/usrp2/firmware/lib/memcpy_wa.h
@@ -0,0 +1,32 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_MEMCPY_WA_H
+#define INCLUDED_MEMCPY_WA_H
+
+#include <stddef.h>
+
+/*
+ * For copying to/from non-byte-adressable memory, such as
+ * the buffers. dst, src, and nbytes must all satisfy (x % 4 == 0)
+ */
+void memcpy_wa(void *dst, const void *src, size_t nbytes);
+
+#endif /* INCLUDED_MEMCPY_WA_H */
+
+
diff --git a/usrp2/firmware/lib/memory_map.h b/usrp2/firmware/lib/memory_map.h
new file mode 100644
index 000000000..7dce59d03
--- /dev/null
+++ b/usrp2/firmware/lib/memory_map.h
@@ -0,0 +1,583 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Overall Memory Map
+ * 0000-7FFF 32K RAM space (16K on 1500, 24K on 2000, 32K on DSP)
+ * 8000-BFFF 16K Buffer Pool
+ * C000-FFFF 16K Peripherals
+ */
+
+
+#ifndef INCLUDED_MEMORY_MAP_H
+#define INCLUDED_MEMORY_MAP_H
+
+#include <stdint.h>
+
+
+#define MASTER_CLK_RATE 100000000 // 100 MHz
+
+
+////////////////////////////////////////////////////////////////
+//
+// Memory map for embedded wishbone bus
+//
+////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////
+// Main RAM, Slave 0
+
+#define RAM_BASE 0x0000
+
+////////////////////////////////////////////////////////////////
+// Buffer Pool RAM, Slave 1
+//
+// The buffers themselves are located in Slave 1, Buffer Pool RAM.
+// The status registers are in Slave 5, Buffer Pool Status.
+// The control register is in Slave 7, Settings Bus.
+
+#define BUFFER_POOL_RAM_BASE 0x8000
+
+#define NBUFFERS 8
+#define BP_NLINES 0x0200 // number of 32-bit lines in a buffer
+#define BP_LAST_LINE (BP_NLINES - 1) // last line in a buffer
+
+#define buffer_pool_ram \
+ ((uint32_t *) BUFFER_POOL_RAM_BASE)
+
+#define buffer_ram(n) (&buffer_pool_ram[(n) * BP_NLINES])
+
+
+/////////////////////////////////////////////////////
+// SPI Core, Slave 2. See core docs for more info
+#define SPI_BASE 0xC000 // Base address (16-bit)
+
+typedef struct {
+ volatile uint32_t txrx0;
+ volatile uint32_t txrx1;
+ volatile uint32_t txrx2;
+ volatile uint32_t txrx3;
+ volatile uint32_t ctrl;
+ volatile uint32_t div;
+ volatile uint32_t ss;
+} spi_regs_t;
+
+#define spi_regs ((spi_regs_t *) SPI_BASE)
+
+
+// Masks for controlling different peripherals
+#define SPI_SS_AD9510 1
+#define SPI_SS_AD9777 2
+#define SPI_SS_RX_DAC 4
+#define SPI_SS_RX_ADC 8
+#define SPI_SS_RX_DB 16
+#define SPI_SS_TX_DAC 32
+#define SPI_SS_TX_ADC 64
+#define SPI_SS_TX_DB 128
+
+// Masks for different parts of CTRL reg
+#define SPI_CTRL_ASS (1<<13)
+#define SPI_CTRL_IE (1<<12)
+#define SPI_CTRL_LSB (1<<11)
+#define SPI_CTRL_TXNEG (1<<10)
+#define SPI_CTRL_RXNEG (1<< 9)
+#define SPI_CTRL_GO_BSY (1<< 8)
+#define SPI_CTRL_CHAR_LEN_MASK 0x7F
+
+////////////////////////////////////////////////
+// I2C, Slave 3
+// See Wishbone I2C-Master Core Specification.
+
+#define I2C_BASE 0xC400
+
+typedef struct {
+ volatile uint32_t prescaler_lo; // r/w
+ volatile uint32_t prescaler_hi; // r/w
+ volatile uint32_t ctrl; // r/w
+ volatile uint32_t data; // wr = transmit reg; rd = receive reg
+ volatile uint32_t cmd_status; // wr = command reg; rd = status reg
+} i2c_regs_t;
+
+#define i2c_regs ((i2c_regs_t *) I2C_BASE)
+
+#define I2C_CTRL_EN (1 << 7) // core enable
+#define I2C_CTRL_IE (1 << 6) // interrupt enable
+
+//
+// STA, STO, RD, WR, and IACK bits are cleared automatically
+//
+#define I2C_CMD_START (1 << 7) // generate (repeated) start condition
+#define I2C_CMD_STOP (1 << 6) // generate stop condition
+#define I2C_CMD_RD (1 << 5) // read from slave
+#define I2C_CMD_WR (1 << 4) // write to slave
+#define I2C_CMD_NACK (1 << 3) // when a rcvr, send ACK (ACK=0) or NACK (ACK=1)
+#define I2C_CMD_RSVD_2 (1 << 2) // reserved
+#define I2C_CMD_RSVD_1 (1 << 1) // reserved
+#define I2C_CMD_IACK (1 << 0) // set to clear pending interrupt
+
+#define I2C_ST_RXACK (1 << 7) // Received acknowledgement from slave (1 = NAK, 0 = ACK)
+#define I2C_ST_BUSY (1 << 6) // 1 after START signal detected; 0 after STOP signal detected
+#define I2C_ST_AL (1 << 5) // Arbitration lost. 1 when core lost arbitration
+#define I2C_ST_RSVD_4 (1 << 4) // reserved
+#define I2C_ST_RSVD_3 (1 << 3) // reserved
+#define I2C_ST_RSVD_2 (1 << 2) // reserved
+#define I2C_ST_TIP (1 << 1) // Transfer-in-progress
+#define I2C_ST_IP (1 << 0) // Interrupt pending
+
+
+////////////////////////////////////////////////
+// GPIO, Slave 4
+//
+// These go to the daughterboard i/o pins
+
+#define GPIO_BASE 0xC800
+
+typedef struct {
+ volatile uint32_t io; // tx data in high 16, rx in low 16
+ volatile uint32_t ddr; // 32 bits, 1 means output. tx in high 16, rx in low 16
+ volatile uint32_t tx_sel; // 16 2-bit fields select which source goes to TX DB
+ volatile uint32_t rx_sel; // 16 2-bit fields select which source goes to RX DB
+} gpio_regs_t;
+
+// each 2-bit sel field is layed out this way
+#define GPIO_SEL_SW 0 // if pin is an output, set by software in the io reg
+#define GPIO_SEL_ATR 1 // if pin is an output, set by ATR logic
+#define GPIO_SEL_DEBUG_0 2 // if pin is an output, debug lines from FPGA fabric
+#define GPIO_SEL_DEBUG_1 3 // if pin is an output, debug lines from FPGA fabric
+
+#define gpio_base ((gpio_regs_t *) GPIO_BASE)
+
+///////////////////////////////////////////////////
+// Buffer Pool Status, Slave 5
+//
+// The buffers themselves are located in Slave 1, Buffer Pool RAM.
+// The status registers are in Slave 5, Buffer Pool Status.
+// The control register is in Slave 7, Settings Bus.
+
+#define BUFFER_POOL_STATUS_BASE 0xCC00
+
+typedef struct {
+ volatile uint32_t last_line[NBUFFERS]; // last line xfer'd in buffer
+ volatile uint32_t status; // error and done flags
+ volatile uint32_t hw_config; // see below
+} buffer_pool_status_t;
+
+#define buffer_pool_status ((buffer_pool_status_t *) BUFFER_POOL_STATUS_BASE)
+
+/*
+ * Buffer n's xfer is done.
+ * Clear this bit by issuing bp_clear_buf(n)
+ */
+#define BPS_DONE(n) (0x00000001 << (n))
+#define BPS_DONE_0 BPS_DONE(0)
+#define BPS_DONE_1 BPS_DONE(1)
+#define BPS_DONE_2 BPS_DONE(2)
+#define BPS_DONE_3 BPS_DONE(3)
+#define BPS_DONE_4 BPS_DONE(4)
+#define BPS_DONE_5 BPS_DONE(5)
+#define BPS_DONE_6 BPS_DONE(6)
+#define BPS_DONE_7 BPS_DONE(7)
+
+/*
+ * Buffer n's xfer had an error.
+ * Clear this bit by issuing bp_clear_buf(n)
+ */
+#define BPS_ERROR(n) (0x00000100 << (n))
+#define BPS_ERROR_0 BPS_ERROR(0)
+#define BPS_ERROR_1 BPS_ERROR(1)
+#define BPS_ERROR_2 BPS_ERROR(2)
+#define BPS_ERROR_3 BPS_ERROR(3)
+#define BPS_ERROR_4 BPS_ERROR(4)
+#define BPS_ERROR_5 BPS_ERROR(5)
+#define BPS_ERROR_6 BPS_ERROR(6)
+#define BPS_ERROR_7 BPS_ERROR(7)
+
+/*
+ * Buffer n is idle. A buffer is idle if it's not
+ * DONE, ERROR, or processing a transaction. If it's
+ * IDLE, it's safe to start a new transaction.
+ *
+ * Clear this bit by starting a xfer with
+ * bp_send_from_buf or bp_receive_to_buf.
+ */
+#define BPS_IDLE(n) (0x00010000 << (n))
+#define BPS_IDLE_0 BPS_IDLE(0)
+#define BPS_IDLE_1 BPS_IDLE(1)
+#define BPS_IDLE_2 BPS_IDLE(2)
+#define BPS_IDLE_3 BPS_IDLE(3)
+#define BPS_IDLE_4 BPS_IDLE(4)
+#define BPS_IDLE_5 BPS_IDLE(5)
+#define BPS_IDLE_6 BPS_IDLE(6)
+#define BPS_IDLE_7 BPS_IDLE(7)
+
+/*
+ * Buffer n has a "slow path" packet in it.
+ * This bit is orthogonal to the bits above and indicates that
+ * the FPGA ethernet rx protocol engine has identified this packet
+ * as one requiring firmware intervention.
+ */
+#define BPS_SLOWPATH(n) (0x01000000 << (n))
+#define BPS_SLOWPATH_0 BPS_SLOWPATH(0)
+#define BPS_SLOWPATH_1 BPS_SLOWPATH(1)
+#define BPS_SLOWPATH_2 BPS_SLOWPATH(2)
+#define BPS_SLOWPATH_3 BPS_SLOWPATH(3)
+#define BPS_SLOWPATH_4 BPS_SLOWPATH(4)
+#define BPS_SLOWPATH_5 BPS_SLOWPATH(5)
+#define BPS_SLOWPATH_6 BPS_SLOWPATH(6)
+#define BPS_SLOWPATH_7 BPS_SLOWPATH(7)
+
+
+#define BPS_DONE_ALL 0x000000ff // mask of all dones
+#define BPS_ERROR_ALL 0x0000ff00 // mask of all errors
+#define BPS_IDLE_ALL 0x00ff0000 // mask of all idles
+#define BPS_SLOWPATH_ALL 0xff000000 // mask of all slowpaths
+
+// The hw_config register
+
+#define HWC_SIMULATION 0x80000000
+#define HWC_WB_CLK_DIV_MASK 0x0000000f
+
+/*!
+ * \brief return non-zero if we're running under the simulator
+ */
+inline static int
+hwconfig_simulation_p(void)
+{
+ return buffer_pool_status->hw_config & HWC_SIMULATION;
+}
+
+/*!
+ * \brief Return Wishbone Clock divisor.
+ * The processor runs at the Wishbone Clock rate which is MASTER_CLK_RATE / divisor.
+ */
+inline static int
+hwconfig_wishbone_divisor(void)
+{
+ return buffer_pool_status->hw_config & HWC_WB_CLK_DIV_MASK;
+}
+
+///////////////////////////////////////////////////
+// Ethernet Core, Slave 6
+
+#define ETH_BASE 0xD000
+
+#include "eth_mac_regs.h"
+
+#define eth_mac ((eth_mac_regs_t *) ETH_BASE)
+
+////////////////////////////////////////////////////
+// Settings Bus, Slave #7, Not Byte Addressable!
+//
+// Output-only from processor point-of-view.
+// 1KB of address space (== 256 32-bit write-only regs)
+
+
+#define MISC_OUTPUT_BASE 0xD400
+#define TX_PROTOCOL_ENGINE_BASE 0xD480
+#define RX_PROTOCOL_ENGINE_BASE 0xD4C0
+#define BUFFER_POOL_CTRL_BASE 0xD500
+#define DSP_TX_BASE 0xD600
+#define DSP_RX_BASE 0xD680
+
+#define LAST_SETTING_REG 0xD7FC // last valid setting register
+
+// --- buffer pool control regs ---
+
+typedef struct {
+ volatile uint32_t ctrl;
+} buffer_pool_ctrl_t;
+
+// buffer pool ports
+
+#define PORT_SERDES 0 // serial/deserializer
+#define PORT_DSP 1 // DSP tx or rx pipeline
+#define PORT_ETH 2 // ethernet tx or rx
+#define PORT_RAM 3 // RAM tx or rx
+
+// the buffer pool ctrl register fields
+
+#define BPC_BUFFER(n) (((n) & 0xf) << 28)
+#define BPC_BUFFER_MASK BPC_BUFFER(~0)
+#define BPC_BUFFER_0 BPC_BUFFER(0)
+#define BPC_BUFFER_1 BPC_BUFFER(1)
+#define BPC_BUFFER_2 BPC_BUFFER(2)
+#define BPC_BUFFER_3 BPC_BUFFER(3)
+#define BPC_BUFFER_4 BPC_BUFFER(4)
+#define BPC_BUFFER_5 BPC_BUFFER(5)
+#define BPC_BUFFER_6 BPC_BUFFER(6)
+#define BPC_BUFFER_7 BPC_BUFFER(7)
+#define BPC_BUFFER_NIL BPC_BUFFER(0x8) // disable
+
+#define BPC_PORT(n) (((n) & 0x7) << 25)
+#define BPC_PORT_MASK BPC_PORT(~0)
+#define BPC_PORT_SERDES BPC_PORT(PORT_SERDES)
+#define BPC_PORT_DSP BPC_PORT(PORT_DSP)
+#define BPC_PORT_ETH BPC_PORT(PORT_ETH)
+#define BPC_PORT_RAM BPC_PORT(PORT_RAM)
+#define BPC_PORT_NIL BPC_PORT(0x4) // disable
+
+#define BPC_CLR (1 << 24) // mutually excl commands
+#define BPC_READ (1 << 23)
+#define BPC_WRITE (1 << 22)
+
+#define BPC_STEP(step) (((step) & 0xf) << 18)
+#define BPC_STEP_MASK BPC_STEP(~0)
+#define BPC_LAST_LINE(line) (((line) & 0x1ff) << 9)
+#define BPC_LAST_LINE_MASK BPC_LAST_LINE(~0)
+#define BPC_FIRST_LINE(line) (((line) & 0x1ff) << 0)
+#define BPC_FIRST_LINE_MASK BPC_FIRST_LINE(~0)
+
+#define buffer_pool_ctrl ((buffer_pool_ctrl_t *) BUFFER_POOL_CTRL_BASE)
+
+// --- misc outputs ---
+
+typedef struct {
+ volatile uint32_t clk_ctrl;
+ volatile uint32_t serdes_ctrl;
+ volatile uint32_t adc_ctrl;
+ volatile uint32_t leds;
+ volatile uint32_t phy_ctrl; // LSB is reset line to eth phy
+ volatile uint32_t debug_mux_ctrl;
+} output_regs_t;
+
+#define SERDES_ENABLE 8
+#define SERDES_PRBSEN 4
+#define SERDES_LOOPEN 2
+#define SERDES_RXEN 1
+
+#define ADC_CTRL_ON 0x0F
+#define ADC_CTRL_OFF 0x00
+
+#define output_regs ((output_regs_t *) MISC_OUTPUT_BASE)
+
+// --- dsp tx regs ---
+
+#define MIN_INTERP 1
+#define MAX_INTERP 128
+
+typedef struct {
+ volatile int32_t freq;
+ volatile uint32_t scale_iq; // {scale_i,scale_q}
+ volatile uint32_t interp_rate;
+ volatile uint32_t clear_state; // clears out state machine, fifos,
+ // NOT freq, scale, interp
+} dsp_tx_regs_t;
+
+#define dsp_tx_regs ((dsp_tx_regs_t *) DSP_TX_BASE)
+
+// --- dsp rx regs ---
+
+#define T_NOW (-1)
+
+#define MIN_DECIM 1
+#define MAX_DECIM 128
+
+typedef struct {
+ volatile int32_t freq;
+ volatile uint32_t scale_iq; // {scale_i,scale_q}
+ volatile uint32_t decim_rate;
+ volatile uint32_t rx_time; // when to begin reception
+ volatile uint32_t rx_command; // {now, chain, num_lines(21), lines_per_frame(9)
+ volatile uint32_t clear_state; // clears out state machine, fifos,
+ // cmd queue, NOT freq, scale, decim
+ volatile uint32_t dcoffset_i; // Bit 31 high sets fixed offset mode, using lower 14 bits,
+ // otherwise it is automatic
+ volatile uint32_t dcoffset_q; // Bit 31 high sets fixed offset mode, using lower 14 bits
+ volatile uint32_t adc_mux; // 4 bits -- lowest 2 for adc_i, next for adc_q
+
+} dsp_rx_regs_t;
+
+#define dsp_rx_regs ((dsp_rx_regs_t *) DSP_RX_BASE)
+
+#define MK_RX_CMD(num_lines, lines_per_frame, now, chain) \
+ (((num_lines) << 9) | ((lines_per_frame) & 0x1ff) \
+ | (((now) & 0x1) << 31) | (((chain) & 0x1) << 30))
+
+/*
+ * --- ethernet tx protocol engine regs (write only) ---
+ *
+ * These registers control the transmit portion of the ethernet
+ * protocol engine (out of USRP2). The protocol engine handles fifo
+ * status and sequence number insertion in outgoing packets, and
+ * automagically generates status packets when required to inform the
+ * host of changes in fifo availability.
+ *
+ * All outgoing packets have their fifo_status field set to the number
+ * of 32-bit lines of fifo available in the ethernet Rx fifo (see
+ * usrp2_eth_packet.h). Seqno's are set if FIXME, else 0.
+ *
+ * FIXME clean this up once we know how it's supposed to behave.
+ */
+
+typedef struct {
+ volatile uint32_t flags; // not yet fully defined (channel?)
+ volatile uint32_t mac_dst0123; // 4 bytes of destination mac addr
+ volatile uint32_t mac_dst45src01; // 2 bytes of dest mac addr; 2 bytes of src mac addr
+ volatile uint32_t mac_src2345; // 4 bytes of destination mac addr
+ volatile uint32_t seqno; // Write to init seqno. It autoincs on match
+} tx_proto_engine_regs_t;
+
+#define tx_proto_engine ((tx_proto_engine_regs_t *) TX_PROTOCOL_ENGINE_BASE)
+
+/*
+ * --- ethernet rx protocol engine regs (write only) ---
+ *
+ * These registers control the receive portion of the ethernet
+ * protocol engine (into USRP2). The protocol engine offloads common
+ * packet inspection operations so that firmware has less to do on
+ * "fast path" packets.
+ *
+ * The registers define conditions which must be matched for a packet
+ * to be considered a "fast path" packet. If a received packet
+ * matches the src and dst mac address, ethertype, flags field, and
+ * expected seqno number it is considered a "fast path" packet, and
+ * the expected seqno is updated. If the packet fails to satisfy any
+ * of the above conditions it's a "slow path" packet, and the
+ * corresponding SLOWPATH flag will be set buffer_status register.
+ */
+
+typedef struct {
+ volatile uint32_t flags; // not yet fully defined (channel?)
+ volatile uint32_t mac_dst0123; // 4 bytes of destination mac addr
+ volatile uint32_t mac_dst45src01; // 2 bytes of dest mac addr; 2 bytes of src mac addr
+ volatile uint32_t mac_src2345; // 4 bytes of destination mac addr
+ volatile uint32_t ethertype_pad; // ethertype in high 16-bits
+} rx_proto_engine_regs_t;
+
+#define rx_proto_engine ((rx_proto_engine_regs_t *) RX_PROTOCOL_ENGINE_BASE)
+
+
+
+///////////////////////////////////////////////////
+// Simple Programmable Interrupt Controller, Slave 8
+
+#define PIC_BASE 0xD800
+
+// Interrupt request lines
+// Bit numbers (LSB == 0) that correpond to interrupts into PIC
+
+#define IRQ_BUFFER 0 // buffer manager
+#define IRQ_TIMER 1
+#define IRQ_SPI 2
+#define IRQ_I2C 3
+#define IRQ_PHY 4 // ethernet PHY
+#define IRQ_UNDERRUN 5
+#define IRQ_OVERRUN 6
+#define IRQ_PPS 7 // pulse per second
+#define IRQ_UART_RX 8
+#define IRQ_UART_TX 9
+
+#define IRQ_TO_MASK(x) (1 << (x))
+
+#define PIC_BUFFER_INT IRQ_TO_MASK(IRQ_BUFFER)
+#define PIC_TIMER_INT IRQ_TO_MASK(IRQ_TIMER)
+#define PIC_SPI_INT IRQ_TO_MASK(IRQ_SPI)
+#define PIC_I2C_INT IRQ_TO_MASK(IRQ_I2C)
+#define PIC_PHY_INT IRQ_TO_MASK(IRQ_PHY)
+#define PIC_UNDERRUN_INT IRQ_TO_MASK(IRQ_UNDERRUN)
+#define PIC_OVERRUN_INT IRQ_TO_MASK(IRQ_OVERRUN)
+#define PIC_PPS_INT IRQ_TO_MASK(IRQ_PPS)
+#define PIC_UART_RX_INT IRQ_TO_MASK(IRQ_UART_RX)
+#define PIC_UART_TX_INT IRQ_TO_MASK(IRQ_UART_TX)
+
+
+typedef struct {
+ volatile uint32_t edge_enable; // mask: 1 -> edge triggered, 0 -> level
+ volatile uint32_t polarity; // mask: 1 -> rising edge
+ volatile uint32_t mask; // mask: 1 -> disabled
+ volatile uint32_t pending; // mask: 1 -> pending; write 1's to clear pending ints
+} pic_regs_t;
+
+#define pic_regs ((pic_regs_t *) PIC_BASE)
+
+///////////////////////////////////////////////////
+// Timer, Slave 9
+
+#define TIMER_BASE 0xDC00
+
+typedef struct {
+ volatile uint32_t time; // R: current, W: set time to interrupt
+} timer_regs_t;
+
+#define timer_regs ((timer_regs_t *) TIMER_BASE)
+
+///////////////////////////////////////////////////
+// UART, Slave 10
+
+#define UART_BASE 0xE000
+
+typedef struct {
+ // All elements are 8 bits except for clkdiv (16), but we use uint32 to make
+ // the hardware for decoding easier
+ volatile uint32_t clkdiv; // Set to 50e6 divided by baud rate (no x16 factor)
+ volatile uint32_t txlevel; // Number of spaces in the FIFO for writes
+ volatile uint32_t rxlevel; // Number of available elements in the FIFO for reads
+ volatile uint32_t txchar; // Write characters to be sent here
+ volatile uint32_t rxchar; // Read received characters here
+} uart_regs_t;
+
+#define uart_regs ((uart_regs_t *) UART_BASE)
+
+///////////////////////////////////////////////////
+// ATR Controller, Slave 11
+
+#define ATR_BASE 0xE400
+
+typedef struct {
+ volatile uint32_t v[16];
+} atr_regs_t;
+
+#define ATR_IDLE 0x0 // indicies into v
+#define ATR_TX 0x1
+#define ATR_RX 0x2
+#define ATR_FULL 0x3
+
+#define atr_regs ((atr_regs_t *) ATR_BASE)
+
+///////////////////////////////////////////////////
+// Time Sync Controller, Slave 12
+
+#define TIMESYNC_BASE 0xE800
+
+typedef struct {
+ volatile uint32_t tick_control;
+ volatile uint32_t tick_interval;
+ volatile uint32_t delta_time;
+} timesync_regs_t;
+
+#define timesync_regs ((timesync_regs_t *) TIMESYNC_BASE)
+
+///////////////////////////////////////////////////
+// SD Card SPI interface, Slave 13
+// All regs are 8 bits wide, but are accessed as if they are 32 bits
+
+#define SDSPI_BASE 0xEC00
+
+typedef struct {
+ volatile uint32_t status;
+ volatile uint32_t clkdiv;
+ volatile uint32_t send_dat;
+ volatile uint32_t receive_dat;
+} sdspi_regs_t;
+
+#define sdspi_regs ((sdspi_regs_t *) SDSPI_BASE)
+
+///////////////////////////////////////////////////
+
+#endif
+
diff --git a/usrp2/firmware/lib/memset_wa.c b/usrp2/firmware/lib/memset_wa.c
new file mode 100644
index 000000000..da5da21ab
--- /dev/null
+++ b/usrp2/firmware/lib/memset_wa.c
@@ -0,0 +1,45 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "memset_wa.h"
+#include <stdint.h>
+#include <stdlib.h>
+
+/*
+ * For setting non-byte-adressable memory, such as
+ * the buffers. dst and nbytes must all satisfy (x % 4 == 0)
+ */
+void *
+memset_wa(void *dst, int c, size_t nbytes)
+{
+ if (((intptr_t) dst & 0x3)
+ || (nbytes & 0x3))
+ exit(1); /* die! */
+
+ int *dp = (int *) dst;
+
+ c &= 0xff;
+ int v = (c << 24) | (c << 16) | (c << 8) | c;
+ unsigned nw = nbytes/4;
+
+ unsigned i;
+ for (i = 0; i < nw; i++)
+ dp[i] = v;
+
+ return dst;
+}
diff --git a/usrp2/firmware/lib/memset_wa.h b/usrp2/firmware/lib/memset_wa.h
new file mode 100644
index 000000000..46d903d53
--- /dev/null
+++ b/usrp2/firmware/lib/memset_wa.h
@@ -0,0 +1,27 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_MEMSET_WA_H
+#define INCLUDED_MEMSET_WA_H
+
+#include <stdlib.h>
+
+void *memset_wa(void *s, int c, size_t n);
+
+
+#endif /* INCLUDED_MEMSET_WA_H */
diff --git a/usrp2/firmware/lib/microblaze.ld b/usrp2/firmware/lib/microblaze.ld
new file mode 100644
index 000000000..ef816cf2e
--- /dev/null
+++ b/usrp2/firmware/lib/microblaze.ld
@@ -0,0 +1,163 @@
+OUTPUT_FORMAT("elf32-microblaze", "", "")
+/* SEARCH_DIR(/home/jwilliams/tmp/microblaze-toolchain-sources/release/lin/microblaze//lib);*/
+
+ENTRY(_start)
+
+MEMORY {
+ flatmem : ORIGIN = 0x0, LENGTH = 0x00008000 /* 32KB */
+}
+
+SECTIONS
+{
+ _TEXT_START_ADDR = DEFINED(_TEXT_START_ADDR) ? _TEXT_START_ADDR : 0x50;
+ .vectors.reset 0x0 : { *(.vectors.reset) } > flatmem
+ .vectors.sw_exception 0x8 : { *(.vectors.sw_exception) } > flatmem
+ .vectors.interrupt 0x10 : { *(.vectors.interrupt) } > flatmem
+ .vectors.hw_exception 0x20 : { *(.vectors.hw_exception) } >flatmem
+ . = _TEXT_START_ADDR;
+ _ftext = .;
+ .text : {
+ *(.text)
+ *(.text.*)
+ *(.gnu.linkonce.t.*)
+ } > flatmem
+ _etext = .;
+ .init : { KEEP (*(.init)) } > flatmem =0
+ .fini : { KEEP (*(.fini)) } > flatmem =0
+ PROVIDE (__CTOR_LIST__ = .);
+ PROVIDE (___CTOR_LIST__ = .);
+ .ctors :
+ {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ /* We don't want to include the .ctor section from
+ from the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ } > flatmem
+ PROVIDE (__CTOR_END__ = .);
+ PROVIDE (___CTOR_END__ = .);
+ PROVIDE (__DTOR_LIST__ = .);
+ PROVIDE (___DTOR_LIST__ = .);
+ .dtors :
+ {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ } > flatmem
+ PROVIDE (__DTOR_END__ = .);
+ PROVIDE (___DTOR_END__ = .);
+ . = ALIGN(4);
+ _frodata = . ;
+ .rodata : {
+ *(.rodata)
+ *(.gnu.linkonce.r.*)
+ CONSTRUCTORS; /* Is this needed? */
+ } > flatmem
+ _erodata = .;
+ /* Alignments by 8 to ensure that _SDA2_BASE_ on a word boundary */
+ /* Note that .sdata2 and .sbss2 must be contiguous */
+ . = ALIGN(8);
+ _ssrw = .;
+ .sdata2 : {
+ *(.sdata2)
+ *(.gnu.linkonce.s2.*)
+ } > flatmem
+ . = ALIGN(4);
+ .sbss2 : {
+ PROVIDE (__sbss2_start = .);
+ *(.sbss2)
+ *(.gnu.linkonce.sb2.*)
+ PROVIDE (__sbss2_end = .);
+ } > flatmem
+ . = ALIGN(8);
+ _essrw = .;
+ _ssrw_size = _essrw - _ssrw;
+ PROVIDE (_SDA2_BASE_ = _ssrw + (_ssrw_size / 2 ));
+ . = ALIGN(4);
+ _fdata = .;
+ .data : {
+ *(.data)
+ *(.gnu.linkonce.d.*)
+ CONSTRUCTORS; /* Is this needed? */
+ } > flatmem
+ _edata = . ;
+ /* Added to handle pic code */
+ .got : {
+ *(.got)
+ } > flatmem
+ .got1 : {
+ *(.got1)
+ } > flatmem
+ .got2 : {
+ *(.got2)
+ } > flatmem
+ /* Added by Sathya to handle C++ exceptions */
+ .eh_frame : {
+ *(.eh_frame)
+ } > flatmem
+ .jcr : {
+ *(.jcr)
+ } > flatmem
+ .gcc_except_table : {
+ *(.gcc_except_table)
+ } > flatmem
+ /* Alignments by 8 to ensure that _SDA_BASE_ on a word boundary */
+ /* Note that .sdata and .sbss must be contiguous */
+ . = ALIGN(8);
+ _ssro = .;
+ .sdata : {
+ *(.sdata)
+ *(.gnu.linkonce.s.*)
+ } > flatmem
+ . = ALIGN(4);
+ .sbss : {
+ PROVIDE (__sbss_start = .);
+ *(.sbss)
+ *(.gnu.linkonce.sb.*)
+ PROVIDE (__sbss_end = .);
+ } > flatmem
+ . = ALIGN(8);
+ _essro = .;
+ _ssro_size = _essro - _ssro;
+ PROVIDE (_SDA_BASE_ = _ssro + (_ssro_size / 2 ));
+ . = ALIGN(4);
+ _fbss = .;
+ .bss : {
+ PROVIDE (__bss_start = .);
+ *(.bss)
+ *(.gnu.linkonce.b.*)
+ *(COMMON)
+ . = ALIGN(4);
+ PROVIDE (__bss_end = .);
+ _heap = .;
+ _HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x0;
+ _STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x800;
+ . += _HEAP_SIZE;
+ _heap_end = .;
+ . += _STACK_SIZE;
+ . = ALIGN(8);
+ _stack = .;
+ _end = .;
+ } > flatmem
+ .tdata : {
+ *(.tdata)
+ *(.gnu.linkonce.td.*)
+ } > flatmem
+ .tbss : {
+ *(.tbss)
+ *(.gnu.linkonce.tb.*)
+ } > flatmem
+}
diff --git a/usrp2/firmware/lib/nonstdio.c b/usrp2/firmware/lib/nonstdio.c
new file mode 100644
index 000000000..1c991afee
--- /dev/null
+++ b/usrp2/firmware/lib/nonstdio.c
@@ -0,0 +1,80 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nonstdio.h>
+
+static const char hex[16] = "0123456789ABCDEF";
+
+// %x
+void
+puthex4(unsigned long x)
+{
+ putchar(hex[x & 0xf]);
+}
+
+// %02x
+void
+puthex8(unsigned long x)
+{
+ putchar(hex[(x >> 4) & 0xf]);
+ putchar(hex[x & 0xf]);
+}
+
+// %04x
+void
+puthex16(unsigned long x)
+{
+ puthex8(x >> 8);
+ puthex8(x);
+}
+
+// %08x
+void
+puthex32(unsigned long x)
+{
+ puthex16(x >> 16);
+ puthex16(x);
+}
+
+void
+puthex4_nl(unsigned long x)
+{
+ puthex4(x);
+ newline();
+}
+
+void
+puthex8_nl(unsigned long x)
+{
+ puthex8(x);
+ newline();
+}
+
+void
+puthex16_nl(unsigned long x)
+{
+ puthex16(x);
+ newline();
+}
+
+void
+puthex32_nl(unsigned long x)
+{
+ puthex32(x);
+ newline();
+}
diff --git a/usrp2/firmware/lib/nonstdio.h b/usrp2/firmware/lib/nonstdio.h
new file mode 100644
index 000000000..3fd9e39bb
--- /dev/null
+++ b/usrp2/firmware/lib/nonstdio.h
@@ -0,0 +1,46 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_NONSTDIO_H
+#define INCLUDED_NONSTDIO_H
+
+#include <stdio.h>
+#include <usrp2_types.h>
+#include <stddef.h>
+
+void putstr(const char *s); // cf puts, no added newline
+void puthex4(unsigned long x); // output 1 hex digit
+void puthex8(unsigned long x); // output 2 hex digits
+void puthex16(unsigned long x); // output 4 hex digits
+void puthex32(unsigned long x); // output 8 hex digits
+void puthex4_nl(unsigned long x); // ... followed by newline
+void puthex8_nl(unsigned long x);
+void puthex16_nl(unsigned long x);
+void puthex32_nl(unsigned long x);
+#define puthex puthex32
+#define puthex_nl puthex32_nl
+void newline(); // putchar('\n')
+
+void print_mac_addr(const unsigned char addr[6]);
+void print_fxpt_freq(u2_fxpt_freq_t v);
+void print_fxpt_gain(u2_fxpt_gain_t v);
+void print_uint64(uint64_t v);
+
+void print_buffer(uint32_t *buf, size_t n);
+
+#endif /* INCLUDED_NONSTDIO_H */
diff --git a/usrp2/firmware/lib/pic.c b/usrp2/firmware/lib/pic.c
new file mode 100644
index 000000000..592a07aef
--- /dev/null
+++ b/usrp2/firmware/lib/pic.c
@@ -0,0 +1,94 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pic.h"
+#include "hal_io.h"
+#include "memory_map.h"
+
+
+#define NVECTORS 8
+
+/*
+ * Our secondary interrupt vector.
+ */
+irq_handler_t pic_vector[NVECTORS] = {
+ nop_handler,
+ nop_handler,
+ nop_handler,
+ nop_handler,
+ nop_handler,
+ nop_handler,
+ nop_handler,
+ nop_handler
+};
+
+
+void
+pic_init(void)
+{
+ // uP is level triggered
+
+ pic_regs->mask = ~0; // mask all interrupts
+ pic_regs->edge_enable = PIC_TIMER_INT | PIC_PHY_INT;
+ pic_regs->polarity = ~0 & ~PIC_PHY_INT; // rising edge
+ pic_regs->pending = ~0; // clear all pending ints
+}
+
+/*
+ * This magic gets pic_interrupt_handler wired into the
+ * system interrupt handler with the appropriate prologue and
+ * epilogue.
+ */
+void pic_interrupt_handler() __attribute__ ((interrupt_handler));
+
+void pic_interrupt_handler()
+{
+ // pending and not masked interrupts
+ int live = pic_regs->pending & ~pic_regs->mask;
+
+ // FIXME loop while there are interrupts to service.
+ // That will reduce our overhead.
+
+ // handle the first one set
+ int i;
+ int mask;
+ for (i=0, mask=1; i < NVECTORS; i++, mask <<= 1){
+ if (mask & live){ // handle this one
+ // puthex_nl(i);
+ (*pic_vector[i])(i);
+ pic_regs->pending = mask; // clear pending interrupt
+ return;
+ }
+ }
+}
+
+void
+pic_register_handler(unsigned irq, irq_handler_t handler)
+{
+ if (irq >= NVECTORS)
+ return;
+ pic_vector[irq] = handler;
+
+ pic_regs->mask &= ~IRQ_TO_MASK(irq);
+}
+
+void
+nop_handler(unsigned irq)
+{
+ // nop
+}
diff --git a/usrp2/firmware/lib/pic.h b/usrp2/firmware/lib/pic.h
new file mode 100644
index 000000000..68918f9ad
--- /dev/null
+++ b/usrp2/firmware/lib/pic.h
@@ -0,0 +1,35 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_PIC_H
+#define INCLUDED_PIC_H
+
+typedef void (*irq_handler_t)(unsigned irq);
+
+void pic_init(void);
+void pic_register_handler(unsigned irq, irq_handler_t handler);
+
+void nop_handler(unsigned irq); // default handler does nothing
+
+// FIXME inline assembler
+int pic_disable_interrupts();
+int pic_enable_interrupts();
+void pic_restore_interrupts(int prev_status);
+
+
+#endif /* INCLUDED_PIC_H */
diff --git a/usrp2/firmware/lib/print_buffer.c b/usrp2/firmware/lib/print_buffer.c
new file mode 100644
index 000000000..9f9104bb5
--- /dev/null
+++ b/usrp2/firmware/lib/print_buffer.c
@@ -0,0 +1,36 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <nonstdio.h>
+
+void
+print_buffer(uint32_t *buf, size_t n)
+{
+ size_t i;
+ for (i = 0; i < n; i++){
+ if (i % 4 == 0)
+ puthex16(i * 4);
+
+ putchar(' ');
+ puthex32(buf[i]);
+ if (i % 4 == 3)
+ newline();
+ }
+
+ newline();
+}
+
diff --git a/usrp2/firmware/lib/print_fxpt.c b/usrp2/firmware/lib/print_fxpt.c
new file mode 100644
index 000000000..185bbc51b
--- /dev/null
+++ b/usrp2/firmware/lib/print_fxpt.c
@@ -0,0 +1,83 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <nonstdio.h>
+
+/*
+ * print uint64_t
+ */
+void
+print_uint64(uint64_t u)
+{
+ const char *_hex = "0123456789ABCDEF";
+ if (u >= 10)
+ print_uint64(u/10);
+ putchar(_hex[u%10]);
+}
+
+static void
+print_thousandths(int thousandths)
+{
+ putchar('.');
+ if (thousandths < 100)
+ putchar('0');
+ if (thousandths < 10)
+ putchar('0');
+ printf("%d", thousandths);
+}
+
+
+void
+print_fxpt_freq(u2_fxpt_freq_t v)
+{
+ if (v < 0){
+ v = -v;
+ putchar('-');
+ }
+
+ int64_t int_part = v >> 20;
+ int32_t frac_part = v & ((1 << 20) - 1);
+
+#if 0
+ // would work, if we had it
+ printf("%lld.%03d", int_part, (frac_part * 1000) >> 20);
+#else
+ print_uint64(int_part);
+ print_thousandths((frac_part * 1000) >> 20);
+#endif
+}
+
+void
+print_fxpt_gain(u2_fxpt_gain_t v)
+{
+ if (v < 0){
+ v = -v;
+ putchar('-');
+ }
+
+ int32_t int_part = v >> 7;
+ int32_t frac_part = v & ((1 << 7) - 1);
+
+#if 0
+ // would work, if we had it
+ printf("%d.%03d", int_part, (frac_part * 1000) >> 7);
+#else
+ printf("%d", int_part);
+ print_thousandths((frac_part * 1000) >> 7);
+#endif
+}
+
diff --git a/usrp2/firmware/lib/print_mac_addr.c b/usrp2/firmware/lib/print_mac_addr.c
new file mode 100644
index 000000000..838fd614a
--- /dev/null
+++ b/usrp2/firmware/lib/print_mac_addr.c
@@ -0,0 +1,30 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#include "nonstdio.h"
+
+void
+print_mac_addr(const unsigned char addr[6])
+{
+ puthex8(addr[0]); putchar(':');
+ puthex8(addr[1]); putchar(':');
+ puthex8(addr[2]); putchar(':');
+ puthex8(addr[3]); putchar(':');
+ puthex8(addr[4]); putchar(':');
+ puthex8(addr[5]);
+}
+
diff --git a/usrp2/firmware/lib/print_rmon_regs.c b/usrp2/firmware/lib/print_rmon_regs.c
new file mode 100644
index 000000000..6d9986909
--- /dev/null
+++ b/usrp2/firmware/lib/print_rmon_regs.c
@@ -0,0 +1,44 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "print_rmon_regs.h"
+#include "eth_mac.h"
+#include "nonstdio.h"
+
+void
+print_rmon_regs(void)
+{
+ int i;
+ for (i=0; i <= 0x10; i++){
+ putstr("RMON[0x");
+ puthex8(i);
+ putstr("] = ");
+ printf("%d\n", eth_mac_read_rmon(i));
+ }
+
+ for (i=0x20; i <= 0x30; i++){
+ putstr("RMON[0x");
+ puthex8(i);
+ putstr("] = ");
+ printf("%d\n", eth_mac_read_rmon(i));
+ }
+}
diff --git a/usrp2/firmware/lib/print_rmon_regs.h b/usrp2/firmware/lib/print_rmon_regs.h
new file mode 100644
index 000000000..44e52da84
--- /dev/null
+++ b/usrp2/firmware/lib/print_rmon_regs.h
@@ -0,0 +1,24 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_PRINT_RMON_REGS_H
+#define INCLUDED_PRINT_RMON_REGS_H
+
+void print_rmon_regs(void);
+
+#endif /* INCLUDED_PRINT_RMON_REGS_H */
diff --git a/usrp2/firmware/lib/printf.c b/usrp2/firmware/lib/printf.c
new file mode 100644
index 000000000..45bd57cb9
--- /dev/null
+++ b/usrp2/firmware/lib/printf.c
@@ -0,0 +1,134 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Based on code from the SDCC z80 library ;)
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+static void
+_printn(unsigned u, unsigned base, char issigned,
+ void (*emitter)(char, void *), void *pData)
+{
+ const char *_hex = "0123456789ABCDEF";
+ if (issigned && ((int)u < 0)) {
+ (*emitter)('-', pData);
+ u = (unsigned)-((int)u);
+ }
+ if (u >= base)
+ _printn(u/base, base, 0, emitter, pData);
+ (*emitter)(_hex[u%base], pData);
+}
+
+static void
+_printf(const char *format, void (*emitter)(char, void *),
+ void *pData, va_list va)
+{
+ while (*format) {
+ if (*format != '%')
+ (*emitter)(*format, pData);
+ else {
+ switch (*++format) {
+ case 0: /* hit end of format string */
+ return;
+ case 'c':
+ {
+ char c = (char)va_arg(va, int);
+ (*emitter)(c, pData);
+ break;
+ }
+ case 'u':
+ {
+ unsigned u = va_arg(va, unsigned);
+ _printn(u, 10, 0, emitter, pData);
+ break;
+ }
+ case 'd':
+ {
+ unsigned u = va_arg(va, unsigned);
+ _printn(u, 10, 1, emitter, pData);
+ break;
+ }
+ case 'x':
+ case 'p':
+ {
+ unsigned u = va_arg(va, unsigned);
+ _printn(u, 16, 0, emitter, pData);
+ break;
+ }
+ case 's':
+ {
+ char *s = va_arg(va, char *);
+ while (*s) {
+ (*emitter)(*s, pData);
+ s++;
+ }
+ break;
+ }
+ }
+ }
+ format++;
+ }
+}
+
+static void
+_char_emitter(char c, void *pData __attribute__((unused)))
+{
+ putchar(c);
+}
+
+int
+printf(const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+
+ _printf(format, _char_emitter, NULL, va);
+
+ va_end(va);
+
+ // wrong return value...
+ return 0;
+}
+
+
+#if 0
+
+// Totally dangerous. Don't use
+static void
+_buf_emitter(char c, void *pData)
+{
+ *((*((char **)pData)))++ = c;
+}
+
+int sprintf(char *pInto, const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+
+ _printf(format, _buf_emitter, &pInto, va);
+ *pInto++ = '\0';
+
+ va_end(va);
+
+ // FIXME wrong return value
+ return 0;
+}
+#endif
diff --git a/usrp2/firmware/lib/printf.c.smaller b/usrp2/firmware/lib/printf.c.smaller
new file mode 100644
index 000000000..4d858648d
--- /dev/null
+++ b/usrp2/firmware/lib/printf.c.smaller
@@ -0,0 +1,134 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Based on code from the SDCC z80 library ;)
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <hal_io.h> /* FIXME refactor into stdio */
+
+#define PUTCHAR(x) hal_putc(x)
+
+
+static void
+_printn(unsigned u, unsigned base, char issigned)
+{
+ const char *_hex = "0123456789ABCDEF";
+ if (issigned && ((int)u < 0)) {
+ PUTCHAR('-');
+ u = (unsigned)-((int)u);
+ }
+ if (u >= base)
+ _printn(u/base, base, 0);
+ PUTCHAR(_hex[u%base]);
+}
+
+static void
+_printf(const char *format, va_list va)
+{
+ while (*format) {
+ if (*format != '%')
+ PUTCHAR(*format);
+ else {
+ switch (*++format) {
+ case 0: /* hit end of format string */
+ return;
+ case 'c':
+ {
+ char c = (char)va_arg(va, int);
+ PUTCHAR(c);
+ break;
+ }
+ case 'u':
+ {
+ unsigned u = va_arg(va, unsigned);
+ _printn(u, 10, 0);
+ break;
+ }
+ case 'd':
+ {
+ unsigned u = va_arg(va, unsigned);
+ _printn(u, 10, 1);
+ break;
+ }
+ case 'x':
+ case 'p':
+ {
+ unsigned u = va_arg(va, unsigned);
+ _printn(u, 16, 0);
+ break;
+ }
+ case 's':
+ {
+ char *s = va_arg(va, char *);
+ while (*s) {
+ PUTCHAR(*s);
+ s++;
+ }
+ break;
+ }
+ }
+ }
+ format++;
+ }
+}
+
+#if 0
+static void
+_char_emitter(char c, void *pData __attribute__((unused)))
+{
+ hal_putc(c);
+}
+#endif
+
+int
+printf(const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+
+ _printf(format, va);
+
+ // wrong return value...
+ return 0;
+}
+
+
+#if 0
+
+// Totally dangerous. Don't use
+static void
+_buf_emitter(char c, void *pData)
+{
+ *((*((char **)pData)))++ = c;
+}
+
+int sprintf(char *pInto, const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+
+ _printf(format, _buf_emitter, &pInto, va);
+ *pInto++ = '\0';
+
+ // FIXME wrong return value
+ return 0;
+}
+#endif
diff --git a/usrp2/firmware/lib/spi.c b/usrp2/firmware/lib/spi.c
new file mode 100644
index 000000000..937397df6
--- /dev/null
+++ b/usrp2/firmware/lib/spi.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "spi.h"
+#include "memory_map.h"
+
+void
+spi_init(void)
+{
+ /*
+ * f_sclk = f_wb / ((div + 1) * 2)
+ */
+ spi_regs->div = 1; // 0 = Div by 2 (25 MHz); 1 = Div-by-4 (12.5 MHz)
+}
+
+void
+spi_wait(void)
+{
+ while (spi_regs->ctrl & SPI_CTRL_GO_BSY)
+ ;
+}
+
+uint32_t
+spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags)
+{
+ flags &= (SPI_CTRL_TXNEG | SPI_CTRL_RXNEG);
+ int ctrl = SPI_CTRL_ASS | (SPI_CTRL_CHAR_LEN_MASK & length) | flags;
+
+ spi_wait();
+
+ // Tell it which SPI slave device to access
+ spi_regs->ss = slave & 0xff;
+
+ // Data we will send
+ spi_regs->txrx0 = data;
+
+ // Run it -- write once and rewrite with GO set
+ spi_regs->ctrl = ctrl;
+ spi_regs->ctrl = ctrl | SPI_CTRL_GO_BSY;
+
+ if(readback) {
+ spi_wait();
+ return spi_regs->txrx0;
+ }
+ else
+ return 0;
+}
diff --git a/usrp2/firmware/lib/spi.h b/usrp2/firmware/lib/spi.h
new file mode 100644
index 000000000..0914d6c3b
--- /dev/null
+++ b/usrp2/firmware/lib/spi.h
@@ -0,0 +1,52 @@
+/* -*- c -*- */
+/*
+ * Copyright 2006,2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_SPI_H
+#define INCLUDED_SPI_H
+
+#include <memory_map.h>
+#include <bool.h>
+
+/*!
+ * \brief One time call to initialize SPI
+ */
+void spi_init(void);
+
+/*!
+ * \brief Wait for last SPI transaction to complete.
+ * Unless you need to know it completed, it's not necessary to call this.
+ */
+void spi_wait(void);
+
+#define SPI_TXONLY false // readback: no
+#define SPI_TXRX true // readback: yes
+
+/*
+ * Flags for spi_transact
+ */
+#define SPIF_PUSH_RISE 0 // push tx data on rising edge of SCLK
+#define SPIF_PUSH_FALL SPI_CTRL_TXNEG // push tx data on falling edge of SCLK
+#define SPIF_LATCH_RISE 0 // latch rx data on rising edge of SCLK
+#define SPIF_LATCH_FALL SPI_CTRL_RXNEG // latch rx data on falling edge of SCLK
+
+
+uint32_t
+spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags);
+
+
+#endif /* INCLUDED_SPI_H */
diff --git a/usrp2/firmware/lib/stdint.h b/usrp2/firmware/lib/stdint.h
new file mode 100644
index 000000000..8086c25d5
--- /dev/null
+++ b/usrp2/firmware/lib/stdint.h
@@ -0,0 +1,34 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_STDINT_H
+#define INCLUDED_STDINT_H
+
+typedef char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+
+typedef int intptr_t;
+typedef unsigned int uintptr_t;
+
+#endif /* INCLUDED_STDINT_H */
diff --git a/usrp2/firmware/lib/stdio.h b/usrp2/firmware/lib/stdio.h
new file mode 100644
index 000000000..12a7ed0bb
--- /dev/null
+++ b/usrp2/firmware/lib/stdio.h
@@ -0,0 +1,38 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_STDIO_H
+#define INCLUDED_STDIO_H
+
+// very trimmed down stdio.h See also nonstdio.h
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef EOF
+#define EOF (-1)
+#endif
+
+int putchar(int c);
+int puts(const char *s);
+int printf(const char *format, ...);
+
+int getchar(void);
+
+#endif /* INCLUDED_STDIO_H */
diff --git a/usrp2/firmware/lib/u2_init.c b/usrp2/firmware/lib/u2_init.c
new file mode 100644
index 000000000..cb4b679c4
--- /dev/null
+++ b/usrp2/firmware/lib/u2_init.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "pic.h"
+#include "hal_io.h"
+#include "lsadc.h"
+#include "lsdac.h"
+#include "buffer_pool.h"
+#include "hal_uart.h"
+#include "i2c.h"
+#include "bool.h"
+#include "mdelay.h"
+#include "ad9777.h"
+#include "clocks.h"
+#include "db.h"
+
+//#include "nonstdio.h"
+
+/*
+ * We ought to arrange for this to be called before main, but for now,
+ * we require that the user's main call u2_init as the first thing...
+ */
+bool
+u2_init(void)
+{
+ // Set GPIOs to inputs
+ hal_gpio_set_ddr(GPIO_TX_BANK, 0x0000, 0xffff);
+ hal_gpio_set_ddr(GPIO_RX_BANK, 0x0000, 0xffff);
+
+ hal_gpio_write(GPIO_TX_BANK, 0x0000, 0xffff); // init s/w output value to zero
+ hal_gpio_write(GPIO_RX_BANK, 0x0000, 0xffff);
+
+ hal_io_init();
+
+ // init spi, so that we can switch over to the high-speed clock
+ spi_init();
+
+ // set up the default clocks
+ clocks_init();
+
+ // clocks_enable_test_clk(true);
+
+ // Enable ADCs
+ output_regs->adc_ctrl = ADC_CTRL_ON;
+
+ // Set up AD9777 DAC
+ ad9777_write_reg(0, R0_1R);
+ ad9777_write_reg(1, R1_INTERP_4X | R1_REAL_MIX);
+ ad9777_write_reg(2, 0);
+ ad9777_write_reg(3, R3_PLL_DIV_1);
+ ad9777_write_reg(4, R4_PLL_ON | R4_CP_AUTO);
+ ad9777_write_reg(5, R5_I_FINE_GAIN(0));
+ ad9777_write_reg(6, R6_I_COARSE_GAIN(0xf));
+ ad9777_write_reg(7, 0); // I dac offset
+ ad9777_write_reg(8, 0);
+ ad9777_write_reg(9, R9_Q_FINE_GAIN(0));
+ ad9777_write_reg(10, R10_Q_COARSE_GAIN(0xf));
+ ad9777_write_reg(11, 0); // Q dac offset
+ ad9777_write_reg(12, 0);
+
+ // Set up serdes
+ output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN);
+
+ pic_init(); // progammable interrupt controller
+ bp_init(); // buffer pool
+ i2c_init();
+ lsadc_init(); // low-speed ADCs
+ lsdac_init(); // low-speed DACs
+ db_init(); // daughterboard init
+
+ hal_enable_ints();
+
+ // flash all leds to let us know board is alive
+ hal_set_leds(0x0, 0x1f);
+ mdelay(100);
+ hal_set_leds(0x1f, 0x1f);
+ mdelay(100);
+ hal_set_leds(0x0, 0x1f);
+ mdelay(100);
+
+#if 0
+ // test register readback
+ int rr, vv;
+ vv = ad9777_read_reg(0);
+ printf("ad9777 reg[0] = 0x%x\n", vv);
+
+ for (rr = 0x04; rr <= 0x0d; rr++){
+ vv = ad9510_read_reg(rr);
+ printf("ad9510 reg[0x%x] = 0x%x\n", rr, vv);
+ }
+#endif
+
+ return true;
+}
diff --git a/usrp2/firmware/lib/u2_init.h b/usrp2/firmware/lib/u2_init.h
new file mode 100644
index 000000000..901e61250
--- /dev/null
+++ b/usrp2/firmware/lib/u2_init.h
@@ -0,0 +1,26 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef INCLUDED_U2_INIT_H
+#define INCLUDED_U2_INIT_H
+
+/*!
+ * one-time init
+ */
+int u2_init(void);
+
+#endif /* INCLUDED_U2_INIT_H */
diff --git a/usrp2/firmware/lib/usrp2_bytesex.h b/usrp2/firmware/lib/usrp2_bytesex.h
new file mode 100644
index 000000000..2b74f2a0b
--- /dev/null
+++ b/usrp2/firmware/lib/usrp2_bytesex.h
@@ -0,0 +1,66 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef INCLUDED_USRP2_BYTESEX_H
+#define INCLUDED_USRP2_BYTESEX_H
+
+// The USRP2 speaks big-endian...
+// Use the standard include files or provide substitutions for
+// htons and friends
+
+#if defined(HAVE_ARPA_INET_H)
+#include <arpa/inet.h>
+#elif defined(HAVE_NETINET_IN_H)
+#include <netinet/in.h>
+#else
+#include <stdint.h>
+
+#ifdef WORDS_BIGENDIAN // nothing to do...
+
+static inline uint32_t htonl(uint32_t x){ return x; }
+static inline uint16_t htons(uint16_t x){ return x; }
+static inline uint32_t ntohl(uint32_t x){ return x; }
+static inline uint16_t ntohs(uint16_t x){ return x; }
+
+#else
+
+#ifdef HAVE_BYTESWAP_H
+#include <byteswap.h>
+#else
+
+static inline uint16_t
+bswap_16 (uint16_t x)
+{
+ return ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8));
+}
+
+static inline uint32_t
+bswap_32 (uint32_t x)
+{
+ return ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \
+ | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24));
+}
+#endif
+
+static inline uint32_t htonl(uint32_t x){ return bswap_32(x); }
+static inline uint16_t htons(uint16_t x){ return bswap_16(x); }
+static inline uint32_t ntohl(uint32_t x){ return bswap_32(x); }
+static inline uint16_t ntohs(uint16_t x){ return bswap_16(x); }
+
+#endif
+#endif
+#endif /* INCLUDED_USRP2_BYTESEX_H */
diff --git a/usrp2/firmware/lib/wb16550.h b/usrp2/firmware/lib/wb16550.h
new file mode 100644
index 000000000..7522f4438
--- /dev/null
+++ b/usrp2/firmware/lib/wb16550.h
@@ -0,0 +1,98 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+
+// Wishbone National Semiconductor 16550A compatible UART
+
+#ifndef INCLUDED_WB16550_H
+#define INCLUDED_WB16550_H
+
+#include <stdint.h>
+
+typedef struct {
+ volatile uint8_t data; // 0 r/w: r: rx fifo, w: tx fifo (if DLAB: LSB of divisor)
+ volatile uint8_t ier; // 1 r/w: Interrupt Enable Register (if DLAB: MSB of divisor)
+ volatile uint8_t iir_fcr; // 2 r/w: r: Interrupt ID Register,
+ // w: Fifo Control Register
+ volatile uint8_t lcr; // 3 r/w: Line Control Register
+ volatile uint8_t mcr; // 4 w: Modem Control Register
+ volatile uint8_t lsr; // 5 r: Line Status Register
+ volatile uint8_t msr; // 6 r: Modem Status Register
+
+} wb16550_reg_t;
+
+#define UART_IER_RDI 0x01 // Enable received data interrupt
+#define UART_IER_THRI 0x02 // Enable transmitter holding reg empty int.
+#define UART_IER_RLSI 0x04 // Enable receiver line status interrupt
+#define UART_IER_MSI 0x08 // Enable modem status interrupt
+
+#define UART_IIR_NO_INT 0x01 // No interrupts pending
+#define UART_IIR_ID_MASK 0x06 // Mask for interrupt ID
+#define UART_IIR_MSI 0x00 // Modem status interrupt
+#define UART_IIR_THRI 0x02 // Tx holding register empty int
+#define UART_IIR_RDI 0x04 // Rx data available int
+#define UART_IIR_RLSI 0x06 // Receiver line status int
+
+#define UART_FCR_ENABLE_FIFO 0x01 // ignore, always enabled
+#define UART_FCR_CLEAR_RCVR 0x02 // Clear the RCVR FIFO
+#define UART_FCR_CLEAR_XMIT 0x04 // Clear the XMIT FIFO
+#define UART_FCR_TRIGGER_MASK 0xC0 // Mask for FIFO trigger range
+#define UART_FCR_TRIGGER_1 0x00 // Rx fifo trigger level: 1 byte
+#define UART_FCR_TRIGGER_4 0x40 // Rx fifo trigger level: 4 bytes
+#define UART_FCR_TRIGGER_8 0x80 // Rx fifo trigger level: 8 bytes
+#define UART_FCR_TRIGGER_14 0xC0 // Rx fifo trigger level: 14 bytes
+
+#define UART_LCR_DLAB 0x80 // Divisor latch access bit
+#define UART_LCR_SBC 0x40 // Set break control
+#define UART_LCR_SPAR 0x20 // Stick parity
+#define UART_LCR_EPAR 0x10 // Even parity select
+#define UART_LCR_PARITY 0x08 // Parity Enable
+#define UART_LCR_STOP 0x04 // Stop bits: 0=1 bit, 1=2 bits
+#define UART_LCR_WLEN5 0x00 // Wordlength: 5 bits
+#define UART_LCR_WLEN6 0x01 // Wordlength: 6 bits
+#define UART_LCR_WLEN7 0x02 // Wordlength: 7 bits
+#define UART_LCR_WLEN8 0x03 // Wordlength: 8 bits
+
+#define UART_MCR_LOOP 0x10 // Enable loopback test mode
+#define UART_MCR_OUT2n 0x08 // Out2 complement (loopback mode)
+#define UART_MCR_OUT1n 0x04 // Out1 complement (loopback mode)
+#define UART_MCR_RTSn 0x02 // RTS complement
+#define UART_MCR_DTRn 0x01 // DTR complement
+
+#define UART_LSR_TEMT 0x40 // Transmitter empty
+#define UART_LSR_THRE 0x20 // Transmit-hold-register empty
+#define UART_LSR_BI 0x10 // Break interrupt indicator
+#define UART_LSR_FE 0x08 // Frame error indicator
+#define UART_LSR_PE 0x04 // Parity error indicator
+#define UART_LSR_OE 0x02 // Overrun error indicator
+#define UART_LSR_DR 0x01 // Receiver data ready
+#define UART_LSR_BRK_ERROR_BITS 0x1E // BI, FE, PE, OE bits
+#define UART_LSR_ERROR 0x80 // At least 1 PE, FE or BI are in the fifo
+
+#define UART_MSR_DCD 0x80 // Data Carrier Detect
+#define UART_MSR_RI 0x40 // Ring Indicator
+#define UART_MSR_DSR 0x20 // Data Set Ready
+#define UART_MSR_CTS 0x10 // Clear to Send
+#define UART_MSR_DDCD 0x08 // Delta DCD
+#define UART_MSR_TERI 0x04 // Trailing edge ring indicator
+#define UART_MSR_DDSR 0x02 // Delta DSR
+#define UART_MSR_DCTS 0x01 // Delta CTS
+#define UART_MSR_ANY_DELTA 0x0F // Any of the delta bits!
+
+
+#endif // INCLUDED_WB16550_H
diff --git a/usrp2/firmware/u2_flash_tool b/usrp2/firmware/u2_flash_tool
new file mode 100755
index 000000000..2b66a4ac0
--- /dev/null
+++ b/usrp2/firmware/u2_flash_tool
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+
+import sys
+from optparse import OptionParser
+
+SECTOR_SIZE = 512 # bytes
+MAX_FILE_SIZE = 1 * (2**20) # maximum number of bytes we'll burn to a slot
+
+FPGA_OFFSET = 0 # offset in flash to fpga image
+FIRMWARE_OFFSET = 1 * (2**20) # offset in flash to firmware image
+
+def read_file_data(filename):
+ f = open(filename, "rb")
+ file_data = f.read(MAX_FILE_SIZE)
+ t = len(file_data) % SECTOR_SIZE
+ if t != 0:
+ file_data += (SECTOR_SIZE - t)*chr(0) # pad to an even sector size w/ zeros
+ return file_data
+
+
+def write_flash(offset, filename, devname):
+ file_data = read_file_data(filename)
+ dev = open(devname, "wb")
+ dev.seek(offset, 0) # seek to absolute byte offset
+ dev.write(file_data)
+ dev.flush()
+ dev.close()
+ return True
+
+
+def verify_flash(offset, filename, devname):
+ file_data = read_file_data(filename)
+ dev = open(devname, "rb")
+ dev.seek(offset, 0) # seek to absolute byte offset
+ dev_data = dev.read(len(file_data))
+ if len(dev_data) != len(file_data):
+ sys.stderr.write("short read on device %s\n" % (devname,))
+ return False
+
+ if file_data == dev_data:
+ return True
+
+ # doesn't match
+ nwrong = 0
+ for i in range(len(file_data)):
+ if dev_data[i] != file_data[i]:
+ sys.stderr.write("mismatch at offset %7d. Expected 0x%02x, got 0x%02x\n" % (
+ i, ord(file_data[i]), ord(dev_data[i])))
+ nwrong += 1
+ if nwrong > 16:
+ sys.stderr.write("> 16 errors, stopping comparison\n")
+ break
+ return False
+
+def read_flash(offset, filename, devname):
+ dev = open(devname, "rb")
+ dev.seek(offset, 0) # seek to absolute byte offset
+ dev_data = dev.read(MAX_FILE_SIZE)
+ dev.close()
+ open(filename, "wb").write(dev_data)
+
+
+def main():
+ parser = OptionParser(usage="%prog: [options] filename")
+ parser.add_option("-w", "--write", action="store_const", const="write", dest="mode",
+ help="write FILE to TARGET slot")
+ parser.add_option("-v", "--verify", action="store_const", const="verify", dest="mode",
+ help="verify FILE against TARGET slot")
+ parser.add_option("-r", "--read", action="store_const", const="read", dest="mode",
+ help="read TARGET slot, write to FILE")
+ parser.add_option("-t", "--target", type="choice", choices=("fpga", "s/w"), default="s/w",
+ help="select TARGET slot from: fpga, s/w [default=%default]")
+ parser.add_option("", "--dev", default=None,
+ help="specify flash device file, e.g., /dev/sdb. Be careful!")
+ parser.set_defaults(target="s/w", mode=None)
+
+ (options, args) = parser.parse_args()
+ if len(args) != 1:
+ parser.print_help()
+ raise SystemExit
+
+ filename = args[0]
+
+ if options.mode is None:
+ sys.stderr.write("specify mode with -w, -v or -r\n")
+ parser.print_help()
+ raise SystemExit
+
+ if options.dev is None:
+ sys.stderr.write("specify the device file with --dev\n")
+ parser.print_help()
+ raise SystemExit
+
+ offset = { "fpga" : FPGA_OFFSET, "s/w" : FIRMWARE_OFFSET }[options.target]
+
+ if options.mode == "write":
+ r = (write_flash(offset, filename, options.dev)
+ and verify_flash(offset, filename, options.dev))
+ elif options.mode == "verify":
+ r = verify_flash(offset, filename, options.dev)
+ elif options.mode == "read":
+ r = read_flash(offset, filename, options.dev)
+ else:
+ raise NotImplemented
+
+ if not r:
+ raise SystemExit, 1
+
+
+if __name__ == "__main__":
+ main()
+
+
+
+
+