├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── COPYING ├── Makefile ├── README.md ├── anyio.c ├── anyio.h ├── bitfile.c ├── bitfile.h ├── boards.h ├── common.c ├── common.h ├── debian ├── README.source ├── changelog ├── compat ├── control ├── copyright ├── rules ├── source │ └── format └── watch ├── eeprom.c ├── eeprom.h ├── eeprom_local.c ├── eeprom_local.h ├── eeprom_remote.c ├── eeprom_remote.h ├── encoder_module.c ├── encoder_module.h ├── epp_boards.c ├── epp_boards.h ├── eth_boards.c ├── eth_boards.h ├── examples ├── pci_analog_write.c └── pci_encoder_read.c ├── hostmot2.c ├── hostmot2.h ├── hostmot2_def.h ├── lbp.c ├── lbp.h ├── lbp16.c ├── lbp16.h ├── mesaflash.1 ├── mesaflash.c ├── pci_boards.c ├── pci_boards.h ├── serial_boards.c ├── serial_boards.h ├── spi_boards.c ├── spi_boards.h ├── sserial_module.c ├── sserial_module.h ├── types.h ├── usb_boards.c └── usb_boards.h /.gitattributes: -------------------------------------------------------------------------------- 1 | WinIo32.* export-ignore 2 | libpci.dll export-ignore 3 | 4 | libpci/** export-ignore 5 | libpci export-ignore 6 | 7 | winio32/** export-ignore 8 | winio32 export-ignore 9 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # vim: sw=2 2 | 3 | on: 4 | push: 5 | pull_request: 6 | release: 7 | types: [published] 8 | check_suite: 9 | types: [rerequested] 10 | 11 | jobs: 12 | test: 13 | runs-on: ubuntu-20.04 14 | steps: 15 | - name: Dump GitHub context 16 | env: 17 | GITHUB_CONTEXT: ${{ toJson(github) }} 18 | run: echo "$GITHUB_CONTEXT" 19 | 20 | - uses: actions/checkout@v4 21 | 22 | - name: Install deps 23 | run: | 24 | sudo apt-get update 25 | sudo apt-get install -y eatmydata 26 | sudo eatmydata apt-get install -y --no-install-suggests --no-install-recommends build-essential devscripts equivs 27 | mk-build-deps -irs sudo -t "apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends -y" 28 | 29 | - name: Build 30 | run: | 31 | make -j$(nproc) 32 | 33 | - name: Clean 34 | run: | 35 | make clean 36 | 37 | - name: Build (package) 38 | run: | 39 | dch -l+`git rev-parse --short HEAD` "actions package build" 40 | debuild -b 41 | 42 | 43 | test-package: 44 | strategy: 45 | fail-fast: false 46 | matrix: 47 | os: ["buster", "bullseye", "stable", "testing", "unstable"] 48 | cpu: ["i386", "amd64", "armhf", "aarch64"] 49 | runs-on: ubuntu-20.04 50 | steps: 51 | - uses: actions/checkout@v4 52 | with: 53 | fetch-depth: 0 54 | 55 | - name: Install tools for dch update 56 | run: | 57 | sudo apt-get update 58 | sudo apt install -y --no-install-suggests --no-install-recommends devscripts 59 | 60 | - name: Update debian changelog 61 | env: 62 | OS_RELEASE: ${{ matrix.os }} 63 | run: | 64 | git checkout HEAD -- debian/changelog 65 | git fetch --tags https://github.com/LinuxCNC/mesaflash 66 | ref=`git describe --tags --always | sed -e 's/^release\///;s/^v//;s/-/+/g'` 67 | DEBEMAIL=noreply@github.com dch -v "${ref}+${OS_RELEASE}-1" "Build from github actions" 68 | head debian/changelog 69 | 70 | - name: Build Debian package 71 | uses: dawidd6/action-debian-package@v1.6.0 72 | with: 73 | source_directory: . 74 | artifacts_directory: output 75 | os_distribution: ${{ matrix.os }} 76 | cpu_architecture: ${{ matrix.cpu }} 77 | 78 | - name: Upload artifact 79 | uses: actions/upload-artifact@v4 80 | with: 81 | path: output 82 | name: debs-${{ matrix.os }}-${{ matrix.cpu }} 83 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | libanyio* 3 | mesaflash 4 | mesaflash.exe 5 | pci_encoder_read 6 | pci_analog_write 7 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2013-2014 Michael Geszkiewicz 3 | # 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | 19 | # target (linux, windows) 20 | TARGET = linux 21 | LIBNAME = libanyio 22 | LIBANYIO = $(LIBNAME).a 23 | 24 | CC = gcc 25 | RM = rm -f 26 | AR = ar 27 | RANLIB = ranlib 28 | PKG_CONFIG ?= pkg-config 29 | 30 | OWNERSHIP ?= --owner root --group root 31 | 32 | # default CFLAGS 33 | CFLAGS ?= -O0 -g -Wall -Wextra -Werror 34 | 35 | # mesaflash needs at least C99 to compile. 36 | # 37 | # The oldest distros we support are Debian Wheezy (EOL 2018-05-31) 38 | # and Ubuntu Precise (EOL 2017-04-28): 39 | # 40 | # Debian Wheezy has gcc 4.7.2, which defaults to C90 but supports C11. 41 | # 42 | # Ubuntu Precise has gcc 4.6.3, which defaults to C90 but supports 43 | # C99 (but does not support C11). 44 | # 45 | # So we explicitly select the newest ancient C standard that we have to 46 | # support here. 47 | CFLAGS += -std=c99 48 | 49 | ifeq ($(TARGET),linux) 50 | $(shell which $(PKG_CONFIG) > /dev/null) 51 | ifeq ($(.SHELLSTATUS), 1) 52 | $(error "can't find pkg-config") 53 | endif 54 | 55 | $(shell $(PKG_CONFIG) --exists libpci > /dev/null) 56 | ifeq ($(.SHELLSTATUS), 1) 57 | $(error "pkg-config can't find libpci") 58 | endif 59 | 60 | $(shell $(PKG_CONFIG) --exists libmd > /dev/null) 61 | ifeq ($(.SHELLSTATUS), 1) 62 | $(error "pkg-config can't find libmd") 63 | endif 64 | 65 | LIBPCI_CFLAGS := $(shell $(PKG_CONFIG) --cflags libpci) 66 | LIBPCI_LDFLAGS := $(shell $(PKG_CONFIG) --libs libpci) 67 | LIBMD_CFLAGS := $(shell $(PKG_CONFIG) --cflags libmd) 68 | LIBMD_LDFLAGS := $(shell $(PKG_CONFIG) --libs libmd) 69 | BIN = mesaflash 70 | LDFLAGS = -lm $(LIBPCI_LDFLAGS) $(LIBMD_LDFLAGS) 71 | CFLAGS += -D_GNU_SOURCE $(LIBPCI_CFLAGS) $(LIBMD_CFLAGS) -D_FILE_OFFSET_BITS=64 72 | 73 | UNAME_M := $(shell uname -m) 74 | 75 | # 76 | # A bunch of platforms lack `sys/io.h`, which means mesaflash builds 77 | # without support for EPP or PCI cards. 78 | # 79 | 80 | ifeq ($(UNAME_M),aarch64) 81 | MESAFLASH_IO ?= 0 82 | endif 83 | 84 | ifeq ($(patsubst arm%,arm,$(UNAME_M)),arm) 85 | ifeq ($(wildcard /usr/include/arm-linux-gnueabihf/asm/io.h),) 86 | MESAFLASH_IO ?= 0 87 | endif 88 | endif 89 | 90 | ifeq ($(UNAME_M),loongarch64) 91 | MESAFLASH_IO ?= 0 92 | endif 93 | 94 | ifeq ($(UNAME_M),parisc) 95 | MESAFLASH_IO ?= 0 96 | endif 97 | 98 | ifeq ($(UNAME_M),m68k) 99 | MESAFLASH_IO ?= 0 100 | endif 101 | 102 | ifeq ($(patsubst mips%,mips,$(UNAME_M)),mips) 103 | MESAFLASH_IO ?= 0 104 | endif 105 | 106 | ifeq ($(patsubst ppc%,ppc,$(UNAME_M)),ppc) 107 | MESAFLASH_IO ?= 0 108 | endif 109 | 110 | ifeq ($(UNAME_M),riscv64) 111 | MESAFLASH_IO ?= 0 112 | endif 113 | 114 | ifeq ($(patsubst s390%,s390,$(UNAME_M)),s390) 115 | MESAFLASH_IO ?= 0 116 | endif 117 | 118 | ifeq ($(UNAME_M),sh) 119 | MESAFLASH_IO ?= 0 120 | endif 121 | 122 | ifeq ($(UNAME_M),sparc64) 123 | MESAFLASH_IO ?= 0 124 | endif 125 | 126 | endif 127 | 128 | ifeq ($(TARGET),windows) 129 | MINGW = c:/MinGW 130 | CFLAGS += -I$(MINGW)/include 131 | BIN = mesaflash.exe 132 | LDFLAGS = -lwsock32 -lws2_32 libpci.dll winio32.dll 133 | CFLAGS += -mno-ms-bitfields 134 | endif 135 | 136 | MESAFLASH_IO ?= 1 137 | CFLAGS += -DMESAFLASH_IO=$(MESAFLASH_IO) 138 | 139 | objects = common.o lbp.o lbp16.o bitfile.o hostmot2.o eeprom.o anyio.o eth_boards.o epp_boards.o usb_boards.o pci_boards.o 140 | objects += sserial_module.o encoder_module.o eeprom_local.o eeprom_remote.o spi_boards.o serial_boards.o 141 | 142 | headers = eth_boards.h pci_boards.h epp_boards.h usb_boards.h spi_boards.h serial_boards.h anyio.h hostmot2.h lbp16.h types.h 143 | headers += common.h eeprom.h lbp.h eeprom_local.h eeprom_remote.h bitfile.h sserial_module.h hostmot2_def.h boards.h 144 | headers += encoder_module.h 145 | 146 | all: $(LIBANYIO) $(BIN) pci_encoder_read pci_analog_write 147 | 148 | $(LIBANYIO) : $(objects) 149 | $(RM) $(LIBANYIO) $(BIN) 150 | $(AR) rcs $(LIBANYIO) $(objects) 151 | $(RANLIB) $(LIBANYIO) 152 | 153 | mesaflash.o : mesaflash.c $(headers) 154 | $(CC) $(CFLAGS) -c mesaflash.c 155 | 156 | $(BIN): mesaflash.o anyio.h $(LIBANYIO) 157 | $(CC) $(CFLAGS) -o $(BIN) mesaflash.o $(LIBANYIO) $(LDFLAGS) 158 | 159 | anyio.o : anyio.c $(headers) 160 | $(CC) $(CFLAGS) -c anyio.c 161 | 162 | eth_boards.o : eth_boards.c $(headers) 163 | $(CC) $(CFLAGS) -c eth_boards.c 164 | 165 | pci_boards.o : pci_boards.c $(headers) 166 | $(CC) $(CFLAGS) -c pci_boards.c 167 | 168 | epp_boards.o : epp_boards.c $(headers) 169 | $(CC) $(CFLAGS) -c epp_boards.c 170 | 171 | usb_boards.o : usb_boards.c $(headers) 172 | $(CC) $(CFLAGS) -c usb_boards.c 173 | 174 | spi_boards.o : spi_boards.c $(headers) 175 | $(CC) $(CFLAGS) -c spi_boards.c 176 | 177 | serial_boards.o : serial_boards.c $(headers) 178 | $(CC) $(CFLAGS) -c serial_boards.c 179 | 180 | sserial_module.o : sserial_module.c $(headers) 181 | $(CC) $(CFLAGS) -c sserial_module.c 182 | 183 | encoder_module.o : encoder_module.c $(headers) 184 | $(CC) $(CFLAGS) -c encoder_module.c 185 | 186 | eeprom_local.o : eeprom_local.c $(headers) 187 | $(CC) $(CFLAGS) -c eeprom_local.c 188 | 189 | eeprom_remote.o : eeprom_remote.c $(headers) 190 | $(CC) $(CFLAGS) -c eeprom_remote.c 191 | 192 | lbp.o : lbp.c $(headers) 193 | $(CC) $(CFLAGS) -c lbp.c 194 | 195 | lbp16.o : lbp16.c $(headers) 196 | $(CC) $(CFLAGS) -c lbp16.c 197 | 198 | hostmot2.o : hostmot2.c $(headers) 199 | $(CC) $(CFLAGS) -c hostmot2.c 200 | 201 | eeprom.o : eeprom.c $(headers) 202 | $(CC) $(CFLAGS) -c eeprom.c 203 | 204 | bitfile.o : bitfile.c $(headers) 205 | $(CC) $(CFLAGS) -c bitfile.c 206 | 207 | common.o : common.c $(headers) 208 | $(CC) $(CFLAGS) -c common.c 209 | 210 | pci_encoder_read.o : examples/pci_encoder_read.c $(LIBANYIO) $(headers) 211 | $(CC) $(CFLAGS) -c examples/pci_encoder_read.c 212 | 213 | pci_encoder_read: pci_encoder_read.o anyio.h encoder_module.h 214 | $(CC) $(CFLAGS) -o pci_encoder_read pci_encoder_read.o $(LIBANYIO) $(LDFLAGS) 215 | 216 | pci_analog_write.o : examples/pci_analog_write.c $(LIBANYIO) $(headers) 217 | $(CC) $(CFLAGS) -c examples/pci_analog_write.c 218 | 219 | pci_analog_write: pci_analog_write.o anyio.h sserial_module.h 220 | $(CC) $(CFLAGS) -o pci_analog_write pci_analog_write.o $(LIBANYIO) $(LDFLAGS) 221 | 222 | clean : 223 | $(RM) *.o $(LIBANYIO) $(BIN) pci_encoder_read pci_analog_write 224 | 225 | .PHONY: install 226 | install: $(BIN) 227 | install -p -D --mode=0755 $(OWNERSHIP) $(BIN) $(DESTDIR)/bin/$(BIN) 228 | install -p -D --mode=0644 $(OWNERSHIP) mesaflash.1 $(DESTDIR)/share/man/man1/mesaflash.1 229 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mesaflash 2 | 3 | Configuration and diagnostic tool for Mesa Electronics PCI(E)/ETH/EPP/USB/SPI boards 4 | 5 | Quickstart: 6 | =========== 7 | 8 | MesaFlash depends on a couple of packages to build, so install those 9 | first: 10 | ``` 11 | sudo apt install libpci-dev libmd-dev pkg-config build-essential git 12 | ``` 13 | Clone MesaFlash: 14 | ``` 15 | git clone https://github.com/LinuxCNC/mesaflash.git 16 | ``` 17 | 18 | From the top level directory, switch to the source directory: 19 | ``` 20 | cd mesaflash 21 | ``` 22 | In the source directory to build MesaFlash: 23 | ``` 24 | make 25 | ``` 26 | To get command line syntax from a local make: 27 | ``` 28 | ./mesaflash --help 29 | ``` 30 | 31 | To build and install MesaFlash, bypassing the operating system packaging system: 32 | ``` 33 | sudo make install 34 | ``` 35 | To run an installed MesaFlash: 36 | ``` 37 | mesaflash --help 38 | ``` 39 | 40 | Depending on permissions and the types of devices you wish to access, you may need to run mesaflash as root, `sudo ./mesaflash` or `sudo mesaflash`. 41 | 42 | Distributions 43 | =============== 44 | **mesaflash** package is available on [Fedora](https://src.fedoraproject.org/rpms/mesaflash) _(version 31 or newer)_ and can be simply installed by using: 45 | ``` 46 | # dnf install mesaflash 47 | ``` 48 | Availability of **mesaflash** for other Linux distributions can be checked on [release-monitoring](https://release-monitoring.org/project/105522/) project page. 49 | -------------------------------------------------------------------------------- /anyio.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #include 20 | #include 21 | #include 22 | #include "anyio.h" 23 | #include "eeprom.h" 24 | #include "bitfile.h" 25 | #include "eth_boards.h" 26 | #include "pci_boards.h" 27 | #include "epp_boards.h" 28 | #include "usb_boards.h" 29 | #include "spi_boards.h" 30 | #include "serial_boards.h" 31 | 32 | supported_board_entry_t supported_boards[] = { 33 | {"ETHER", BOARD_ETH | BOARD_WILDCARD}, 34 | {"SPI", BOARD_SPI | BOARD_WILDCARD}, 35 | {"7I92", BOARD_ETH}, 36 | {"7I92T", BOARD_ETH}, 37 | {"7I93", BOARD_ETH}, 38 | {"7I94", BOARD_ETH}, 39 | {"7I94T", BOARD_ETH}, 40 | {"7I95", BOARD_ETH}, 41 | {"7I95T", BOARD_ETH}, 42 | {"7I96", BOARD_ETH}, 43 | {"7I96S", BOARD_ETH}, 44 | {"7I97", BOARD_ETH}, 45 | {"7I97T", BOARD_ETH}, 46 | {"7I98", BOARD_ETH}, 47 | {"7I80HD-16", BOARD_ETH}, 48 | {"7I80HD-25", BOARD_ETH}, 49 | {"7I80DB-16", BOARD_ETH}, 50 | {"7I80DB-25", BOARD_ETH}, 51 | {"7I80HDT", BOARD_ETH}, 52 | {"7I76E", BOARD_ETH}, 53 | {"7I76EU", BOARD_ETH}, 54 | 55 | {"LITEHM2", BOARD_ETH}, 56 | 57 | {"4I74", BOARD_PCI}, 58 | {"5I24", BOARD_PCI}, 59 | {"5I25", BOARD_PCI}, 60 | {"6I24", BOARD_PCI}, 61 | {"6I25", BOARD_PCI}, 62 | {"5I20", BOARD_PCI}, 63 | {"RECOVER", BOARD_PCI}, 64 | {"4I65", BOARD_PCI}, 65 | {"4I68", BOARD_PCI}, 66 | {"5I21", BOARD_PCI}, 67 | {"5I22", BOARD_PCI}, 68 | {"5I23", BOARD_PCI}, 69 | {"4I69", BOARD_PCI}, 70 | {"3X20", BOARD_PCI}, 71 | 72 | {"7C80", BOARD_MULTI_INTERFACE | BOARD_EPP | BOARD_SPI}, 73 | {"7C81", BOARD_MULTI_INTERFACE | BOARD_EPP | BOARD_SPI}, 74 | {"7I43", BOARD_MULTI_INTERFACE | BOARD_EPP | BOARD_USB}, 75 | {"7I90HD", BOARD_MULTI_INTERFACE | BOARD_EPP | BOARD_SPI | BOARD_SER}, 76 | {"7I64", BOARD_MULTI_INTERFACE | BOARD_USB | BOARD_SPI}, 77 | 78 | {"AUTO", BOARD_MULTI_INTERFACE | BOARD_WILDCARD | BOARD_USB | BOARD_EPP | BOARD_SPI | BOARD_SER | BOARD_PCI}, 79 | {NULL, 0}, 80 | }; 81 | 82 | board_t boards[MAX_BOARDS]; 83 | int boards_count; 84 | 85 | int anyio_init(board_access_t *access) { 86 | if (access == NULL) { 87 | return -EINVAL; 88 | } 89 | return 0; 90 | } 91 | 92 | void anyio_cleanup(board_access_t *access) { 93 | if (access == NULL) { 94 | return; 95 | } 96 | if (access->open_iface & BOARD_ETH) 97 | eth_boards_cleanup(access); 98 | #if MESAFLASH_IO 99 | if (access->open_iface & BOARD_PCI) 100 | pci_boards_cleanup(access); 101 | if (access->open_iface & BOARD_EPP) 102 | epp_boards_cleanup(access); 103 | #endif 104 | if (access->open_iface & BOARD_USB) 105 | usb_boards_cleanup(access); 106 | if (access->open_iface & BOARD_SPI) 107 | spi_boards_cleanup(access); 108 | if (access->open_iface & BOARD_SER) 109 | serial_boards_cleanup(access); 110 | access->open_iface = 0; 111 | } 112 | 113 | int anyio_find_dev(board_access_t *access) { 114 | int i, ret = 0; 115 | supported_board_entry_t *supported_board = NULL; 116 | 117 | if (access == NULL) { 118 | return -1; 119 | } 120 | 121 | for (i = 0; supported_boards[i].name != NULL; i++) { 122 | if (strncmp(supported_boards[i].name, access->device_name, strlen(supported_boards[i].name)) == 0) { 123 | supported_board = &supported_boards[i]; 124 | break; 125 | } 126 | } 127 | 128 | if (supported_board == NULL) { 129 | printf("ERROR: Unsupported device %s\n", access->device_name); 130 | anyio_print_supported_board_names(); 131 | return -1; 132 | } 133 | 134 | access->open_iface = 0; 135 | if (supported_board->type & BOARD_WILDCARD) 136 | access->open_iface = BOARD_WILDCARD; 137 | if (access->type == BOARD_ANY) { 138 | if (supported_board->type & BOARD_MULTI_INTERFACE) { 139 | printf("ERROR: you must select transport layer for board\n"); 140 | return -1; 141 | } 142 | if (supported_board->type & BOARD_ETH) { 143 | ret = eth_boards_init(access); 144 | access->open_iface |= BOARD_ETH; 145 | ret = eth_boards_scan(access); 146 | if (ret < 0) { 147 | return ret; 148 | } 149 | } 150 | #if MESAFLASH_IO 151 | if (supported_board->type & BOARD_PCI) { 152 | ret = pci_boards_init(access); 153 | if (ret < 0) { 154 | return ret; 155 | } 156 | access->open_iface |= BOARD_PCI; 157 | pci_boards_scan(access); 158 | } 159 | if (supported_board->type & BOARD_EPP) { 160 | ret = epp_boards_init(access); 161 | if (ret < 0) { 162 | return ret; 163 | } 164 | access->open_iface |= BOARD_EPP; 165 | epp_boards_scan(access); 166 | } 167 | #endif 168 | if (supported_board->type & BOARD_USB) { 169 | ret = usb_boards_init(access); 170 | access->open_iface |= BOARD_USB; 171 | usb_boards_scan(access); 172 | } 173 | if (supported_board->type & BOARD_SPI) { 174 | ret = spi_boards_init(access); 175 | access->open_iface |= BOARD_SPI; 176 | spi_boards_scan(access); 177 | } 178 | if (supported_board->type & BOARD_SER) { 179 | ret = serial_boards_init(access); 180 | access->open_iface |= BOARD_SER; 181 | serial_boards_scan(access); 182 | } 183 | } else { 184 | if (access->type & BOARD_ETH) { 185 | ret = eth_boards_init(access); 186 | access->open_iface |= BOARD_ETH; 187 | eth_boards_scan(access); 188 | } 189 | #if MESAFLASH_IO 190 | if (access->type & BOARD_PCI) { 191 | ret = pci_boards_init(access); 192 | if (ret < 0) { 193 | return ret; 194 | } 195 | access->open_iface |= BOARD_PCI; 196 | pci_boards_scan(access); 197 | } 198 | if (access->type & BOARD_EPP) { 199 | ret = epp_boards_init(access); 200 | if (ret < 0) { 201 | return ret; 202 | } 203 | access->open_iface |= BOARD_EPP; 204 | epp_boards_scan(access); 205 | } 206 | #endif 207 | if (access->type & BOARD_USB) { 208 | ret = usb_boards_init(access); 209 | access->open_iface |= BOARD_USB; 210 | usb_boards_scan(access); 211 | } 212 | if (access->type & BOARD_SPI) { 213 | ret = spi_boards_init(access); 214 | access->open_iface |= BOARD_SPI; 215 | spi_boards_scan(access); 216 | } 217 | if (access->type & BOARD_SER) { 218 | ret = serial_boards_init(access); 219 | access->open_iface |= BOARD_SER; 220 | serial_boards_scan(access); 221 | } 222 | } 223 | 224 | return 0; 225 | } 226 | 227 | board_t *anyio_get_dev(board_access_t *access, int board_number) { 228 | int i, j; 229 | 230 | if (access == NULL) { 231 | return NULL; 232 | } 233 | for (i = 0, j = 0; i < boards_count; i++) { 234 | board_t *board = NULL; 235 | board = &boards[i]; 236 | if (((strncmp(access->device_name, board->llio.board_name, strlen(access->device_name)) == 0) && 237 | (strlen(access->device_name) == strlen(board->llio.board_name))) || access->open_iface & BOARD_WILDCARD) { 238 | j++; 239 | if (j == board_number) { 240 | return board; 241 | } 242 | } 243 | } 244 | return NULL; 245 | } 246 | 247 | int anyio_dev_write_flash(board_t *board, char *bitfile_name, int fallback_flag, int fix_boot_flag, int sha256_check_flag) { 248 | int ret; 249 | 250 | if (board == NULL) { 251 | return -EINVAL; 252 | } 253 | if (board->llio.write_flash != NULL) { 254 | u32 addr = board->flash_start_address; 255 | 256 | if (fallback_flag == 1) { 257 | if (board->fpga_type == FPGA_TYPE_EFINIX) { 258 | addr = EFINIX_FALLBACK_ADDRESS; 259 | } else { 260 | addr = XILINX_FALLBACK_ADDRESS; 261 | } 262 | } 263 | ret = board->llio.write_flash(&(board->llio), bitfile_name, addr, fix_boot_flag, sha256_check_flag); 264 | } else { 265 | printf("ERROR: Board %s doesn't support flash writing.\n", board->llio.board_name); 266 | return -EINVAL; 267 | } 268 | return ret; 269 | } 270 | 271 | int anyio_dev_verify_flash(board_t *board, char *bitfile_name, int fallback_flag) { 272 | int ret; 273 | 274 | if (board == NULL) { 275 | return -EINVAL; 276 | } 277 | if (board->llio.verify_flash != NULL) { 278 | u32 addr = board->flash_start_address; 279 | 280 | if (fallback_flag == 1) { 281 | if (board->fpga_type == FPGA_TYPE_EFINIX) { 282 | addr = EFINIX_FALLBACK_ADDRESS; 283 | } else { 284 | addr = XILINX_FALLBACK_ADDRESS; 285 | } 286 | } 287 | ret = board->llio.verify_flash(&(board->llio), bitfile_name, addr); 288 | } else { 289 | printf("ERROR: Board %s doesn't support flash verification.\n", board->llio.board_name); 290 | return -EINVAL; 291 | } 292 | return ret; 293 | } 294 | 295 | int anyio_dev_backup_flash(board_t *board, char *bitfile_name) { 296 | int ret; 297 | 298 | if (board == NULL) { 299 | return -EINVAL; 300 | } 301 | if (board->llio.backup_flash != NULL) { 302 | ret = board->llio.backup_flash(&(board->llio), bitfile_name); 303 | } else { 304 | printf("ERROR: Board %s doesn't support backup flash.\n", board->llio.board_name); 305 | return -EINVAL; 306 | } 307 | return ret; 308 | } 309 | 310 | int anyio_dev_restore_flash(board_t *board, char *bitfile_name) { 311 | int ret; 312 | 313 | if (board == NULL) { 314 | return -EINVAL; 315 | } 316 | if (board->llio.restore_flash != NULL) { 317 | ret = board->llio.restore_flash(&(board->llio), bitfile_name); 318 | } else { 319 | printf("ERROR: Board %s doesn't support restore flash.\n", board->llio.board_name); 320 | return -EINVAL; 321 | } 322 | return ret; 323 | } 324 | 325 | int anyio_dev_program_fpga(board_t *board, char *bitfile_name) { 326 | int ret; 327 | 328 | if (board == NULL) { 329 | return -EINVAL; 330 | } 331 | if (board->llio.reset == NULL) { 332 | printf("ERROR: Board %s doesn't support FPGA resetting.\n", board->llio.board_name); 333 | return -EINVAL; 334 | } 335 | if (board->llio.program_fpga == NULL) { 336 | printf("ERROR: Board %s doesn't support FPGA programming.\n", board->llio.board_name); 337 | return -EINVAL; 338 | } 339 | 340 | ret = board->llio.reset(&(board->llio)); 341 | if (ret != 0) { 342 | return ret; 343 | } 344 | board->llio.program_fpga(&(board->llio), bitfile_name); 345 | return 0; 346 | } 347 | 348 | int anyio_dev_set_remote_ip(board_t *board, char *lbp16_set_ip_addr) { 349 | int ret; 350 | 351 | if (board == NULL) { 352 | return -EINVAL; 353 | } 354 | if ((board->type & BOARD_ETH) == 0) { 355 | return -EPERM; 356 | } 357 | 358 | ret = eth_set_remote_ip(lbp16_set_ip_addr); 359 | if (ret == 0) { 360 | printf("Board IP updated successfully.\n"); 361 | printf("You must power cycle board to load updated eeprom settings.\n"); 362 | } 363 | return ret; 364 | } 365 | int anyio_dev_set_led_mode(board_t *board, char *lbp16_set_led_mode) { 366 | int ret; 367 | 368 | if (board == NULL) { 369 | return -EINVAL; 370 | } 371 | if ((board->type & BOARD_ETH) == 0) { 372 | return -EPERM; 373 | } 374 | 375 | ret = eth_set_led_mode(lbp16_set_led_mode); 376 | if (ret == 0) { 377 | printf("Board LED mode updated successfully.\n"); 378 | printf("You must power cycle board to load updated eeprom settings.\n"); 379 | } 380 | return ret; 381 | } 382 | 383 | int anyio_dev_reload(board_t *board, int fallback_flag) { 384 | if (board == NULL) { 385 | return -EINVAL; 386 | } 387 | if (board->llio.reload == NULL) { 388 | printf("ERROR: Board %s doesn't support FPGA configuration reloading.\n", board->llio.board_name); 389 | return -EINVAL; 390 | } 391 | return board->llio.reload(&(board->llio), fallback_flag); 392 | } 393 | 394 | int anyio_dev_reset(board_t *board) { 395 | if (board == NULL) { 396 | return -EINVAL; 397 | } 398 | if (board->llio.reset == NULL) { 399 | printf("ERROR: Board %s doesn't support FPGA resetting.\n", board->llio.board_name); 400 | return -EINVAL; 401 | } 402 | return board->llio.reset(&(board->llio)); 403 | } 404 | 405 | void anyio_dev_print_hm2_info(board_t *board, int xml_flag) { 406 | if (board == NULL) { 407 | return; 408 | } 409 | hm2_read_idrom(&(board->llio.hm2)); 410 | hm2_print_pin_file(&(board->llio), xml_flag); 411 | } 412 | 413 | void anyio_dev_print_pin_descriptors(board_t *board) { 414 | if (board == NULL) { 415 | return; 416 | } 417 | hm2_read_idrom(&(board->llio.hm2)); 418 | hm2_print_pin_descriptors(&board->llio); 419 | } 420 | 421 | void anyio_dev_print_localio_descriptors(board_t *board) { 422 | if (board == NULL) { 423 | return; 424 | } 425 | hm2_read_idrom(&(board->llio.hm2)); 426 | hm2_print_localio_descriptors(&board->llio); 427 | } 428 | 429 | void anyio_dev_print_sserial_info(board_t *board) { 430 | if (board == NULL) { 431 | return; 432 | } 433 | hm2_read_idrom(&(board->llio.hm2)); 434 | sserial_module_init(&(board->llio)); 435 | } 436 | 437 | void anyio_bitfile_print_info(char *bitfile_name, int verbose_flag) { 438 | FILE *fp; 439 | char part_name[32]; 440 | 441 | if (bitfile_name == NULL) { 442 | return; 443 | } 444 | fp = fopen(bitfile_name, "rb"); 445 | if (fp == NULL) { 446 | printf("Can't open file %s: %s\n", bitfile_name, strerror(errno)); 447 | return; 448 | } 449 | print_bitfile_header(fp, (char*) &part_name, verbose_flag); 450 | fclose(fp); 451 | } 452 | 453 | void anyio_print_supported_board_names() { 454 | printf("Supported card names are:\n"); 455 | for (size_t i=0; supported_boards[i].name != NULL; i++) { 456 | printf("%10s,",supported_boards[i].name); 457 | if ((((i+1) % 6) == 0) & (i != 0)) { printf("\n"); }; 458 | } 459 | printf("\n"); 460 | } 461 | 462 | void anyio_dev_enable_all_module_outputs(board_t *board) { 463 | if (board == NULL) { 464 | return; 465 | } 466 | hm2_read_idrom(&(board->llio.hm2)); 467 | hm2_enable_all_module_outputs(&(board->llio.hm2)); 468 | } 469 | 470 | void anyio_dev_safe_io(board_t *board) { 471 | if (board == NULL) { 472 | return; 473 | } 474 | hm2_read_idrom(&(board->llio.hm2)); 475 | hm2_safe_io(&(board->llio.hm2)); 476 | } 477 | 478 | 479 | -------------------------------------------------------------------------------- /anyio.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __ANYIO_H 20 | #define __ANYIO_H 21 | 22 | #ifdef _WIN32 23 | #include 24 | #include "winio32/winio.h" 25 | #endif 26 | #include "boards.h" 27 | 28 | int anyio_init(board_access_t *access); 29 | void anyio_cleanup(board_access_t *access); 30 | int anyio_find_dev(board_access_t *access); 31 | board_t *anyio_get_dev(board_access_t *access, int board_number); 32 | int anyio_dev_write_flash(board_t *board, char *bitfile_name, int fallback_flag, int fix_boot_flag, int sha256_check_flag); 33 | int anyio_dev_verify_flash(board_t *board, char *bitfile_name, int fallback_flag); 34 | int anyio_dev_backup_flash(board_t *board, char *bitfile_name); 35 | int anyio_dev_restore_flash(board_t *board, char *bitfile_name); 36 | int anyio_dev_program_fpga(board_t *board, char *bitfile_name); 37 | int anyio_dev_set_remote_ip(board_t *board, char *lbp16_set_ip_addr); 38 | int anyio_dev_set_led_mode(board_t *board, char *lbp16_set_led_mode); 39 | int anyio_dev_reload(board_t *board, int fallback_flag); 40 | int anyio_dev_reset(board_t *board); 41 | void anyio_dev_print_hm2_info(board_t *board, int xml_flag); 42 | void anyio_dev_print_pin_descriptors(board_t *board); 43 | void anyio_dev_print_localio_descriptors(board_t *board); 44 | void anyio_dev_enable_all_module_outputs(board_t *board); 45 | void anyio_dev_safe_io(board_t *board); 46 | void anyio_dev_print_sserial_info(board_t *board); 47 | void anyio_bitfile_print_info(char *bitfile_name, int verbose_flag); 48 | void anyio_print_supported_board_names(); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /bitfile.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #include 20 | #include 21 | #include "types.h" 22 | #include "bitfile.h" 23 | 24 | // prints info about bitfile and returns header length or -1 when error 25 | int print_bitfile_header(FILE *fp, char *part_name, int verbose_flag) { 26 | u8 buff[256]; 27 | int sleng; 28 | int bytesread, conflength; 29 | int ret = 0; 30 | char str[80]; 31 | char * partns; 32 | printf("Checking file... "); 33 | bytesread = fread(&buff, 1, 14, fp); 34 | ret += bytesread; 35 | if (bytesread != 14) { 36 | if (feof(fp)) 37 | printf("Error: Unexpected end of file\n"); 38 | else 39 | printf("Error: IO error\n"); 40 | return -1; 41 | } 42 | if ((buff[0] == 0) && (buff[1] == 9)) { 43 | printf("OK\n File type: Xilinx bit file\n"); 44 | if ((buff[11] == 0) && (buff[12] == 1) && (buff[13] == 0x61)) { 45 | bytesread = fread(&buff, 1, 2, fp); 46 | ret += bytesread; 47 | sleng = buff[0]*256 + buff[1]; 48 | bytesread = fread(&buff, 1, sleng, fp); 49 | ret += bytesread; 50 | if (verbose_flag == 1) { 51 | printf(" Design name: %s\n", buff); 52 | } 53 | 54 | bytesread = fread(&buff, 1, 3, fp); 55 | ret += bytesread; 56 | sleng = buff[1]*256 + buff[2]; 57 | bytesread = fread(&buff, 1, sleng, fp); 58 | ret += bytesread; 59 | if (verbose_flag == 1) { 60 | printf(" Part name: %s\n", buff); 61 | } 62 | strcpy(part_name, (char*) &buff); 63 | 64 | bytesread = fread(&buff, 1, 3, fp); 65 | ret += bytesread; 66 | sleng = buff[1]*256 + buff[2]; 67 | bytesread = fread(&buff, 1, sleng, fp); 68 | ret += bytesread; 69 | if (verbose_flag == 1) { 70 | printf(" Design date: %s\n", buff); 71 | } 72 | 73 | bytesread = fread(&buff, 1, 3, fp); 74 | ret += bytesread; 75 | sleng = buff[1]*256 + buff[2]; 76 | bytesread = fread(&buff, 1, sleng, fp); 77 | ret += bytesread; 78 | if (verbose_flag == 1) { 79 | printf(" Design time: %s\n", buff); 80 | } 81 | 82 | bytesread = fread(&buff, 1, 5, fp); 83 | ret += bytesread; 84 | conflength = buff[1]*16777216; 85 | conflength = conflength + buff[2]*65536; 86 | conflength = conflength + buff[3]*256; 87 | conflength = conflength + buff[4]; 88 | if (verbose_flag == 1) { 89 | printf(" Config Length: %d\n", conflength); 90 | } 91 | } 92 | return ret; 93 | } 94 | rewind(fp); 95 | fgets(str, 20 ,fp); 96 | ret += strlen(str); 97 | if (strncmp(str,"Version",7) == 0) { 98 | printf("OK\n File type: Efinix bin file\n"); 99 | if (verbose_flag == 1) { 100 | printf(" Compiler %s", str); 101 | } 102 | // Compiler version 103 | fgets(str, 60, fp); 104 | ret += strlen(str); 105 | if (verbose_flag == 1) { 106 | printf(" %s", str); 107 | } 108 | // Date 109 | fgets(str, 60, fp); 110 | ret += strlen(str); 111 | if (verbose_flag == 1) { 112 | printf(" %s", str); 113 | } 114 | // Project 115 | fgets(str, 80, fp); 116 | ret += strlen(str); 117 | fgets(str, 80, fp); 118 | ret += strlen(str); 119 | if (verbose_flag == 1) { 120 | printf(" %s", str); 121 | } 122 | // Family 123 | fgets(str, 60, fp); 124 | ret += strlen(str); 125 | if (verbose_flag == 1) { 126 | printf(" %s", str); 127 | } 128 | // Device 129 | fgets(str, 60, fp); 130 | ret += strlen(str); 131 | if (verbose_flag == 1) { 132 | printf(" %s", str); 133 | } 134 | partns = strtok(str," "); 135 | partns = strtok(NULL," "); 136 | partns[(strlen(partns)-1)] = '\0'; 137 | strcpy(part_name, partns); 138 | // Configuration device width 139 | fgets(str, 60, fp); 140 | ret += strlen(str); 141 | if (verbose_flag == 1) { 142 | printf(" %s", str); 143 | } 144 | // Configuration mode 145 | fgets(str, 60, fp); 146 | ret += strlen(str); 147 | if (verbose_flag == 1) { 148 | printf(" %s", str); 149 | } 150 | // Padded bits 151 | fgets(str, 60, fp); 152 | ret += strlen(str); 153 | if (verbose_flag == 1) { 154 | printf(" %s", str); 155 | } 156 | 157 | return ret; 158 | } 159 | if ((buff[0] == 0xFF) && (buff[1] == 0xFF) && (buff[2] == 0xFF) && (buff[3] == 0xFF)) { 160 | printf("Looks like a BIN file\n"); 161 | return -1; 162 | } 163 | printf("Invalid bitfile header!\n"); 164 | return -1; 165 | } 166 | 167 | // 168 | // the fpga was originally designed to be programmed serially... even 169 | // though we are doing it using a parallel interface, the bit ordering 170 | // is based on the serial interface, and the data needs to be reversed 171 | // 172 | 173 | u8 bitfile_reverse_bits(u8 data) { 174 | static const u8 swaptab[256] = { 175 | 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 176 | 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 177 | 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 178 | 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 179 | 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 180 | 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 181 | 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 182 | 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 183 | 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 184 | 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, 185 | 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 186 | 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 187 | 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 188 | 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 189 | 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 190 | 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF 191 | }; 192 | return swaptab[data]; 193 | } 194 | -------------------------------------------------------------------------------- /bitfile.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __BITFILE_H 20 | #define __BITFILE_H 21 | 22 | #include 23 | #include "types.h" 24 | 25 | int print_bitfile_header(FILE *fp, char *part_name, int verbose_flag); 26 | u8 bitfile_reverse_bits(u8 data); 27 | 28 | #endif 29 | 30 | -------------------------------------------------------------------------------- /boards.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __BOARDS_H 20 | #define __BOARDS_H 21 | 22 | #ifdef _WIN32 23 | #include "winio32/winio.h" 24 | #endif 25 | #include "hostmot2.h" 26 | 27 | #include "eeprom.h" 28 | 29 | #define MAX_BOARDS 8 30 | 31 | #define BOARD_ANY (0) 32 | #define BOARD_MULTI_INTERFACE (1<<0) 33 | #define BOARD_ETH (1<<1) 34 | #define BOARD_PCI (1<<2) 35 | #define BOARD_EPP (1<<3) 36 | #define BOARD_USB (1<<4) 37 | #define BOARD_SPI (1<<5) 38 | #define BOARD_SER (1<<6) 39 | #define BOARD_WILDCARD (1<<30) 40 | typedef enum {BOARD_MODE_CPLD, BOARD_MODE_FPGA} board_mode; 41 | typedef enum {BOARD_FLASH_NONE = 0, BOARD_FLASH_HM2, BOARD_FLASH_IO, BOARD_FLASH_GPIO, BOARD_FLASH_REMOTE, BOARD_FLASH_EPP} board_flash; 42 | typedef enum {FPGA_TYPE_XILINX, FPGA_TYPE_EFINIX} fpga_type; 43 | 44 | typedef struct { 45 | char *name; 46 | u32 type; 47 | } supported_board_entry_t; 48 | 49 | typedef struct board_struct board_t; 50 | 51 | struct board_struct { 52 | u32 type; 53 | board_mode mode; 54 | fpga_type fpga_type; 55 | board_flash flash; 56 | u8 flash_id; 57 | u32 flash_start_address; 58 | int fallback_support; 59 | int recover; 60 | char dev_addr[16]; 61 | 62 | struct pci_dev *dev; 63 | void *base; 64 | int len; 65 | u64 mem_base; 66 | #ifdef _WIN32 67 | tagPhysStruct_t mem_handle; 68 | #endif 69 | u16 ctrl_base_addr; 70 | u16 data_base_addr; 71 | 72 | u16 base_lo; 73 | u16 base_hi; 74 | void *region; 75 | void *region_hi; 76 | int epp_wide; 77 | 78 | int (*open)(board_t *self); 79 | int (*close)(board_t *self); 80 | void (*print_info)(board_t *self); 81 | 82 | llio_t llio; 83 | }; 84 | 85 | typedef struct { 86 | char *device_name; 87 | u32 type; 88 | u32 open_iface; 89 | int list; 90 | int address; 91 | int verbose; 92 | int recover; 93 | char *dev_addr; 94 | char *dev_hi_addr; 95 | } board_access_t; 96 | 97 | extern board_t boards[MAX_BOARDS]; 98 | extern int boards_count; 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /common.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifdef __linux__ 20 | #include 21 | #elif _WIN32 22 | #include 23 | #endif 24 | #include 25 | #include 26 | #include "types.h" 27 | #include "common.h" 28 | #include "eeprom.h" 29 | 30 | #ifdef _WIN32 31 | void init_io_library() { 32 | InitializeWinIo(); 33 | } 34 | 35 | void release_io_library() { 36 | ShutdownWinIo(); 37 | } 38 | 39 | u8 inb(u32 addr) { 40 | u32 val; 41 | GetPortVal((WORD) addr, &val, 1); 42 | return val & 0xFF; 43 | } 44 | 45 | void outb(u8 data, u32 addr) { 46 | SetPortVal((WORD) addr, (DWORD) data, 1); 47 | } 48 | 49 | u16 inw(u32 addr) { 50 | u32 val; 51 | GetPortVal((WORD) addr, &val, 2); 52 | return val & 0xFFFF; 53 | } 54 | 55 | void outw(u16 data, u32 addr) { 56 | SetPortVal((WORD) addr, (DWORD) data, 2); 57 | } 58 | 59 | u32 inl(u32 addr) { 60 | u32 val; 61 | GetPortVal((WORD) addr, &val, 4); 62 | return val; 63 | } 64 | 65 | void outl(u32 data, u32 addr) { 66 | SetPortVal((WORD) addr, (DWORD) data, 4); 67 | } 68 | 69 | void *map_memory(u32 base, u32 size, tagPhysStruct_t *phys) { 70 | void *ptr; 71 | 72 | memset(phys, 0, sizeof(tagPhysStruct_t)); 73 | phys->pvPhysAddress = (DWORD64)(DWORD32) base; 74 | phys->dwPhysMemSizeInBytes = size; 75 | 76 | ptr = MapPhysToLin(phys); 77 | return ptr; 78 | } 79 | 80 | void *unmap_memory(tagPhysStruct_t *phys) { 81 | UnmapPhysicalMemory(phys); 82 | } 83 | #endif 84 | 85 | void sleep_ns(u64 nanoseconds) { 86 | #ifdef __linux__ 87 | struct timespec tv, tvret; 88 | 89 | tv.tv_sec = 0; 90 | tv.tv_nsec = nanoseconds; 91 | nanosleep(&tv, &tvret); 92 | #elif _WIN32 93 | Sleep(nanoseconds/1000/1000); 94 | #endif 95 | } 96 | 97 | void show_formatted_size(u32 size) { 98 | if (size < 1024) { 99 | printf(" [size=%u]", size); 100 | } else if (size < 1024*1024) { 101 | printf(" [size=%uK]", size/1024); 102 | } else if (size < 0x80000000) { 103 | printf(" [size=%uM]", size/(1024*1024)); 104 | } else { 105 | printf(" [size=%08X]", size); 106 | } 107 | } 108 | 109 | void board_init_struct(board_t *board) { 110 | memset(board, 0, sizeof(board_t)); 111 | board->llio.board = board; 112 | board->llio.hm2.llio = &(board->llio); 113 | } 114 | 115 | void show_board_info(board_t *board) { 116 | int i; 117 | 118 | printf("Board info:\n"); 119 | if (board->flash_id > 0) { 120 | printf(" Flash size: %s (id: 0x%02X)\n", eeprom_get_flash_type(board->flash_id), board->flash_id); 121 | } 122 | printf(" Connectors count: %d\n", board->llio.num_ioport_connectors); 123 | printf(" Pins per connector: %d\n", board->llio.pins_per_connector); 124 | printf(" Connectors names:"); 125 | for (i = 0; i < board->llio.num_ioport_connectors; i++) { 126 | printf(" %s", board->llio.ioport_connector_name[i]); 127 | } 128 | printf("\n"); 129 | printf(" FPGA type: %s\n", board->llio.fpga_part_number); 130 | printf(" Number of leds: %d\n", board->llio.num_leds); 131 | } 132 | -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __COMMON_H 20 | #define __COMMON_H 21 | 22 | #include "types.h" 23 | #include "boards.h" 24 | 25 | #ifdef _WIN32 26 | #include "winio32/winio.h" 27 | 28 | void init_io_library(); 29 | void release_io_library(); 30 | u8 inb(u32 addr); 31 | void outb(u8 data, u32 addr); 32 | u16 inw(u32 addr); 33 | void outw(u16 data, u32 addr); 34 | u32 inl(u32 addr); 35 | void outl(u32 data, u32 addr); 36 | void *map_memory(u32 base, u32 size, tagPhysStruct_t *phys); 37 | void *unmap_memory(tagPhysStruct_t *phys); 38 | #endif 39 | 40 | #define LO_BYTE(x) ((x) & 0xFF) 41 | #define HI_BYTE(x) (((x) & 0xFF00) >> 8) 42 | 43 | void sleep_ns(u64 nanoseconds); 44 | void show_formatted_size(u32 size); 45 | void board_init_struct(board_t *board); 46 | void show_board_info(board_t *board); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /debian/README.source: -------------------------------------------------------------------------------- 1 | Debian packaging of LinuxCNC/Mesaflash 2 | ====================================== 3 | 4 | The following steps were performed to transform Upstream's git repository 5 | into a source tarball and a debian subdirectory that is compliant with the 6 | latest release of the Debian Policy. 7 | 8 | Steps 9 | ----- 10 | 11 | 1. Generate the source tarball 12 | 13 | debian/rules get-orig-source 14 | 15 | 2. Prepare shell to work in temp directory 16 | 17 | export WORKDIR=$(mktemp -d) 18 | mv mesaflash_*.orig.tar.xz ${WORKDIR}/ 19 | bash 20 | cd $WORKDIR 21 | 22 | 2. Unpack 23 | 24 | tar xJvf mesaflash_*.orig.tar.xz 25 | 26 | 3. Slightly adapt for unstable 27 | 28 | bash 29 | cd $WORKDIR/mesaflash 30 | rm debian/compat 31 | sed -i 's/debhelper .*,/debhelper-compat (= 13),/' debian/control 32 | sed -i '/^Standards-Version: /s/ [0-9.]*/ 4.6.0/' debian/control 33 | sed -i '1s/ stable;/ unstable;/' debian/changelog 34 | 35 | 4. build Debian package 36 | 37 | dpkg-buildpackage 38 | 39 | 5. get all the files just created 40 | 41 | exit 42 | mv ${WORKDIR}/mesaflash_* .. 43 | 44 | 45 | Above sketched differences are not impeding routine workflows of Debian 46 | packaging. For instance we found that the tool routine-update (from the 47 | Debian Science team) deals with these adaptations just fine. 48 | 49 | 50 | How to contribute 51 | ----------------- 52 | 53 | LinuxCNC does not have a representation on salsa.debian.org. 54 | Please join us on https://github.com/LinuxCNC/mesaflash/ . 55 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | mesaflash (3.4.9-1) unstable; urgency=medium 2 | 3 | * Add set ledmode option 4 | * Add inverted txen pin printout to pktuart and sserial 5 | * Merge pull request #77 from fangyaling/master 6 | * Add check for new arch Loongarch64 7 | 8 | -- Andy Pugh Sun, 15 Oct 2023 20:25:51 +0100 9 | 10 | mesaflash (3.4.8-1) unstable; urgency=medium 11 | 12 | * Fix recover option for 6I24/6I25 (broken by name munging) 13 | * Merge pull request #76 from sensille/litehm2 14 | * Add MPG encoder names to inm module pins 15 | * mesaflash: add first support for litehm2 16 | * Add MX3660, MX4660 pinouts 17 | * Add the period measurement module 18 | * Add 5I25T reload support 19 | * Forgot the PCI default FPGA type 20 | * Add 7I80HDT,5I25T support 21 | * Fix some typos in 7I97 and 7I95 pinouts 22 | 23 | -- Peter C. Wallace Wed, 19 Jul 2023 20:25:51 -0700 24 | 25 | mesaflash (3.4.7-1) unstable; urgency=medium 26 | 27 | * Add 7I95T support, Fix boot jumper UP/UP meaning for Efinix 28 | * Bugfix: Lengthen Efinix file header max path length 29 | * Merge pull request #75 from LinuxCNC/fix-ci 30 | * gitbug actions: add some whitespace to make the list more legible 31 | * github actions: teach vim about shiftwidth in this file 32 | * github actions: minor reorg 33 | * github actions: bump actions/checkout version 34 | * dch: add note that uploads are sponsored by Petter Reinholdtsen 35 | 36 | -- Peter C. Wallace Thu, 16 Feb 2023 20:25:51 -0700 37 | 38 | mesaflash (3.4.6-1) unstable; urgency=medium 39 | 40 | * Add new Mesa boards: 7C81, 7I96S, 7I92T 41 | * Add OutM and OneShoto module support. 42 | * Add backup/restore for PCI cards. 43 | * Add support for Efinix FPGAs. 44 | * Show daughterboards better. 45 | * Add --print-lio to show Local I/O pins. 46 | * Add --version. 47 | * Better manpage and --help info. 48 | * Misc bugfixes. 49 | 50 | * Upload sponsored by Petter Reinholdtsen. 51 | 52 | -- Sebastian Kuzminsky Sat, 05 Nov 2022 12:38:09 -0600 53 | 54 | mesaflash (3.4.2-1) unstable; urgency=medium 55 | 56 | * Switch from openssl to libmd for sha256. 57 | 58 | * Upload sponsored by Petter Reinholdtsen. 59 | 60 | -- Sebastian Kuzminsky Sun, 16 Jan 2022 09:47:57 -0700 61 | 62 | mesaflash (3.4.1-1) unstable; urgency=medium 63 | 64 | * Add --backup-flash and --restore-flash command-line options. 65 | * Add --sha256-check command-line option. 66 | * Fix building on more platforms that lack sys/io.h. 67 | * Add Homepage link, fix Source link. Closes: #1001880 68 | 69 | -- Sebastian Kuzminsky Sat, 15 Jan 2022 12:38:11 -0700 70 | 71 | mesaflash (3.4.0-2) unstable; urgency=medium 72 | 73 | * Revised d/copyright 74 | 75 | -- Sebastian Kuzminsky Sat, 20 Nov 2021 17:52:00 +0100 76 | 77 | mesaflash (3.4.0-1) UNRELEASED; urgency=medium 78 | 79 | * Cosmetics in preparation of upload to Debian. 80 | * Several bug fixes. 81 | * Fixes for PCI on Raspberry Pi Compute Module 4. 82 | * Better daughter-board reporting. 83 | * No longer support building on Windows. 84 | * Better IO error detection and handling. 85 | 86 | -- LinuxCNC Developers Mon, 27 Sep 2021 16:36:14 -0600 87 | 88 | mesaflash (3.4.0~pre1-1) UNRELEASED; urgency=medium 89 | 90 | * Add a manpage. 91 | * Fix several compile warnings. 92 | * Add `--device AUTO` and `--device SPI`. 93 | 94 | -- LinuxCNC Developers Fri, 22 May 2020 10:30:23 -0600 95 | 96 | mesaflash (3.4.0~pre0-1) UNRELEASED; urgency=medium 97 | 98 | * mesaflash is now maintained by the LinuxCNC organization. 99 | 100 | -- LinuxCNC Developers Thu, 23 Apr 2020 10:34:49 -0600 101 | 102 | mesaflash (3.3.0~pre0+dfsg-0) UNRELEASED; urgency=low 103 | 104 | * support Mesa 7i93 ethernet board 105 | * support Mesa 7i96 ethernet board 106 | * Verify firmware after writing 107 | * Many bug fixes 108 | 109 | -- Sebastian Kuzminsky Tue, 27 Jun 2017 21:52:31 -0600 110 | 111 | mesaflash (3.2.1) UNRELEASED; urgency=low 112 | 113 | * Fix some compile warnings and link issues on Debian Stretch. 114 | 115 | -- Sebastian Kuzminsky Tue, 27 Jun 2017 10:25:59 -0600 116 | 117 | mesaflash (3.2.0) UNRELEASED; urgency=low 118 | 119 | * Don't check bitfile destinations while gpio recovering 6i24/6i25 boards 120 | * Use modules base address from module descriptor, not from regmap 121 | * Don't check bitfile id for 5i24 and 6i24 while --write and --verify 122 | * Fix support for 7i92, 5i24 and 6i24 123 | * Add support for 6i24 PCIE board 124 | * Improve and clean reporting sserial remote data 125 | * Show FPGA programming time in verbose mode 126 | * Always show full info about bit file while using 'info' command 127 | * Add xml output from 'readhmid' command to use with pncconf 128 | 129 | -- Michael Geszkiewicz 27 Sep 2015 19:24:42 -0500 130 | 131 | mesaflash (3.1.0) UNRELEASED; urgency=low 132 | 133 | * First stable release. 134 | * Support 7i90HD under linux in SPI and rs422 mode 135 | * Better EPP support 136 | * Support ICAP firmware reloading on ethernet and pci boards. 137 | * Print more debug data in verbose mode 138 | * Use default device address (0x378 for epp and 192.168.1.121 for eth) 139 | if --addr option is missing in command line 140 | * Reduce overhead of verify operation (thanks jepler) 141 | * Don't write and verify flash if bitfile destination part name is not 142 | equal to current board fpga name 143 | * Add support for 7i92 ethernet board 144 | * Update windows port 145 | * Correctly generates *.pin files with option --readhmid 146 | * Show details about connected sserial devices with --sserial 147 | * Factor out all libanyio access code to external static library 148 | * Add support for write/verify eeprom on 7i43 board via EPPIO bitfile 149 | * Add command to set remote ip address in ethernet eeprom 150 | * Remove obsolete command line options 151 | * Add example programs how to use libanyio to communicate with 7i77 152 | (encoder in and analog out) 153 | 154 | -- Michael Geszkiewicz Sat, 24 Nov 2014 01:07:22 -0500 155 | 156 | mesaflash (3.0.0) UNRELEASED; urgency=low 157 | 158 | * Initial release. 159 | 160 | -- Michael Geszkiewicz Sat, 19 Apr 2014 21:03:31 -0500 161 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: mesaflash 2 | Maintainer: LinuxCNC Developers 3 | Uploaders: Sebastian Kuzminsky , Jeff Epler 4 | Section: misc 5 | Priority: optional 6 | Standards-Version: 3.9.4 7 | Build-Depends: debhelper (>= 9), 8 | libpci-dev, 9 | libmd-dev, 10 | pkg-config 11 | Rules-Requires-Root: binary-targets 12 | Homepage: https://github.com/LinuxCNC/mesaflash 13 | Vcs-Browser: https://github.com/linuxcnc/mesaflash 14 | Vcs-Git: https://github.com/LinuxCNC/mesaflash.git -b master 15 | 16 | Package: mesaflash 17 | Architecture: any 18 | Depends: ${shlibs:Depends}, ${misc:Depends} 19 | Description: Mesa Electronics utility tool 20 | This package provides a tool for the configuration and/or diagnosis of 21 | Mesa Electronics boards. The cards provide I/O channels for robotics 22 | applications and have a strong user base in the LinuxCNC community. 23 | This tool works for all cards, be they directly plugged into your 24 | computer via PCI(E) or connected by a cable (ETH/EPP/USB/SPI). 25 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: mesaflash 3 | Upstream-Contact: LinuxCNC Developers 4 | Source: https://github.com/LinuxCNC/mesaflash 5 | 6 | Files: * 7 | Copyright: 2013-2015 Michael Geszkiewicz 8 | 2014,2016,2020-2021 Jeff Epler 9 | 2015 Joe Calderon 10 | 2017,2020 Sebastian Kuzminsky 11 | 2019-2021 Peter Wallace 12 | 2020 Damian Wrobel 13 | 2020 Curtis Dutton 14 | License: GPL-2.0+ 15 | 16 | Files: debian/* 17 | Copyright: 2015 Chris Radek 18 | 2016,2021 Jeff Epler 19 | 2014-2021 Sebastian Kuzminsky 20 | 2021 Steffen Moeller 21 | License: GPL-2.0+ 22 | 23 | License: GPL-2.0+ 24 | This package is free software; you can redistribute it and/or modify 25 | it under the terms of the GNU General Public License as published by 26 | the Free Software Foundation; either version 2 of the License, or 27 | (at your option) any later version. 28 | . 29 | This package is distributed in the hope that it will be useful, 30 | but WITHOUT ANY WARRANTY; without even the implied warranty of 31 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 32 | GNU General Public License for more details. 33 | . 34 | You should have received a copy of the GNU General Public License 35 | along with this program. If not, see 36 | . 37 | On Debian systems, the complete text of the GNU General 38 | Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". 39 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | include /usr/share/dpkg/architecture.mk 3 | DPKG_EXPORT_BUILDTOOLS=1 4 | include /usr/share/dpkg/buildtools.mk 5 | include /usr/share/dpkg/pkg-info.mk 6 | 7 | # Makefile uses uname, which is wrong for cross builds. 8 | MESAFLASH_IO:=$(if $(wildcard /usr/include/$(DEB_HOST_MULTIARCH)/asm/io.h),1,0) 9 | export MESAFLASH_IO 10 | 11 | %: 12 | dh $@ 13 | 14 | override_dh_auto_install: 15 | $(MAKE) DESTDIR=$$(pwd)/debian/mesaflash/usr install 16 | 17 | .PHONY: get-orig-source 18 | get-orig-source: $(DEB_SOURCE)_$(DEB_VERSION_UPSTREAM).orig.tar.xz 19 | 20 | $(DEB_SOURCE)_$(DEB_VERSION_UPSTREAM).orig.tar.xz: 21 | git archive --prefix="mesaflash/" HEAD | xz --compress > $@ 22 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /debian/watch: -------------------------------------------------------------------------------- 1 | version=3 2 | opts=uversionmangle=s/-pre/~pre/,filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/mesaflash-$1\.tar\.gz/ \ 3 | https://github.com/LinuxCNC/mesaflash/tags .*/v?(\d\S*)\.tar\.gz 4 | -------------------------------------------------------------------------------- /eeprom.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __EEPROM_H 20 | #define __EEPROM_H 21 | 22 | #include "hostmot2.h" 23 | #include "bitfile.h" 24 | 25 | #define ID_EEPROM_1M 0x10 26 | #define ID_EEPROM_2M 0x11 27 | #define ID_EEPROM_4M 0x12 28 | #define ID_EEPROM_8M 0x13 29 | #define ID_EEPROM_16M 0x14 30 | #define ID_EEPROM_32M 0x15 31 | 32 | #define PAGE_SIZE 256 33 | #define SECTOR_SIZE 65536 34 | #define BOOT_BLOCK_SIZE 64 35 | 36 | #define BOOT_ADDRESS 0x000000 37 | #define XILINX_FALLBACK_ADDRESS 0x010000 38 | #define EFINIX_FALLBACK_ADDRESS 0x000000 39 | 40 | typedef struct { 41 | void (*set_cs_low)(llio_t *self); 42 | void (*set_cs_high)(llio_t *self); 43 | void (*prefix)(llio_t *self); 44 | void (*suffix)(llio_t *self); 45 | void (*send_byte)(llio_t *self, u8 byte); 46 | u8 (*recv_byte)(llio_t *self); 47 | void (*read_page)(llio_t *self, u32 addr, void *buff); 48 | void (*write_page)(llio_t *self, u32 addr, void *buff); 49 | void (*erase_sector)(llio_t *self, u32 addr); 50 | int (*start_programming)(llio_t *self, u32 start_address, int fsize); 51 | } spi_eeprom_dev_t; 52 | 53 | extern u8 boot_block[BOOT_BLOCK_SIZE]; 54 | 55 | char *eeprom_get_flash_type(u8 flash_id); 56 | u32 eeprom_calc_user_space(u8 flash_id); 57 | void eeprom_prepare_boot_block(u8 flash_id); 58 | int start_programming(llio_t *self, u32 start_address, int fsize); 59 | int eeprom_write(llio_t *self, char *bitfile_name, u32 start_address, int fix_boot_flag, int sha256_check_flag); 60 | int eeprom_verify(llio_t *self, char *bitfile_name, u32 start_address); 61 | int flash_backup(llio_t *self, char *bitfile_name); 62 | int flash_erase(llio_t *self); 63 | int flash_restore(llio_t *self, char *bitfile_name); 64 | void eeprom_init(llio_t *self); 65 | void eeprom_cleanup(llio_t *self); 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /eeprom_local.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifdef __linux__ 20 | #if MESAFLASH_IO 21 | #include 22 | #endif 23 | #include 24 | #elif _WIN32 25 | #include 26 | #include "libpci/pci.h" 27 | #endif 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "types.h" 33 | #include "eeprom.h" 34 | #include "eeprom_local.h" 35 | #include "hostmot2.h" 36 | #include "bitfile.h" 37 | #include "epp_boards.h" 38 | 39 | extern u8 boot_block[BOOT_BLOCK_SIZE]; 40 | extern u8 page_buffer[PAGE_SIZE]; 41 | extern u8 file_buffer[SECTOR_SIZE]; 42 | 43 | extern spi_eeprom_dev_t eeprom_access; 44 | 45 | // spi access via hm2 registers 46 | 47 | static void wait_for_data_hm2(llio_t *self) { 48 | u32 i = 0; 49 | u32 data = 0; 50 | 51 | for (i = 0; (((data & 0xFF) & SPI_DAV_MASK) == 0) && (i < 5000) ; i++) { 52 | self->read(self, HM2_SPI_CTRL_REG, &data, sizeof(data)); 53 | } 54 | if (i == 5000) { 55 | printf("%x timeout waiting for SPI data\n", data); 56 | } 57 | } 58 | 59 | static void set_cs_high_hm2(llio_t *self) { 60 | u32 data = 1; 61 | 62 | self->write(self, HM2_SPI_CTRL_REG, &data, sizeof(data)); 63 | } 64 | 65 | static void set_cs_low_hm2(llio_t *self) { 66 | u32 data = 0; 67 | 68 | self->write(self, HM2_SPI_CTRL_REG, &data, sizeof(data)); 69 | } 70 | 71 | static void prefix_hm2(llio_t *self) { 72 | set_cs_low_hm2(self); 73 | } 74 | 75 | static void suffix_hm2(llio_t *self) { 76 | set_cs_high_hm2(self); 77 | } 78 | 79 | static void send_byte_hm2(llio_t *self, u8 byte) { 80 | u32 data = byte; 81 | 82 | self->write(self, HM2_SPI_DATA_REG, &data, sizeof(data)); 83 | wait_for_data_hm2(self); 84 | } 85 | 86 | static u8 recv_byte_hm2(llio_t *self) { 87 | u32 data = 0; 88 | u32 recv = 0; 89 | 90 | self->write(self, HM2_SPI_DATA_REG, &data, sizeof(data)); 91 | wait_for_data_hm2(self); 92 | self->read(self, HM2_SPI_DATA_REG, &recv, sizeof(recv)); 93 | return (u8) recv & 0xFF; 94 | } 95 | 96 | // spi access via gpio pins of xio2001 bridge on 6i25 97 | 98 | static u16 GPIO_reg_val; 99 | 100 | static void set_cs_high_gpio(llio_t *self) { 101 | board_t *board = self->board; 102 | 103 | GPIO_reg_val = GPIO_reg_val | 0x2; 104 | pci_write_word(board->dev, XIO2001_GPIO_DATA_REG, GPIO_reg_val); 105 | } 106 | 107 | static void set_cs_low_gpio(llio_t *self) { 108 | board_t *board = self->board; 109 | 110 | GPIO_reg_val = GPIO_reg_val & (~ 0x2); 111 | pci_write_word(board->dev, XIO2001_GPIO_DATA_REG, GPIO_reg_val); 112 | } 113 | 114 | static void set_din_high_gpio(llio_t *self) { 115 | board_t *board = self->board; 116 | 117 | GPIO_reg_val = GPIO_reg_val | 0x8; 118 | pci_write_word(board->dev, XIO2001_GPIO_DATA_REG, GPIO_reg_val); 119 | } 120 | 121 | static void set_din_low_gpio(llio_t *self) { 122 | board_t *board = self->board; 123 | 124 | GPIO_reg_val = GPIO_reg_val & (~0x8); 125 | pci_write_word(board->dev, XIO2001_GPIO_DATA_REG, GPIO_reg_val); 126 | } 127 | 128 | static void set_clock_high_gpio(llio_t *self) { 129 | board_t *board = self->board; 130 | 131 | GPIO_reg_val = GPIO_reg_val | 0x10; 132 | pci_write_word(board->dev, XIO2001_GPIO_DATA_REG, GPIO_reg_val); 133 | } 134 | 135 | static void set_clock_low_gpio(llio_t *self) { 136 | board_t *board = self->board; 137 | 138 | GPIO_reg_val = GPIO_reg_val & (~ 0x10); 139 | pci_write_word(board->dev, XIO2001_GPIO_DATA_REG, GPIO_reg_val); 140 | } 141 | 142 | static int get_bit_gpio(llio_t *self) { 143 | board_t *board = self->board; 144 | u16 data; 145 | 146 | data = pci_read_word(board->dev, XIO2001_GPIO_DATA_REG); 147 | if (data & 0x4) 148 | return 1; 149 | else 150 | return 0; 151 | } 152 | 153 | static void prefix_gpio(llio_t *self) { 154 | set_cs_high_gpio(self); 155 | set_din_low_gpio(self); 156 | set_clock_low_gpio(self); 157 | set_cs_low_gpio(self); 158 | } 159 | 160 | static void suffix_gpio(llio_t *self) { 161 | set_cs_high_gpio(self); 162 | set_din_low_gpio(self); 163 | } 164 | 165 | static void init_gpio(llio_t *self) { 166 | board_t *board = self->board; 167 | 168 | pci_write_word(board->dev, XIO2001_GPIO_ADDR_REG, 0x001B); 169 | pci_write_word(board->dev, XIO2001_SBAD_STAT_REG, 0x0000); 170 | GPIO_reg_val = 0x0003; 171 | pci_write_word(board->dev, XIO2001_GPIO_DATA_REG, GPIO_reg_val); 172 | } 173 | 174 | static void restore_gpio(llio_t *self) { 175 | board_t *board = self->board; 176 | 177 | GPIO_reg_val = 0x0003; 178 | pci_write_word(board->dev, XIO2001_GPIO_DATA_REG, GPIO_reg_val); 179 | pci_write_word(board->dev, XIO2001_GPIO_ADDR_REG, 0x0000); 180 | } 181 | 182 | static void send_byte_gpio(llio_t *self, u8 byte) { 183 | u32 mask = DATA_MASK; 184 | int i; 185 | 186 | for (i = 0; i < CMD_LEN; i++) { 187 | if ((mask & byte) == 0) 188 | set_din_low_gpio(self); 189 | else 190 | set_din_high_gpio(self); 191 | mask >>= 1; 192 | set_clock_high_gpio(self); 193 | set_clock_low_gpio(self); 194 | } 195 | } 196 | 197 | static u8 recv_byte_gpio(llio_t *self) { 198 | u32 mask, data = 0; 199 | int i; 200 | 201 | mask = DATA_MASK; 202 | for (i = 0; i < DATA_LEN; i++) { 203 | if (get_bit_gpio(self) == 1) 204 | data |= mask; 205 | mask >>= 1; 206 | set_clock_high_gpio(self); 207 | set_clock_low_gpio(self); 208 | } 209 | return data; 210 | } 211 | 212 | // spi access via io ports like on 3x20 213 | 214 | #if MESAFLASH_IO 215 | static void wait_for_data_io(llio_t *self) { 216 | board_t *board = self->board; 217 | u32 i = 0; 218 | u8 data = 0; 219 | 220 | for (i = 0; (((data & 0xFF) & SPI_DAV_MASK) == 0) && (i < 5000) ; i++) { 221 | data = inb(board->data_base_addr + IO_SPI_CS_OFFSET); 222 | } 223 | if (i == 5000) { 224 | printf("%x timeout waiting for SPI data\n", data); 225 | } 226 | } 227 | 228 | static void set_cs_high_io(llio_t *self) { 229 | board_t *board = self->board; 230 | 231 | outb(1, board->data_base_addr + IO_SPI_CS_OFFSET); 232 | } 233 | 234 | static void set_cs_low_io(llio_t *self) { 235 | board_t *board = self->board; 236 | 237 | outb(0, board->data_base_addr + IO_SPI_CS_OFFSET); 238 | } 239 | 240 | static void prefix_io(llio_t *self) { 241 | set_cs_low_io(self); 242 | } 243 | 244 | static void suffix_io(llio_t *self) { 245 | set_cs_high_io(self); 246 | } 247 | 248 | static void send_byte_io(llio_t *self, u8 byte) { 249 | board_t *board = self->board; 250 | 251 | outb(byte, board->data_base_addr + IO_SPI_SREG_OFFSET); 252 | } 253 | 254 | static u8 recv_byte_io(llio_t *self) { 255 | board_t *board = self->board; 256 | 257 | outb(0, board->data_base_addr + IO_SPI_SREG_OFFSET); 258 | wait_for_data_io(self); 259 | return inb(board->data_base_addr + IO_SPI_SREG_OFFSET); 260 | } 261 | 262 | // spi access via epp on board 7i43 with EPPIO firmware 263 | 264 | void wait_for_data_epp(llio_t *self) { 265 | board_t *board = self->board; 266 | u32 i = 0; 267 | u8 data = 0; 268 | 269 | epp_addr8(board, EPP_SPI_CS_REG); 270 | for (i = 0; ((data & SPI_DAV_MASK) == 0) && (i < 100) ; i++) { 271 | data = epp_read8(board); 272 | } 273 | if (i == 100) { 274 | printf("%x timeout waiting for SPI data\n", data); 275 | } 276 | } 277 | 278 | static void set_cs_high_epp(llio_t *self) { 279 | board_t *board = self->board; 280 | 281 | epp_addr8(board, EPP_SPI_CS_REG); 282 | epp_write8(board, 1); 283 | } 284 | 285 | static void set_cs_low_epp(llio_t *self) { 286 | board_t *board = self->board; 287 | 288 | epp_addr8(board, EPP_SPI_CS_REG); 289 | epp_write8(board, 0); 290 | } 291 | 292 | static void prefix_epp(llio_t *self) { 293 | set_cs_low_epp(self); 294 | } 295 | 296 | static void suffix_epp(llio_t *self) { 297 | set_cs_high_epp(self); 298 | } 299 | 300 | static void send_byte_epp(llio_t *self, u8 byte) { 301 | board_t *board = self->board; 302 | 303 | epp_addr8(board, EPP_SPI_SREG_REG); 304 | epp_write8(board, byte); 305 | } 306 | 307 | static u8 recv_byte_epp(llio_t *self) { 308 | board_t *board = self->board; 309 | 310 | epp_addr8(board, EPP_SPI_SREG_REG); 311 | epp_write8(board, 0); 312 | wait_for_data_epp(self); 313 | epp_addr8(board, EPP_SPI_SREG_REG); 314 | return epp_read8(board); 315 | } 316 | #endif 317 | 318 | // pci flash 319 | 320 | static void send_address(llio_t *self, u32 addr) { 321 | eeprom_access.send_byte(self, (addr >> 16) & 0xFF); 322 | eeprom_access.send_byte(self, (addr >> 8) & 0xFF); 323 | eeprom_access.send_byte(self, addr & 0xFF); 324 | } 325 | 326 | static void write_enable(llio_t *self) { 327 | eeprom_access.prefix(self); 328 | eeprom_access.send_byte(self, SPI_CMD_WRITE_ENABLE); 329 | eeprom_access.suffix(self); 330 | } 331 | 332 | static u8 read_status(llio_t *self) { 333 | u8 ret; 334 | 335 | eeprom_access.prefix(self); 336 | eeprom_access.send_byte(self, SPI_CMD_READ_STATUS); 337 | ret = eeprom_access.recv_byte(self); 338 | eeprom_access.suffix(self); 339 | return ret; 340 | } 341 | 342 | u8 read_flash_id(llio_t *self) { 343 | u8 ret; 344 | 345 | eeprom_access.prefix(self); 346 | eeprom_access.send_byte(self, SPI_CMD_READ_IDROM); 347 | send_address(self, 0); // three dummy bytes 348 | ret = eeprom_access.recv_byte(self); 349 | eeprom_access.suffix(self); 350 | return ret; 351 | } 352 | 353 | static void wait_for_write(llio_t *self) { 354 | u8 stat = read_status(self); 355 | 356 | while ((stat & WRITE_IN_PROGRESS_MASK) != 0) { 357 | stat = read_status(self); 358 | } 359 | } 360 | 361 | // eeprom access functions 362 | 363 | static void read_page(llio_t *self, u32 addr, void *buff) { 364 | int i; 365 | 366 | eeprom_access.prefix(self); 367 | eeprom_access.send_byte(self, SPI_CMD_READ); 368 | send_address(self, addr); 369 | for (i = 0; i < PAGE_SIZE; i++, buff++) { 370 | *((u8 *) buff) = eeprom_access.recv_byte(self); 371 | } 372 | eeprom_access.suffix(self); 373 | } 374 | 375 | static void write_page(llio_t *self, u32 addr, void *buff) { 376 | int i; 377 | u8 byte; 378 | 379 | write_enable(self); 380 | eeprom_access.prefix(self); 381 | eeprom_access.send_byte(self, SPI_CMD_PAGE_WRITE); 382 | send_address(self, addr);// { note that add 0..7 should be 0} 383 | for (i = 0; i < PAGE_SIZE; i++) { 384 | byte = *(u8 *) (buff + i); 385 | eeprom_access.send_byte(self, byte); 386 | } 387 | eeprom_access.suffix(self); 388 | wait_for_write(self); 389 | } 390 | 391 | static void erase_sector(llio_t *self, u32 addr) { 392 | write_enable(self); 393 | eeprom_access.prefix(self); 394 | eeprom_access.send_byte(self, SPI_CMD_SECTOR_ERASE); 395 | send_address(self, addr); 396 | eeprom_access.suffix(self); 397 | wait_for_write(self); 398 | } 399 | 400 | static int local_start_programming(llio_t *self, u32 start_address, int fsize) { 401 | int ret; 402 | 403 | eeprom_access.set_cs_high(self); 404 | ret = start_programming(self, start_address, fsize); 405 | eeprom_access.set_cs_high(self); 406 | return ret; 407 | } 408 | 409 | static void done_programming(llio_t *self) { 410 | eeprom_access.set_cs_high(self); 411 | } 412 | 413 | // global functions 414 | 415 | int local_write_flash(llio_t *self, char *bitfile_name, u32 start_address, int fix_boot_flag, int sha256_check_flag) { 416 | int ret; 417 | 418 | ret = eeprom_write(self, bitfile_name, start_address, fix_boot_flag, sha256_check_flag); 419 | done_programming(self); 420 | return ret; 421 | } 422 | 423 | int local_verify_flash(llio_t *self, char *bitfile_name, u32 start_address) { 424 | return eeprom_verify(self, bitfile_name, start_address); 425 | } 426 | 427 | int local_backup_flash(llio_t *self, char *bitfile_name) { 428 | return flash_backup(self, bitfile_name); 429 | } 430 | 431 | int local_restore_flash(llio_t *self, char *bitfile_name) { 432 | return flash_restore(self, bitfile_name); 433 | } 434 | 435 | void open_spi_access_local(llio_t *self) { 436 | board_t *board = self->board; 437 | 438 | switch (board->flash) { 439 | case BOARD_FLASH_NONE: 440 | break; 441 | case BOARD_FLASH_HM2: 442 | eeprom_access.set_cs_low = &set_cs_low_hm2; 443 | eeprom_access.set_cs_high = &set_cs_high_hm2; 444 | eeprom_access.prefix = &prefix_hm2; 445 | eeprom_access.suffix = &suffix_hm2; 446 | eeprom_access.send_byte = &send_byte_hm2; 447 | eeprom_access.recv_byte = &recv_byte_hm2; 448 | break; 449 | case BOARD_FLASH_IO: 450 | #if MESAFLASH_IO 451 | eeprom_access.set_cs_low = &set_cs_low_io; 452 | eeprom_access.set_cs_high = &set_cs_high_io; 453 | eeprom_access.prefix = &prefix_io; 454 | eeprom_access.suffix = &suffix_io; 455 | eeprom_access.send_byte = &send_byte_io; 456 | eeprom_access.recv_byte = &recv_byte_io; 457 | #endif 458 | break; 459 | case BOARD_FLASH_GPIO: 460 | eeprom_access.set_cs_low = &set_cs_low_gpio; 461 | eeprom_access.set_cs_high = &set_cs_high_gpio; 462 | eeprom_access.prefix = &prefix_gpio; 463 | eeprom_access.suffix = &suffix_gpio; 464 | eeprom_access.send_byte = &send_byte_gpio; 465 | eeprom_access.recv_byte = &recv_byte_gpio; 466 | init_gpio(self); 467 | break; 468 | case BOARD_FLASH_EPP: 469 | #if MESAFLASH_IO 470 | eeprom_access.set_cs_low = &set_cs_low_epp; 471 | eeprom_access.set_cs_high = &set_cs_high_epp; 472 | eeprom_access.prefix = &prefix_epp; 473 | eeprom_access.suffix = &suffix_epp; 474 | eeprom_access.send_byte = &send_byte_epp; 475 | eeprom_access.recv_byte = &recv_byte_epp; 476 | #endif 477 | break; 478 | case BOARD_FLASH_REMOTE: 479 | break; 480 | } 481 | eeprom_access.read_page = &read_page; 482 | eeprom_access.write_page = &write_page; 483 | eeprom_access.erase_sector = &erase_sector; 484 | eeprom_access.start_programming = &local_start_programming; 485 | }; 486 | 487 | void close_spi_access_local(llio_t *self) { 488 | board_t *board = self->board; 489 | 490 | switch (board->flash) { 491 | case BOARD_FLASH_NONE: 492 | case BOARD_FLASH_HM2: 493 | case BOARD_FLASH_IO: 494 | case BOARD_FLASH_EPP: 495 | case BOARD_FLASH_REMOTE: 496 | break; 497 | case BOARD_FLASH_GPIO: 498 | restore_gpio(self); 499 | break; 500 | } 501 | } 502 | -------------------------------------------------------------------------------- /eeprom_local.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __EEPROM_LOCAL_H 20 | #define __EEPROM_LOCAL_H 21 | 22 | #include "hostmot2.h" 23 | 24 | #define SPI_DAV_MASK 0x04 25 | 26 | // gpio access 27 | #define XIO2001_SBAD_STAT_REG 0x00B2 28 | #define XIO2001_GPIO_ADDR_REG 0x00B4 29 | #define XIO2001_GPIO_DATA_REG 0x00B6 30 | 31 | #define DATA_MASK 0x80 32 | #define ADDR_MASK 0x800000 33 | 34 | #define CMD_LEN 8 35 | #define DATA_LEN 8 36 | #define ADDR_LEN 24 37 | 38 | // io access 39 | #define IO_SPI_SREG_OFFSET 0x40 40 | #define IO_SPI_CS_OFFSET 0x44 41 | 42 | // epp access 43 | #define EPP_SPI_CS_REG 0x7D 44 | #define EPP_SPI_SREG_REG 0x7E 45 | 46 | u8 read_flash_id(llio_t *self); 47 | int local_write_flash(llio_t *self, char *bitfile_name, u32 start_address, int fix_boot_flag, int sha256_check_flag); 48 | int local_verify_flash(llio_t *self, char *bitfile_name, u32 start_address); 49 | int local_backup_flash(llio_t *self, char *bitfile_name); 50 | int local_restore_flash(llio_t *self, char *bitfile_name); 51 | void open_spi_access_local(llio_t *self); 52 | void close_spi_access_local(llio_t *self); 53 | 54 | #endif 55 | 56 | 57 | -------------------------------------------------------------------------------- /eeprom_remote.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "types.h" 24 | #include "eeprom.h" 25 | #include "eeprom_remote.h" 26 | #include "eth_boards.h" 27 | #include "lbp16.h" 28 | #include "bitfile.h" 29 | 30 | extern u8 boot_block[BOOT_BLOCK_SIZE]; 31 | extern u8 page_buffer[PAGE_SIZE]; 32 | extern u8 file_buffer[SECTOR_SIZE]; 33 | 34 | extern spi_eeprom_dev_t eeprom_access; 35 | 36 | // eeprom access functions 37 | 38 | static void read_page(llio_t *self, u32 addr, void *buff) { 39 | (void)self; 40 | lbp16_cmd_addr_data32 write_addr_pck; 41 | lbp16_cmd_addr read_page_pck; 42 | 43 | LBP16_INIT_PACKET8(write_addr_pck, CMD_WRITE_FPGA_FLASH_ADDR32(1), FLASH_ADDR_REG, addr); 44 | LBP16_INIT_PACKET4(read_page_pck, CMD_READ_FPGA_FLASH_ADDR32(64), FLASH_DATA_REG); 45 | 46 | lbp16_send_packet_checked(&write_addr_pck, sizeof(write_addr_pck)); 47 | lbp16_send_packet_checked(&read_page_pck, sizeof(read_page_pck)); 48 | lbp16_recv_packet_checked(buff, PAGE_SIZE); 49 | } 50 | 51 | static void write_page(llio_t *self, u32 addr, void *buff) { 52 | (void)self; 53 | lbp16_cmd_addr_data32 write_addr_pck; 54 | lbp16_write_flash_page_packets write_page_pck; 55 | u32 ignored; 56 | 57 | LBP16_INIT_PACKET8(write_addr_pck, CMD_WRITE_FPGA_FLASH_ADDR32(1), FLASH_ADDR_REG, addr); 58 | lbp16_send_packet_checked(&write_addr_pck, sizeof(write_addr_pck)); 59 | 60 | LBP16_INIT_PACKET6(write_page_pck.write_ena_pck, CMD_WRITE_COMM_CTRL_ADDR16(1), COMM_CTRL_WRITE_ENA_REG, 0x5A03); 61 | LBP16_INIT_PACKET4(write_page_pck.fl_write_page_pck, CMD_WRITE_FPGA_FLASH_ADDR32(64), FLASH_DATA_REG); 62 | memcpy(&write_page_pck.fl_write_page_pck.page, buff, 256); 63 | lbp16_send_packet_checked(&write_page_pck, sizeof(write_page_pck)); 64 | // packet read for board syncing 65 | lbp16_read(CMD_READ_FPGA_FLASH_ADDR32(1), FLASH_ADDR_REG, &ignored, 4); 66 | } 67 | 68 | static void erase_sector(llio_t *self, u32 addr) { 69 | (void)self; 70 | lbp16_erase_flash_sector_packets sector_erase_pck; 71 | lbp16_cmd_addr_data32 write_addr_pck; 72 | u32 ignored; 73 | 74 | LBP16_INIT_PACKET8(write_addr_pck, CMD_WRITE_FPGA_FLASH_ADDR32(1), FLASH_ADDR_REG, addr); 75 | lbp16_send_packet_checked(&write_addr_pck, sizeof(write_addr_pck)); 76 | 77 | LBP16_INIT_PACKET6(sector_erase_pck.write_ena_pck, CMD_WRITE_COMM_CTRL_ADDR16(1), COMM_CTRL_WRITE_ENA_REG, 0x5A03); 78 | LBP16_INIT_PACKET8(sector_erase_pck.fl_erase_pck, CMD_WRITE_FPGA_FLASH_ADDR32(1), FLASH_SEC_ERASE_REG, 0); 79 | lbp16_send_packet_checked(§or_erase_pck, sizeof(sector_erase_pck)); 80 | // packet read for board syncing 81 | lbp16_read(CMD_READ_FPGA_FLASH_ADDR32(1), FLASH_ADDR_REG, &ignored, 4); 82 | } 83 | 84 | static int remote_start_programming(llio_t *self, u32 start_address, int fsize) { 85 | return start_programming(self, start_address, fsize); 86 | } 87 | 88 | // global functions 89 | 90 | int remote_write_flash(llio_t *self, char *bitfile_name, u32 start_address, int fix_boot_flag, int sha256_check_flag) { 91 | return eeprom_write(self, bitfile_name, start_address, fix_boot_flag, sha256_check_flag); 92 | } 93 | 94 | int remote_verify_flash(llio_t *self, char *bitfile_name, u32 start_address) { 95 | return eeprom_verify(self, bitfile_name, start_address); 96 | } 97 | 98 | int remote_backup_flash(llio_t *self, char *bitfile_name) { 99 | return flash_backup(self, bitfile_name); 100 | } 101 | 102 | int remote_restore_flash(llio_t *self, char *bitfile_name) { 103 | return flash_restore(self, bitfile_name); 104 | } 105 | 106 | void open_spi_access_remote(llio_t *self) { 107 | (void)self; 108 | eeprom_access.read_page = &read_page; 109 | eeprom_access.write_page = &write_page; 110 | eeprom_access.erase_sector = &erase_sector; 111 | eeprom_access.start_programming = &remote_start_programming; 112 | }; 113 | 114 | void close_spi_access_remote(llio_t *self) { 115 | (void)self; 116 | }; 117 | -------------------------------------------------------------------------------- /eeprom_remote.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __EEPROM_REMOTE_H 20 | #define __EEPROM_REMOTE_H 21 | 22 | #include "hostmot2.h" 23 | 24 | int remote_write_flash(llio_t *self, char *bitfile_name, u32 start_address, int fix_boot_flag, int sha256_check_flag); 25 | int remote_verify_flash(llio_t *self, char *bitfile_name, u32 start_address); 26 | int remote_backup_flash(llio_t *self, char *bitfile_name); 27 | int remote_restore_flash(llio_t *self, char *bitfile_name); 28 | void open_spi_access_remote(llio_t *self); 29 | void close_spi_access_remote(llio_t *self); 30 | 31 | #endif 32 | 33 | 34 | -------------------------------------------------------------------------------- /encoder_module.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #include 20 | #include 21 | #include 22 | #include "types.h" 23 | #include "encoder_module.h" 24 | #include "hostmot2.h" 25 | 26 | double seconds_per_tsdiv_clock; 27 | 28 | static void enable_encoder_pins(hostmot2_t *hm2) { 29 | int i; 30 | 31 | for (i = 0; i < HM2_MAX_PINS; i++) { 32 | if (hm2->pins[i].gtag == HM2_GTAG_NONE) { 33 | break; 34 | } 35 | if ((hm2->pins[i].sec_tag == HM2_GTAG_MUXED_ENCODER_SEL)) { 36 | hm2_set_pin_source(hm2, i, HM2_PIN_SOURCE_IS_SECONDARY); 37 | if (hm2->pins[i].sec_pin & HM2_PIN_OUTPUT) { 38 | hm2_set_pin_direction(hm2, i, HM2_PIN_DIR_IS_OUTPUT); 39 | } 40 | } 41 | } 42 | } 43 | 44 | // Return the physical ports to default 45 | static void disable_encoder_pins(llio_t *llio) { 46 | (void)llio; 47 | } 48 | 49 | int encoder_init(encoder_module_t *enc, board_t *board, int instance, int delay) { 50 | hm2_module_desc_t *md = hm2_find_module(&(board->llio.hm2), HM2_GTAG_MUXED_ENCODER); 51 | u32 clock, control; 52 | 53 | if (md == NULL) { 54 | printf("No encoder module found.\n"); 55 | return -1; 56 | } 57 | if (instance >= (md->instances - 1)) { 58 | printf("encoder instance number to high.\n"); 59 | return -1; 60 | } 61 | 62 | memset(enc, 0, sizeof(encoder_module_t)); 63 | enc->scale = 1.0; 64 | enc->board = board; 65 | enc->base_address = md->base_address; 66 | enc->instance = instance; 67 | enc->instance_stride = (md->strides & 0xF0) == 0 ? board->llio.hm2.idrom.instance_stride0 : board->llio.hm2.idrom.instance_stride1; 68 | 69 | enable_encoder_pins(&(enc->board->llio.hm2)); 70 | 71 | if (md->clock_tag == HM2_CLOCK_LOW_TAG) { 72 | clock = (enc->board->llio.hm2.idrom.clock_low / 1e6 * delay) - 2; 73 | seconds_per_tsdiv_clock = (double)(clock + 2) / (double)enc->board->llio.hm2.idrom.clock_low; 74 | } else if (md->clock_tag == HM2_CLOCK_HIGH_TAG) { 75 | clock = (enc->board->llio.hm2.idrom.clock_high / 1e6 * delay) - 2; 76 | seconds_per_tsdiv_clock = (double)(clock + 2) / (double)enc->board->llio.hm2.idrom.clock_high; 77 | } 78 | enc->board->llio.write(&(enc->board->llio), enc->base_address + HM2_MOD_OFFS_MUX_ENCODER_TSSDIV, &clock, sizeof(clock)); 79 | enc->board->llio.read(&(enc->board->llio), enc->base_address + HM2_MOD_OFFS_MUX_ENCODER_LATCH_CCR + enc->instance*enc->instance_stride, &control, sizeof(control)); 80 | control |= HM2_ENCODER_FILTER; 81 | control &= ~(HM2_ENCODER_QUADRATURE_ERROR); 82 | enc->board->llio.write(&(enc->board->llio), enc->base_address + HM2_MOD_OFFS_MUX_ENCODER_LATCH_CCR + enc->instance*enc->instance_stride, &control, sizeof(control)); 83 | 84 | return 0; 85 | } 86 | 87 | int encoder_cleanup(encoder_module_t *enc) { 88 | disable_encoder_pins(&(enc->board->llio)); 89 | 90 | return 0; 91 | } 92 | 93 | int encoder_read(encoder_module_t *enc) { 94 | board_t *board; 95 | u32 tsc, count, control; 96 | u16 reg_count, reg_time_stamp; 97 | int prev_raw_counts = enc->raw_counts, reg_count_diff, tsc_rollover = 0; 98 | int dT_clocks; 99 | double dT_seconds; 100 | int dS_counts; 101 | double dS_meters; 102 | 103 | if (enc == NULL) { 104 | return -1; 105 | } 106 | board = enc->board; 107 | 108 | board->llio.read(&(board->llio), enc->base_address + HM2_MOD_OFFS_MUX_ENCODER_TS_COUNT, &tsc, sizeof(tsc)); 109 | board->llio.read(&(board->llio), enc->base_address + HM2_MOD_OFFS_MUX_ENCODER_COUNTER + enc->instance*enc->instance_stride, &count, sizeof(count)); 110 | board->llio.read(&(board->llio), enc->base_address + HM2_MOD_OFFS_MUX_ENCODER_LATCH_CCR + enc->instance*enc->instance_stride, &control, sizeof(control)); 111 | 112 | if (enc->scale == 0) { 113 | enc->scale = 1.0; 114 | } 115 | reg_count = count & 0xFFFF; 116 | reg_count_diff = (int)reg_count - enc->count; 117 | reg_time_stamp = count >> 16; 118 | if (reg_count_diff == 0) { 119 | enc->velocity = 0; 120 | } else { 121 | if (reg_count_diff > 32768) reg_count_diff -= 65536; 122 | if (reg_count_diff < -32768) reg_count_diff += 65536; 123 | enc->raw_counts += reg_count_diff; 124 | 125 | if (reg_time_stamp < enc->time_stamp) { 126 | // tsc rollover! 127 | tsc_rollover++; 128 | } 129 | 130 | dT_clocks = (reg_time_stamp - enc->time_stamp) + (tsc_rollover << 16); 131 | dT_seconds = (double) dT_clocks * seconds_per_tsdiv_clock; 132 | dS_counts = enc->raw_counts - prev_raw_counts; 133 | dS_meters = (double) dS_counts / enc->scale; 134 | 135 | if (dT_clocks > 0) { 136 | enc->velocity = dS_meters / dT_seconds; 137 | } 138 | } 139 | 140 | enc->position = enc->raw_counts / enc->scale; 141 | enc->count = reg_count; 142 | enc->time_stamp = reg_time_stamp; 143 | enc->global_time_stamp = tsc; 144 | 145 | return 0; 146 | } 147 | -------------------------------------------------------------------------------- /encoder_module.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __ENCODER_MODULE_H 20 | #define __ENCODER_MODULE_H 21 | 22 | #include "boards.h" 23 | #include "hostmot2.h" 24 | 25 | typedef struct { 26 | u16 count; 27 | u16 time_stamp; 28 | u16 global_time_stamp; 29 | int raw_counts; 30 | double position; 31 | double velocity; 32 | double scale; 33 | int quad_error; 34 | board_t *board; 35 | u16 base_address; 36 | int instance; 37 | int instance_stride; 38 | } encoder_module_t; 39 | 40 | int encoder_init(encoder_module_t *enc, board_t *board, int instance, int delay); 41 | int encoder_cleanup(encoder_module_t *enc); 42 | int encoder_read(encoder_module_t *enc); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /epp_boards.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __EPP_BOARDS_H 20 | #define __EPP_BOARDS_H 21 | 22 | #include "boards.h" 23 | 24 | #define EPP_STATUS_OFFSET 1 25 | #define EPP_CONTROL_OFFSET 2 26 | #define EPP_ADDRESS_OFFSET 3 27 | #define EPP_DATA_OFFSET 4 28 | 29 | #define ECP_CONFIG_A_HIGH_OFFSET 0 30 | #define ECP_CONFIG_B_HIGH_OFFSET 1 31 | #define ECP_CONTROL_HIGH_OFFSET 2 32 | 33 | #define EPP_ADDR_AUTOINCREMENT 0x8000 34 | 35 | void epp_addr8(board_t *board, u8 addr); 36 | u8 epp_read8(board_t *board); 37 | void epp_write8(board_t *board, u8 data); 38 | int epp_boards_init(board_access_t *access); 39 | void epp_boards_cleanup(board_access_t *access); 40 | void epp_boards_scan(board_access_t *access); 41 | void epp_print_info(board_t *board); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /eth_boards.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __ETH_BOARDS_H 20 | #define __ETH_BOARDS_H 21 | 22 | #include "boards.h" 23 | 24 | int eth_boards_init(board_access_t *access); 25 | void eth_boards_cleanup(board_access_t *access); 26 | int eth_boards_scan(board_access_t *access); 27 | void eth_print_info(board_t *board); 28 | int eth_send_packet(void *packet, int size); 29 | int eth_recv_packet(void *buffer, int size); 30 | int lbp16_read(u16 cmd, u32 addr, void *buffer, int size); 31 | int lbp16_write(u16 cmd, u32 addr, void *buffer, int size); 32 | void eth_socket_set_dest_ip(char *addr_name); 33 | int eth_set_remote_ip(char *ip_addr); 34 | int eth_set_led_mode(char *led_mode); 35 | 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /examples/pci_analog_write.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "../anyio.h" 27 | #include "../sserial_module.h" 28 | #ifdef __linux__ 29 | #include 30 | #include 31 | #elif _WIN32 32 | #include "libpci/pci.h" 33 | #endif 34 | 35 | static int device_flag; 36 | static int instance_flag; 37 | static int instance = 0; 38 | static int delay_flag; 39 | static int delay = 50; 40 | static int verbose_flag; 41 | static board_access_t board_access; 42 | 43 | static struct option long_options[] = { 44 | {"device", required_argument, 0, 'd'}, 45 | {"instance", required_argument, 0, 'i'}, 46 | {"delay", required_argument, 0, 't'}, 47 | {"verbose", no_argument, &verbose_flag, 1}, 48 | {0, 0, 0, 0} 49 | }; 50 | 51 | void print_short_usage() { 52 | printf("Example program for writing analog output on pci boards\n"); 53 | printf("Syntax:\n"); 54 | printf(" pci_analog_write --device str [--instance i] [--delay d] [--verbose]\n"); 55 | printf(" --device select active device name\n"); 56 | printf(" --instance select analog output instance 'i' for reading, default 0\n"); 57 | printf(" --delay how long to wait between analog output writes in miliseconds, default 50\n"); 58 | printf(" --verbose printf additional info during execution\n"); 59 | } 60 | 61 | int process_cmd_line(int argc, char *argv[]) { 62 | int c; 63 | 64 | while (1) { 65 | /* getopt_long stores the option index here. */ 66 | int option_index = 0; 67 | 68 | c = getopt_long(argc, argv, "", long_options, &option_index); 69 | 70 | /* Detect the end of the options. */ 71 | if (c == -1) break; 72 | switch (c) { 73 | case 0: { 74 | /* If this option set a flag, do nothing else now. */ 75 | if (long_options[option_index].flag != 0) break; 76 | printf ("option %s", long_options[option_index].name); 77 | if (optarg) 78 | printf (" with arg %s", optarg); 79 | printf ("\n"); 80 | } 81 | break; 82 | 83 | case 'd': { 84 | int i; 85 | 86 | if (device_flag > 0) { 87 | printf("Error: multiply --device option\n"); 88 | exit(-1); 89 | } 90 | board_access.device_name = optarg; 91 | for (i = 0; optarg[i] != '\0'; i++) 92 | board_access.device_name[i] = toupper(board_access.device_name[i]); 93 | 94 | device_flag++; 95 | } 96 | break; 97 | 98 | case 'i': { 99 | if (instance_flag > 0) { 100 | printf("Error: multiply --instance option\n"); 101 | exit(-1); 102 | } 103 | instance = strtol(optarg, NULL, 10); 104 | instance_flag++; 105 | } 106 | break; 107 | 108 | case 't': { 109 | if (delay_flag > 0) { 110 | printf("Error: multiply --delay option\n"); 111 | exit(-1); 112 | } 113 | delay = strtol(optarg, NULL, 10); 114 | delay_flag++; 115 | } 116 | break; 117 | 118 | case '?': 119 | /* getopt_long already printed an error message. */ 120 | return -1; 121 | break; 122 | 123 | default: 124 | abort(); 125 | } 126 | } 127 | 128 | return 0; 129 | } 130 | 131 | int main(int argc, char *argv[]) { 132 | board_t *board = NULL; 133 | int ret = 0; 134 | sserial_module_t ssmod; 135 | opd_mode_1_7i77_t out; 136 | u32 *out_ptr = (u32 *) &out; 137 | 138 | if (argc == 1) { 139 | print_short_usage(); 140 | return 0; 141 | } 142 | if (process_cmd_line(argc, argv) == -1) { 143 | return -1; 144 | } 145 | 146 | board_access.verbose = verbose_flag; 147 | 148 | if (anyio_init(&board_access) != 0) { // init library 149 | return -1; 150 | } 151 | ret = anyio_find_dev(&board_access); // find board 152 | if (ret < 0) { 153 | return -1; 154 | } 155 | board = anyio_get_dev(&board_access, 1); // if found the get board handle 156 | if (board == NULL) { 157 | printf("No %s board found\n", board_access.device_name); 158 | return -1; 159 | } 160 | 161 | board->open(board); // open board for communication 162 | board->print_info(board); // print what card it is 163 | hm2_read_idrom(&(board->llio.hm2)); // read hostmot2 idrom 164 | 165 | ret = sserial_init(&ssmod, board, 0, 1, SSLBP_REMOTE_7I77_ANALOG); 166 | out.analog0 = 1 * 0xFFF / 10; 167 | out.analog1 = 2 * 0xFFF / 10; 168 | out.analog2 = 3 * 0xFFF / 10; 169 | out.analog3 = 4 * 0xFFF / 10; 170 | out.analog4 = 5 * 0xFFF / 10; 171 | out.analog5 = 6 * 0xFFF / 10; 172 | out.analogena = 1; 173 | out.spinena = 1; 174 | ssmod.interface0 = *out_ptr; 175 | ssmod.interface1 = *(out_ptr + 1); 176 | ssmod.interface2 = *(out_ptr + 2); 177 | while (1) { 178 | sserial_write(&ssmod); 179 | printf("sserial remote status %x\n", ssmod.cs); 180 | usleep(delay*1000); // wait delay ms 181 | } 182 | 183 | sserial_cleanup(&ssmod); 184 | 185 | board->close(board); // close board communication 186 | 187 | anyio_cleanup(&board_access); // close library 188 | 189 | return 0; 190 | } 191 | -------------------------------------------------------------------------------- /examples/pci_encoder_read.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "../anyio.h" 27 | #include "../encoder_module.h" 28 | #ifdef __linux__ 29 | #include 30 | #include 31 | #elif _WIN32 32 | #include "libpci/pci.h" 33 | #endif 34 | 35 | static int device_flag; 36 | static int instance_flag; 37 | static int instance = 0; 38 | static int delay_flag; 39 | static int delay = 50; 40 | static int verbose_flag; 41 | static board_access_t board_access; 42 | 43 | static struct option long_options[] = { 44 | {"device", required_argument, 0, 'd'}, 45 | {"instance", required_argument, 0, 'i'}, 46 | {"delay", required_argument, 0, 't'}, 47 | {"verbose", no_argument, &verbose_flag, 1}, 48 | {0, 0, 0, 0} 49 | }; 50 | 51 | void print_short_usage() { 52 | printf("Example program forreading encoder on pci boards\n"); 53 | printf("Syntax:\n"); 54 | printf(" pci_encoder_read --device str [--instance i] [--delay d] [--verbose]\n"); 55 | printf(" --device select active device name\n"); 56 | printf(" --instance select encoder instance 'i' for reading, default 0\n"); 57 | printf(" --delay how long to wait between encoder reads in miliseconds, default 50\n"); 58 | printf(" --verbose printf additional info during execution\n"); 59 | } 60 | 61 | int process_cmd_line(int argc, char *argv[]) { 62 | int c; 63 | 64 | while (1) { 65 | /* getopt_long stores the option index here. */ 66 | int option_index = 0; 67 | 68 | c = getopt_long(argc, argv, "", long_options, &option_index); 69 | 70 | /* Detect the end of the options. */ 71 | if (c == -1) break; 72 | switch (c) { 73 | case 0: { 74 | /* If this option set a flag, do nothing else now. */ 75 | if (long_options[option_index].flag != 0) break; 76 | printf ("option %s", long_options[option_index].name); 77 | if (optarg) 78 | printf (" with arg %s", optarg); 79 | printf ("\n"); 80 | } 81 | break; 82 | 83 | case 'd': { 84 | int i; 85 | 86 | if (device_flag > 0) { 87 | printf("Error: multiply --device option\n"); 88 | exit(-1); 89 | } 90 | board_access.device_name = optarg; 91 | for (i = 0; optarg[i] != '\0'; i++) 92 | board_access.device_name[i] = toupper(board_access.device_name[i]); 93 | 94 | device_flag++; 95 | } 96 | break; 97 | 98 | case 'i': { 99 | if (instance_flag > 0) { 100 | printf("Error: multiply --instance option\n"); 101 | exit(-1); 102 | } 103 | instance = strtol(optarg, NULL, 10); 104 | instance_flag++; 105 | } 106 | break; 107 | 108 | case 't': { 109 | if (delay_flag > 0) { 110 | printf("Error: multiply --delay option\n"); 111 | exit(-1); 112 | } 113 | delay = strtol(optarg, NULL, 10); 114 | delay_flag++; 115 | } 116 | break; 117 | 118 | case '?': 119 | /* getopt_long already printed an error message. */ 120 | return -1; 121 | break; 122 | 123 | default: 124 | abort(); 125 | } 126 | } 127 | 128 | return 0; 129 | } 130 | 131 | int main(int argc, char *argv[]) { 132 | board_t *board = NULL; 133 | int ret = 0; 134 | encoder_module_t enc; 135 | 136 | if (argc == 1) { 137 | print_short_usage(); 138 | return 0; 139 | } 140 | if (process_cmd_line(argc, argv) == -1) { 141 | return -1; 142 | } 143 | 144 | board_access.verbose = verbose_flag; 145 | 146 | if (anyio_init(&board_access) != 0) { // init library 147 | return -1; 148 | } 149 | ret = anyio_find_dev(&board_access); // find board 150 | if (ret < 0) { 151 | return -1; 152 | } 153 | board = anyio_get_dev(&board_access, 1); // if found the get board handle 154 | if (board == NULL) { 155 | printf("No %s board found\n", board_access.device_name); 156 | return -1; 157 | } 158 | 159 | board->open(board); // open board for communication 160 | board->print_info(board); // print what card it is 161 | hm2_read_idrom(&(board->llio.hm2)); // read hostmot2 idrom 162 | 163 | ret = encoder_init(&enc, board, instance, delay); // init encoder 'instance' module on 'board' 164 | if (ret < 0) { 165 | goto fail0; 166 | } 167 | 168 | while (1) { 169 | encoder_read(&enc); // read encoder 170 | printf("tsc = %u, raw_counts = %u, velocity = %.2f\n", enc.global_time_stamp, enc.raw_counts, enc.velocity); 171 | usleep(delay*1000); // wait delay ms 172 | } 173 | 174 | encoder_cleanup(&enc); // cleanup enocder module 175 | 176 | fail0: 177 | board->close(board); // close board communication 178 | 179 | anyio_cleanup(&board_access); // close library 180 | 181 | return 0; 182 | } 183 | -------------------------------------------------------------------------------- /hostmot2.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __HOSTMOT2_H 20 | #define __HOSTMOT2_H 21 | 22 | #include "types.h" 23 | #include "hostmot2_def.h" 24 | 25 | typedef struct { 26 | int index; 27 | char name[64]; 28 | } sw_mode_t; 29 | 30 | typedef struct { 31 | u32 unit; 32 | u16 sw_revision; 33 | u16 hw_revision; 34 | char name[4]; 35 | sw_mode_t sw_modes[256]; 36 | int sw_modes_cnt; 37 | } sserial_device_t; 38 | 39 | #define HM2_MAX_TAGS 255 40 | #define MAX_BOB_NAMES 42 41 | #define ANYIO_MAX_IOPORT_CONNECTORS 8 42 | 43 | typedef struct llio_struct llio_t; 44 | 45 | typedef struct { 46 | llio_t *llio; 47 | char config_name[8]; 48 | hm2_idrom_desc_t idrom; 49 | hm2_module_desc_t modules[HM2_MAX_MODULES]; 50 | hm2_pin_desc_t pins[HM2_MAX_PINS]; 51 | } hostmot2_t; 52 | 53 | struct llio_struct { 54 | int (*read)(llio_t *self, u32 addr, void *buffer, int size); 55 | int (*write)(llio_t *self, u32 addr, void *buffer, int size); 56 | int (*write_flash)(llio_t *self, char *bitfile_name, u32 start_address, int fix_boot_flag, int sha256_check_flag); 57 | int (*verify_flash)(llio_t *self, char *bitfile_name, u32 start_address); 58 | int (*backup_flash)(llio_t *self, char *bitfile_name); 59 | int (*restore_flash)(llio_t *self, char *bitfile_name); 60 | int (*program_fpga)(llio_t *self, char *bitfile_name); 61 | int (*reset)(llio_t *self); 62 | int (*reload)(llio_t *self, int fallback_flag); 63 | int num_ioport_connectors; 64 | int pins_per_connector; 65 | const char *ioport_connector_name[ANYIO_MAX_IOPORT_CONNECTORS]; 66 | u16 bob_hint[ANYIO_MAX_IOPORT_CONNECTORS]; 67 | int num_leds; 68 | const char *fpga_part_number; 69 | char board_name[16]; 70 | void *board; 71 | hostmot2_t hm2; 72 | sserial_interface_t ss_interface[HM2_SSERIAL_MAX_INTERFACES]; 73 | sserial_device_t ss_device[HM2_SSERIAL_MAX_CHANNELS]; 74 | int verbose; 75 | }; 76 | 77 | typedef struct { 78 | u8 tag; 79 | char *name[32]; 80 | } pin_name_t; 81 | 82 | typedef struct { 83 | u16 bobname; 84 | char *name[32]; 85 | } bob_pin_name_t; 86 | 87 | typedef struct { 88 | char *name; 89 | u8 tag; 90 | } mod_name_t; 91 | 92 | void hm2_read_idrom(hostmot2_t *hm2); 93 | hm2_module_desc_t *hm2_find_module(hostmot2_t *hm2, u8 gtag); 94 | void hm2_print_pin_file(llio_t *llio, int xml_flag); 95 | void hm2_print_pin_descriptors(llio_t *llio); 96 | void hm2_print_localio_descriptors(llio_t *llio); 97 | void hm2_enable_all_module_outputs(hostmot2_t *hm2); 98 | void hm2_safe_io(hostmot2_t *hm2); 99 | void hm2_set_pin_source(hostmot2_t *hm2, u32 pin_number, u8 source); 100 | void hm2_set_pin_direction(hostmot2_t *hm2, u32 pin_number, u8 direction); 101 | void sserial_module_init(llio_t *llio); 102 | 103 | int hm2_find_bob_hint_by_name(const char *arg); 104 | void hm2_print_bob_hint_names(); 105 | 106 | #endif 107 | 108 | -------------------------------------------------------------------------------- /hostmot2_def.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __HOSTMOT2_DEF_H 20 | #define __HOSTMOT2_DEF_H 21 | 22 | #include "types.h" 23 | 24 | #define HM2_AREA_SIZE 0x10000 25 | 26 | // 27 | // Pin Descriptor constants 28 | // 29 | 30 | #define HM2_PIN_SOURCE_IS_PRIMARY 0x00 31 | #define HM2_PIN_SOURCE_IS_SECONDARY 0x01 32 | #define HM2_PIN_DIR_IS_INPUT 0x02 33 | #define HM2_PIN_DIR_IS_OUTPUT 0x04 34 | 35 | #define HM2_GTAG_NONE 0x00 36 | #define HM2_GTAG_IRQ_LOGIC 0x01 37 | #define HM2_GTAG_WATCHDOG 0x02 38 | #define HM2_GTAG_IOPORT 0x03 39 | #define HM2_GTAG_ENCODER 0x04 40 | #define HM2_GTAG_STEPGEN 0x05 41 | #define HM2_GTAG_PWMGEN 0x06 42 | #define HM2_GTAG_SPI 0x07 43 | #define HM2_GTAG_SSI 0x08 44 | #define HM2_GTAG_UART_TX 0x09 45 | #define HM2_GTAG_UART_RX 0x0A 46 | #define HM2_GTAG_TRAM 0x0B 47 | #define HM2_GTAG_MUXED_ENCODER 0x0C 48 | #define HM2_GTAG_MUXED_ENCODER_SEL 0x0D 49 | #define HM2_GTAG_BSPI 0x0E 50 | #define HM2_GTAG_DBSPI 0x0F 51 | #define HM2_GTAG_DPLL 0x10 52 | #define HM2_GTAG_MUXED_ENCODER_MIM 0x11 53 | #define HM2_GTAG_MUXED_ENCODER_SEL_MIM 0x12 54 | #define HM2_GTAG_TPPWM 0x13 55 | #define HM2_GTAG_WAVEGEN 0x14 56 | #define HM2_GTAG_DAQ_FIFO 0x15 57 | #define HM2_GTAG_BIN_OSC 0x16 58 | #define HM2_GTAG_BIN_DMDMA 0x17 59 | #define HM2_GTAG_BISS 0x18 60 | #define HM2_GTAG_FABS 0x19 61 | #define HM2_GTAG_HM2DPLL 0x1A 62 | #define HM2_GTAG_PKTUART_TX 0x1B 63 | #define HM2_GTAG_PKTUART_RX 0x1C 64 | #define HM2_GTAG_INMUX 0x1E 65 | #define HM2_GTAG_SIGMA5 0x1F 66 | #define HM2_GTAG_INM 0x23 67 | #define HM2_GTAG_DPAINTER 0x2A 68 | #define HM2_GTAG_XYMOD 0x2B 69 | #define HM2_GTAG_RCPWMGEN 0x2C 70 | #define HM2_GTAG_OUTM 0x2D 71 | #define HM2_GTAG_LIOPORT 0x40 72 | #define HM2_GTAG_LED 0x80 73 | #define HM2_GTAG_RESOLVER 0xC0 74 | #define HM2_GTAG_SSERIAL 0xC1 75 | #define HM2_GTAG_TWIDDLER 0xC2 76 | #define HM2_GTAG_SSR 0xC3 77 | #define HM2_GTAG_CPDRIVE 0xC4 78 | #define HM2_GTAG_DSAD 0xC5 79 | #define HM2_GTAG_SSERIALB 0xC6 80 | #define HM2_GTAG_ONESHOT 0xC7 81 | #define HM2_GTAG_PERIOD 0xC8 82 | #define HM2_GTAG_BSPID 0xC9 83 | 84 | 85 | // HM2 EEPROM SPI INTERFACE 86 | 87 | #define HM2_SPI_CTRL_REG 0x0070 88 | #define HM2_SPI_DATA_REG 0x0074 89 | 90 | // HM2 ICAP INTERFACE 91 | 92 | #define HM2_ICAP_REG 0x0078 93 | #define HM2_ICAP_COOKIE 0x1CAB1CAB 94 | 95 | // hm2 access 96 | #define SPI_CMD_PAGE_WRITE 0x02 97 | #define SPI_CMD_READ 0x03 98 | #define SPI_CMD_READ_STATUS 0x05 99 | #define SPI_CMD_WRITE_ENABLE 0x06 100 | #define SPI_CMD_READ_IDROM 0xAB 101 | #define SPI_CMD_SECTOR_ERASE 0xD8 102 | 103 | #define WRITE_IN_PROGRESS_MASK 0x01 104 | 105 | // IDROM 106 | 107 | #define HM2_COOKIE_REG 0x0100 108 | #define HM2_CONFIG_NAME 0x0104 109 | #define HM2_IDROM_ADDR 0x010C 110 | 111 | #define HM2_CONFIG_NAME_LEN 8 112 | #define HM2_COOKIE 0x55AACAFE 113 | 114 | #define HM2_MAX_MODULES 32 115 | #define HM2_MAX_PINS 144 116 | 117 | typedef struct { 118 | u32 idrom_type; 119 | u32 offset_to_modules; 120 | u32 offset_to_pins; 121 | char board_name[8]; 122 | u32 fpga_size; 123 | u32 fpga_pins; 124 | u32 io_ports; 125 | u32 io_width; 126 | u32 port_width; 127 | u32 clock_low; 128 | u32 clock_high; 129 | u32 instance_stride0; 130 | u32 instance_stride1; 131 | u32 register_stride0; 132 | u32 register_stride1; 133 | } hm2_idrom_desc_t; 134 | 135 | #define HM2_CLOCK_LOW_TAG 0x01 136 | #define HM2_CLOCK_HIGH_TAG 0x02 137 | 138 | typedef struct { 139 | u8 gtag; 140 | u8 version; 141 | u8 clock_tag; 142 | u8 instances; 143 | u16 base_address; 144 | u8 registers; 145 | u8 strides; 146 | u32 mp_bitmap; 147 | } hm2_module_desc_t; 148 | 149 | #define HM2_CHAN_GLOBAL 0x80 150 | #define HM2_PIN_OUTPUT 0x80 151 | 152 | typedef struct { 153 | u8 sec_pin; 154 | u8 sec_tag; 155 | u8 sec_chan; 156 | u8 gtag; 157 | } hm2_pin_desc_t; 158 | 159 | // LEDS MODULE 160 | 161 | #define HM2_MOD_OFFS_LED 0x0200 162 | 163 | // WATCHDOG MODULE 164 | 165 | #define HM2_MOD_OFFS_WD_TIMER 0x0000 166 | #define HM2_MOD_OFFS_WD_STATUS 0x0100 167 | #define HM2_MOD_OFFS_WD_RESET 0x0200 168 | 169 | // GPIO MODULE 170 | 171 | #define HM2_MOD_OFFS_GPIO 0x0000 172 | #define HM2_MOD_OFFS_GPIO_DDR 0x0100 173 | #define HM2_MOD_OFFS_GPIO_ALT_SOURCE 0x0200 174 | #define HM2_MOD_OFFS_GPIO_OPEN_DRAIN 0x0300 175 | #define HM2_MOD_OFFS_GPIO_INVERT_OUT 0x0400 176 | 177 | // STEPGEN MODULE 178 | 179 | #define HM2_MOD_OFFS_STEPGEN_RATE 0x0000 180 | #define HM2_MOD_OFFS_STEPGEN_ACCUM 0x0100 181 | #define HM2_MOD_OFFS_STEPGEN_MODE 0x0200 182 | #define HM2_MOD_OFFS_STEPGEN_DIR_SETUP 0x0300 183 | #define HM2_MOD_OFFS_STEPGEN_DIR_HOLD 0x0400 184 | #define HM2_MOD_OFFS_STEPGEN_STEP_LEN 0x0500 185 | #define HM2_MOD_OFFS_STEPGEN_STEP_SPACE 0x0600 186 | #define HM2_MOD_OFFS_STEPGEN_TABLE_DATA 0x0700 187 | #define HM2_MOD_OFFS_STEPGEN_TABLE_LEN 0x0800 188 | #define HM2_MOD_OFFS_STEPGEN_DDS 0x0900 189 | 190 | // ENCODER MODULE 191 | 192 | #define HM2_MOD_OFFS_ENCODER_COUNTER 0x0000 193 | #define HM2_MOD_OFFS_ENCODER_LATCH_CCR 0x0100 194 | #define HM2_MOD_OFFS_ENCODER_TSSDIV 0x0200 195 | #define HM2_MOD_OFFS_ENCODER_TS_COUNT 0x0300 196 | #define HM2_MOD_OFFS_ENCODER_FILTER_RATE 0x0400 197 | 198 | // MUXED ENCODER MODULE 199 | 200 | #define HM2_MOD_OFFS_MUX_ENCODER_COUNTER 0x0000 201 | #define HM2_MOD_OFFS_MUX_ENCODER_LATCH_CCR 0x0100 202 | #define HM2_MOD_OFFS_MUX_ENCODER_TSSDIV 0x0200 203 | #define HM2_MOD_OFFS_MUX_ENCODER_TS_COUNT 0x0300 204 | #define HM2_MOD_OFFS_MUX_ENCODER_FILTER_RATE 0x0400 205 | 206 | #define HM2_ENCODER_QUADRATURE_ERROR (1 << 15) 207 | #define HM2_ENCODER_AB_MASK_POLARITY (1 << 14) 208 | #define HM2_ENCODER_LATCH_ON_PROBE (1 << 13) 209 | #define HM2_ENCODER_PROBE_POLARITY (1 << 12) 210 | #define HM2_ENCODER_FILTER (1 << 11) 211 | #define HM2_ENCODER_COUNTER_MODE (1 << 10) 212 | #define HM2_ENCODER_INDEX_MASK (1 << 9) 213 | #define HM2_ENCODER_INDEX_MASK_POLARITY (1 << 8) 214 | #define HM2_ENCODER_INDEX_JUSTONCE (1 << 6) 215 | #define HM2_ENCODER_CLEAR_ON_INDEX (1 << 5) 216 | #define HM2_ENCODER_LATCH_ON_INDEX (1 << 4) 217 | #define HM2_ENCODER_INDEX_POLARITY (1 << 3) 218 | #define HM2_ENCODER_INPUT_INDEX (1 << 2) 219 | #define HM2_ENCODER_INPUT_B (1 << 1) 220 | #define HM2_ENCODER_INPUT_A (1 << 0) 221 | 222 | #define HM2_ENCODER_CONTROL_MASK 0x0000FFFF 223 | 224 | // SSERIAL MODULE 225 | 226 | #define HM2_SSERIAL_MAX_INTERFACES 4 227 | #define HM2_SSERIAL_MAX_CHANNELS 8 228 | 229 | #define HM2_MOD_OFFS_SSERIAL_CMD 0x0000 230 | #define HM2_MOD_OFFS_SSERIAL_DATA 0x0100 231 | #define HM2_MOD_OFFS_SSERIAL_CS 0x0200 232 | #define HM2_MOD_OFFS_SSERIAL_INTERFACE0 0x0300 233 | #define HM2_MOD_OFFS_SSERIAL_INTERFACE1 0x0400 234 | #define HM2_MOD_OFFS_SSERIAL_INTERFACE2 0x0500 235 | 236 | #define SSLBP_TYPE_LOC 0 237 | #define SSLBP_WIDTH_LOC 1 238 | #define SSLBP_MAJOR_REV_LOC 2 239 | #define SSLBP_MINOR_REV_LOC 3 240 | #define SSLBP_CHANNEL_START_LOC 4 241 | #define SSLBP_CHANNEL_STRIDE_LOC 5 242 | #define SSLBP_PROCESSOR_TYPE_LOC 6 243 | #define SSLBP_NR_CHANNELS_LOC 7 244 | #define SSLBP_CLOCK_LOC 0x230 245 | 246 | #define SSLBP_START_NORMAL 0x0900 247 | #define SSLBP_START_SETUP 0x0F00 248 | #define SSLBP_STOP 0x0800 249 | #define SSLBP_DOIT 0x1000 250 | #define SSLBP_REQUEST 0x2000 251 | #define SSLBP_RESET 0x4000 252 | #define SSLBP_READ 0x0000 253 | #define SSLBP_WRITE 0x8000 254 | 255 | #define SSLBP_CMD_START_NORMAL_MODE(x) (SSLBP_START_NORMAL | ((1 << x) & 0xFF)) 256 | #define SSLBP_CMD_START_SETUP_MODE(x) (SSLBP_START_SETUP | ((1 << x) & 0xFF)) 257 | #define SSLBP_CMD_STOP(x) (SSLBP_STOP | ((1 << x) & 0xFF)) 258 | #define SSLBP_CMD_STOPALL (SSLBP_STOP) 259 | #define SSLBP_CMD_RESET (SSLBP_RESET) 260 | #define SSLBP_CMD_DOIT(x) (SSLBP_DOIT | ((1 << x) & 0xFF)) 261 | #define SSLBP_CMD_READ(x) (SSLBP_REQUEST | SSLBP_READ | (x & 0x3FF)) 262 | #define SSLBP_CMD_WRITE(x) (SSLBP_REQUEST | SSLBP_WRITE | ((x & 0x3FF)) 263 | 264 | #define LBP_DATA 0xA0 265 | #define LBP_MODE 0xB0 266 | 267 | #define LBP_IN 0x00 268 | #define LBP_IO 0x40 269 | #define LBP_OUT 0x80 270 | 271 | #define LBP_PAD 0x00 272 | #define LBP_BITS 0x01 273 | #define LBP_UNSIGNED 0x02 274 | #define LBP_SIGNED 0x03 275 | #define LBP_NONVOL_UNSIGNED 0x04 276 | #define LBP_NONVOL_SIGNED 0x05 277 | #define LBP_STREAM 0x06 278 | #define LBP_BOOLEAN 0x07 279 | #define LBP_ENCODER 0x08 280 | #define LBP_ENCODER_H 0x18 // For Fanuc Absolute Encoders with separate 281 | #define LBP_ENCODER_L 0x28 // part and full count fields 282 | 283 | #define SSLBP_REMOTE_7I76_IO_SPINDLE 0x10000000 284 | #define SSLBP_REMOTE_7I77_ANALOG 0x11000000 285 | #define SSLBP_REMOTE_7I77_IO 0x12000000 286 | 287 | // must match BOB name order 288 | # define BOB_7I76 1 289 | # define BOB_7I77 2 290 | # define BOB_7I94_0 3 291 | # define BOB_7I94_1 4 292 | # define BOB_7I95_0 5 293 | # define BOB_7I95_1 6 294 | # define BOB_7I96_0 7 295 | # define BOB_7I96_1 8 296 | # define BOB_7I96_2 9 297 | # define BOB_7I97_0 10 298 | # define BOB_7I97_1 11 299 | # define BOB_7I97_2 12 300 | # define BOB_7C80_0 13 301 | # define BOB_7C80_1 14 302 | # define BOB_7C81_0 15 303 | # define BOB_7C81_1 16 304 | # define BOB_7C81_2 17 305 | # define BOB_7I74 18 306 | # define BOB_7I78 19 307 | # define BOB_7I85 20 308 | # define BOB_7I85S 21 309 | # define BOB_7I88 22 310 | # define BOB_7I89 23 311 | # define BOB_DMM4250 24 312 | # define BOB_5ABOB 25 313 | # define BOB_G540 26 314 | # define BOB_C11 27 315 | # define BOB_C11G 28 316 | # define BOB_7I33TA 29 317 | # define BOB_7I37TA 30 318 | # define BOB_7I44 31 319 | # define BOB_7I47 32 320 | # define BOB_7I47S 33 321 | # define BOB_7I48 34 322 | # define BOB_7I52 35 323 | # define BOB_7I52S 36 324 | # define BOB_MX3660 37 325 | # define BOB_MX4660_1 38 326 | # define BOB_MX4660_2 39 327 | # define BOB_7I75 40 328 | # define BOB_BENEZAN 41 329 | # define BOB_HDR26 42 330 | 331 | 332 | 333 | 334 | struct sserial_pdd_struct { 335 | u8 record_type; 336 | u8 data_size; 337 | u8 data_type; 338 | u8 data_dir; 339 | float param_min; 340 | float param_max; 341 | u16 param_addr; 342 | } __attribute__ ((__packed__)); 343 | typedef struct sserial_pdd_struct sserial_pdd_t; 344 | 345 | struct sserial_md_struct { 346 | u8 record_type; 347 | u8 mode_index; 348 | u8 mode_type; 349 | u8 unused; 350 | }; 351 | typedef struct sserial_md_struct sserial_md_t; 352 | 353 | typedef struct { 354 | u8 type; 355 | u8 width; 356 | u8 ver_major; 357 | u8 ver_minor; 358 | u8 gp_inputs; 359 | u8 gp_outputs; 360 | u8 processor_type; 361 | u8 channels_count; 362 | u32 clock; 363 | int baud_rate; 364 | } sserial_interface_t; 365 | 366 | #endif 367 | -------------------------------------------------------------------------------- /lbp.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifdef _WIN32 20 | #include 21 | #endif 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "types.h" 28 | #include "boards.h" 29 | #include "lbp.h" 30 | 31 | #ifdef __linux__ 32 | static int sd = -1; 33 | #elif _WIN32 34 | HANDLE sd; 35 | #endif 36 | 37 | void lbp_send_checked(void *packet, int size) { 38 | #ifdef __linux__ 39 | int result = write(sd, packet, size); 40 | if (result != size) { 41 | perror("write(lbp_send_checked)"); 42 | abort(); 43 | } 44 | #elif _WIN32 45 | BOOL result = WriteFile(sd, packet, size, &send, NULL); 46 | if (!result) { 47 | printf("WriteFile(lbp_send_checked): %d\n", GetLastError()); 48 | } 49 | #endif 50 | } 51 | 52 | void lbp_recv_checked(void *packet, int size) { 53 | #ifdef __linux__ 54 | int result = read(sd, packet, size); 55 | if (result != size) { 56 | perror("read(lbp_recv_checked)"); 57 | abort(); 58 | } 59 | #elif _WIN32 60 | BOOL result = ReadFile(sd, packet, size, &recv, NULL); 61 | if (!result) { 62 | printf("ReadFile(lbp_recv_checked): %d\n", GetLastError()); 63 | } 64 | #endif 65 | } 66 | 67 | u8 lbp_read_ctrl(u8 cmd) { 68 | u8 data; 69 | 70 | lbp_send_checked(&cmd, 1); 71 | lbp_recv_checked(&data, 1); 72 | if (LBP_SENDRECV_DEBUG) 73 | printf("send(%X), recv(%X)\n", cmd, data); 74 | 75 | return data; 76 | } 77 | 78 | int lbp_read(u16 addr, void *buffer) { 79 | lbp_cmd_addr packet; 80 | u32 *ptr = buffer; 81 | 82 | packet.cmd = LBP_CMD_READ | LBP_ARGS_32BIT; 83 | packet.addr_hi = LO_BYTE(addr); 84 | packet.addr_lo = HI_BYTE(addr); 85 | 86 | lbp_send_checked(&packet, sizeof(lbp_cmd_addr)); 87 | lbp_recv_checked(buffer, 4); 88 | if (LBP_SENDRECV_DEBUG) 89 | printf("lbp_read(%02X:%04X): %08X\n", packet.cmd, addr, *ptr); 90 | 91 | return 0; 92 | } 93 | 94 | int lbp_write(u16 addr, void *buffer) { 95 | lbp_cmd_addr_data packet; 96 | 97 | packet.cmd = LBP_CMD_WRITE | LBP_ARGS_32BIT; 98 | packet.addr_hi = LO_BYTE(addr); 99 | packet.addr_lo = HI_BYTE(addr); 100 | memcpy(&packet.data, buffer, 4); 101 | 102 | lbp_send_checked(&packet, sizeof(lbp_cmd_addr_data)); 103 | if (LBP_SENDRECV_DEBUG) 104 | printf("lbp_write(%02X:%04X)\n", packet.cmd, addr); 105 | 106 | return 0; 107 | } 108 | 109 | void lbp_print_info() { 110 | u8 data; 111 | 112 | data = lbp_read_ctrl(LBP_CMD_READ_VERSION); 113 | printf(" LBP version %d\n", data); 114 | } 115 | 116 | void lbp_init(board_access_t *access) { 117 | #ifdef __linux__ 118 | sd = open(access->dev_addr, O_RDWR, O_NONBLOCK); 119 | if (sd == -1) 120 | perror("Unable to open the serial port\n"); 121 | #elif _WIN32 122 | char dev_name[32]; 123 | 124 | snprintf(dev_name, 32, "\\\\.\\%s", access->dev_addr); 125 | sd = CreateFile(dev_name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); 126 | if (sd == INVALID_HANDLE_VALUE) { 127 | printf("Unable to open the serial port %d\n", errno); 128 | } 129 | #endif 130 | } 131 | 132 | void lbp_release() { 133 | #ifdef __linux__ 134 | close(sd); 135 | #endif 136 | } 137 | -------------------------------------------------------------------------------- /lbp.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __LBP_H 20 | #define __LBP_H 21 | 22 | #include "types.h" 23 | #include "common.h" 24 | 25 | #define LBP_SENDRECV_DEBUG 0 26 | 27 | #define LBP_COOKIE 0x5A 28 | 29 | #define LBP_ARGS_8BIT 0b00000000 30 | #define LBP_ARGS_16BIT 0b00000001 31 | #define LBP_ARGS_32BIT 0b00000010 32 | #define LBP_ARGS_64BIT 0b00000011 33 | #define LBP_ADDR 0b00000100 34 | #define LBP_NO_ADDR 0b00000000 35 | #define LBP_ADDR_AUTO_INC 0b00001000 36 | #define LBP_RPC_INCLUDES_DATA 0b00010000 37 | #define LBP_WRITE 0b00100000 38 | #define LBP_READ 0b00000000 39 | #define LBP_CMD_RW 0b01000000 40 | 41 | #define LBP_CMD_READ (LBP_CMD_RW | LBP_READ | LBP_ADDR) 42 | #define LBP_CMD_WRITE (LBP_CMD_RW | LBP_WRITE | LBP_ADDR) 43 | 44 | #define LBP_CMD_READ_UNIT_ADDR 0xC0 45 | #define LBP_CMD_READ_STATUS 0xC1 46 | #define LBP_CMD_READ_ENA_RPCMEM 0xCA 47 | #define LBP_CMD_READ_CMD_TIMEOUT 0xCB 48 | #define LBP_CMD_READ_DEV_NAME0 0xD0 49 | #define LBP_CMD_READ_DEV_NAME1 0xD1 50 | #define LBP_CMD_READ_DEV_NAME2 0xD2 51 | #define LBP_CMD_READ_DEV_NAME3 0xD3 52 | #define LBP_CMD_READ_CONFIG_NAME0 0xD4 53 | #define LBP_CMD_READ_CONFIG_NAME1 0xD5 54 | #define LBP_CMD_READ_CONFIG_NAME2 0xD6 55 | #define LBP_CMD_READ_CONFIG_NAME3 0xD7 56 | #define LBP_CMD_READ_LO_ADDR 0xD8 57 | #define LBP_CMD_READ_HI_ADDR 0xD9 58 | #define LBP_CMD_READ_VERSION 0xDA 59 | #define LBP_CMD_READ_UNIT_ID 0xDB 60 | #define LBP_CMD_READ_RPC_PITCH 0xDC 61 | #define LBP_CMD_READ_RPC_SIZE_LO 0xDD 62 | #define LBP_CMD_READ_RPC_SIZE_HI 0xDE 63 | #define LBP_CMD_READ_COOKIE 0xDF 64 | #define LBP_CMD_READ_NV 0xEC 65 | 66 | #define LBP_NVEEPROM_BYTE 0x01 67 | 68 | struct lbp_cmd_addr_struct { 69 | u8 cmd; 70 | u8 addr_hi; 71 | u8 addr_lo; 72 | } __attribute__ ((__packed__)); 73 | typedef struct lbp_cmd_addr_struct lbp_cmd_addr; 74 | 75 | struct lbp_cmd_addr_data_struct { 76 | u8 cmd; 77 | u8 addr_hi; 78 | u8 addr_lo; 79 | u32 data; 80 | } __attribute__ ((__packed__)); 81 | typedef struct lbp_cmd_addr_data_struct lbp_cmd_addr_data; 82 | 83 | void lbp_send_checked(void *packet, int size); 84 | void lbp_recv_checked(void *packet, int size); 85 | u8 lbp_read_ctrl(u8 cmd); 86 | int lbp_read(u16 addr, void *buffer); 87 | int lbp_write(u16 addr, void *buffer); 88 | void lbp_print_info(); 89 | void lbp_init(board_access_t *access); 90 | void lbp_release(); 91 | 92 | #endif 93 | 94 | -------------------------------------------------------------------------------- /lbp16.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "types.h" 24 | #include "lbp16.h" 25 | #include "eth_boards.h" 26 | #include "serial_boards.h" 27 | 28 | static lbp16_access_t lbp16_access; 29 | 30 | void lbp16_send_packet_checked(void *packet, int size) { 31 | int result = lbp16_access.send_packet(packet, size); 32 | if (size != result) { 33 | perror("lbp16_access.send_packet"); 34 | abort(); 35 | } 36 | } 37 | 38 | int lbp16_recv_packet(void *packet, int size) { 39 | return lbp16_access.recv_packet(packet, size); 40 | } 41 | 42 | void lbp16_recv_packet_checked(void *packet, int size) { 43 | int result = lbp16_access.recv_packet(packet, size); 44 | if (size != result) { 45 | perror("lbp16_access.recv_packet"); 46 | abort(); 47 | } 48 | } 49 | 50 | int lbp16_read(u16 cmd, u32 addr, void *buffer, int size) { 51 | lbp16_cmd_addr packet; 52 | u8 local_buff[size]; 53 | 54 | LBP16_INIT_PACKET4(packet, cmd, addr); 55 | if (LBP16_SENDRECV_DEBUG) { 56 | printf("SEND: %02X %02X %02X %02X | REQUEST %d bytes\n", packet.cmd_hi, packet.cmd_lo, packet.addr_hi, packet.addr_lo, size); 57 | } 58 | lbp16_access.send_packet(&packet, sizeof(packet)); 59 | lbp16_access.recv_packet(&local_buff, sizeof(local_buff)); 60 | if (LBP16_SENDRECV_DEBUG) { 61 | printf("RECV: %zd bytes\n", sizeof(local_buff)); 62 | } 63 | memcpy(buffer, local_buff, size); 64 | 65 | return 0; 66 | } 67 | 68 | int lbp16_write(u16 cmd, u32 addr, void *buffer, int size) { 69 | static struct { 70 | lbp16_cmd_addr wr_packet; 71 | u8 tmp_buffer[LBP16_MAX_PACKET_DATA_SIZE*8]; 72 | } packet; 73 | 74 | LBP16_INIT_PACKET4(packet.wr_packet, cmd, addr); 75 | memcpy(&packet.tmp_buffer, buffer, size); 76 | if (LBP16_SENDRECV_DEBUG) { 77 | printf("SEND: %02X %02X %02X %02X | WRITE %d bytes\n", packet.wr_packet.cmd_hi, packet.wr_packet.cmd_lo, 78 | packet.wr_packet.addr_hi, packet.wr_packet.addr_lo, size); 79 | } 80 | lbp16_access.send_packet(&packet, sizeof(lbp16_cmd_addr) + size); 81 | 82 | return 0; 83 | } 84 | 85 | int lbp16_board_reset(llio_t *self) { 86 | (void)self; 87 | lbp16_cmd_addr_data16 packet; 88 | 89 | LBP16_INIT_PACKET6(packet, CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1C, 0x0001); // reset if != 0 90 | lbp16_send_packet_checked(&packet, sizeof(packet)); 91 | 92 | return 0; 93 | } 94 | 95 | int lbp16_board_reload(llio_t *self, int fallback_flag) { 96 | board_t *board = self->board; 97 | u32 boot_addr; 98 | u16 fw_ver; 99 | lbp16_cmd_addr_data16 packet[14]; 100 | lbp16_cmd_addr fw_packet; 101 | 102 | LBP16_INIT_PACKET4(fw_packet, CMD_READ_BOARD_INFO_ADDR16(1), offsetof(lbp_info_area, firmware_version)); 103 | lbp16_send_packet_checked(&fw_packet, sizeof(fw_packet)); 104 | lbp16_recv_packet_checked(&fw_ver, sizeof(fw_ver)); 105 | 106 | if ((board->type & BOARD_ETH) && (fw_ver < 15)) { 107 | printf("ERROR: FPGA reload only supported by ethernet card firmware > 14.\n"); 108 | return -1; 109 | } else if ((board->type & BOARD_SER) && (fw_ver < 2)) { 110 | printf("ERROR: FPGA reload only supported by serial card firmware > 2.\n"); 111 | return -1; 112 | } 113 | 114 | if (board->fpga_type == FPGA_TYPE_EFINIX) { 115 | // Efinix config register instructions 116 | if (fallback_flag == 1) { 117 | LBP16_INIT_PACKET6(packet[0], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0x0004); // image number 0 + config enable 118 | LBP16_INIT_PACKET6(packet[1], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0x000C); // image number 0 + config enable + config start 119 | } else { 120 | LBP16_INIT_PACKET6(packet[0], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0x0005); // image number 1 + config enable 121 | LBP16_INIT_PACKET6(packet[1], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0x000D); // image number 1 + config enable + config start 122 | } 123 | lbp16_send_packet_checked(&packet, sizeof(packet)); 124 | } else { 125 | // Xilinx ICAP instructions 126 | if (fallback_flag == 1) { 127 | boot_addr = 0x10000; 128 | } else { 129 | boot_addr = 0x0; 130 | } 131 | boot_addr |= 0x0B000000; // plus read command in high byte 132 | 133 | LBP16_INIT_PACKET6(packet[0], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0xFFFF); // dummy 134 | LBP16_INIT_PACKET6(packet[1], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0xFFFF); // dummy 135 | LBP16_INIT_PACKET6(packet[2], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0xAA99); // sync 136 | LBP16_INIT_PACKET6(packet[3], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0x5566); // sync 137 | LBP16_INIT_PACKET6(packet[4], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0x3261); // load low flash start address 138 | LBP16_INIT_PACKET6(packet[5], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, boot_addr & 0xFFFF); // start addr 139 | LBP16_INIT_PACKET6(packet[6], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0x3281); // load high start address + read command 140 | LBP16_INIT_PACKET6(packet[7], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, boot_addr >> 16); // start addr (plus read command in high byte) 141 | LBP16_INIT_PACKET6(packet[8], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0x30A1); // load command register 142 | LBP16_INIT_PACKET6(packet[9], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0x000E); // IPROG command 143 | LBP16_INIT_PACKET6(packet[10], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0x2000); // NOP 144 | LBP16_INIT_PACKET6(packet[11], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0x2000); // NOP 145 | LBP16_INIT_PACKET6(packet[12], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0x2000); // NOP 146 | LBP16_INIT_PACKET6(packet[13], CMD_WRITE_COMM_CTRL_ADDR16(1), 0x1E, 0x2000); // NOP 147 | lbp16_send_packet_checked(&packet, sizeof(packet)); 148 | } 149 | return 0; 150 | } 151 | 152 | void lbp16_init(int board_type) { 153 | switch (board_type) { 154 | case BOARD_ETH: 155 | lbp16_access.send_packet = ð_send_packet; 156 | lbp16_access.recv_packet = ð_recv_packet; 157 | break; 158 | case BOARD_SER: 159 | lbp16_access.send_packet = &serial_send_packet; 160 | lbp16_access.recv_packet = &serial_recv_packet; 161 | break; 162 | default: 163 | break; 164 | } 165 | } 166 | 167 | void lbp_cleanup(int board_type) { 168 | (void)board_type; 169 | } 170 | -------------------------------------------------------------------------------- /lbp16.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __LBP16_H 20 | #define __LBP16_H 21 | 22 | #include "types.h" 23 | #include "common.h" 24 | 25 | #define LBP16_SENDRECV_DEBUG 0 26 | 27 | #define LBP16_UDP_PORT 27181 28 | #define LBP16_HW_IP "192.168.1.121" 29 | 30 | #define LBP16_MEM_SPACE_COUNT 8 31 | 32 | #define LBP16_CMD_SIZE 2 33 | #define LBP16_ADDR_SIZE 2 34 | #define LBP16_CMDADDR_PACKET_SIZE (LBP16_CMD_SIZE + LBP16_ADDR_SIZE) 35 | #define LBP16_CMDONLY_PACKET_SIZE (LBP16_CMD_SIZE) 36 | #define LBP16_MAX_PACKET_DATA_SIZE 0x7F 37 | 38 | #define FLASH_ADDR_REG 0x0000 39 | #define FLASH_DATA_REG 0x0004 40 | #define FLASH_ID_REG 0x0008 41 | #define FLASH_SEC_ERASE_REG 0x000C 42 | 43 | #define ETH_EEPROM_IP_REG 0x0020 44 | #define ETH_EEPROM_LED_MODE_REG 0x0028 45 | 46 | #define COMM_CTRL_WRITE_ENA_REG 0x001A 47 | 48 | #define LBP16_ADDR_AUTO_INC 0x0080 49 | #define LBP16_ARGS_8BIT 0x0000 50 | #define LBP16_ARGS_16BIT 0x0100 51 | #define LBP16_ARGS_32BIT 0x0200 52 | #define LBP16_ARGS_64BIT 0x0300 53 | #define LBP16_SPACE_HM2 0x0000 54 | #define LBP16_SPACE_ETH_CHIP 0x0400 55 | #define LBP16_SPACE_ETH_EEPROM 0x0800 56 | #define LBP16_SPACE_FPGA_FLASH 0x0C00 57 | #define LBP16_SPACE_TIMER 0x1000 58 | #define LBP16_SPACE_COMM_CTRL 0x1800 59 | #define LBP16_SPACE_BOARD_INFO 0x1C00 60 | #define LBP16_SPACE_ACC 0x0000 61 | #define LBP16_INFO_ACC 0x2000 62 | #define LBP16_READ 0x0000 63 | #define LBP16_ADDR 0x4000 64 | #define LBP16_NO_ADDR 0x0000 65 | #define LBP16_WRITE 0x8000 66 | 67 | #define CMD_READ_AREA_INFO_16 (LBP16_READ | LBP16_ADDR | LBP16_INFO_ACC | LBP16_ARGS_16BIT) 68 | #define CMD_READ_ADDR_16 (LBP16_READ | LBP16_ADDR | LBP16_SPACE_ACC | LBP16_ARGS_16BIT) 69 | #define CMD_READ_ADDR_32 (LBP16_READ | LBP16_ADDR | LBP16_SPACE_ACC | LBP16_ARGS_32BIT) 70 | #define CMD_WRITE_ADDR_16 (LBP16_WRITE | LBP16_ADDR | LBP16_SPACE_ACC | LBP16_ARGS_16BIT) 71 | #define CMD_WRITE_ADDR_16_INCR (LBP16_WRITE | LBP16_ADDR | LBP16_SPACE_ACC | LBP16_ADDR_AUTO_INC | LBP16_ARGS_16BIT) 72 | #define CMD_WRITE_ADDR_32 (LBP16_WRITE | LBP16_ADDR | LBP16_SPACE_ACC | LBP16_ARGS_32BIT) 73 | #define CMD_WRITE_ADDR_32_INCR (LBP16_WRITE | LBP16_ADDR | LBP16_SPACE_ACC | LBP16_ADDR_AUTO_INC | LBP16_ARGS_32BIT) 74 | 75 | #define CMD_READ_AREA_INFO_ADDR16(space, size) (CMD_READ_AREA_INFO_16 | space | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 76 | #define CMD_READ_AREA_INFO_ADDR16_INCR(space, size) (CMD_READ_AREA_INFO_16 | LBP16_ADDR_AUTO_INC | space | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 77 | 78 | #define CMD_READ_HOSTMOT2_ADDR32(size) (CMD_READ_ADDR_32 | LBP16_SPACE_HM2 | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 79 | #define CMD_READ_HOSTMOT2_ADDR32_INCR(size) (CMD_READ_ADDR_32 | LBP16_SPACE_HM2 | LBP16_ADDR_AUTO_INC | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 80 | #define CMD_READ_ETH_CHIP_ADDR16(size) (CMD_READ_ADDR_16 | LBP16_SPACE_ETH_CHIP | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 81 | #define CMD_READ_ETH_CHIP_ADDR16_INCR(size) (CMD_READ_ADDR_16 | LBP16_SPACE_ETH_CHIP | LBP16_ADDR_AUTO_INC | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 82 | #define CMD_READ_ETH_EEPROM_ADDR16(size) (CMD_READ_ADDR_16 | LBP16_SPACE_ETH_EEPROM | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 83 | #define CMD_READ_ETH_EEPROM_ADDR16_INCR(size) (CMD_READ_ADDR_16 | LBP16_SPACE_ETH_EEPROM | LBP16_ADDR_AUTO_INC | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 84 | #define CMD_READ_FPGA_FLASH_ADDR32(size) (CMD_READ_ADDR_32 | LBP16_SPACE_FPGA_FLASH | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 85 | #define CMD_READ_TIMER_ADDR16(size) (CMD_READ_ADDR_16 | LBP16_SPACE_TIMER | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 86 | #define CMD_READ_TIMER_ADDR16_INCR(size) (CMD_READ_ADDR_16 | LBP16_SPACE_TIMER | LBP16_ADDR_AUTO_INC | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 87 | #define CMD_READ_COMM_CTRL_ADDR16(size) (CMD_READ_ADDR_16 | LBP16_SPACE_COMM_CTRL | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 88 | #define CMD_READ_COMM_CTRL_ADDR16_INCR(size) (CMD_READ_ADDR_16 | LBP16_SPACE_COMM_CTRL | LBP16_ADDR_AUTO_INC | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 89 | #define CMD_READ_BOARD_INFO_ADDR16(size) (CMD_READ_ADDR_16 | LBP16_SPACE_BOARD_INFO | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 90 | #define CMD_READ_BOARD_INFO_ADDR16_INCR(size) (CMD_READ_ADDR_16 | LBP16_SPACE_BOARD_INFO | LBP16_ADDR_AUTO_INC | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 91 | 92 | #define CMD_WRITE_HOSTMOT2_ADDR32(size) (CMD_WRITE_ADDR_32 | LBP16_SPACE_HM2 | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 93 | #define CMD_WRITE_HOSTMOT2_ADDR32_INCR(size) (CMD_WRITE_ADDR_32 | LBP16_SPACE_HM2 | LBP16_ADDR_AUTO_INC | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 94 | #define CMD_WRITE_FPGA_FLASH_ADDR32(size) (CMD_WRITE_ADDR_32 | LBP16_SPACE_FPGA_FLASH | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 95 | #define CMD_WRITE_COMM_CTRL_ADDR16(size) (CMD_WRITE_ADDR_16 | LBP16_SPACE_COMM_CTRL | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 96 | #define CMD_WRITE_ETH_EEPROM_ADDR16(size) (CMD_WRITE_ADDR_16 | LBP16_SPACE_ETH_EEPROM | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 97 | #define CMD_WRITE_ETH_EEPROM_ADDR16_INCR(size) (CMD_WRITE_ADDR_16_INCR | LBP16_SPACE_ETH_EEPROM | ((size) & LBP16_MAX_PACKET_DATA_SIZE)) 98 | 99 | // common packets 100 | #define CMD_READ_HM2_COOKIE (CMD_READ_HOSTMOT2_ADDR32(1)) 101 | #define CMD_READ_FLASH_IDROM (CMD_READ_FPGA_FLASH_ADDR32(1)) 102 | 103 | typedef struct { 104 | u8 cmd_hi; 105 | u8 cmd_lo; 106 | } lbp16_cmd; 107 | 108 | typedef struct { 109 | u8 cmd_hi; 110 | u8 cmd_lo; 111 | u8 addr_hi; 112 | u8 addr_lo; 113 | } lbp16_cmd_addr; 114 | 115 | typedef struct { 116 | u8 cmd_hi; 117 | u8 cmd_lo; 118 | u8 addr_hi; 119 | u8 addr_lo; 120 | u8 data_hi; 121 | u8 data_lo; 122 | } lbp16_cmd_addr_data16; 123 | 124 | typedef struct { 125 | u8 cmd_hi; 126 | u8 cmd_lo; 127 | u8 addr_hi; 128 | u8 addr_lo; 129 | u8 data1; 130 | u8 data2; 131 | u8 data3; 132 | u8 data4; 133 | } lbp16_cmd_addr_data32; 134 | 135 | typedef struct { 136 | u8 cmd_hi; 137 | u8 cmd_lo; 138 | u8 addr_hi; 139 | u8 addr_lo; 140 | u8 page[256]; 141 | } lbp16_write_flash_page_packet; 142 | 143 | typedef struct { 144 | lbp16_cmd_addr_data16 write_ena_pck; 145 | lbp16_cmd_addr_data32 fl_erase_pck; 146 | } lbp16_erase_flash_sector_packets; 147 | 148 | typedef struct { 149 | lbp16_cmd_addr_data16 write_ena_pck; 150 | lbp16_write_flash_page_packet fl_write_page_pck; 151 | } lbp16_write_flash_page_packets; 152 | 153 | typedef struct { 154 | lbp16_cmd_addr_data16 write_ena_pck; 155 | lbp16_cmd_addr_data32 eth_write_ip_pck; 156 | } lbp16_write_ip_addr_packets; 157 | 158 | typedef struct { 159 | lbp16_cmd_addr_data16 write_ena_pck; 160 | lbp16_cmd_addr_data16 eth_write_led_pck; 161 | } lbp16_write_led_mode_packets; 162 | 163 | #define LBP16_INIT_PACKET4(packet, cmd, addr) do { \ 164 | packet.cmd_hi = LO_BYTE(cmd); \ 165 | packet.cmd_lo = HI_BYTE(cmd); \ 166 | packet.addr_hi = LO_BYTE(addr); \ 167 | packet.addr_lo = HI_BYTE(addr); \ 168 | } while (0); 169 | 170 | #define LBP16_INIT_PACKET4_SERIAL(packet, cmd, addr) do { \ 171 | packet.cmd_hi = HI_BYTE(cmd); \ 172 | packet.cmd_lo = LO_BYTE(cmd); \ 173 | packet.addr_hi = HI_BYTE(addr); \ 174 | packet.addr_lo = LO_BYTE(addr); \ 175 | } while (0); 176 | 177 | #define LBP16_INIT_PACKET6(packet, cmd, addr, data) do { \ 178 | packet.cmd_hi = LO_BYTE(cmd); \ 179 | packet.cmd_lo = HI_BYTE(cmd); \ 180 | packet.addr_hi = LO_BYTE(addr); \ 181 | packet.addr_lo = HI_BYTE(addr); \ 182 | packet.data_hi = LO_BYTE(data); \ 183 | packet.data_lo = HI_BYTE(data); \ 184 | } while (0); 185 | 186 | #define LBP16_INIT_PACKET8(packet, cmd, addr, data) do { \ 187 | packet.cmd_hi = LO_BYTE(cmd); \ 188 | packet.cmd_lo = HI_BYTE(cmd); \ 189 | packet.addr_hi = LO_BYTE(addr); \ 190 | packet.addr_lo = HI_BYTE(addr); \ 191 | packet.data1 = LO_BYTE(data); \ 192 | packet.data2 = HI_BYTE(data); \ 193 | packet.data3 = LO_BYTE((data >> 16) & 0xFFFF); \ 194 | packet.data4 = HI_BYTE((data >> 16) & 0xFFFF); \ 195 | } while (0); 196 | 197 | typedef struct { 198 | u16 cookie; 199 | u16 size; 200 | u16 range; 201 | u16 addr; 202 | u8 name[8]; 203 | } lbp_mem_info_area; 204 | 205 | typedef struct { 206 | u16 reserved1; 207 | u16 mac_addr_lo; 208 | u16 mac_addr_mid; 209 | u16 mac_addr_hi; 210 | u16 reserved2; 211 | u16 reserved3; 212 | u16 reserved4; 213 | u16 reserved5; 214 | u8 name[16]; 215 | u16 ip_addr_lo; 216 | u16 ip_addr_hi; 217 | u16 reserved6; 218 | u16 reserved7; 219 | u16 led_debug; 220 | u16 reserved8; 221 | u16 reserved9; 222 | u16 reserved10; 223 | } lbp_eth_eeprom_area; 224 | 225 | typedef struct { 226 | u16 uSTimeStampReg; 227 | u16 WaituSReg; 228 | u16 HM2Timeout; 229 | } lbp_timers_area; 230 | 231 | typedef struct { 232 | u16 ErrorReg; 233 | u16 LBPParseErrors; 234 | u16 LBPMemErrors; 235 | u16 LBPWriteErrors; 236 | u16 RXPacketCount; 237 | u16 RXGoodCount; 238 | u16 RXBadCount; 239 | u16 TXPacketCount; 240 | u16 TXGoodCount; 241 | u16 TXBadCount; 242 | u16 led_mode; 243 | u16 DebugLEDPtr; 244 | u16 Scratch; 245 | } lbp_status_area; 246 | 247 | typedef struct { 248 | u8 name[16]; 249 | u16 LBP16_version; 250 | u16 firmware_version; 251 | u16 jumpers; 252 | } lbp_info_area; 253 | 254 | typedef struct { 255 | int (*send_packet)(void *packet, int size); 256 | int (*recv_packet)(void *buffer, int size); 257 | } lbp16_access_t; 258 | 259 | void lbp16_init(int board_type); 260 | void lbp16_cleanup(int board_type); 261 | int lbp16_read(u16 cmd, u32 addr, void *buffer, int size); 262 | int lbp16_write(u16 cmd, u32 addr, void *buffer, int size); 263 | int lbp16_board_reset(llio_t *self); 264 | int lbp16_board_reload(llio_t *self, int fallback_flag); 265 | void lbp16_send_packet_checked(void *packet, int size); 266 | int lbp16_recv_packet(void *packet, int size); 267 | void lbp16_recv_packet_checked(void *packet, int size); 268 | 269 | #endif 270 | -------------------------------------------------------------------------------- /mesaflash.1: -------------------------------------------------------------------------------- 1 | .TH MESAFLASH 1 "November 5 2022" "version 3.4.6" 2 | .SH NAME 3 | MesaFlash \- utility to flash Mesa Electronics FPGA Cards 4 | .SH SYNOPSIS 5 | .B mesaflash [options] [commands] 6 | .SH DESCRIPTION 7 | .B mesaflash 8 | Read, write, configure Mesa Electronics FPGA cards. 9 | .SH OPTIONS 10 | .TP 11 | .BI --device " name" 12 | Select active device name. If no command is given it will detect board 13 | with given name and print info about it. 14 | 15 | The special values "ETHER", "SPI" and "AUTO" will attempt to detect a device 16 | on ethernet, SPI, or any interface; --addr still needs to be specified for 17 | non-PCI devices. 18 | .TP 19 | .BI --addr " [ip]|[device]" 20 | Use ip or device name to look for (IP address for Ethernet boards, 21 | serial device name for USB boards and serial boards, SPI device name for 22 | SPI boards) 23 | .TP 24 | .B --addr_hi 25 | Set the high register address for the EPP interface. 26 | .TP 27 | .B --epp 28 | Use EPP interface to connect to board, only for boards with multiple 29 | interfaces (7c80, 7c81, 7i43, 7i90, 7i64). 30 | .TP 31 | .B --usb 32 | Use USB interface to connect to board, only for boards with multiple 33 | interfaces (7c80, 7c81, 7i43, 7i90, 7i64). 34 | .TP 35 | .B --spi 36 | Use SPI interface to connect to board, only for boards with multiple 37 | interfaces (7c80, 7c81, 7i43, 7i90, 7i64). 38 | .TP 39 | .B --serial 40 | Use serial interface to connect to board, only for boards with multiple 41 | interfaces (7i43, 7i90, 7i64). 42 | .TP 43 | .B --fallback 44 | Use the fallback area of the FLASH memory while executing commands. 45 | .TP 46 | .B --recover 47 | Access board using PCI bridge GPIO (currently only 6I24/6I25). 48 | .TP 49 | .B --xml 50 | Format output from 'readhmid' command into XML. 51 | .TP 52 | .BI --dbname# " name" 53 | Set daughter board name to 'name' for FPGA connector 'N'. 54 | Allows readhmid to include daughterboard terminal names, 55 | where # can be in the range 1 to 6 (1 means first FPGA connector). 56 | .TP 57 | .B --verbose 58 | Print detailed information while running commands. 59 | .SH COMMANDS 60 | .TP 61 | .BI --write " filename" 62 | Writes a standard bitfile 'filename' configuration to the userarea of 63 | the FLASH memory (IMPORTANT! 'filename' must be VALID FPGA configuration file). 64 | .TP 65 | .B --fix-boot-block 66 | If a write operation does not detect a valid boot block, write one. 67 | .TP 68 | .B --no-auto-verify 69 | Don't automatically verify after writing. 70 | .TP 71 | .BI --verify " filename" 72 | Verifies the FLASH memory configuration against the bitfile 'filename'. 73 | .TP 74 | .BI --program " filename" 75 | Writes a standard bitfile 'filename' configuration to the FPGA 76 | (IMPORTANT! 'filename' must be VALID FPGA configuration file). 77 | .TP 78 | .BI --backup-flash " filename|dirname" 79 | Backup all content the FLASH memory to the file 'filename' 80 | or to the directory 'dirname' with auto naming dump file. 81 | .TP 82 | .BI --restore-flash " filename" 83 | Restore all content the FLASH memory from a file 'filename' 84 | (IMPORTANT! Can't use a dump file from different types 85 | of boards. Unacceptable interrupt the restoring process. 86 | If the restoring process was interrupted, do not turn off 87 | the board power and do not reload board, and run restore 88 | process again). Required SHA256 checksum file 'filename.sha256'. 89 | .TP 90 | .B --sha256-check 91 | Integrity check FPGA configuration bitfile before writing. 92 | Required SHA256 checksum file 'filename.sha256'. 93 | .TP 94 | .B --readhmid 95 | Print hostmot2 configuration in PIN file format. 96 | .TP 97 | .B --print-pd 98 | Print hostmot2 Pin Descriptors. 99 | .TP 100 | .B --reload 101 | Do full FPGA reload from FLASH memory (only Ethernet, SPI and PCI boards). 102 | .TP 103 | .B --reset 104 | Do full firmware reset (only Ethernet and serial boards). 105 | .TP 106 | .B --sserial 107 | Print full information about all sserial remote boards. 108 | .TP 109 | .BI --rpo " address" 110 | Read hostmot2 variable directly at 'address'. 111 | .TP 112 | .BI --wpo " address value" 113 | Write hostmot2 variable directly at 'address' with 'value'. 114 | .TP 115 | .BI --set ip="n.n.n.n" 116 | Set board IP address in EEPROM memory to n.n.n.n (only Ethernet boards). 117 | .TP 118 | .BI --info " filename" 119 | Print info about configuration in 'filename'. 120 | .TP 121 | .B --help 122 | Print the help message 123 | .SH BUGS 124 | No known bugs. 125 | .SH AUTHOR 126 | LinuxCNC Developer Community 127 | .PP 128 | Michael Geszkiewicz 129 | .PP 130 | Peter Wallace 131 | .SH COPYRIGHT 132 | GNU GPL v2+ License 133 | .PP 134 | Copyright (c) 2020 Sebastian Kuzminsky 135 | .PP 136 | Copyright (c) 2019 Peter Wallace 137 | .PP 138 | Copyright (c) 2013-2015 Michael Geszkiewicz 139 | -------------------------------------------------------------------------------- /pci_boards.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __PCI_BOARDS_H 20 | #define __PCI_BOARDS_H 21 | 22 | #include "types.h" 23 | #include "boards.h" 24 | 25 | #define VENDORID_MESAPCI 0x2718 26 | #define VENDORID_PLX 0x10B5 27 | #define VENDORID_XIO2001 0x104C 28 | 29 | #define DEVICEID_MESA4I74 0x4174 30 | #define DEVICEID_MESA5I24 0x5124 31 | #define DEVICEID_MESA5I25 0x5125 32 | #define DEVICEID_MESA5I25T 0x5925 33 | #define DEVICEID_MESA6I24 0x6124 34 | #define DEVICEID_MESA6I25 0x6125 35 | #define DEVICEID_PLX9030 0x9030 36 | #define DEVICEID_PLX9054 0x9054 37 | #define DEVICEID_PLX9056 0x9056 38 | #define DEVICEID_PLX8112 0x8112 39 | #define DEVICEID_XIO2001 0x8240 40 | 41 | #define SUBDEVICEID_MESA5I20 0x3131 42 | #define SUBDEVICEID_MESA4I65 0x3132 43 | #define SUBDEVICEID_MESA4I68_OLD 0x3133 44 | #define SUBDEVICEID_MESA4I68 0x3311 45 | #define SUBDEVICEID_MESA5I21 0x3312 46 | #define SUBDEVICEID_MESA5I22_15 0x3313 47 | #define SUBDEVICEID_MESA5I22_10 0x3314 48 | #define SUBDEVICEID_MESA5I23 0x3315 49 | #define SUBDEVICEID_MESA3X20_10 0x3427 50 | #define SUBDEVICEID_MESA3X20_15 0x3428 51 | #define SUBDEVICEID_MESA3X20_20 0x3429 52 | #define SUBDEVICEID_MESA4I69_16 0x3472 53 | #define SUBDEVICEID_MESA4I69_25 0x3473 54 | 55 | #define EEPROM_93C66_SIZE 256 56 | #define EEPROM_93C66_CMD_LEN 3 57 | #define EEPROM_93C66_ADDR_LEN 8 58 | #define EEPROM_93C66_DATA_LEN 16 59 | 60 | #define EEPROM_93C66_CMD_WREN 4 61 | #define EEPROM_93C66_CMD_WRITE 5 62 | #define EEPROM_93C66_CMD_READ 6 63 | #define EEPROM_93C66_CMD_ERASE 7 64 | 65 | #define EEPROM_93C66_CMD_MASK 0x04 66 | #define EEPROM_93C66_ADDR_MASK 0x80 67 | #define EEPROM_93C66_DATA_MASK 0x8000 68 | 69 | // 70 | // PLX 9030 (5i20, 4i65) 71 | // 72 | 73 | // I/O registers 74 | #define PLX9030_CTRL_INIT_OFFSET 0x0052 75 | #define PLX9030_CTRL_STAT_OFFSET 0x0054 /* 9030 GPIO register (region 1) */ 76 | 77 | // bit number in 9030 INIT register 78 | #define PLX9030_EECLK_MASK 0x0100 79 | #define PLX9030_EECS_MASK 0x0200 80 | #define PLX9030_EEDI_MASK 0x0400 81 | #define PLX9030_EEDO_MASK 0x0800 82 | 83 | // bit number in 9030 GPIO register 84 | #define PLX9030_GPIO_3_MASK (1<<11) /* GPIO 3 */ 85 | #define PLX9030_DONE_MASK (1<<11) /* GPIO 3 */ 86 | #define PLX9030_INIT_MASK (1<<14) /* GPIO 4 */ 87 | #define PLX9030_LED_MASK (1<<17) /* GPIO 5 */ 88 | #define PLX9030_GPIO_6_MASK (1<<20) /* GPIO 6 */ 89 | #define PLX9030_WRITE_MASK (1<<23) /* GPIO 7 */ 90 | #define PLX9030_PROGRAM_MASK (1<<26) /* GPIO 8 */ 91 | 92 | // the LAS?BRD registers are in the PLX 9030 93 | // 94 | // The HostMot2 firmware needs the #READY bit (0x2) set in order to work, 95 | // but the EEPROMs on some older 5i20 cards dont set them right. 96 | // The driver detects this problem and fixes it up. 97 | // 98 | 99 | #define PLX9030_LAS0BRD_OFFSET 0x28 100 | #define PLX9030_LAS1BRD_OFFSET 0x2C 101 | #define PLX9030_LAS2BRD_OFFSET 0x30 102 | #define PLX9030_LAS3BRD_OFFSET 0x34 103 | 104 | #define PLX9030_LASxBRD_READY 0x2 105 | 106 | // 107 | // PLX 9054 (5i22, 5i23, 4i68, 4i69) 108 | // Note: also used for the PLX 9056 (3x20) 109 | // 110 | 111 | // I/O register indices. 112 | #define PLX905X_CTRL_STAT_OFFSET 0x006C // 32-bit control/status register. 113 | #define PLX9056_VPD_ADDR 0x4E 114 | #define PLX9056_VPD_DATA 0x50 115 | #define PLX9056_VPD_FMASK 0x8000 // F bit in VPD address register 116 | 117 | // bit number in 9054 GPIO register 118 | // yes, the direction control bits are not in the same order as the I/O bits 119 | #define PLX905X_DONE_MASK (1<<17) // GPI 120 | #define PLX905X_PROGRAM_MASK (1<<16) // GPO, active low 121 | #define PLX905X_DONE_ENABLE (1<<18) // GPI direction control, 1=input 122 | #define PLX905X_PROG_ENABLE (1<<19) // GPO direction control, 1=output 123 | 124 | /* how long should we wait for DONE when programming 9054-based cards */ 125 | #define PLX905X_DONE_WAIT 20000 126 | 127 | int pci_boards_init(board_access_t *access); 128 | void pci_boards_cleanup(board_access_t *access); 129 | void pci_boards_scan(board_access_t *access); 130 | void pci_print_info(board_t *board); 131 | 132 | #endif 133 | 134 | -------------------------------------------------------------------------------- /serial_boards.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "types.h" 30 | #include "anyio.h" 31 | #include "serial_boards.h" 32 | #include "lbp16.h" 33 | #include "eeprom.h" 34 | #include "eeprom_remote.h" 35 | 36 | extern board_t boards[MAX_BOARDS]; 37 | extern int boards_count; 38 | 39 | static int sd = -1; 40 | 41 | // serial access functions 42 | 43 | int serial_send_packet(void *packet, int size) { 44 | int rc, ret; 45 | int r = 0, timeouts = 0; 46 | struct timespec timeout = {0, 50*1000*1000}; 47 | struct pollfd fds[1]; 48 | fds[0].fd = sd; 49 | fds[0].events = POLLOUT; 50 | 51 | while (r < size) { 52 | rc = ppoll(fds, 1, &timeout, NULL); 53 | if (rc > 0) { 54 | ret = write(sd, packet, size); 55 | r += ret; 56 | } else if (rc == 0) { 57 | timeouts ++; 58 | if (timeouts == 5) { 59 | printf("serial write timeout!\n"); 60 | return -1; 61 | } 62 | } else if (rc < 0) { 63 | break; 64 | } 65 | } 66 | return r; 67 | } 68 | 69 | int serial_recv_packet(void *packet, int size) { 70 | int rc, ret; 71 | int r = 0, timeouts = 0; 72 | struct timespec timeout = {0, 300*1000*1000}; 73 | struct pollfd fds[1]; 74 | fds[0].fd = sd; 75 | fds[0].events = POLLIN; 76 | char buffer[1024]; 77 | 78 | while (r < size) { 79 | rc = ppoll(fds, 1, &timeout, NULL); 80 | if (rc > 0) { 81 | ret = read(sd, buffer + r, 1); 82 | if (ret < 0) { 83 | printf("serial read error: %s\n", strerror(errno)); 84 | return -1; 85 | } else if (ret == 0) { 86 | printf("serial read EOF\n"); 87 | return -1; 88 | } 89 | r += ret; 90 | } else if (rc == 0) { 91 | timeouts ++; 92 | if (timeouts == 5) { 93 | printf("serial read timeout!\n"); 94 | return -1; 95 | } 96 | } else if (rc < 0) { 97 | break; 98 | } 99 | } 100 | memcpy(packet, buffer, r); 101 | return r; 102 | } 103 | 104 | static int serial_read(llio_t *self, u32 addr, void *buffer, int size) { 105 | (void)self; 106 | return lbp16_read(CMD_READ_HOSTMOT2_ADDR32_INCR(size/4), addr, buffer, size); 107 | } 108 | 109 | static int serial_write(llio_t *self, u32 addr, void *buffer, int size) { 110 | (void)self; 111 | return lbp16_write(CMD_WRITE_HOSTMOT2_ADDR32_INCR(size/4), addr, buffer, size); 112 | } 113 | 114 | static int serial_board_open(board_t *board) { 115 | eeprom_init(&(board->llio)); 116 | lbp16_read(CMD_READ_FLASH_IDROM, FLASH_ID_REG, &(board->flash_id), sizeof(u32)); 117 | if (board->fallback_support == 1) { 118 | eeprom_prepare_boot_block(board->flash_id); 119 | board->flash_start_address = eeprom_calc_user_space(board->flash_id); 120 | } else { 121 | board->flash_start_address = 0; 122 | } 123 | return 0; 124 | } 125 | 126 | static int serial_board_close(board_t *board) { 127 | (void)board; 128 | return 0; 129 | } 130 | 131 | // public functions 132 | 133 | int serial_boards_init(board_access_t *access) { 134 | #ifdef __linux__ 135 | struct termios options; 136 | 137 | sd = open(access->dev_addr, O_RDWR | O_NOCTTY | O_NONBLOCK); 138 | if (sd == -1) { 139 | perror("Unable to open the serial port\n"); 140 | } 141 | 142 | tcgetattr(sd, &options); /* Get the current options for the port */ 143 | cfsetispeed(&options, B115200); /* Set the baud rates to 9600 */ 144 | cfsetospeed(&options, B115200); 145 | 146 | options.c_cflag &= ~CSTOPB; 147 | options.c_cflag &= ~CSIZE; 148 | options.c_cflag |= CS8; 149 | options.c_cflag &= ~(PARENB | PARODD); // shut off parity 150 | 151 | 152 | options.c_lflag = 0; 153 | 154 | options.c_cflag &= ~CRTSCTS; /* Disable hardware flow control */ 155 | options.c_iflag &= ~IGNBRK; 156 | 157 | options.c_oflag = 0; 158 | 159 | tcsetattr(sd, TCSANOW, &options); 160 | #elif _WIN32 161 | char dev_name[32]; 162 | 163 | snprintf(dev_name, 32, "\\\\.\\%s", access->dev_addr); 164 | sd = CreateFile(dev_name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); 165 | if (sd == INVALID_HANDLE_VALUE) { 166 | printf("Unable to open the serial port %d\n", errno); 167 | } 168 | #endif 169 | lbp16_init(BOARD_SER); 170 | return 0; 171 | } 172 | 173 | void serial_boards_cleanup(board_access_t *access) { 174 | (void)access; 175 | close(sd); 176 | } 177 | 178 | void serial_boards_scan(board_access_t *access) { 179 | lbp16_cmd_addr packet; 180 | char buff[16]; 181 | 182 | LBP16_INIT_PACKET4(packet, CMD_READ_BOARD_INFO_ADDR16_INCR(8), 0); 183 | lbp16_send_packet_checked(&packet, sizeof(packet)); 184 | lbp16_recv_packet_checked(buff, 16); 185 | if (strncmp(buff, "7I90HD", 6) == 0) { 186 | board_t *board = &boards[boards_count]; 187 | 188 | board_init_struct(board); 189 | 190 | board->type = BOARD_SER; 191 | strncpy(board->dev_addr, access->dev_addr, 16); 192 | strncpy(board->llio.board_name, buff, 16); 193 | board->llio.num_ioport_connectors = 3; 194 | board->llio.pins_per_connector = 24; 195 | board->llio.ioport_connector_name[0] = "P1"; 196 | board->llio.ioport_connector_name[1] = "P2"; 197 | board->llio.ioport_connector_name[2] = "P3"; 198 | board->llio.fpga_part_number = "6slx9tqg144"; 199 | board->llio.num_leds = 2; 200 | board->llio.read = &serial_read; 201 | board->llio.write = &serial_write; 202 | board->llio.write_flash = &remote_write_flash; 203 | board->llio.verify_flash = &remote_verify_flash; 204 | board->llio.reset = &lbp16_board_reset; 205 | board->llio.reload = &lbp16_board_reload; 206 | 207 | board->open = &serial_board_open; 208 | board->close = &serial_board_close; 209 | board->print_info = &serial_print_info; 210 | board->flash = BOARD_FLASH_REMOTE; 211 | board->fallback_support = 1; 212 | board->llio.verbose = access->verbose; 213 | 214 | boards_count++; 215 | } 216 | } 217 | 218 | void serial_print_info(board_t *board) { 219 | lbp16_cmd_addr packet; 220 | int i, j; 221 | char *mem_types[16] = {NULL, "registers", "memory", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "EEPROM", "flash"}; 222 | char *mem_writeable[2] = {"RO", "RW"}; 223 | char *acc_types[4] = {"8-bit", "16-bit", "32-bit", "64-bit"}; 224 | lbp_mem_info_area mem_area; 225 | lbp_timers_area timers_area; 226 | lbp_status_area stat_area; 227 | lbp_info_area info_area; 228 | lbp16_cmd_addr cmds[LBP16_MEM_SPACE_COUNT]; 229 | 230 | printf("\nSerial device %s at %s\n", board->llio.board_name, board->dev_addr); 231 | if (board->llio.verbose == 0) 232 | return; 233 | 234 | LBP16_INIT_PACKET4(cmds[0], CMD_READ_AREA_INFO_ADDR16_INCR(LBP16_SPACE_HM2, sizeof(mem_area)/2), 0); 235 | LBP16_INIT_PACKET4(cmds[1], 0, 0); 236 | LBP16_INIT_PACKET4(cmds[2], 0, 0); 237 | LBP16_INIT_PACKET4(cmds[3], CMD_READ_AREA_INFO_ADDR16_INCR(LBP16_SPACE_FPGA_FLASH, sizeof(mem_area)/2), 0); 238 | LBP16_INIT_PACKET4(cmds[4], 0, 0); 239 | LBP16_INIT_PACKET4(cmds[5], 0, 0); 240 | LBP16_INIT_PACKET4(cmds[6], CMD_READ_AREA_INFO_ADDR16_INCR(LBP16_SPACE_COMM_CTRL, sizeof(mem_area)/2), 0); 241 | LBP16_INIT_PACKET4(cmds[7], CMD_READ_AREA_INFO_ADDR16_INCR(LBP16_SPACE_BOARD_INFO, sizeof(mem_area)/2), 0); 242 | 243 | LBP16_INIT_PACKET4(packet, CMD_READ_COMM_CTRL_ADDR16_INCR(sizeof(stat_area)/2), 0); 244 | memset(&stat_area, 0, sizeof(stat_area)); 245 | lbp16_send_packet_checked(&packet, sizeof(packet)); 246 | lbp16_recv_packet_checked(&stat_area, sizeof(stat_area)); 247 | 248 | LBP16_INIT_PACKET4(packet, CMD_READ_BOARD_INFO_ADDR16_INCR(sizeof(info_area)/2), 0); 249 | memset(&info_area, 0, sizeof(info_area)); 250 | lbp16_send_packet_checked(&packet, sizeof(packet)); 251 | lbp16_recv_packet_checked(&info_area, sizeof(info_area)); 252 | 253 | if (info_area.LBP16_version >= 3) { 254 | LBP16_INIT_PACKET4(cmds[4], CMD_READ_AREA_INFO_ADDR16_INCR(LBP16_SPACE_TIMER, sizeof(mem_area)/2), 0); 255 | LBP16_INIT_PACKET4(packet, CMD_READ_TIMER_ADDR16_INCR(sizeof(timers_area)/2), 0); 256 | memset(&timers_area, 0, sizeof(timers_area)); 257 | lbp16_send_packet_checked(&packet, sizeof(packet)); 258 | lbp16_recv_packet_checked(&timers_area, sizeof(timers_area)); 259 | } 260 | 261 | printf("Communication:\n"); 262 | printf(" transport layer: serial\n"); 263 | printf(" protocol: LBP16 version %d\n", info_area.LBP16_version); 264 | 265 | show_board_info(board); 266 | 267 | printf("Board firmware info:\n"); 268 | printf(" memory spaces:\n"); 269 | for (i = 0; i < LBP16_MEM_SPACE_COUNT; i++) { 270 | u32 size; 271 | 272 | if ((cmds[i].cmd_lo == 0) && (cmds[i].cmd_hi == 0)) continue; 273 | memset(&mem_area, 0, sizeof(mem_area)); 274 | lbp16_send_packet_checked(&cmds[i], sizeof(cmds[i])); 275 | lbp16_recv_packet_checked(&mem_area, sizeof (mem_area)); 276 | 277 | printf(" %d: %.*s (%s, %s", i, (int)sizeof(mem_area.name), mem_area.name, mem_types[(mem_area.size >> 8) & 0x7F], 278 | mem_writeable[(mem_area.size & 0x8000) >> 15]); 279 | for (j = 0; j < 4; j++) { 280 | if ((mem_area.size & 0xFF) & 1 << j) 281 | printf(", %s)", acc_types[j]); 282 | } 283 | size = pow(2, mem_area.range & 0x3F); 284 | show_formatted_size(size); 285 | if (((mem_area.size >> 8) & 0x7F) >= 0xE) 286 | printf(", page size: %u, erase size: %u", 287 | (unsigned int) pow(2, (mem_area.range >> 6) & 0x1F), (unsigned int) pow(2, (mem_area.range >> 11) & 0x1F)); 288 | printf("\n"); 289 | } 290 | 291 | printf(" [space 0] HostMot2\n"); 292 | printf(" [space 3] FPGA flash eeprom:\n"); 293 | printf(" flash size: %s (id: 0x%02X)\n", eeprom_get_flash_type(board->flash_id), board->flash_id); 294 | 295 | if (info_area.LBP16_version >= 3) { 296 | printf(" [space 4] timers:\n"); 297 | printf(" uSTimeStampReg: 0x%04X\n", timers_area.uSTimeStampReg); 298 | printf(" WaituSReg: 0x%04X\n", timers_area.WaituSReg); 299 | printf(" HM2Timeout: 0x%04X\n", timers_area.HM2Timeout); 300 | } 301 | 302 | printf(" [space 6] LBP16 control/status:\n"); 303 | printf(" packets received: all %d, good %d, bad %d\n", stat_area.RXPacketCount, stat_area.RXGoodCount, stat_area.RXBadCount); 304 | printf(" packets sent: all %d, good %d, bad %d\n", stat_area.TXPacketCount, stat_area.TXGoodCount, stat_area.TXBadCount); 305 | printf(" parse errors: %d, mem errors %d, write errors %d\n", stat_area.LBPParseErrors, stat_area.LBPMemErrors, stat_area.LBPWriteErrors); 306 | printf(" error flags: 0x%04X\n", stat_area.ErrorReg); 307 | printf(" debug LED ptr: 0x%04X\n", stat_area.DebugLEDPtr); 308 | printf(" scratch: 0x%04X\n", stat_area.Scratch); 309 | 310 | printf(" [space 7] LBP16 info:\n"); 311 | printf(" board name: %.*s\n", (int)sizeof(info_area.name), info_area.name); 312 | printf(" LBP16 protocol version %d\n", info_area.LBP16_version); 313 | printf(" board firmware version %d\n", info_area.firmware_version); 314 | } 315 | -------------------------------------------------------------------------------- /serial_boards.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __SERIAL_BOARDS_H 20 | #define __SERIAL_BOARDS_H 21 | 22 | #include "anyio.h" 23 | 24 | int serial_send_packet(void *packet, int size); 25 | int serial_recv_packet(void *packet, int size); 26 | int serial_boards_init(board_access_t *access); 27 | void serial_boards_cleanup(board_access_t *access); 28 | void serial_boards_scan(board_access_t *access); 29 | void serial_print_info(board_t *board); 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /spi_boards.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "types.h" 34 | #include "eeprom.h" 35 | #include "eeprom_local.h" 36 | #include "spi_boards.h" 37 | #include "common.h" 38 | 39 | extern board_t boards[MAX_BOARDS]; 40 | extern int boards_count; 41 | 42 | static bool canDo32 = true; 43 | 44 | static int sd = -1; 45 | struct spi_ioc_transfer settings; 46 | 47 | static int spidev_set_lsb_first(int fd, u8 lsb_first) { 48 | return ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb_first); 49 | } 50 | 51 | static int spidev_set_mode(int fd, u8 mode) { 52 | return ioctl(fd, SPI_IOC_WR_MODE, &mode); 53 | } 54 | 55 | static int spidev_set_max_speed_hz(int fd, u32 speed_hz) { 56 | return ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed_hz); 57 | } 58 | 59 | static int spidev_set_bits_per_word(int fd, u8 bits) { 60 | return ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); 61 | } 62 | 63 | static u32 read_command(u16 addr, unsigned nelem) { 64 | bool increment = true; 65 | return (addr << 16) | SPILBP_CMD_READ | (increment ? SPILBP_ADDR_AUTO_INC : 0) | (nelem << 4); 66 | } 67 | 68 | static u32 write_command(u16 addr, unsigned nelem) { 69 | bool increment = true; 70 | return (addr << 16) | SPILBP_CMD_WRITE | (increment ? SPILBP_ADDR_AUTO_INC : 0) | (nelem << 4); 71 | } 72 | 73 | static int spi_board_open(board_t *board) { 74 | eeprom_init(&(board->llio)); 75 | board->flash_id = read_flash_id(&(board->llio)); 76 | if (board->fallback_support == 1) { 77 | eeprom_prepare_boot_block(board->flash_id); 78 | board->flash_start_address = eeprom_calc_user_space(board->flash_id); 79 | } else { 80 | board->flash_start_address = 0; 81 | } 82 | return 0; 83 | } 84 | 85 | static int spi_board_close(board_t *board) { 86 | (void)board; 87 | return 0; 88 | } 89 | 90 | int spi_boards_init(board_access_t *access) { 91 | settings.speed_hz = 20 * 1000 * 1000; 92 | settings.bits_per_word = 32; 93 | 94 | sd = open(access->dev_addr, O_RDWR); 95 | if(sd == -1) { 96 | perror("open"); 97 | return -1; 98 | } 99 | spidev_set_lsb_first(sd, false); 100 | spidev_set_mode(sd, 0); 101 | // Either the following test fails on SPI5 or theres an issue with 32 bit SPI access 102 | // so... disable 32 bit access for now. 103 | // The cost of forcing 8 bit access is minor as it only slows flashing/verification. 104 | // So, for now, just force 8 bit access for everyone. 105 | // if ((spidev_set_bits_per_word(sd, settings.bits_per_word) < 0) 106 | // { 107 | // fprintf(stderr,"unable to set bpw32, fallback to bpw8\n"); 108 | canDo32 = false; 109 | settings.bits_per_word = 8; 110 | spidev_set_bits_per_word(sd, settings.bits_per_word); 111 | // } 112 | spidev_set_max_speed_hz(sd, settings.speed_hz); 113 | 114 | return 0; 115 | } 116 | 117 | void spi_boards_cleanup(board_access_t *access) { 118 | (void)access; 119 | if(sd != -1) close(sd); 120 | } 121 | 122 | void reorderBuffer(char *pBuf, int numInts) 123 | { 124 | int lcv; 125 | for (lcv = 0; lcv < numInts; lcv++) 126 | { 127 | pBuf[0] ^= pBuf[3]; 128 | pBuf[3] ^= pBuf[0]; 129 | pBuf[0] ^= pBuf[3]; 130 | pBuf[1] ^= pBuf[2]; 131 | pBuf[2] ^= pBuf[1]; 132 | pBuf[1] ^= pBuf[2]; 133 | pBuf += 4; 134 | } 135 | } 136 | 137 | int spi_read(llio_t *self, u32 addr, void *buffer, int size) { 138 | (void)self; 139 | if(size % 4 != 0) return -1; 140 | int numInts = 1+size/4; 141 | u32 trxbuf[numInts]; 142 | 143 | trxbuf[0] = read_command(addr, size/4); 144 | memset(trxbuf+1, 0, size); 145 | struct spi_ioc_transfer t; 146 | t = settings; 147 | t.tx_buf = t.rx_buf = (uint64_t)(intptr_t)trxbuf; 148 | t.len = sizeof(trxbuf); 149 | if (!canDo32) 150 | { 151 | reorderBuffer((char *) trxbuf, 1); 152 | } 153 | 154 | int r = ioctl(sd, SPI_IOC_MESSAGE(1), &t); 155 | 156 | if(r < 0) return r; 157 | 158 | if (!canDo32) 159 | { 160 | reorderBuffer((char *) trxbuf, numInts); 161 | } 162 | 163 | memcpy(buffer, trxbuf+1, size); 164 | return 0; 165 | } 166 | 167 | int spi_write(llio_t *self, u32 addr, void *buffer, int size) { 168 | (void)self; 169 | if(size % 4 != 0) return -1; 170 | int numInts = 1+size/4; 171 | u32 txbuf[numInts]; 172 | 173 | txbuf[0] = write_command(addr, size/4); 174 | memcpy(txbuf + 1, buffer, size); 175 | 176 | struct spi_ioc_transfer t; 177 | t = settings; 178 | t.tx_buf = (uint64_t)(intptr_t)txbuf; 179 | t.len = sizeof(txbuf); 180 | if (!canDo32) 181 | { 182 | reorderBuffer((char *) txbuf, numInts); 183 | } 184 | 185 | int r = ioctl(sd, SPI_IOC_MESSAGE(1), &t); 186 | if(r <= 0) return r; 187 | return 0; 188 | } 189 | 190 | static int spi_board_reload(llio_t *self, int fallback_flag) { 191 | board_t *board = self->board; 192 | int i; 193 | u32 boot_addr, cookie; 194 | 195 | spi_read(&(board->llio), HM2_ICAP_REG, &cookie, sizeof(u32)); 196 | if (cookie != HM2_ICAP_COOKIE) { 197 | printf("ERROR: Active firmware too old to support --reload\n"); 198 | return -1; 199 | } 200 | 201 | if (fallback_flag == 1) { 202 | boot_addr = 0x10000; 203 | } else { 204 | boot_addr = 0x0; 205 | } 206 | boot_addr |= 0x0B000000; // plus read command in high byte 207 | 208 | u32 data[14] = { 209 | 0xFFFF, // dummy 210 | 0xFFFF, // dummy 211 | 0xAA99, // sync 212 | 0x5566, // sync 213 | 0x3261, // load low flash start address 214 | boot_addr & 0xFFFF, // start addr 215 | 0x3281, // load high start address + read command 216 | boot_addr >> 16, // start addr (plus read command in high byte) 217 | 0x30A1, // load command register 218 | 0x000E, // IPROG command 219 | 0x2000, // NOP 220 | 0x2000, // NOP 221 | 0x2000, // NOP 222 | 0x2000 // NOP 223 | }; 224 | 225 | 226 | for (i = 0; i < 14; i++) { 227 | spi_write(&(board->llio), HM2_ICAP_REG, &data[i], sizeof(u32)); 228 | usleep(1000); 229 | } 230 | printf("Waiting for FPGA configuration..."); 231 | sleep(2); 232 | printf("OK\n"); 233 | return 0; 234 | } 235 | 236 | void spi_boards_scan(board_access_t *access) { 237 | u32 buf[4]; 238 | u32 cookie[] = {0x55aacafe, 0x54534f48, 0x32544f4d}; 239 | board_t *board = &boards[boards_count]; 240 | 241 | board_init_struct(board); 242 | if (spi_read(&(board->llio), HM2_COOKIE_REG, &buf, sizeof(buf)) < 0) { 243 | return; 244 | } 245 | 246 | if(memcmp(buf, cookie, sizeof(cookie))) { 247 | fprintf(stderr, "Unexpected cookie at %04x..%04zx:\n%08x %08x %08x\n", 248 | HM2_COOKIE_REG, HM2_COOKIE_REG + sizeof(buf), 249 | buf[0], buf[1], buf[2]); 250 | return; 251 | } 252 | 253 | char ident[8]; 254 | if(spi_read(&(board->llio), buf[3] + 0xc, &ident, sizeof(ident)) < 0) return; 255 | 256 | if(!memcmp(ident, "MESA7I90", 8)) { 257 | board_t *board = &boards[boards_count]; 258 | board->type = BOARD_SPI; 259 | strcpy(board->dev_addr, access->dev_addr); 260 | strcpy(board->llio.board_name, "7I90"); 261 | board->llio.num_ioport_connectors = 3; 262 | board->llio.pins_per_connector = 24; 263 | board->llio.ioport_connector_name[0] = "P1"; 264 | board->llio.ioport_connector_name[1] = "P2"; 265 | board->llio.ioport_connector_name[2] = "P3"; 266 | board->llio.num_leds = 2; 267 | board->llio.verbose = access->verbose; 268 | board->llio.write = spi_write; 269 | board->llio.read = spi_read; 270 | board->llio.write_flash = local_write_flash; 271 | board->llio.verify_flash = local_verify_flash; 272 | board->llio.reload = &spi_board_reload; 273 | board->llio.fpga_part_number = "6slx9tqg144"; 274 | board->open = spi_board_open; 275 | board->close = spi_board_close; 276 | board->print_info = spi_print_info; 277 | board->flash = BOARD_FLASH_HM2; 278 | board->fallback_support = 1; 279 | boards_count ++; 280 | } else if(!memcmp(ident, "MESA7C80", 8)) { 281 | board_t *board = &boards[boards_count]; 282 | board->type = BOARD_SPI; 283 | strcpy(board->dev_addr, access->dev_addr); 284 | strcpy(board->llio.board_name, "7C80"); 285 | board->llio.num_ioport_connectors = 2; 286 | board->llio.pins_per_connector = 27; 287 | board->llio.ioport_connector_name[0] = "StepGens+Misc"; 288 | board->llio.ioport_connector_name[1] = "Outputs+P1"; 289 | board->llio.bob_hint[0] = BOB_7C80_0; 290 | board->llio.bob_hint[1] = BOB_7C80_1; 291 | board->llio.num_leds = 4; 292 | board->llio.verbose = access->verbose; 293 | board->llio.write = spi_write; 294 | board->llio.read = spi_read; 295 | board->llio.write_flash = local_write_flash; 296 | board->llio.verify_flash = local_verify_flash; 297 | board->llio.reload = &spi_board_reload; 298 | board->llio.fpga_part_number = "6slx9tqg144"; 299 | board->open = spi_board_open; 300 | board->close = spi_board_close; 301 | board->print_info = spi_print_info; 302 | board->flash = BOARD_FLASH_HM2; 303 | board->fallback_support = 1; 304 | boards_count ++; 305 | } else if(!memcmp(ident, "MESA7C81", 8)) { 306 | board_t *board = &boards[boards_count]; 307 | board->type = BOARD_SPI; 308 | strcpy(board->dev_addr, access->dev_addr); 309 | strcpy(board->llio.board_name, "7C81"); 310 | board->llio.num_ioport_connectors = 3; 311 | board->llio.pins_per_connector = 19; 312 | board->llio.ioport_connector_name[0] = "P1+Serial"; 313 | board->llio.ioport_connector_name[1] = "P2+Serial"; 314 | board->llio.ioport_connector_name[2] = "P7+Serial"; 315 | board->llio.bob_hint[0] = BOB_7C81_0; 316 | board->llio.bob_hint[1] = BOB_7C81_1; 317 | board->llio.bob_hint[2] = BOB_7C81_2; 318 | board->llio.num_leds = 4; 319 | board->llio.verbose = access->verbose; 320 | board->llio.write = spi_write; 321 | board->llio.read = spi_read; 322 | board->llio.write_flash = local_write_flash; 323 | board->llio.verify_flash = local_verify_flash; 324 | board->llio.reload = &spi_board_reload; 325 | board->llio.fpga_part_number = "6slx9tqg144"; 326 | board->open = spi_board_open; 327 | board->close = spi_board_close; 328 | board->print_info = spi_print_info; 329 | board->flash = BOARD_FLASH_HM2; 330 | board->fallback_support = 1; 331 | boards_count ++; 332 | } else { 333 | for(size_t i=0; i 23 | 24 | #ifdef __linux__ 25 | typedef u_int8_t u8; 26 | typedef u_int16_t u16; 27 | typedef u_int32_t u32; 28 | #elif _WIN32 29 | #include 30 | typedef BYTE u8; 31 | typedef WORD u16; 32 | typedef DWORD u32; 33 | #endif 34 | 35 | #include 36 | #if ULONG_MAX > 0xffffffff 37 | typedef unsigned long u64; 38 | #else 39 | typedef unsigned long long u64; 40 | #endif 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /usb_boards.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "types.h" 25 | #include "common.h" 26 | #include "eeprom.h" 27 | #include "bitfile.h" 28 | #include "lbp.h" 29 | #include "hostmot2.h" 30 | #include "usb_boards.h" 31 | 32 | extern board_t boards[MAX_BOARDS]; 33 | extern int boards_count; 34 | static u8 file_buffer[SECTOR_SIZE]; 35 | 36 | int usb_read(llio_t *self, u32 addr, void *buffer, int size) { 37 | (void)self; 38 | while (size > 0) { 39 | lbp_read(addr & 0xFFFF, buffer); 40 | addr += 4; 41 | buffer += 4; 42 | size -= 4; 43 | } 44 | return 0; 45 | } 46 | 47 | int usb_write(llio_t *self, u32 addr, void *buffer, int size) { 48 | (void)self; 49 | while (size > 0) { 50 | lbp_write(addr & 0xFFFF, buffer); 51 | addr += 4; 52 | buffer += 4; 53 | size -= 4; 54 | } 55 | return 0; 56 | } 57 | 58 | static int usb_program_fpga(llio_t *self, char *bitfile_name) { 59 | board_t *board = self->board; 60 | int bindex, bytesread; 61 | char part_name[32]; 62 | struct stat file_stat; 63 | FILE *fp; 64 | u8 cmd = '0'; 65 | 66 | if (stat(bitfile_name, &file_stat) != 0) { 67 | printf("Can't find file %s\n", bitfile_name); 68 | return -1; 69 | } 70 | fp = fopen(bitfile_name, "rb"); 71 | if (fp == NULL) { 72 | printf("Can't open file %s: %s\n", bitfile_name, strerror(errno)); 73 | return -1; 74 | } 75 | if (print_bitfile_header(fp, (char*) &part_name, board->llio.verbose) == -1) { 76 | fclose(fp); 77 | return -1; 78 | } 79 | 80 | printf("Programming FPGA...\n"); 81 | printf(" |"); 82 | fflush(stdout); 83 | 84 | lbp_send_checked(&cmd, 1); 85 | lbp_send_checked(&cmd, 1); 86 | lbp_send_checked(&cmd, 1); 87 | lbp_send_checked(&cmd, 1); 88 | // program the FPGA 89 | while (!feof(fp)) { 90 | bytesread = fread(&file_buffer, 1, 8192, fp); 91 | bindex = 0; 92 | while (bindex < bytesread) { 93 | file_buffer[bindex] = bitfile_reverse_bits(file_buffer[bindex]); 94 | bindex++; 95 | } 96 | lbp_send_checked(&file_buffer, bytesread); 97 | printf("W"); 98 | fflush(stdout); 99 | } 100 | 101 | printf("\n"); 102 | fclose(fp); 103 | 104 | return 0; 105 | } 106 | 107 | static int usb_board_open(board_t *board) { 108 | (void)board; 109 | return 0; 110 | } 111 | 112 | static int usb_board_close(board_t *board) { 113 | (void)board; 114 | return 0; 115 | } 116 | 117 | int usb_boards_init(board_access_t *access) { 118 | lbp_init(access); 119 | return 0; 120 | } 121 | 122 | void usb_boards_cleanup(board_access_t *access) { 123 | (void)access; 124 | lbp_release(); 125 | } 126 | 127 | void usb_boards_scan(board_access_t *access) { 128 | board_t *board = &boards[boards_count]; 129 | u8 cmd, data; 130 | char dev_name[4]; 131 | 132 | board_init_struct(board); 133 | 134 | data = lbp_read_ctrl(LBP_CMD_READ_COOKIE); 135 | if (data == LBP_COOKIE) { 136 | dev_name[0] = lbp_read_ctrl(LBP_CMD_READ_DEV_NAME0); 137 | dev_name[1] = lbp_read_ctrl(LBP_CMD_READ_DEV_NAME1); 138 | dev_name[2] = lbp_read_ctrl(LBP_CMD_READ_DEV_NAME2); 139 | dev_name[3] = lbp_read_ctrl(LBP_CMD_READ_DEV_NAME3); 140 | 141 | if (strncmp(dev_name, "7I64", 4) == 0) { 142 | board->type = BOARD_USB; 143 | strcpy(board->dev_addr, access->dev_addr); 144 | strncpy(board->llio.board_name, dev_name, 4); 145 | board->llio.verbose = access->verbose; 146 | 147 | boards_count++; 148 | } else if (strncmp(dev_name, "7I43", 4) == 0) { // found 7i43 with HOSTMOT2 149 | board->type = BOARD_USB; 150 | board->mode = BOARD_MODE_FPGA; 151 | strcpy(board->dev_addr, access->dev_addr); 152 | strcpy(board->llio.board_name, "7I43"); 153 | board->llio.num_ioport_connectors = 2; 154 | board->llio.pins_per_connector = 24; 155 | board->llio.ioport_connector_name[0] = "P3"; 156 | board->llio.ioport_connector_name[1] = "P4"; 157 | board->llio.num_leds = 8; 158 | board->llio.read = &usb_read; 159 | board->llio.write = &usb_write; 160 | 161 | board->open = &usb_board_open; 162 | board->close = &usb_board_close; 163 | board->print_info = &usb_print_info; 164 | board->llio.verbose = access->verbose; 165 | 166 | u32 cookie; 167 | lbp_read(HM2_COOKIE_REG, &cookie); 168 | if (cookie == HM2_COOKIE) { 169 | u32 fpga_size; 170 | u32 addr; 171 | 172 | lbp_read(HM2_IDROM_ADDR, &addr); 173 | lbp_read((addr & 0xFFFF) + offsetof(hm2_idrom_desc_t, fpga_size), &fpga_size); 174 | if (fpga_size == 400) { 175 | board->llio.fpga_part_number = "3s400tq144"; 176 | } else { 177 | board->llio.fpga_part_number = "3s200tq144"; 178 | } 179 | } 180 | 181 | boards_count++; 182 | } 183 | return; 184 | } 185 | 186 | cmd = '1'; 187 | lbp_send_checked(&cmd, 1); 188 | lbp_recv_checked(&data, 1); 189 | if ((data & 0x01) == 0) { // found 7i43 without flashed FPGA 190 | board->type = BOARD_USB; 191 | board->mode = BOARD_MODE_CPLD; 192 | strcpy(board->dev_addr, access->dev_addr); 193 | strcpy(board->llio.board_name, "7I43"); 194 | board->llio.num_ioport_connectors = 2; 195 | board->llio.pins_per_connector = 24; 196 | board->llio.ioport_connector_name[0] = "P3"; 197 | board->llio.ioport_connector_name[1] = "P4"; 198 | cmd = '0'; 199 | lbp_send_checked(&cmd, 1); 200 | lbp_recv_checked(&data, 1); 201 | if (data & 0x01) 202 | board->llio.fpga_part_number = "3s400tq144"; 203 | else 204 | board->llio.fpga_part_number = "3s200tq144"; 205 | board->llio.num_leds = 8; 206 | board->llio.program_fpga = &usb_program_fpga; 207 | board->llio.verbose = access->verbose; 208 | board->open = &usb_board_open; 209 | board->close = &usb_board_close; 210 | board->print_info = &usb_print_info; 211 | 212 | boards_count++; 213 | return; 214 | } 215 | } 216 | 217 | void usb_boards_release(board_access_t *access) { 218 | (void)access; 219 | lbp_release(); 220 | } 221 | 222 | void usb_print_info(board_t *board) { 223 | printf("\nUSB device %s at %s\n", board->llio.board_name, board->dev_addr); 224 | if (board->llio.verbose == 1) { 225 | if (board->mode == BOARD_MODE_CPLD) { 226 | printf(" controlled by CPLD\n"); 227 | lbp_print_info(); 228 | } else if (board->mode == BOARD_MODE_FPGA) { 229 | printf(" controlled by FPGA\n"); 230 | } 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /usb_boards.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2013-2014 Michael Geszkiewicz 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | // 18 | 19 | #ifndef __USB_BOARDS_H 20 | #define __USB_BOARDS_H 21 | 22 | #include "boards.h" 23 | 24 | int usb_boards_init(board_access_t *access); 25 | void usb_boards_cleanup(board_access_t *access); 26 | void usb_boards_scan(board_access_t *access); 27 | void usb_boards_release(board_access_t *access); 28 | void usb_print_info(board_t *board); 29 | 30 | #endif 31 | --------------------------------------------------------------------------------