├── fx2pipe
├── NEWS
├── ChangeLog
├── AUTHORS
├── lib
│ ├── linkedlist.h
│ ├── Makefile.am
│ └── Makefile.in
├── build.sh
├── usb_io
│ ├── Makefile.am
│ ├── urbcache.cc
│ ├── urbcache.h
│ ├── fx2usb.h
│ ├── cycfx2dev.h
│ ├── fx2usb.cc
│ ├── usbdevice_fs.h
│ ├── wwusb.cc
│ ├── wwusb.h
│ └── Makefile.in
├── INSTALL
├── README
├── fx2pipe
│ ├── Makefile.am
│ ├── fx2pipe.h
│ ├── main.cc
│ └── fx2pipe.cc
├── .gitignore
├── firmware
│ ├── Makefile
│ ├── fx2pipe.ihx
│ ├── fx2pipe_static.cc
│ └── fx2pipe.c
├── configure.ac
├── Makefile.am
├── oconfig.h
├── config.h.in
└── missing
├── README.txt
├── test
├── elk
│ └── reset.bin.gz
├── beeb
│ └── reset.bin.gz
├── master
│ └── reset.bin.gz
├── beebr65c02
│ └── reset.bin.gz
├── 816_blitter
│ ├── hog816_emu.data
│ ├── snes_tests.data
│ ├── hog816_native.data
│ └── hog816_interrupt.data
├── clean_tests.sh
├── run_816_tests.sh
└── run_tests.sh
├── ftdi_async_mode
├── build.sh
└── stream_test.c
├── src
├── em_6502.h
├── em_6800.h
├── em_65816.h
├── tube_decode.h
├── symbols.h
├── musl_tsearch.h
├── memory.h
├── matcher.c
├── profiler.h
├── profiler_instr.c
├── defs.h
├── symbols.c
├── profiler_block.c
├── musl_tsearch.c
├── profiler.c
└── profiler_call.c
├── fx2sharp
├── fx2sharp
│ ├── packages.config
│ ├── App.config
│ ├── fx2sharp.csproj.user
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── fx2pipe_hoglet.hex
│ └── fx2sharp.csproj
└── fx2sharp.sln
└── .gitignore
/fx2pipe/NEWS:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fx2pipe/ChangeLog:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fx2pipe/AUTHORS:
--------------------------------------------------------------------------------
1 | Author: Wolfgang Wieser
2 |
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | See the github wiki for more details.
2 |
--------------------------------------------------------------------------------
/test/elk/reset.bin.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoglet67/6502Decoder/HEAD/test/elk/reset.bin.gz
--------------------------------------------------------------------------------
/test/beeb/reset.bin.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoglet67/6502Decoder/HEAD/test/beeb/reset.bin.gz
--------------------------------------------------------------------------------
/fx2pipe/lib/linkedlist.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoglet67/6502Decoder/HEAD/fx2pipe/lib/linkedlist.h
--------------------------------------------------------------------------------
/test/master/reset.bin.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoglet67/6502Decoder/HEAD/test/master/reset.bin.gz
--------------------------------------------------------------------------------
/test/beebr65c02/reset.bin.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoglet67/6502Decoder/HEAD/test/beebr65c02/reset.bin.gz
--------------------------------------------------------------------------------
/test/816_blitter/hog816_emu.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoglet67/6502Decoder/HEAD/test/816_blitter/hog816_emu.data
--------------------------------------------------------------------------------
/test/816_blitter/snes_tests.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoglet67/6502Decoder/HEAD/test/816_blitter/snes_tests.data
--------------------------------------------------------------------------------
/test/816_blitter/hog816_native.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoglet67/6502Decoder/HEAD/test/816_blitter/hog816_native.data
--------------------------------------------------------------------------------
/test/816_blitter/hog816_interrupt.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoglet67/6502Decoder/HEAD/test/816_blitter/hog816_interrupt.data
--------------------------------------------------------------------------------
/ftdi_async_mode/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | gcc -I /usr/include/libftdi1 -I /usr/include/libusb-1.0/ stream_test.c -o stream_test -lftdi1 -lusb-1.0
3 |
--------------------------------------------------------------------------------
/fx2pipe/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cd firmware
4 | make clobber
5 | make
6 | cd ..
7 |
8 | ./configure
9 | make clean
10 | make
11 |
--------------------------------------------------------------------------------
/src/em_6502.h:
--------------------------------------------------------------------------------
1 | #ifndef _INCLUDE_EM_6502_H
2 | #define _INCLUDE_EM_6502_H
3 |
4 | #include "defs.h"
5 |
6 | extern cpu_emulator_t em_6502;
7 |
8 | #endif
9 |
--------------------------------------------------------------------------------
/src/em_6800.h:
--------------------------------------------------------------------------------
1 | #ifndef _INCLUDE_EM_6800_H
2 | #define _INCLUDE_EM_6800_H
3 |
4 | #include "defs.h"
5 |
6 | extern cpu_emulator_t em_6800;
7 |
8 | #endif
9 |
--------------------------------------------------------------------------------
/src/em_65816.h:
--------------------------------------------------------------------------------
1 | #ifndef _INCLUDE_EM_65816_H
2 | #define _INCLUDE_EM_65816_H
3 |
4 | #include "defs.h"
5 |
6 | extern cpu_emulator_t em_65816;
7 |
8 | #endif
9 |
--------------------------------------------------------------------------------
/fx2pipe/lib/Makefile.am:
--------------------------------------------------------------------------------
1 | INCLUDES = -I. -I$(top_srcdir) -I$(top_builddir)
2 |
3 | noinst_LIBRARIES = lib_fx2pipe_supp.a
4 | lib_fx2pipe_supp_a_SOURCES = \
5 | linkedlist.h \
6 | linearqueue.h
7 |
--------------------------------------------------------------------------------
/fx2sharp/fx2sharp/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/tube_decode.h:
--------------------------------------------------------------------------------
1 | #ifndef _TUBE_DECODE_H
2 | #define _TUBE_DECODE_H
3 |
4 | #include
5 |
6 | void tube_read(int reg, uint8_t data);
7 | void tube_write(int reg, uint8_t data);
8 |
9 | #endif
10 |
--------------------------------------------------------------------------------
/fx2sharp/fx2sharp/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/fx2pipe/usb_io/Makefile.am:
--------------------------------------------------------------------------------
1 | INCLUDES = -I. -I$(top_srcdir) -I$(top_builddir)
2 |
3 | noinst_LIBRARIES = lib_usb_io.a
4 | lib_usb_io_a_SOURCES = \
5 | wwusb.h wwusb.cc \
6 | fx2usb.h fx2usb.cc \
7 | urbcache.h urbcache.cc \
8 | cycfx2dev.h cycfx2dev.cc
9 |
--------------------------------------------------------------------------------
/src/symbols.h:
--------------------------------------------------------------------------------
1 | #ifndef _SYMBOLS_H
2 |
3 | #define _SYMBOLS_H
4 |
5 | void symbol_init(int size);
6 |
7 | void symbol_add(char *name, int address);
8 |
9 | char *symbol_lookup(int address);
10 |
11 | void symbol_import_swift(char *filename);
12 |
13 | #endif
14 |
--------------------------------------------------------------------------------
/test/clean_tests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | declare -a machine_names
4 |
5 | machine_names=(
6 | master
7 | beeb
8 | elk
9 | beebr65c02
10 | )
11 |
12 | for machine in "${machine_names[@]}"
13 | do
14 | rm -f ${machine}/*.tmp
15 | rm -f ${machine}/*.log
16 | done
17 |
--------------------------------------------------------------------------------
/fx2pipe/INSTALL:
--------------------------------------------------------------------------------
1 | BUILD INSTRUCTIONS:
2 |
3 | Usual configure && make voodoo.
4 |
5 | The firmware is not built by "make" since this requires special tools.
6 | Instead source code and pre-compiled binaries are distributed.
7 | To build the firmware, run "make" in firmware.
8 |
9 | Volunteers welcome for any type of improvement!
10 |
11 |
--------------------------------------------------------------------------------
/fx2pipe/README:
--------------------------------------------------------------------------------
1 | This is a relatively simple USB high speed input or output pipe
2 | program.
3 |
4 | It either reads data from stdin and sends it over the USB or
5 | reads data from the USB and sends it to stdout.
6 | Works with Cypress FX2 chip, hence the name fx2pipe.
7 |
8 | For build instructions, please see INSTALL.
9 |
10 | Wolfgang
11 |
--------------------------------------------------------------------------------
/fx2pipe/fx2pipe/Makefile.am:
--------------------------------------------------------------------------------
1 | INCLUDES = -I. -I$(top_srcdir) -I$(top_builddir)
2 |
3 | bin_PROGRAMS = fx2pipe
4 | fx2pipe_SOURCES = main.cc \
5 | fx2pipe.h fx2pipe.cc \
6 | ../firmware/fx2pipe_static.cc
7 | fx2pipe_LDADD = ../usb_io/lib_usb_io.a ../lib/lib_fx2pipe_supp.a -lusb
8 |
9 | # fx2pipe_LDADD = $(QTLIBS) -L/usr/X11R6/lib -lX11 -lXft
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | #*
3 | decode6502
4 | matcher
5 | not_in_git/
6 | *.log
7 | *.bin
8 | *.tmp
9 | clark_bcd_full.bin.gz
10 | dormann_d6502.bin.gz
11 | dormann_d65c00.bin.gz
12 | dormann_d65c01.bin.gz
13 | dormann_d65c10.bin.gz
14 | dormann_d65c11.bin.gz
15 | extended_tests.zip
16 | /.dir-locals.el
17 | decode6502.dSYM/
18 | test/**/*.ref
19 | test/**/*.dif
20 | fx2sharp/fx2sharp/bin
21 | fx2sharp/fx2sharp/obj
22 | fx2sharp/.vs
23 | fx2sharp/packages
24 | decode6502.exe
25 | src/main.c.bak
26 |
--------------------------------------------------------------------------------
/fx2pipe/.gitignore:
--------------------------------------------------------------------------------
1 | /Makefile
2 | /config.h
3 | /config.log
4 | /config.status
5 | /firmware/fx2pipe.asm
6 | #/firmware/fx2pipe.ihx
7 | /firmware/fx2pipe.lk
8 | /firmware/fx2pipe.lst
9 | /firmware/fx2pipe.map
10 | /firmware/fx2pipe.mem
11 | /firmware/fx2pipe.rel
12 | /firmware/fx2pipe.rst
13 | /firmware/fx2pipe.sym
14 | #/firmware/fx2pipe_static.cc
15 | /fx2pipe/.deps/
16 | /fx2pipe/Makefile
17 | /fx2pipe/fx2pipe
18 | /lib/Makefile
19 | /stamp-h1
20 | /usb_io/.deps/
21 | /usb_io/Makefile
22 | *.o
23 | *.a
24 |
--------------------------------------------------------------------------------
/fx2sharp/fx2sharp/fx2sharp.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ShowAllFiles
5 |
6 |
7 | --debug -n=1M d:\temp\temp.bin
8 |
9 |
10 | -n=16M --debug d:\temp\temp.bin
11 |
12 |
--------------------------------------------------------------------------------
/src/musl_tsearch.h:
--------------------------------------------------------------------------------
1 | #ifndef HEADER_DBD91B1DA09E43B1B27A0CE43D8B5E7B
2 | #define HEADER_DBD91B1DA09E43B1B27A0CE43D8B5E7B
3 |
4 | typedef enum { tpreorder, tpostorder, tendorder, tleaf } TVISIT;
5 |
6 | void ttdestroy(void *root, void (*freekey)(void *));
7 |
8 | void *ttfind(const void *key, void *const *rootp, int(*cmp)(const void *, const void *));
9 |
10 | void *ttsearch(const void *key, void **rootp, int (*cmp)(const void *, const void *));
11 |
12 | void *ttdelete(const void *restrict key, void **restrict rootp, int(*cmp)(const void *, const void *));
13 |
14 | void ttwalk(const void *root, void (*action)(const void *, TVISIT, int));
15 |
16 | #endif
17 |
--------------------------------------------------------------------------------
/fx2pipe/firmware/Makefile:
--------------------------------------------------------------------------------
1 | INCLUDES=-Iinclude
2 |
3 | CC=sdcc -mmcs51
4 |
5 | SHELL=bash
6 |
7 | fx2pipe_static.cc: fx2pipe.ihx
8 | @echo "#include /* For NULL... */" > fx2pipe_static.cc
9 | @echo >> fx2pipe_static.cc
10 | @echo "const char *fx2pipe_static_firmware[]={" >> fx2pipe_static.cc
11 | @bash -c 'while read line ; do echo -e "\t\"$$line\"," >> fx2pipe_static.cc ; done < fx2pipe.ihx'
12 | @echo -e "\tNULL" >> fx2pipe_static.cc
13 | @echo "};" >> fx2pipe_static.cc
14 | @echo "Created fx2pipe_static.cc"
15 |
16 | fx2pipe.ihx: fx2pipe.c
17 | $(CC) $(INCLUDES) fx2pipe.c
18 | ls -l fx2pipe.ihx
19 |
20 | clean:
21 | rm -f fx2pipe.{asm,ihx,lnk,lst,map,mem,rel,rst,sym}
22 |
23 | clobber: clean
24 | rm -f fx2pipe_static.cc
25 |
--------------------------------------------------------------------------------
/fx2pipe/configure.ac:
--------------------------------------------------------------------------------
1 | # Process this file with autoconf to produce a configure script.
2 | AC_INIT
3 | AM_INIT_AUTOMAKE(fx2pipe,0.8)
4 | AC_CONFIG_SRCDIR([fx2pipe/fx2pipe.cc])
5 | AM_CONFIG_HEADER(config.h)
6 |
7 | # Checks for programs.
8 | AC_PROG_CC
9 | AC_PROG_CPP
10 | AC_PROG_INSTALL
11 | AC_PROG_CXX
12 | AC_PROG_RANLIB
13 |
14 | # Checks for header files.
15 | AC_HEADER_STDC
16 |
17 | # Checks for typedefs, structures, and compiler characteristics.
18 | AC_C_CONST
19 | AC_C_INLINE
20 | AC_TYPE_SIZE_T
21 | AC_CHECK_TYPE(ssize_t,int)
22 |
23 | # Checks for library functions.
24 | AC_FUNC_ERROR_AT_LINE
25 | AC_PROG_GCC_TRADITIONAL
26 | #AC_FUNC_MALLOC
27 |
28 | AC_CONFIG_FILES([Makefile
29 | lib/Makefile
30 | usb_io/Makefile
31 | fx2pipe/Makefile ])
32 | AC_OUTPUT
33 |
--------------------------------------------------------------------------------
/src/memory.h:
--------------------------------------------------------------------------------
1 | #ifndef MEMORY_H
2 | #define MEMORY_H
3 |
4 | #include "defs.h"
5 |
6 | typedef enum {
7 | MEM_INSTR = 0,
8 | MEM_POINTER = 1,
9 | MEM_DATA = 2,
10 | MEM_STACK = 3,
11 | MEM_FETCH = 4,
12 | } mem_access_t;
13 |
14 | void memory_init(int size, machine_t machine, int logtube);
15 |
16 | void memory_set_modelling(int bitmask);
17 |
18 | void memory_set_rd_logging(int bitmask);
19 |
20 | void memory_set_wr_logging(int bitmask);
21 |
22 | void memory_read(int data, int ea, mem_access_t type);
23 |
24 | void memory_write(int data, int ea, mem_access_t type);
25 |
26 | int memory_read_raw(int ea);
27 |
28 | int memory_read_raw(int ea);
29 |
30 | void memory_destroy();
31 |
32 | int write_bankid(char *buffer, int ea);
33 |
34 | #endif
35 |
--------------------------------------------------------------------------------
/fx2pipe/Makefile.am:
--------------------------------------------------------------------------------
1 | #CFLAGS = @CFLAGS@ -W -Wall -D_GNU_SOURCE
2 | #CXXFLAGS = @CXXFLAGS@ -W -Wall -D_GNU_SOURCE
3 |
4 | OPTCXXFLAGS = -W -Wall -Wformat -Woverloaded-virtual \
5 | -O2 -march=i586 -fno-rtti -fno-exceptions -fomit-frame-pointer \
6 | -D_GNU_SOURCE
7 | OPTCFLAGS = -W -Wall -Wformat \
8 | -O2 -march=i586 -fomit-frame-pointer \
9 | -D_GNU_SOURCE
10 |
11 | # Pass ADDFLAGS if you want to set -fmessage-length or the like.
12 | ADDFLAGS=""
13 |
14 | SUBDIRS = lib usb_io fx2pipe
15 |
16 | EXTRA_DIST = oconfig.h firmware
17 |
18 |
19 | opt: FORCE
20 | $(MAKE) CFLAGS="$(OPTCFLAGS) $(ADDFLAGS)" CXXFLAGS="$(OPTCXXFLAGS) $(ADDFLAGS)" all
21 |
22 | checkopt: FORCE
23 | $(MAKE) CFLAGS="$(OPTCFLAGS) $(ADDFLAGS)" CXXFLAGS="$(OPTCXXFLAGS) $(ADDFLAGS)" check
24 |
25 | FORCE:
26 |
--------------------------------------------------------------------------------
/fx2sharp/fx2sharp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.136
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "fx2sharp", "fx2sharp\fx2sharp.csproj", "{C629F22F-2110-460D-A8E0-ADEEACE0CEEF}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {C629F22F-2110-460D-A8E0-ADEEACE0CEEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {C629F22F-2110-460D-A8E0-ADEEACE0CEEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {C629F22F-2110-460D-A8E0-ADEEACE0CEEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {C629F22F-2110-460D-A8E0-ADEEACE0CEEF}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {C33A9E65-9866-4340-988E-AAC19789B28A}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/src/matcher.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #define N 24
6 |
7 | #define SIZE (1< de [
7 | *
8 | * This file may be distributed and/or modified under the terms of the
9 | * GNU General Public License version 2 as published by the Free Software
10 | * Foundation. (See COPYING.GPL for details.)
11 | *
12 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14 | *
15 | */
16 |
17 | #include "urbcache.h"
18 |
19 | #include
20 |
21 |
22 | void URBCache::_size_oops()
23 | {
24 | assert(0);
25 | }
26 |
27 |
28 | void *URBCache::_GetAlloc()
29 | {
30 | void *ptr=malloc(elem_size);
31 | if(!ptr)
32 | { fprintf(stderr,"URB alloc failire\n"); abort(); }
33 | return(ptr);
34 | }
35 |
36 |
37 | void URBCache::clear()
38 | {
39 | for(int i=0; i
5 | #include
6 |
7 | #include "defs.h"
8 |
9 | // Slot for instructions that fall outside the region of interest
10 | // (don't change this or lots of things will break!)
11 | #define OTHER_CONTEXT 0x10000
12 |
13 | // Maximum length of bar of asterisks
14 | #define BAR_WIDTH 50
15 |
16 | // Flags are currently specific to the block profiler
17 | #define FLAG_IMP 1
18 | #define FLAG_JSR 2
19 | #define FLAG_JMP 4
20 | #define FLAG_BB_TAKEN 8
21 | #define FLAG_FB_TAKEN 16
22 | #define FLAG_BB_NOT_TAKEN 32
23 | #define FLAG_FB_NOT_TAKEN 64
24 | #define FLAG_JMP_IND 128
25 | #define FLAG_JMP_INDX 256
26 |
27 | // A common data type, useful for several of the profilers
28 | typedef struct {
29 | uint32_t cycles;
30 | uint32_t instructions;
31 | uint32_t calls;
32 | int flags;
33 | } address_t;
34 |
35 | // All profiler instance data should start with this type
36 |
37 | typedef struct {
38 | const char *name;
39 | const char *arg;
40 | void (*init)(void *ptr, cpu_emulator_t *em);
41 | void (*profile_instruction)(void *ptr, int pc, int opcode, int op1, int op2, int num_cycles);
42 | void (*done)(void *ptr);
43 | } profiler_t;
44 |
45 | // Public methods, called from main program
46 |
47 | void profiler_parse_opt(int key, char *arg, struct argp_state *state);
48 | void profiler_init(cpu_emulator_t *em);
49 | void profiler_profile_instruction(int pc, int opcode, int op1, int op2, int num_cycles);
50 | void profiler_done();
51 |
52 | // Helper methods, for use by profiler implementations
53 |
54 | void profiler_output_helper(address_t *profile_counts, int show_bars, int show_other, cpu_emulator_t *em);
55 |
56 | #endif
57 |
--------------------------------------------------------------------------------
/fx2pipe/oconfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * oconfig.h
3 | *
4 | * Basic config header for FX2 pipe code.
5 | *
6 | * NOTE: This file must be included first by all other source code files.
7 | *
8 | * Copyright (c) 2006 by Wolfgang Wieser ] wwieser (a) gmx <*> de [
9 | *
10 | * This file may be distributed and/or modified under the terms of the
11 | * GNU General Public License version 2 as published by the Free Software
12 | * Foundation. (See COPYING.GPL for details.)
13 | *
14 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
15 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 | *
17 | */
18 |
19 | #ifndef _INCLUDE_FX2PIPE_OCONFIG_H_
20 | #define _INCLUDE_FX2PIPE_OCONFIG_H_ 1
21 |
22 | #define QT_THREAD_SUPPORT 1
23 |
24 | // Include autoconf-generated config header:
25 | #include "config.h"
26 |
27 | #include
28 | #include /* for ssize_t... */
29 |
30 | typedef u_int64_t uint64;
31 | typedef u_int32_t uint32;
32 | typedef u_int16_t uint16;
33 | typedef int64_t int64;
34 | typedef int32_t int32;
35 | typedef int16_t int16;
36 |
37 | // We need to define this for some linux flavours since sometimes
38 | // likely/unlikely are not part of system headers for non-kernel-compiles
39 | // although they are needed at certain other places...
40 | #define likely(x) (x)
41 | #define unlikely(x) (x)
42 |
43 | // Some basics...
44 |
45 | /// Operator delete which will do nothing for NULL pointers and set the passed
46 | /// pointer to NULL after deletion.
47 | template inline void DELETE(T* &ptr)
48 | { if(ptr) { delete ptr; ptr=NULL; } }
49 |
50 | #if 1
51 | # include
52 | #else
53 | /// Operator new with placement.
54 | inline void *operator new(size_t,void *ptr)
55 | { return(ptr); }
56 | #endif
57 |
58 | #endif /* _INCLUDE_FX2PIPE_OCONFIG_H_ */
59 |
--------------------------------------------------------------------------------
/fx2pipe/config.h.in:
--------------------------------------------------------------------------------
1 | /* config.h.in. Generated from configure.ac by autoheader. */
2 |
3 | /* Define to 1 if you have the header file. */
4 | #undef HAVE_INTTYPES_H
5 |
6 | /* Define to 1 if you have the header file. */
7 | #undef HAVE_MEMORY_H
8 |
9 | /* Define to 1 if you have the header file. */
10 | #undef HAVE_STDINT_H
11 |
12 | /* Define to 1 if you have the header file. */
13 | #undef HAVE_STDLIB_H
14 |
15 | /* Define to 1 if you have the header file. */
16 | #undef HAVE_STRINGS_H
17 |
18 | /* Define to 1 if you have the header file. */
19 | #undef HAVE_STRING_H
20 |
21 | /* Define to 1 if you have the header file. */
22 | #undef HAVE_SYS_STAT_H
23 |
24 | /* Define to 1 if you have the header file. */
25 | #undef HAVE_SYS_TYPES_H
26 |
27 | /* Define to 1 if you have the header file. */
28 | #undef HAVE_UNISTD_H
29 |
30 | /* Name of package */
31 | #undef PACKAGE
32 |
33 | /* Define to the address where bug reports for this package should be sent. */
34 | #undef PACKAGE_BUGREPORT
35 |
36 | /* Define to the full name of this package. */
37 | #undef PACKAGE_NAME
38 |
39 | /* Define to the full name and version of this package. */
40 | #undef PACKAGE_STRING
41 |
42 | /* Define to the one symbol short name of this package. */
43 | #undef PACKAGE_TARNAME
44 |
45 | /* Define to the home page for this package. */
46 | #undef PACKAGE_URL
47 |
48 | /* Define to the version of this package. */
49 | #undef PACKAGE_VERSION
50 |
51 | /* Define to 1 if you have the ANSI C header files. */
52 | #undef STDC_HEADERS
53 |
54 | /* Version number of package */
55 | #undef VERSION
56 |
57 | /* Define to empty if `const' does not conform to ANSI C. */
58 | #undef const
59 |
60 | /* Define to `__inline__' or `__inline' if that's what the C compiler
61 | calls it, or to nothing if 'inline' is not supported under any name. */
62 | #ifndef __cplusplus
63 | #undef inline
64 | #endif
65 |
66 | /* Define to `unsigned int' if does not define. */
67 | #undef size_t
68 |
69 | /* Define to `int' if does not define. */
70 | #undef ssize_t
71 |
--------------------------------------------------------------------------------
/fx2sharp/fx2sharp/fx2pipe_hoglet.hex:
--------------------------------------------------------------------------------
1 | :03000000020006F5
2 | :03005F0002000399
3 | :030003000203B441
4 | :20006200901003E0FE3395E0FFBE1205BF0002800CBE2105BF000280047F0080027F01008A
5 | :2000820000000000000000000000000000000000EF6007901007E0FE80027E1290E600EE0D
6 | :2000A200F00000000000000000000000000000000000EF6007901004E0FF80027FC390E63B
7 | :2000C20001EFF0000000000000000000000000000000000090E60B7403F000000000000056
8 | :2000E200000000000000000000000090E670E4F00000000000000000000000000000000044
9 | :200102000090E6097404F0000000000000000000000000000000000090E614E4F000000098
10 | :20012200000000000000000000000000000090E612E4F00000000000000000000000000061
11 | :200142000000000090E61AE4F0000000000000000000000000000000000090E618E4F000D7
12 | :200162000000000000000000000000000000000075B200901003E0FE3395E0FFBE1205BF9A
13 | :2001820000028003020274901005E0FD90E614F00000000000000000000000000000000064
14 | :2001A2000090E6047480F0000000000000000000000000000000000090E6047482F000007F
15 | :2001C20000000000000000000000000000000090E6047484F00000000000000000000000BB
16 | :2001E20000000000000090E6047486F0000000000000000000000000000000000090E6041F
17 | :200202007488F0000000000000000000000000000000000090E604E4F000000000000000A2
18 | :2002220000000000000000000000901006E0FD90E61AF000000000000000000000000000B9
19 | :200242000000000090E6247402F0000000000000000000000000000000000090E625E4F02D
20 | :20026200000000000000000000000000000000000022BE2105BF0002800122901005E0FF8E
21 | :2002820090E612F0000000000000000000000000000000000090E6047480F0000000000086
22 | :2002A20000000000000000000000000090E6047482F00000000000000000000000000000DC
23 | :2002C20000000090E6047484F0000000000000000000000000000000000090E6047486F056
24 | :2002E200000000000000000000000000000000000090E6047488F000000000000000000096
25 | :20030200000000000000000090E604E4F0000000000000000000000000000000000090E617
26 | :20032200497482F0000000000000000000000000000000000090E6497482F00000000000E7
27 | :20034200000000000000000000000000901005E0FF3395E05307037E00BF0005BE00028090
28 | :2003620008BF0333BE0030801790E6497482F0000000000000000000000000000000000054
29 | :2003820090E6497482F00000000000000000000000000000000000901006E0FF90E618F0B3
30 | :1703A20000000000000000000000000000000000002212006280FE30
31 | :06003500E478FFF6D8FD9F
32 | :200013007900E94400601B7A009003BD780175A000E493F2A308B8000205A0D9F4DAF275D3
33 | :02003300A0FF2C
34 | :20003B007800E84400600A790175A000E4F309D8FC7800E84400600C7900900001E4F0A3C3
35 | :04005B00D8FCD9FAFA
36 | :0D0006007581071203B9E582600302000353
37 | :0403B9007582002227
38 | :00000001FF
39 |
--------------------------------------------------------------------------------
/fx2pipe/firmware/fx2pipe.ihx:
--------------------------------------------------------------------------------
1 | :03000000020006F5
2 | :03005F0002000399
3 | :030003000203C332
4 | :20006200901003E0FE3395E0FFBE1205BF0002800CBE2105BF000280047F0080027F01008A
5 | :2000820000000000000000000000000000000000EF6007901007E0FE80027E1290E600EE0D
6 | :2000A200F00000000000000000000000000000000000EF6007901004E0FF80027FC390E63B
7 | :2000C20001EFF0000000000000000000000000000000000090E60B7403F000000000000056
8 | :2000E200000000000000000000000090E670E4F00000000000000000000000000000000044
9 | :2001020000901004E0FF30E40790E609E4F0800690E6097404F0000000000000000000007F
10 | :200122000000000000000090E614E4F0000000000000000000000000000000000090E612D7
11 | :20014200E4F0000000000000000000000000000000000090E61AE4F0000000000000000065
12 | :2001620000000000000000000090E618E4F0000000000000000000000000000000000075A6
13 | :20018200B200901003E0FE3395E0FFBE1205BF00028003020283901005E0FD90E614F000E7
14 | :2001A2000000000000000000000000000000000090E6047480F000000000000000000000DF
15 | :2001C2000000000000000090E6047402F0000000000000000000000000000000000090E6C7
16 | :2001E200047404F0000000000000000000000000000000000090E6047406F00000000000AD
17 | :2002020000000000000000000000000090E6047408F00000000000000000000000000000F6
18 | :2002220000000090E604E4F00000000000000000000000000000000000901006E0FD90E675
19 | :200242001AF0000000000000000000000000000000000090E6247402F00000000000000092
20 | :200262000000000000000000000090E625E4F000000000000000000000000000000000000D
21 | :2002820022BE2105BF0002800122901005E0FF90E612F000000000000000000000000000F6
22 | :2002A2000000000090E6047480F0000000000000000000000000000000000090E60474826E
23 | :2002C200F0000000000000000000000000000000000090E6047484F00000000000000000CA
24 | :2002E20000000000000000000090E6047486F0000000000000000000000000000000000098
25 | :2003020090E6047488F0000000000000000000000000000000000090E604E4F00000000027
26 | :200322000000000000000000000000000090E6497482F00000000000000000000000000016
27 | :200342000000000090E6497482F00000000000000000000000000000000000901005E0FF72
28 | :200362003395E05307037E00BF0005BE00028008BF0333BE0030801790E6497482F00000CD
29 | :2003820000000000000000000000000000000090E6497482F00000000000000000000000B6
30 | :2003A200000000000000901006E0FF90E618F0000000000000000000000000000000000038
31 | :0603C2002212006280FE21
32 | :06003500E478FFF6D8FD9F
33 | :200013007900E94400601B7A009003CC780175A000E493F2A308B8000205A0D9F4DAF275C4
34 | :02003300A0FF2C
35 | :20003B007800E84400600A790175A000E4F309D8FC7800E84400600C7900900001E4F0A3C3
36 | :04005B00D8FCD9FAFA
37 | :0D0006007581071203C8E582600302000344
38 | :0403C8007582002218
39 | :00000001FF
40 |
--------------------------------------------------------------------------------
/src/profiler_instr.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "profiler.h"
7 |
8 | typedef struct {
9 | profiler_t profiler;
10 | int profile_min;
11 | int profile_max;
12 | int profile_bucket;
13 | address_t profile_counts[OTHER_CONTEXT + 1];
14 | cpu_emulator_t *em;
15 | } profiler_instr_t;
16 |
17 | static void p_init(void *ptr, cpu_emulator_t *em) {
18 | profiler_instr_t *instance = (profiler_instr_t *)ptr;
19 | memset((void *)instance->profile_counts, 0, sizeof(instance->profile_counts));
20 | instance->em = em;
21 | }
22 |
23 | static void p_profile_instruction(void *ptr, int pc, int opcode, int op1, int op2, int num_cycles) {
24 | profiler_instr_t *instance = (profiler_instr_t *)ptr;
25 | int bucket = OTHER_CONTEXT;
26 | if (pc >= instance->profile_min && pc <= instance->profile_max) {
27 | if (instance->profile_bucket < 2) {
28 | bucket = pc & 0xffff;
29 | } else {
30 | bucket = ((pc & 0xffff) / instance->profile_bucket) * instance->profile_bucket;
31 | }
32 | }
33 | instance->profile_counts[bucket].instructions++;
34 | instance->profile_counts[bucket].cycles += num_cycles;
35 | }
36 |
37 | static void p_done(void *ptr) {
38 | profiler_instr_t *instance = (profiler_instr_t *)ptr;
39 | profiler_output_helper(instance->profile_counts, 1, 0, instance->em);
40 | }
41 |
42 | void *profiler_instr_create(char *arg) {
43 |
44 | profiler_instr_t *instance = (profiler_instr_t *)calloc(1, sizeof(profiler_instr_t));
45 |
46 | instance->profiler.name = "instr";
47 | instance->profiler.arg = arg ? strdup(arg) : "";
48 | instance->profiler.init = p_init;
49 | instance->profiler.profile_instruction = p_profile_instruction;
50 | instance->profiler.done = p_done;
51 | instance->profile_min = 0x0000;
52 | instance->profile_max = 0xffff;
53 | instance->profile_bucket = 1;
54 |
55 | if (arg && strlen(arg) > 0) {
56 | char *min = strtok(arg, ",");
57 | char *max = strtok(NULL, ",");
58 | char *bucket = strtok(NULL, ",");
59 | if (min && strlen(min) > 0) {
60 | instance->profile_min = strtol(min, (char **)NULL, 16);
61 | }
62 | if (max && strlen(max) > 0) {
63 | instance->profile_max = strtol(max, (char **)NULL, 16);
64 | }
65 | if (bucket && strlen(bucket) > 0) {
66 | instance->profile_bucket = strtol(bucket, (char **)NULL, 16);
67 | }
68 | }
69 |
70 | return instance;
71 | }
72 |
--------------------------------------------------------------------------------
/fx2pipe/firmware/fx2pipe_static.cc:
--------------------------------------------------------------------------------
1 | #include /* For NULL... */
2 |
3 | const char *fx2pipe_static_firmware[]={
4 | ":03000000020006F5",
5 | ":03005F0002000399",
6 | ":030003000203C332",
7 | ":20006200901003E0FE3395E0FFBE1205BF0002800CBE2105BF000280047F0080027F01008A",
8 | ":2000820000000000000000000000000000000000EF6007901007E0FE80027E1290E600EE0D",
9 | ":2000A200F00000000000000000000000000000000000EF6007901004E0FF80027FC390E63B",
10 | ":2000C20001EFF0000000000000000000000000000000000090E60B7403F000000000000056",
11 | ":2000E200000000000000000000000090E670E4F00000000000000000000000000000000044",
12 | ":2001020000901004E0FF30E40790E609E4F0800690E6097404F0000000000000000000007F",
13 | ":200122000000000000000090E614E4F0000000000000000000000000000000000090E612D7",
14 | ":20014200E4F0000000000000000000000000000000000090E61AE4F0000000000000000065",
15 | ":2001620000000000000000000090E618E4F0000000000000000000000000000000000075A6",
16 | ":20018200B200901003E0FE3395E0FFBE1205BF00028003020283901005E0FD90E614F000E7",
17 | ":2001A2000000000000000000000000000000000090E6047480F000000000000000000000DF",
18 | ":2001C2000000000000000090E6047402F0000000000000000000000000000000000090E6C7",
19 | ":2001E200047404F0000000000000000000000000000000000090E6047406F00000000000AD",
20 | ":2002020000000000000000000000000090E6047408F00000000000000000000000000000F6",
21 | ":2002220000000090E604E4F00000000000000000000000000000000000901006E0FD90E675",
22 | ":200242001AF0000000000000000000000000000000000090E6247402F00000000000000092",
23 | ":200262000000000000000000000090E625E4F000000000000000000000000000000000000D",
24 | ":2002820022BE2105BF0002800122901005E0FF90E612F000000000000000000000000000F6",
25 | ":2002A2000000000090E6047480F0000000000000000000000000000000000090E60474826E",
26 | ":2002C200F0000000000000000000000000000000000090E6047484F00000000000000000CA",
27 | ":2002E20000000000000000000090E6047486F0000000000000000000000000000000000098",
28 | ":2003020090E6047488F0000000000000000000000000000000000090E604E4F00000000027",
29 | ":200322000000000000000000000000000090E6497482F00000000000000000000000000016",
30 | ":200342000000000090E6497482F00000000000000000000000000000000000901005E0FF72",
31 | ":200362003395E05307037E00BF0005BE00028008BF0333BE0030801790E6497482F00000CD",
32 | ":2003820000000000000000000000000000000090E6497482F00000000000000000000000B6",
33 | ":2003A200000000000000901006E0FF90E618F0000000000000000000000000000000000038",
34 | ":0603C2002212006280FE21",
35 | ":06003500E478FFF6D8FD9F",
36 | ":200013007900E94400601B7A009003CC780175A000E493F2A308B8000205A0D9F4DAF275C4",
37 | ":02003300A0FF2C",
38 | ":20003B007800E84400600A790175A000E4F309D8FC7800E84400600C7900900001E4F0A3C3",
39 | ":04005B00D8FCD9FAFA",
40 | ":0D0006007581071203C8E582600302000344",
41 | ":0403C8007582002218",
42 | ":00000001FF",
43 | NULL
44 | };
45 |
--------------------------------------------------------------------------------
/fx2pipe/usb_io/urbcache.h:
--------------------------------------------------------------------------------
1 | /*
2 | * usb_io/urbcache.h
3 | *
4 | * URB cache class.
5 | *
6 | * Copyright (c) 2006 by Wolfgang Wieser ] wwieser (a) gmx <*> de [
7 | *
8 | * This file may be distributed and/or modified under the terms of the
9 | * GNU General Public License version 2 as published by the Free Software
10 | * Foundation. (See COPYING.GPL for details.)
11 | *
12 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14 | *
15 | */
16 |
17 | #ifndef _INCLUDE_FX2PIPE_USBIO_URBCACHE_H_
18 | #define _INCLUDE_FX2PIPE_USBIO_URBCACHE_H_ 1
19 |
20 | #include "../oconfig.h"
21 | #include "../lib/linkedlist.h"
22 |
23 | #include
24 |
25 |
26 | /**
27 | * \short User request block cache.
28 | * \author Wolfgang Wieser ] wwieser (a) gmx <*> de [
29 | *
30 | * This is a generic memory chunk chache for equally-sized memory
31 | * chunks.
32 | *
33 | * It has a size limit and get() and put() statements which use
34 | * normal libc-malloc/free (de)allocation if limits are exceeded.
35 | *
36 | * Not thread-safe. Not "C++-safe".
37 | */
38 | class URBCache
39 | {
40 | private:
41 | /// Max number of elements to store.
42 | int stack_size;
43 | /// Index of next free element on stack; 0 if empty.
44 | int top_idx;
45 | /// Stack of elements; array of size stack_size.
46 | void **stack;
47 | /// Size of each element just for enforcing equal sizes.
48 | /// This is only needed to enforce that get() and put() are
49 | /// dealing with equally-sized memory chunks all the time...
50 | size_t elem_size;
51 |
52 | /// Slow path of the get() operation.
53 | void *_GetAlloc();
54 | /// Internally used; see get(), put().
55 | void _size_oops();
56 |
57 | private:
58 | /// Do not use.
59 | void operator=(const URBCache &);
60 | /// Do not use.
61 | URBCache(const URBCache &);
62 |
63 | public:
64 | /**
65 | * \short Create an URB cache.
66 | *
67 | * The cache will store at most max_elem URBs.
68 | * Each URB must have the size elem_size.
69 | */
70 | URBCache(int max_elem,size_t _elem_size);
71 | /// Destructor will free all elements in the free list.
72 | ~URBCache();
73 |
74 | /// Clear the cache freeing all elements.
75 | void clear();
76 |
77 | /// Get a memory chunk of passed size which must match elem_size.
78 | inline void *get(size_t size)
79 | {
80 | if(size>elem_size) _size_oops();
81 | return(top_idx ? stack[--top_idx] : _GetAlloc());
82 | }
83 |
84 | /// Put back ("free") memory chunk; passed size must match again...
85 | inline void put(void *ptr,size_t size)
86 | {
87 | if(size>elem_size) _size_oops();
88 | if(top_idx ${log}"
71 | ${DECODE} ${common_options} ${test_options[${name}]} ${data} > ${log}
72 |
73 | fail_count=`grep fail ${log} | wc -l`
74 | md5=`md5sum ${log} | cut -c1-8`
75 | size=$(stat ${STATARGS} "${log}")
76 |
77 |
78 | diff_count="-1"
79 |
80 | # If the --ref option is given, then save the current log file as a reference
81 | if [ "${REF}" == "1" ]; then
82 | mv ${log} ${ref}
83 | else
84 | if [ -f ${ref} ]; then
85 | diff ${ref} ${log} | head -10000 > ${dif}
86 | diff_count=`wc -l <${dif}`
87 | fi
88 | fi
89 |
90 | echo " Trace MD5: ${md5}; Prediction fail count: ${fail_count}; Reference diff count: ${diff_count}"
91 |
92 |
93 | echo
94 |
95 |
96 | # if [ "${fail_count}" != "0" ]; then
97 | # echo
98 | # grep -10 -m 100 fail ${log}
99 | # echo
100 | # fi
101 |
102 | done
103 |
--------------------------------------------------------------------------------
/src/defs.h:
--------------------------------------------------------------------------------
1 | #ifndef DEFS
2 | #define DEFS
3 |
4 | #include
5 |
6 | typedef enum {
7 | MACHINE_DEFAULT,
8 | MACHINE_BEEB,
9 | MACHINE_MASTER,
10 | MACHINE_ELK,
11 | MACHINE_ATOM,
12 | MACHINE_MEK6800D2,
13 | MACHINE_BLITTER,
14 | } machine_t;
15 |
16 | typedef enum {
17 | CPU_UNKNOWN,
18 | CPU_6502,
19 | CPU_6502_ARLET,
20 | CPU_65C02,
21 | CPU_65C02_ROCKWELL,
22 | CPU_65C02_WDC,
23 | CPU_65C02_ARLET,
24 | CPU_65C02_ALAND,
25 | CPU_65C816,
26 | CPU_6800,
27 | } cpu_t;
28 |
29 | // Sample Queue Depth - needs to fit the longest instruction
30 | #define DEPTH 13
31 |
32 | // Sample_type_t is an abstraction of both the 6502 SYNC and the 65816 VDA/VPA
33 |
34 | typedef enum { // 6502 Sync 65815 VDA/VPA
35 | UNKNOWN, // ? ? ?
36 | INTERNAL, // - 0 0
37 | PROGRAM, // - 0 1
38 | DATA, // 0 1 0
39 | OPCODE, // 1 1 1
40 | LAST // a marker for the end of stream
41 | } sample_type_t;
42 |
43 | typedef struct {
44 | uint32_t sample_count;
45 | uint32_t cycle_count;
46 | sample_type_t type;
47 | uint8_t data;
48 | int8_t rnw; // -1 indicates unknown
49 | int8_t rst; // -1 indicates unknown
50 | int8_t e; // -1 indicates unknown (65816 e pin)
51 | int8_t user; // -1 indicates unknown (user defined signal)
52 | } sample_t;
53 |
54 |
55 | typedef struct {
56 | int pc;
57 | int pb;
58 | uint8_t opcode;
59 | uint8_t op1;
60 | uint8_t op2;
61 | uint8_t op3;
62 | uint8_t opcount;
63 | } instruction_t;
64 |
65 | void write_hex1(char *buffer, int value);
66 | void write_hex2(char *buffer, int value);
67 | void write_hex4(char *buffer, int value);
68 | void write_hex6(char *buffer, int value);
69 | int write_s (char *buffer, const char *s);
70 |
71 | typedef struct {
72 | cpu_t cpu_type;
73 | machine_t machine;
74 | int idx_data;
75 | int idx_rnw;
76 | int idx_sync;
77 | int idx_rdy;
78 | int idx_phi1;
79 | int idx_phi2;
80 | int idx_user;
81 | int idx_rst;
82 | int idx_vda;
83 | int idx_vpa;
84 | int idx_e;
85 | int vec_rst;
86 | int show_address;
87 | int show_hex;
88 | int show_instruction;
89 | int show_state;
90 | int show_bbcfwa;
91 | int show_cycles;
92 | int show_samplenums;
93 | int show_something;
94 | int bbctube;
95 | int undocumented;
96 | int e_flag;
97 | int ms_flag;
98 | int xs_flag;
99 | int sp_reg;
100 | int pb_reg;
101 | int db_reg;
102 | int dp_reg;
103 | int byte;
104 | int debug;
105 | int skip;
106 | int skew_rd;
107 | int skew_wr;
108 | char *labels_file;
109 | int mem_model;
110 | int profile;
111 | int trigger_start;
112 | int trigger_stop;
113 | int trigger_skipint;
114 | char *filename;
115 | int show_romno;
116 | } arguments_t;
117 |
118 | typedef struct {
119 | void (*init)(arguments_t *args);
120 | int (*match_interrupt)(sample_t *sample_q, int num_samples);
121 | int (*count_cycles)(sample_t *sample_q, int intr_seen);
122 | void (*reset)(sample_t *sample_q, int num_cycles, instruction_t *instruction);
123 | void (*interrupt)(sample_t *sample_q, int num_cycles, instruction_t *instruction);
124 | void (*emulate)(sample_t *sample_q, int num_cycles, instruction_t *instruction);
125 | int (*disassemble)(char *bp, instruction_t *instruction);
126 | int (*get_PC)();
127 | int (*get_PB)();
128 | int (*read_memory)(int address);
129 | char *(*get_state)();
130 | int (*get_and_clear_fail)();
131 | } cpu_emulator_t;
132 |
133 | extern int failflag;
134 |
135 | #endif
136 |
--------------------------------------------------------------------------------
/fx2pipe/usb_io/fx2usb.h:
--------------------------------------------------------------------------------
1 | /*
2 | * usb_io/fx2usb.h
3 | *
4 | * Low-level routines for data IO with Cypress FX2 chip.
5 | *
6 | * Copyright (c) 2006 by Wolfgang Wieser ] wwieser (a) gmx <*> de [
7 | *
8 | * This file may be distributed and/or modified under the terms of the
9 | * GNU General Public License version 2 as published by the Free Software
10 | * Foundation. (See COPYING.GPL for details.)
11 | *
12 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14 | *
15 | */
16 |
17 | #ifndef _INCLUDE_USBIO_FX2USB_H_
18 | #define _INCLUDE_USBIO_FX2USB_H_ 1
19 |
20 | #include "../oconfig.h"
21 | #include "../usb_io/wwusb.h"
22 |
23 |
24 | /**
25 | * \short FX2 USB Device representation.
26 | * \author Wolfgang Wieser ] wwieser (a) gmx <*> de [
27 | *
28 | * Derived from WWUSBDevice; provides a simple extension for certain
29 | * things like firmware downloading.
30 | */
31 | class FX2USBDevice : public WWUSBDevice
32 | {
33 | private:
34 |
35 | /// Internally used by connect() to download firmware.
36 | ErrorCode _DownloadFirmware(struct usb_device *usbdev,const char *path,
37 | const char **static_firmware,
38 | const char *cfg_buf,size_t cfg_len,size_t cfg_adr);
39 | /// Internally used by connect().
40 | ErrorCode _connect(
41 | struct usb_device *fx2_dev,
42 | const char *firmware_path,const char **static_firmware,
43 | const char *cfg_buf,size_t cfg_len,size_t cfg_adr);
44 | private:
45 | /// Do not use.
46 | void operator=(const FX2USBDevice &);
47 | /// Do not use.
48 | FX2USBDevice(const FX2USBDevice &);
49 | public:
50 | /// Create not-set-up FX2 device.
51 | FX2USBDevice();
52 | /// Destructor...
53 | virtual ~FX2USBDevice();
54 |
55 | /**
56 | * \short Connect to FX2 and dowload firmware.
57 | *
58 | * NOTE: When connecting an FX2 device, do not use one of the
59 | * connect() calls from WWUSBDevice. Instead use this one.
60 | *
61 | * This will first find the FX2 device to use, download the firmware,
62 | * disconnect [to give the FX2 a chance for its re-numeration which is
63 | * probably pointless in this case] and then connect again.
64 | *
65 | * Step-by-step:
66 | *
67 | * Will first trigger a disconnect() first to be sure.
68 | *
69 | * Then, will look for a device with vendor and product IDs
70 | * initial_vendor,initial_product or (if not found) for an
71 | * unconfigured FX2. (Use -1,-1 to switch off.)
72 | * Actually, the code will look for the n_th match; use 0 for the
73 | * first device, 1 for the second, etc.
74 | *
75 | * Then, will connect, download firmware and disconnect.
76 | * The firmware is taken from the file firmware_path which must be
77 | * an Intel HEX file. If firmware_path is NULL, an alternate
78 | * firmware can be specified as static_firmware which is a
79 | * NULL-terminated array of strings; each element being one line of an
80 | * Intel HEX file. If firmware_path is an empty string, no firmware
81 | * will be downloaded.
82 | *
83 | * You can pass an additional config in cfg_buf of size cfg_len
84 | * which will be put at address cfg_adr before taking the FX2 out
85 | * of the reset. If unused, use NULL,0,0.
86 | *
87 | * Then, will connect to the device again. We use bus and device
88 | * paths ("IDs") since these will not change even if the USB IDs
89 | * change due to re-numeration.
90 | *
91 | * Errors are written to stderr.
92 | */
93 | ErrorCode connect(int initial_vendor,int initial_product,int n_th,
94 | const char *firmware_path,const char **static_firmware,
95 | const char *cfg_buf,size_t cfg_len,size_t cfg_adr);
96 | ErrorCode connect(
97 | const char *bus,const char *dev,
98 | const char *firmware_path,const char **static_firmware,
99 | const char *cfg_buf,size_t cfg_len,size_t cfg_adr);
100 | };
101 |
102 | #endif /* _INCLUDE_USBIO_FX2USB_H_ */
103 |
--------------------------------------------------------------------------------
/src/symbols.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "defs.h"
7 | #include "symbols.h"
8 |
9 | typedef enum {
10 | SWS_GROUND,
11 | SWS_GOT_SQUARE,
12 | SWS_GOT_CURLY,
13 | SWS_IN_NAME,
14 | SWS_TOO_LONG,
15 | SWS_NAME_END,
16 | SWS_IN_VALUE,
17 | SWS_AWAIT_COMMA
18 | } swstate;
19 |
20 | // Being very lazy here using an array!
21 | static char **symbol_table = NULL;
22 |
23 | static int max_address = -1;
24 |
25 | void symbol_init(int size) {
26 | symbol_table = (char **)malloc(size * sizeof(char *));
27 | for (int i = 0; i < size;i++) {
28 | symbol_table[i] = NULL;
29 | }
30 | max_address = size - 1;
31 | }
32 |
33 | void symbol_add(char *name, int address) {
34 | if (address >= 0 && address <= max_address) {
35 | char *copy = (char *)malloc(strlen(name)+1);
36 | strcpy(copy, name);
37 | symbol_table[address] = copy;
38 | } else {
39 | // This case should never happen
40 | fprintf(stderr, "symbol %s:%04x out of range\r\n", name, address);
41 | exit(1);
42 | }
43 | }
44 |
45 | char *symbol_lookup(int address) {
46 | if (address >= 0 && address <= max_address) {
47 | return symbol_table[address];
48 | } else {
49 | return NULL;
50 | }
51 | }
52 |
53 | void symbol_import_swift(char *filename)
54 | {
55 | FILE *fp = fopen(filename, "r");
56 | if (fp) {
57 | swstate state = SWS_GROUND;
58 | char name[80], *name_ptr, *name_end = name+sizeof(name);
59 | uint32_t addr;
60 | int ch, syms = 0;
61 | while ((ch = getc(fp)) != EOF) {
62 | switch(state) {
63 | case SWS_GROUND:
64 | if (ch == '[')
65 | state = SWS_GOT_SQUARE;
66 | break;
67 | case SWS_GOT_SQUARE:
68 | if (ch == '{')
69 | state = SWS_GOT_CURLY;
70 | else if (ch != '[')
71 | state = SWS_GROUND;
72 | break;
73 | case SWS_GOT_CURLY:
74 | if (ch == '\'') {
75 | name_ptr = name;
76 | state = SWS_IN_NAME;
77 | }
78 | else if (!strchr(" \t\r\n", ch))
79 | state = SWS_GROUND;
80 | break;
81 | case SWS_IN_NAME:
82 | if (ch == '\'') {
83 | *name_ptr = 0;
84 | state = SWS_NAME_END;
85 | }
86 | else if (name_ptr >= name_end) {
87 | fprintf(stderr, "swift import name too long");
88 | state = SWS_TOO_LONG;
89 | }
90 | else
91 | *name_ptr++ = ch;
92 | break;
93 | case SWS_TOO_LONG:
94 | if (ch == '\'') {
95 | name_ptr = 0;
96 | state = SWS_NAME_END;
97 | }
98 | break;
99 | case SWS_NAME_END:
100 | if (ch == ':') {
101 | addr = 0;
102 | state = SWS_IN_VALUE;
103 | }
104 | else if (!strchr(" \t\r\n", ch))
105 | state = SWS_GROUND;
106 | break;
107 | case SWS_IN_VALUE:
108 | if (ch >= '0' && ch <= '9')
109 | addr = addr * 10 + ch - '0';
110 | else if (ch == 'L') {
111 | symbol_add(name, addr);
112 | state = SWS_AWAIT_COMMA;
113 | syms++;
114 | }
115 | else if (ch == ',') {
116 | symbol_add(name, addr);
117 | state = SWS_GOT_CURLY;
118 | syms++;
119 | }
120 | else
121 | state = SWS_GROUND;
122 | break;
123 | case SWS_AWAIT_COMMA:
124 | if (ch == ',')
125 | state = SWS_GOT_CURLY;
126 | else if (!strchr(" \t\r\n", ch))
127 | state = SWS_GROUND;
128 | }
129 | }
130 | fclose(fp);
131 | }
132 | else
133 | fprintf(stderr, "unable to open '%s': %s\n", filename, strerror(errno));
134 | }
135 |
--------------------------------------------------------------------------------
/fx2sharp/fx2sharp/fx2sharp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Debug
7 | AnyCPU
8 | {C629F22F-2110-460D-A8E0-ADEEACE0CEEF}
9 | Exe
10 | fx2sharp
11 | fx2sharp
12 | v4.6
13 | 512
14 | true
15 | true
16 |
17 |
18 |
19 |
20 |
21 | AnyCPU
22 | true
23 | full
24 | false
25 | bin\Debug\
26 | DEBUG;TRACE
27 | prompt
28 | 4
29 | true
30 |
31 |
32 | AnyCPU
33 | pdbonly
34 | true
35 | bin\Release\
36 | TRACE
37 | prompt
38 | 4
39 | true
40 |
41 |
42 |
43 | C:\Program Files (x86)\Cypress\EZ-USB FX3 SDK\1.3\library\c_sharp\lib\CyUSB.dll
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | Always
62 |
63 |
64 |
65 |
66 |
67 |
68 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/fx2pipe/usb_io/cycfx2dev.h:
--------------------------------------------------------------------------------
1 | /*
2 | * cycfx2dev.h - Cypress FX2 device class: low-level routines.
3 | *
4 | * Copyright (c) 2006--2009 by Wolfgang Wieser ] wwieser (a) gmx <*> de [
5 | *
6 | * This file may be distributed and/or modified under the terms of the
7 | * GNU General Public License version 2 as published by the Free Software
8 | * Foundation. (See COPYING.GPL for details.)
9 | *
10 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12 | *
13 | */
14 |
15 | #ifndef _CYCFX2PROG_CYCFX2DEVICE_
16 | #define _CYCFX2PROG_CYCFX2DEVICE_ 1
17 |
18 | #include
19 |
20 |
21 | extern struct usb_device *USBFindDevice(const char *bus,const char *dev);
22 | extern struct usb_device *USBFindDevice(int vendor,int product,int nth=0);
23 |
24 |
25 | class CypressFX2Device
26 | {
27 | private:
28 | struct usb_device *usbdev;
29 | struct usb_dev_handle *usbhdl;
30 |
31 | // Force a certail "alt" interface; -1 for none.
32 | int force_alt_interface;
33 |
34 | // Internally used: Program one line of an Intel HEX file.
35 | // The arguments path and line are just needed for error reporting.
36 | int _ProgramIHexLine(const char *buf,const char *path,int line);
37 | private:
38 | CypressFX2Device(const CypressFX2Device &);
39 | void operator=(const CypressFX2Device &);
40 | public:
41 | CypressFX2Device()
42 | { usbdev=NULL; usbhdl=NULL; force_alt_interface=-1; }
43 | ~CypressFX2Device()
44 | { close(); }
45 |
46 | // Is opened?
47 | inline bool IsOpen() const
48 | { return(usbhdl); }
49 |
50 | // Open usb device; will close previous one.
51 | // Returns 0 on success; 1 on error. Errors written to stderr.
52 | int open(struct usb_device *_usbdev);
53 |
54 | // Close device. Returns 0 on success. Errors written to stderr.
55 | int close();
56 |
57 | // Read an intel hex file and download it.
58 | // Returns 0 on success; 1 on error. Errors written to stderr.
59 | int ProgramIHexFile(const char *path);
60 | // Like ProgramIHexFile() but Intel HEX is supplied as NULL-terminated
61 | // array of strings; each line of the hex file as string element.
62 | int ProgramStaticIHex(const char **ihex);
63 | // Read a flat binary file and download it.
64 | int ProgramBinFile(const char *path,size_t start_addr=0);
65 | // Download/write a chunk of ram into the device.
66 | int WriteRAM(size_t addr,const unsigned char *data,size_t nbytes);
67 | // Read a portion of ram from the device.
68 | int ReadRAM(size_t addr,unsigned char *data,size_t nbytes);
69 |
70 | // Put the Cypress FX2 into reset or release reset.
71 | // running=1 -> running; running=0 -> reset.
72 | int FX2Reset(bool running);
73 |
74 | // Read from endpoint.
75 | // type: 'b','B' -> bulk; 'i','I' -> interrupt
76 | // Capital letters mean that data may be shorter than expected.
77 | // endpoint must be address (like 0x86 for EP 6 in).
78 | // Returns number of read bytes. See source comment!!
79 | int BlockRead(int endpoint,unsigned char *buf,size_t nbytes,
80 | char type='b');
81 | // Counterpart for BlockRead; type is 'b' or 'i' but not 'B'/'I'.
82 | int BlockWrite(int endpoint,const unsigned char *buf,size_t nbytes,
83 | char type='b');
84 | // Returns number of written bytes. See source comment!!
85 |
86 | // Benchmark block (bulk/interrupt) reading.
87 | // type: 'b' -> bulk; 'i' -> interrupt
88 | // endpoint must be address (like 0x86 for EP 6 in).
89 | int BenchBlockRead(int endpoint,size_t nbytes,size_t chunk_size,
90 | char type='b');
91 |
92 | // Set the alt interface to use at next block read/write.
93 | // Use -1 for automatic FX2-default values.
94 | int ForceAltInterface(int alt_if=-1)
95 | { force_alt_interface=alt_if; return(0); }
96 |
97 | // Send a USB control message.
98 | int CtrlMsg(unsigned char requesttype,
99 | unsigned char request,int value,int index,
100 | const unsigned char *ctl_buf=NULL,size_t ctl_buf_size=0);
101 | };
102 |
103 | #endif /* _CYCFX2PROG_CYCFX2DEVICE_ */
104 |
--------------------------------------------------------------------------------
/src/profiler_block.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "profiler.h"
7 |
8 | typedef struct {
9 | profiler_t profiler;
10 | int profile_min;
11 | int profile_max;
12 | address_t profile_counts[OTHER_CONTEXT + 1];
13 | int last_opcode;
14 | cpu_emulator_t *em;
15 | } profiler_block_t;
16 |
17 | static void p_init(void *ptr, cpu_emulator_t *em) {
18 | profiler_block_t *instance = (profiler_block_t *)ptr;
19 | memset((void *)instance->profile_counts, 0, sizeof(instance->profile_counts));
20 | instance->profile_counts[OTHER_CONTEXT].flags = 1;
21 | instance->em = em;
22 | }
23 |
24 | static void p_profile_instruction(void *ptr, int pc, int opcode, int op1, int op2, int num_cycles) {
25 | profiler_block_t *instance = (profiler_block_t *)ptr;
26 | int addr;
27 | if (pc >= instance->profile_min && pc <= instance->profile_max) {
28 | addr = pc & 0xffff;
29 | } else {
30 | addr = OTHER_CONTEXT;
31 | }
32 | instance->profile_counts[addr].instructions++;
33 | instance->profile_counts[addr].cycles += num_cycles;
34 | // Test the test instruction to catch the destination of an indiect JMP
35 | // (this will break if the following instruction is interrupted)
36 | if (instance->last_opcode == 0x6c) {
37 | instance->profile_counts[addr].flags |= FLAG_JMP_IND;
38 | } else if (instance->last_opcode == 0x7c) {
39 | instance->profile_counts[addr].flags |= FLAG_JMP_INDX;
40 | }
41 | if (opcode == 0x20) {
42 | // Note the destination of JSR
43 | addr = (op2 << 8 | op1) & 0xffff;
44 | instance->profile_counts[addr].flags |= FLAG_JSR;
45 | } else if (opcode == 0x4c) {
46 | // Note the destination of JMP
47 | addr = (op2 << 8 | op1) & 0xffff;
48 | instance->profile_counts[addr].flags |= FLAG_JMP;
49 | } else if (pc >= 0 && (((opcode & 0x1f) == 0x10) || (opcode == 0x80))) {
50 | // Note the destination of Bxx
51 | addr = ((pc + 2) + ((int8_t)(op1))) & 0xffff;
52 | instance->profile_counts[addr ].flags |= addr < pc ? FLAG_BB_TAKEN : FLAG_FB_TAKEN;
53 | instance->profile_counts[pc + 2].flags |= addr < pc ? FLAG_BB_NOT_TAKEN : FLAG_FB_NOT_TAKEN;
54 | }
55 | instance->last_opcode = opcode;
56 | }
57 |
58 | static void p_done(void *ptr) {
59 | profiler_block_t *instance = (profiler_block_t *)ptr;
60 | address_t block_counts[OTHER_CONTEXT + 1];
61 | memset((void *)block_counts, 0, sizeof(block_counts));
62 | int current_block = OTHER_CONTEXT;
63 | int addr;
64 | for (addr = 0; addr <= OTHER_CONTEXT; addr++) {
65 | if (instance->profile_counts[addr].flags) {
66 | current_block = addr;
67 | block_counts[current_block].flags = instance->profile_counts[addr].flags;
68 | block_counts[current_block].calls = instance->profile_counts[addr].instructions;
69 | }
70 | block_counts[current_block].cycles += instance->profile_counts[addr].cycles;
71 | block_counts[current_block].instructions += instance->profile_counts[addr].instructions;
72 | }
73 | profiler_output_helper(block_counts, 0, 1, instance->em);
74 | }
75 |
76 | void *profiler_block_create(char *arg) {
77 |
78 | profiler_block_t *instance = (profiler_block_t *)calloc(1, sizeof(profiler_block_t));
79 |
80 | instance->profiler.name = "block";
81 | instance->profiler.arg = arg ? strdup(arg) : "";
82 | instance->profiler.init = p_init;
83 | instance->profiler.profile_instruction = p_profile_instruction;
84 | instance->profiler.done = p_done;
85 | instance->profile_min = 0x0000;
86 | instance->profile_max = 0xffff;
87 |
88 | if (arg && strlen(arg) > 0) {
89 | char *min = strtok(arg, ",");
90 | char *max = strtok(NULL, ",");
91 | if (min && strlen(min) > 0) {
92 | instance->profile_min = strtol(min, (char **)NULL, 16);
93 | }
94 | if (max && strlen(max) > 0) {
95 | instance->profile_max = strtol(max, (char **)NULL, 16);
96 | }
97 | }
98 |
99 | return instance;
100 | }
101 |
--------------------------------------------------------------------------------
/fx2pipe/usb_io/fx2usb.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * usb_io/fx2usb.cc
3 | *
4 | * Low-level routines for data IO with Cypress FX2 chip.
5 | *
6 | * Copyright (c) 2006 by Wolfgang Wieser ] wwieser (a) gmx <*> de [
7 | *
8 | * This file may be distributed and/or modified under the terms of the
9 | * GNU General Public License version 2 as published by the Free Software
10 | * Foundation. (See COPYING.GPL for details.)
11 | *
12 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14 | *
15 | */
16 |
17 | #include "../usb_io/fx2usb.h"
18 | #include "../usb_io/cycfx2dev.h" /* Needed for programming. */
19 |
20 | #include
21 | #include
22 |
23 | #include
24 |
25 |
26 | FX2USBDevice::ErrorCode FX2USBDevice::_DownloadFirmware(
27 | struct usb_device *usbdev,const char *path,const char **static_firmware,
28 | const char *cfg_buf,size_t cfg_len,size_t cfg_adr)
29 | {
30 | CypressFX2Device fx2dev;
31 |
32 | ErrorCode ec=ECFailure;
33 | do {
34 | if(fx2dev.open(usbdev)) break;
35 |
36 | // [none] means: Just reset.
37 | char what='n'; // none
38 | if(!path && static_firmware) what='b'; // builtin static firmware
39 | if(path && *path) what='f'; // file
40 |
41 | fprintf(stderr,"Downloading firmware %s%s%s...\n",
42 | what=='f' ? "\"" : "",
43 | what=='f' ? path : what=='b' ? "[builtin]" : "[none]",
44 | what=='f' ? "\"" : "");
45 |
46 | if(fx2dev.FX2Reset(/*running=*/0)) break;
47 |
48 | if(what=='f' && fx2dev.ProgramIHexFile(path)) break;
49 | else if(what=='b' && fx2dev.ProgramStaticIHex(static_firmware)) break;
50 |
51 | if(cfg_buf &&
52 | fx2dev.WriteRAM(cfg_adr,(const uchar*)cfg_buf,cfg_len)) break;
53 |
54 | if(fx2dev.FX2Reset(/*running=*/1)) break;
55 |
56 | ec=ECSuccess;
57 | } while(0);
58 |
59 | // Important: Close device again since we need to re-open it using
60 | // our own code.
61 | if(fx2dev.close())
62 | { ec=ECFailure; }
63 |
64 | if(ec)
65 | {
66 | // FIXME: We should be a bit more precise here...
67 | fprintf(stderr,"Failed to connect FX2 and download firmware.\n");
68 | }
69 |
70 | return(ec);
71 | }
72 |
73 |
74 | FX2USBDevice::ErrorCode FX2USBDevice::_connect(
75 | struct usb_device *fx2_dev,
76 | const char *firmware_path,const char **static_firmware,
77 | const char *cfg_buf,size_t cfg_len,size_t cfg_adr)
78 | {
79 | if(!fx2_dev)
80 | {
81 | fprintf(stderr,"Device not attached to USB.\n");
82 | return(ECNoSuchDevice);
83 | }
84 |
85 | char *bus = strdup(fx2_dev->bus->dirname);
86 | char *dev = strdup(fx2_dev->filename);
87 | if(!bus || !dev)
88 | { return(ECFailure); }
89 |
90 | ErrorCode ec=_DownloadFirmware(fx2_dev,firmware_path,static_firmware,
91 | cfg_buf,cfg_len, cfg_adr);
92 | if(ec)
93 | {
94 | free(bus);
95 | free(dev);
96 | return(ec);
97 | }
98 |
99 | // Wait some time for FX2 CPU initialization and maybe re-numeration.
100 | // FIXME: Maybe this is not enough.
101 | usleep(10000);
102 |
103 | // Re-connect using bus and device paths since these should not change.
104 | // FIXME: These DO change if the firmware renumerates (which the
105 | // built-in fx2pipe firmware does not). So, this works only for
106 | // firmware which does not renumerate.
107 | ec=WWUSBDevice::connect(bus,dev);
108 | free(bus);
109 | free(dev);
110 | if(ec)
111 | {
112 | fprintf(stderr,"Failed to re-connect to (configured) FX2 (ec=%d)\n",ec);
113 | return(ec);
114 | }
115 |
116 | return(ECSuccess);
117 | }
118 |
119 |
120 | FX2USBDevice::ErrorCode FX2USBDevice::connect(
121 | int initial_vendor,int initial_product,int n_th,
122 | const char *firmware_path,const char **static_firmware,
123 | const char *cfg_buf,size_t cfg_len,size_t cfg_adr)
124 | {
125 | // Be sure not to be connected.
126 | disconnect();
127 |
128 | // *** Connect for the first time. ***
129 | struct usb_device *fx2_dev=NULL;
130 | if(initial_vendor>=0 && initial_product>=0)
131 | { fx2_dev=USBFindDevice(/*vendor=*/initial_vendor,
132 | /*product=*/initial_product,n_th); }
133 | // Search for unconfigured FX2:
134 | else
135 | { fx2_dev=USBFindDevice(/*vendor=*/0x04b4,/*product=*/0x8613,n_th); }
136 |
137 | return(_connect(fx2_dev,
138 | firmware_path,static_firmware,
139 | cfg_buf,cfg_len,cfg_adr));
140 | }
141 |
142 | FX2USBDevice::ErrorCode FX2USBDevice::connect(
143 | const char *bus,const char *dev,
144 | const char *firmware_path,const char **static_firmware,
145 | const char *cfg_buf,size_t cfg_len,size_t cfg_adr)
146 | {
147 | // Be sure not to be connected.
148 | disconnect();
149 |
150 | // *** Connect for the first time. ***
151 | struct usb_device *fx2_dev=USBFindDevice(bus,dev);
152 |
153 | return(_connect(fx2_dev,
154 | firmware_path,static_firmware,
155 | cfg_buf,cfg_len,cfg_adr));
156 | }
157 |
158 |
159 | FX2USBDevice::FX2USBDevice() :
160 | WWUSBDevice()
161 | {
162 | }
163 |
164 | FX2USBDevice::~FX2USBDevice()
165 | {
166 | }
167 |
--------------------------------------------------------------------------------
/fx2pipe/fx2pipe/fx2pipe.h:
--------------------------------------------------------------------------------
1 | /*
2 | * usb_io/fx2pipe.h
3 | *
4 | * Cypress FX2 pipe IO main class.
5 | *
6 | * Copyright (c) 2006--2009 by Wolfgang Wieser ] wwieser (a) gmx <*> de [
7 | *
8 | * This file may be distributed and/or modified under the terms of the
9 | * GNU General Public License version 2 as published by the Free Software
10 | * Foundation. (See COPYING.GPL for details.)
11 | *
12 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14 | *
15 | */
16 |
17 | #ifndef _INCLUDE_USBIO_FX2PIPE_H_
18 | #define _INCLUDE_USBIO_FX2PIPE_H_ 1
19 |
20 | #include "../oconfig.h"
21 | #include "../lib/linkedlist.h"
22 | #include "../usb_io/fx2usb.h"
23 | #include "../usb_io/urbcache.h"
24 |
25 | #include
26 |
27 |
28 | // This is defined somewhere in main.cc
29 | extern volatile int caught_sigint;
30 | // Builtin firmware from ../firmware/fx2pipe_static.cc:
31 | extern const char *fx2pipe_static_firmware[];
32 |
33 | /**
34 | * \short Cypress FX2 pipe IO main class.
35 | * \author Wolfgang Wieser ] wwieser (a) gmx <*> de [
36 | *
37 | * Not C++-safe. Not thread-safe.
38 | */
39 | class FX2Pipe : public FX2USBDevice
40 | {
41 | public:
42 | /// URB used by USBIOThread.
43 | struct MyURB : FX2Pipe::URB
44 | {
45 | /// URB cache against allocation overhead.
46 | static URBCache urb_cache;
47 |
48 | /// Allocate buffer and attach it. Must be done before submission.
49 | void AllocBuffer(size_t size);
50 |
51 | MyURB(uchar dir_ep,uchar _type=USBDEVFS_URB_TYPE_BULK);
52 | ~MyURB();
53 |
54 | /** Custom operators new and delete for URB caching. */
55 | /// \{
56 | void *operator new(size_t size)
57 | { return(urb_cache.get(size)); }
58 | void operator delete(void *ptr,size_t size)
59 | { urb_cache.put(ptr,size); }
60 | /// \}
61 | };
62 |
63 | private:
64 | /// Number of successive reaped URBs with errors.
65 | /// May only be accessed by IO thread.
66 | int successive_error_urbs;
67 |
68 | /// Error counter for exit value.
69 | int x_errors;
70 |
71 | /// Start time when we submitted the initial URBs.
72 | timeval starttime;
73 | /// End time when everything's done.
74 | timeval endtime;
75 | /// Time of last status display update.
76 | timeval last_update_time;
77 | /// Number of bytes transferred at last update.
78 | int64 last_update_transferred;
79 |
80 | /// Submitted bytes: Number of bytes submitted but not all of them
81 | /// are yet transferred.
82 | int64 submitted_bytes;
83 | /// Transferred bytes:
84 | /// Number of bytes successfully transferred.
85 | int64 transferred_bytes;
86 |
87 | /// EOF on stdio (1) or transfer limit reached (2).
88 | int stdio_eof;
89 |
90 | /// See FirwareConfig.
91 | static const int FirmwareConfigAdr=0x1003;
92 |
93 | /// Write transferred bytes, time and transfer rate.
94 | void _DisplayTransferStatistics(const timeval *endtime,int final);
95 |
96 | /// Initialize/connect to USB device. Also download firmware.
97 | /// Returns error code.
98 | int _ConnectAndInitUSB();
99 | /// Counterpart of ConnectAndInitUSB: cleanup.
100 | void _CleanupUSB();
101 |
102 | /// Submit one URB. 0 on success; 1 on failure.
103 | int _SubmitOneURB();
104 | /// Submit a bunch of URBs initially to fill the pipeline.
105 | int _SubmitInitialURBs();
106 | /// Cancel all the pending osci data URBs.
107 | void _CancelAllPendingDataURBs();
108 |
109 | /// Overriding virtual from WWUSBDevice.
110 | ErrorCode URBNotify(URB *u);
111 | /// Overriding virtual from WWUSBDevice.
112 | void DeleteURB(URB *u);
113 |
114 | public:
115 | /// Some config:
116 | /// This config is meant to be set in the beginning and not to be
117 | /// changed afterwards.
118 | int n_th_usb_dev; /// Connect to n-th matching USB device. Start with 0.
119 | /// VID and PID of device to search; -1 for defaults.
120 | int search_vid,search_pid;
121 |
122 | /// Max number of bytes to transfer; negative for unlimited.
123 | int64 transfer_limit;
124 |
125 | /// IO block size.
126 | uint io_block_size;
127 | /// Pipeline size (number of URBs).
128 | int pipeline_size;
129 |
130 | /// Direction: -1 -> IN (default); +1 -> OUT
131 | int dir;
132 |
133 | /// Don't use stdio but throw away data / write NUL data.
134 | int no_stdio;
135 |
136 | /// SCHED_OTHER or SCHED_FIFO or SCHED_RR
137 | int schedule_policy;
138 | /// Priority; used if schedule_policy!=SCHED_OTHER.
139 | int schedule_priority;
140 |
141 | /// Path to firmware IHX file. NULL for builtin firmware.
142 | const char *firmware_hex_path;
143 |
144 | /// This is at address FirmwareConfigAdr in the FX2.
145 | struct FirwareConfig
146 | {
147 | uchar FC_DIR; // [0] 0x12 or 0x21
148 | uchar FC_IFCONFIG; // [1]
149 | uchar FC_EPCFG; // [2]
150 | uchar FC_EPFIFOCFG; // [3]
151 | uchar FC_CPUCS; // [4]
152 | }__attribute__((__packed__)) fc;
153 |
154 | private:
155 | /// Do not use.
156 | FX2Pipe(const FX2Pipe &);
157 | /// Do not use.
158 | void operator=(const FX2Pipe &);
159 | public:
160 | FX2Pipe();
161 | ~FX2Pipe();
162 |
163 | /// Actually run the IO code...
164 | int run();
165 | };
166 |
167 | #endif /* _INCLUDE_USBIO_FX2PIPE_H_ */
168 |
--------------------------------------------------------------------------------
/src/musl_tsearch.c:
--------------------------------------------------------------------------------
1 | /* musl as a whole is licensed under the following standard MIT license: */
2 |
3 | /* ---------------------------------------------------------------------- */
4 | /* Copyright © 2005-2020 Rich Felker, et al. */
5 |
6 | /* Permission is hereby granted, free of charge, to any person obtaining */
7 | /* a copy of this software and associated documentation files (the */
8 | /* "Software"), to deal in the Software without restriction, including */
9 | /* without limitation the rights to use, copy, modify, merge, publish, */
10 | /* distribute, sublicense, and/or sell copies of the Software, and to */
11 | /* permit persons to whom the Software is furnished to do so, subject to */
12 | /* the following conditions: */
13 |
14 | /* The above copyright notice and this permission notice shall be */
15 | /* included in all copies or substantial portions of the Software. */
16 |
17 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
18 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
19 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
20 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
21 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
22 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
23 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
24 | /* ---------------------------------------------------------------------- */
25 |
26 | #include
27 | #include "musl_tsearch.h"
28 |
29 | /* AVL tree height < 1.44*log2(nodes+2)-0.3, MAXH is a safe upper bound. */
30 | #define MAXH (sizeof(void*)*8*3/2)
31 |
32 | struct node {
33 | const void *key;
34 | void *a[2];
35 | int h;
36 | };
37 |
38 | void ttdestroy(void *root, void (*freekey)(void *))
39 | {
40 | struct node *r = root;
41 |
42 | if (r == 0)
43 | return;
44 | ttdestroy(r->a[0], freekey);
45 | ttdestroy(r->a[1], freekey);
46 | if (freekey) freekey((void *)r->key);
47 | free(r);
48 | }
49 |
50 | void *ttfind(const void *key, void *const *rootp,
51 | int(*cmp)(const void *, const void *))
52 | {
53 | if (!rootp)
54 | return 0;
55 |
56 | struct node *n = *rootp;
57 | for (;;) {
58 | if (!n)
59 | break;
60 | int c = cmp(key, n->key);
61 | if (!c)
62 | break;
63 | n = n->a[c>0];
64 | }
65 | return n;
66 | }
67 |
68 | static inline int height(struct node *n) { return n ? n->h : 0; }
69 |
70 | static int rot(void **p, struct node *x, int dir /* deeper side */)
71 | {
72 | struct node *y = x->a[dir];
73 | struct node *z = y->a[!dir];
74 | int hx = x->h;
75 | int hz = height(z);
76 | if (hz > height(y->a[dir])) {
77 | /*
78 | * x
79 | * / \ dir z
80 | * A y / \
81 | * / \ --> x y
82 | * z D /| |\
83 | * / \ A B C D
84 | * B C
85 | */
86 | x->a[dir] = z->a[!dir];
87 | y->a[!dir] = z->a[dir];
88 | z->a[!dir] = x;
89 | z->a[dir] = y;
90 | x->h = hz;
91 | y->h = hz;
92 | z->h = hz+1;
93 | } else {
94 | /*
95 | * x y
96 | * / \ / \
97 | * A y --> x D
98 | * / \ / \
99 | * z D A z
100 | */
101 | x->a[dir] = z;
102 | y->a[!dir] = x;
103 | x->h = hz+1;
104 | y->h = hz+2;
105 | z = y;
106 | }
107 | *p = z;
108 | return z->h - hx;
109 | }
110 |
111 | /* balance *p, return 0 if height is unchanged. */
112 | static int __tsearch_balance(void **p)
113 | {
114 | struct node *n = *p;
115 | int h0 = height(n->a[0]);
116 | int h1 = height(n->a[1]);
117 | if (h0 - h1 + 1u < 3u) {
118 | int old = n->h;
119 | n->h = h0h - old;
121 | }
122 | return rot(p, n, h0key);
140 | if (!c)
141 | return n;
142 | a[i++] = &n->a[c>0];
143 | n = n->a[c>0];
144 | }
145 | r = malloc(sizeof *r);
146 | if (!r)
147 | return 0;
148 | r->key = key;
149 | r->a[0] = r->a[1] = 0;
150 | r->h = 1;
151 | /* insert new node, rebalance ancestors. */
152 | *a[--i] = r;
153 | while (i && __tsearch_balance(a[--i]));
154 | return r;
155 | }
156 |
157 | void *ttdelete(const void *restrict key, void **restrict rootp,
158 | int(*cmp)(const void *, const void *))
159 | {
160 | if (!rootp)
161 | return 0;
162 |
163 | void **a[MAXH+1];
164 | struct node *n = *rootp;
165 | struct node *parent;
166 | struct node *child;
167 | int i=0;
168 | /* *a[0] is an arbitrary non-null pointer that is returned when
169 | the root node is deleted. */
170 | a[i++] = rootp;
171 | a[i++] = rootp;
172 | for (;;) {
173 | if (!n)
174 | return 0;
175 | int c = cmp(key, n->key);
176 | if (!c)
177 | break;
178 | a[i++] = &n->a[c>0];
179 | n = n->a[c>0];
180 | }
181 | parent = *a[i-2];
182 | if (n->a[0]) {
183 | /* free the preceding node instead of the deleted one. */
184 | struct node *deleted = n;
185 | a[i++] = &n->a[0];
186 | n = n->a[0];
187 | while (n->a[1]) {
188 | a[i++] = &n->a[1];
189 | n = n->a[1];
190 | }
191 | deleted->key = n->key;
192 | child = n->a[0];
193 | } else {
194 | child = n->a[1];
195 | }
196 | /* freed node has at most one child, move it up and rebalance. */
197 | free(n);
198 | *a[--i] = child;
199 | while (--i && __tsearch_balance(a[i]));
200 | return parent;
201 | }
202 |
203 | static void walk(const struct node *r, void (*action)(const void *, TVISIT, int), int d)
204 | {
205 | if (!r)
206 | return;
207 | if (r->h == 1)
208 | action(r, tleaf, d);
209 | else {
210 | action(r, tpreorder, d);
211 | walk(r->a[0], action, d+1);
212 | action(r, tpostorder, d);
213 | walk(r->a[1], action, d+1);
214 | action(r, tendorder, d);
215 | }
216 | }
217 |
218 | void ttwalk(const void *root, void (*action)(const void *, TVISIT, int))
219 | {
220 | walk(root, action, 0);
221 | }
222 |
--------------------------------------------------------------------------------
/src/profiler.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "profiler.h"
5 | #include "symbols.h"
6 |
7 | extern profiler_t *profiler_instr_create(char *arg);
8 | extern profiler_t *profiler_block_create(char *arg);
9 | extern profiler_t *profiler_call_create(char *arg);
10 |
11 | #define MAX_PROFILERS 10
12 |
13 | static profiler_t *active_list[MAX_PROFILERS] = { NULL } ;
14 |
15 | void profiler_parse_opt(int key, char *arg, struct argp_state *state) {
16 | static int active_count = 0;
17 | switch (key) {
18 | case 'p':
19 | if (arg && strlen(arg) > 0) {
20 | char *type = strtok(arg, ",");
21 | char *rest = strtok(NULL, "");
22 | // Act as a factory method for profilers
23 | profiler_t *instance = NULL;
24 | if (strcasecmp(type, "instr") == 0) {
25 | instance = profiler_instr_create(rest);
26 | } else if (strcasecmp(type, "block") == 0) {
27 | instance = profiler_block_create(rest);
28 | } else if (strcasecmp(type, "call") == 0) {
29 | instance = profiler_call_create(rest);
30 | }
31 | if (instance) {
32 | active_list[active_count++] = instance;
33 | active_list[active_count] = NULL;
34 | } else {
35 | argp_error(state, "unknown profiler type %s", type);
36 | }
37 | }
38 | break;
39 | }
40 | }
41 |
42 | void profiler_init(cpu_emulator_t *em) {
43 | profiler_t **pp = active_list;
44 | while (*pp) {
45 | (*pp)->init(*pp, em);
46 | pp++;
47 | }
48 | }
49 |
50 | void profiler_profile_instruction(int pc, int opcode, int op1, int op2, int num_cycles) {
51 | profiler_t **pp = active_list;
52 | while (*pp) {
53 | (*pp)->profile_instruction(*pp, pc, opcode, op1, op2, num_cycles);
54 | pp++;
55 | }
56 | }
57 |
58 | void profiler_done() {
59 | profiler_t **pp = active_list;
60 | while (*pp) {
61 | printf("==============================================================================\n");
62 | printf("Profiler: %s; Args: %s\n", (*pp)->name, (*pp)->arg);
63 | printf("==============================================================================\n");
64 | (*pp)->done(*pp);
65 | pp++;
66 | }
67 | }
68 |
69 | void profiler_output_helper(address_t *profile_counts, int show_bars, int show_other, cpu_emulator_t *em) {
70 | address_t *ptr;
71 |
72 | uint32_t max_cycles = 0;
73 | uint64_t total_cycles = 0;
74 | uint64_t page_crossing_cycles = 0;
75 | uint64_t total_instr = 0;
76 | double total_percent = 0.0;
77 | double bar_scale;
78 |
79 | char buffer[256];
80 |
81 | ptr = profile_counts;
82 |
83 | for (int addr = 0; addr <= OTHER_CONTEXT; addr++) {
84 | if (ptr->cycles > max_cycles) {
85 | max_cycles = ptr->cycles;
86 | }
87 | total_cycles += ptr->cycles;
88 | total_instr += ptr->instructions;
89 | if (em && ptr->cycles) {
90 | int opcode = em->read_memory(addr);
91 | // TODO: BRA (0x80) should only be counted on the C02/C816
92 | if (((opcode & 0x1f) == 0x10) || (opcode == 0x80)) {
93 | int offset = em->read_memory(addr + 1);
94 | // Is the target in a different page?
95 | if (((addr + 2) & 0xff00) != ((addr + 2 + (int8_t)offset) & 0xff00)) {
96 | // A small amount of maths gives us the cycles that could be saved if the branch were in the same page
97 | page_crossing_cycles += (ptr->cycles - 2 * ptr->instructions) / 2;
98 | }
99 | }
100 | }
101 | ptr++;
102 | }
103 |
104 | bar_scale = (double) BAR_WIDTH / (double) max_cycles;
105 |
106 | ptr = profile_counts;
107 | for (int addr = 0; addr <= OTHER_CONTEXT; addr++) {
108 | char *name = symbol_lookup(addr);
109 | if (name) {
110 | printf("\n%s\n", name);
111 | }
112 | if (ptr->cycles) {
113 | double percent = 100.0 * (ptr->cycles) / (double) total_cycles;
114 | total_percent += percent;
115 | if (addr == OTHER_CONTEXT) {
116 | printf("****");
117 | } else {
118 | printf("%04x", addr);
119 | if (em) {
120 | instruction_t instruction;
121 | instruction.pc = addr;
122 | instruction.opcode = em->read_memory(addr);
123 | instruction.op1 = em->read_memory(addr + 1);
124 | instruction.op2 = em->read_memory(addr + 2);
125 | int n = em->disassemble(buffer, &instruction);
126 | printf(" %s", buffer);
127 | for (int i = n; i < 12; i++) {
128 | putchar(' ');
129 | }
130 | }
131 | }
132 | printf(" : %8d cycles (%10.6f%%) %8d ins (%4.2f cpi)", ptr->cycles, percent, ptr->instructions, (double) ptr->cycles / (double) ptr->instructions);
133 | if (show_other) {
134 | printf(" %8d calls", ptr->calls);
135 | printf(" (");
136 | printf(ptr->flags & FLAG_JSR ? "J" : " ");
137 | printf(ptr->flags & FLAG_JMP ? "j" : " ");
138 | printf(ptr->flags & FLAG_BB_TAKEN ? "B" : " ");
139 | printf(ptr->flags & FLAG_FB_TAKEN ? "F" : " ");
140 | printf(ptr->flags & FLAG_BB_NOT_TAKEN ? "b" : " ");
141 | printf(ptr->flags & FLAG_FB_NOT_TAKEN ? "f" : " ");
142 | printf(ptr->flags & FLAG_JMP_IND ? "i" : " ");
143 | printf(ptr->flags & FLAG_JMP_INDX ? "x" : " ");
144 | printf(")");
145 | }
146 | if (show_bars) {
147 | printf(" ");
148 | for (int i = 0; i < (int) (bar_scale * ptr->cycles); i++) {
149 | printf("*");
150 | }
151 | }
152 | printf("\n");
153 | }
154 | ptr++;
155 | }
156 | printf(" : %8" PRIu64 " cycles (%10.6f%%) %8" PRIu64 " ins (%4.2f cpi)\n", total_cycles, total_percent, total_instr, (double) total_cycles / (double) total_instr);
157 | printf(" : %8" PRIu64 " branch page crossing cycles (%10.6f%%)\n",page_crossing_cycles, (double) page_crossing_cycles * 100.0 / (double) total_cycles);
158 | }
159 |
--------------------------------------------------------------------------------
/src/profiler_call.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "musl_tsearch.h"
7 | #include "profiler.h"
8 | #include "symbols.h"
9 |
10 | #define DEBUG 0
11 |
12 | // Constants for call based profiling
13 | // (6502 stack can only hold 128 addresses)
14 | #define CALL_STACK_SIZE 128
15 |
16 | static cpu_emulator_t *my_em;
17 |
18 | typedef struct call_stack {
19 | int stack[CALL_STACK_SIZE];
20 | struct call_stack *parent;
21 | int index;
22 | uint64_t call_count;
23 | uint64_t cycle_count;
24 | } call_stack_t;
25 |
26 |
27 | typedef struct {
28 | profiler_t profiler;
29 | void *root;
30 | call_stack_t *current;
31 | int profile_enabled;
32 | cpu_emulator_t *em;
33 | } profiler_call_t;
34 |
35 |
36 | // One copy of these means profile_done is not thread safe, not concerned about this
37 | static uint64_t total_cycles;
38 | static double total_percent;
39 |
40 | static int compare_nodes(const void *av, const void *bv) {
41 | const call_stack_t *a = (call_stack_t *) av;
42 | const call_stack_t *b = (call_stack_t *) bv;
43 | int ret = 0;
44 | for (int i = 0; i < a->index && i < b->index; i++) {
45 | if (a->stack[i] < b->stack[i]) {
46 | ret = -1;
47 | break;
48 | } else if (a->stack[i] > b->stack[i]) {
49 | ret = 1;
50 | break;
51 | }
52 | }
53 | if (ret == 0) {
54 | if (a->index < b->index) {
55 | ret = -1;
56 | } else if (a->index > b->index) {
57 | ret = 1;
58 | }
59 | }
60 | return ret;
61 | }
62 |
63 | static void p_init(void *ptr, cpu_emulator_t *em) {
64 | profiler_call_t *instance = (profiler_call_t *)ptr;
65 | call_stack_t *root_context = (call_stack_t *)malloc(sizeof(call_stack_t));
66 | root_context->index = 0;
67 | root_context->cycle_count = 0;
68 | root_context->call_count = 0;
69 | root_context->parent = NULL;
70 | if (instance->root) {
71 | ttdestroy(instance->root, free);
72 | }
73 | instance->root = NULL;
74 | instance->current = *(call_stack_t **)ttsearch(root_context, &instance->root, compare_nodes);
75 | instance->profile_enabled = 1;
76 | instance->em = em;
77 | my_em = em;
78 | }
79 |
80 | static void p_profile_instruction(void *ptr, int pc, int opcode, int op1, int op2, int num_cycles) {
81 | profiler_call_t *instance = (profiler_call_t *)ptr;
82 | if (!instance->profile_enabled) {
83 | return;
84 | }
85 | instance->current->cycle_count += num_cycles;
86 | if (opcode == 0x20) {
87 | // TODO: What about interrupts
88 | if (instance->current->index < CALL_STACK_SIZE) {
89 | int addr = (op2 << 8 | op1) & 0xffff;
90 | #if DEBUG
91 | printf("*** pushing %04x to %d\n", addr, current->index);
92 | #endif
93 | // Create a new child node, in case it's not already in the tree
94 | call_stack_t *child = (call_stack_t *) malloc(sizeof(call_stack_t));
95 | memcpy((void*) child, (void *)(instance->current), sizeof(call_stack_t));
96 | child->stack[child->index] = addr;
97 | child->index++;
98 | child->parent = instance->current;
99 | child->cycle_count = 0;
100 | child->call_count = 0;
101 | instance->current = *(call_stack_t **)ttsearch(child, &instance->root, compare_nodes);
102 | // If the child already existed, then free the just created node
103 | if (instance->current != child) {
104 | free(child);
105 | }
106 | instance->current->call_count++;
107 | } else {
108 | printf("warning: call stack overflowed, disabling further profiling\n");
109 | for (int i = 0; i < instance->current->index; i++) {
110 | printf("warning: stack[%3d] = %04x\n", i, instance->current->stack[i]);
111 | }
112 | instance->profile_enabled = 0;
113 | }
114 | }
115 | if (opcode == 0x60) {
116 | if (instance->current->parent) {
117 | #if DEBUG
118 | printf("*** popping %d\n", current->index);
119 | #endif
120 | instance->current = instance->current->parent;
121 | } else {
122 | printf("warning: call stack underflowed, re-initialize call graph\n");
123 | p_init(ptr, instance->em);
124 | }
125 | }
126 | }
127 |
128 | static void print_node(const call_stack_t *node) {
129 | int first = 1;
130 | double percent = 100.0 * (double) node->cycle_count / (double) total_cycles;
131 | total_percent += percent;
132 | printf("%8" PRIu64 " cycles (%10.6f%%) %8" PRIu64 " calls: ", node->cycle_count, percent, node->call_count);
133 | for (int i = 0; i < node->index; i++) {
134 | if (!first) {
135 | printf("->");
136 | }
137 | first = 0;
138 | char *name=symbol_lookup(node->stack[i]);
139 | if (name) {
140 | if (name[0] == '.') name++;
141 | printf("%s", name);
142 | } else {
143 | printf("%04X", node->stack[i]);
144 | }
145 | }
146 | printf("\n");
147 | }
148 |
149 | static void count_call_walker(const void *nodep, const TVISIT which, const int depth) {
150 | if (which == tpostorder || which == tleaf) {
151 | total_cycles += (*(call_stack_t **)nodep)->cycle_count;
152 | }
153 | }
154 |
155 | static void dump_call_walker(const void *nodep, const TVISIT which, const int depth) {
156 | if (which == tpostorder || which == tleaf) {
157 | print_node(*(call_stack_t **)nodep);
158 | }
159 | }
160 |
161 | static void p_done(void *ptr) {
162 | profiler_call_t *instance = (profiler_call_t *)ptr;
163 | total_cycles = 0;
164 | ttwalk(instance->root, count_call_walker);
165 | total_percent = 0;
166 | ttwalk(instance->root, dump_call_walker);
167 | printf("%8" PRIu64 " cycles (%10.6f%%)\n", total_cycles, total_percent);
168 | }
169 |
170 | void *profiler_call_create(char *arg) {
171 | profiler_call_t *instance = (profiler_call_t *)calloc(1, sizeof(profiler_call_t));
172 |
173 | instance->profiler.name = "call";
174 | instance->profiler.arg = arg ? strdup(arg) : "";
175 | instance->profiler.init = p_init;
176 | instance->profiler.profile_instruction = p_profile_instruction;
177 | instance->profiler.done = p_done;
178 |
179 | return instance;
180 | }
181 |
--------------------------------------------------------------------------------
/test/run_tests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | DECODE=../decode6502
4 |
5 | EXTENDED_TEST_FILE_BASE="https://github.com/hoglet67/6502Decoder/releases/download/test_data"
6 | EXTENDED_TEST_FILE_NAME="extended_tests.zip"
7 |
8 | MAXDIFFSIZE=500000000
9 |
10 | common_options="--phi2= --mem=FFF"
11 |
12 | machine_names=(
13 | beeb
14 | master
15 | elk
16 | beebr65c02
17 | )
18 |
19 | declare -A machine_options
20 |
21 | machine_options[master]="--machine=master"
22 | machine_options[beeb]="--machine=beeb"
23 | machine_options[elk]="--machine=elk"
24 | machine_options[beebr65c02]="--machine=beeb --cpu=r65c02"
25 |
26 | data_names=(
27 | reset
28 | )
29 |
30 | extended_data_names=(
31 | dormann_d6502
32 | dormann_d65c00
33 | dormann_d65c01
34 | dormann_d65c10
35 | dormann_d65c11
36 | clark_bcd_full
37 | )
38 |
39 | declare -A data_options
40 |
41 | data_options[reset]="-h -s"
42 | data_options[dormann_d6502]="--quiet"
43 | data_options[dormann_d65c00]="--quiet"
44 | data_options[dormann_d65c01]="--quiet"
45 | data_options[dormann_d65c10]="--quiet"
46 | data_options[dormann_d65c11]="--quiet"
47 | data_options[clark_bcd_full]="--quiet"
48 |
49 | test_names=(
50 | sync
51 | sync_nornw
52 | sync_norst
53 | sync_nordy
54 | sync_nornw_norst
55 | sync_nornw_nordy
56 | sync_norst_nordy
57 | sync_nornw_norst_nordy
58 | nosync
59 | nosync_nornw
60 | nosync_norst
61 | nosync_nordy
62 | nosync_nornw_norst
63 | nosync_nornw_nordy
64 | nosync_norst_nordy
65 | nosync_nornw_norst_nordy
66 | )
67 |
68 | declare -A test_options
69 |
70 | test_options[sync]=""
71 | test_options[sync_nornw]="--rnw="
72 | test_options[sync_norst]="--rst="
73 | test_options[sync_nordy]="--rdy="
74 | test_options[sync_nornw_norst]="--rnw= --rst="
75 | test_options[sync_nornw_nordy]="--rnw= --rdy="
76 | test_options[sync_norst_nordy]="--rst= --rdy="
77 | test_options[sync_nornw_norst_nordy]="--rnw= --rst= --rdy="
78 | test_options[nosync]="--sync="
79 | test_options[nosync_nornw]="--sync= --rnw="
80 | test_options[nosync_norst]="--sync= --rst="
81 | test_options[nosync_nordy]="--sync= --rdy="
82 | test_options[nosync_nornw_norst]="--sync= --rnw= --rst="
83 | test_options[nosync_nornw_nordy]="--sync= --rnw= --rdy="
84 | test_options[nosync_norst_nordy]="--sync= --rst= --rdy="
85 | test_options[nosync_nornw_norst_nordy]="--sync= --rnw= --rst= --rdy="
86 |
87 | # Use the sync based decoder as the deference
88 | ref=${test_names[0]}
89 |
90 | # Parse the command line options
91 | POSITIONAL=()
92 | EXTENDED=0
93 | while [[ $# -gt 0 ]]
94 | do
95 | key="$1"
96 |
97 | case $key in
98 | -e|--extended)
99 | EXTENDED=1
100 | shift # past argument
101 | ;;
102 | *) # unknown option
103 | POSITIONAL+=("$1") # save it in an array for later
104 | shift # past argument
105 | ;;
106 | esac
107 | done
108 |
109 | if [ "${EXTENDED}" == "1" ]; then
110 | echo "Running extended tests:"
111 | wget -nv -N ${EXTENDED_TEST_FILE_BASE}/${EXTENDED_TEST_FILE_NAME}
112 | unzip -o ${EXTENDED_TEST_FILE_NAME}
113 | data_names+=(${extended_data_names[@]})
114 | else
115 | echo "Running basic tests:"
116 | fi
117 |
118 | if [[ `uname` = Darwin ]]; then
119 | STATARGS=-f%z
120 | else
121 | STATARGS=-c%s
122 | fi
123 |
124 | for data in "${data_names[@]}"
125 | do
126 | for machine in "${machine_names[@]}"
127 | do
128 | if [ -f ${machine}/${data}.bin.gz ]; then
129 | # First, generate all the data for the test cases
130 | echo "=============================================================================="
131 | echo "Running ${machine} ${data} tests"
132 | echo "=============================================================================="
133 | echo
134 | gunzip < ${machine}/${data}.bin.gz > ${machine}/${data}.tmp
135 | refmd5=""
136 | reflog=""
137 | for test in "${test_names[@]}"
138 | do
139 | log=${machine}/trace_${data}_${test}.log
140 | runcmd="${DECODE} ${common_options} ${data_options[${data}]} ${machine_options[${machine}]} ${test_options[${test}]} ${machine}/${data}.tmp > ${log}"
141 | echo "Test: ${test}"
142 | echo " % ${runcmd}"
143 | eval $runcmd
144 | # If the file contains a RESET marker, prune any lines before this
145 | if grep -q RESET ${log}; then
146 | sed -n '/RESET/,$p' < ${log} > tmp.log
147 | mv tmp.log ${log}
148 | fi
149 | fail_count=`grep fail ${log} | wc -l`
150 | md5=`md5sum ${log} | cut -c1-8`
151 | size=$(stat ${STATARGS} "${log}")
152 | echo " Trace MD5: ${md5}; Prediction fail count: ${fail_count}"
153 | # Log some context around each failure (limit to 100 failures)
154 | # Compare md5 of results with ref, rather than using diff, as diff can blow up
155 | if [ "${test}" == "${ref}" ]; then
156 | refmd5=${md5}
157 | reflog=${machine}/trace_${data}_${ref}.log
158 | echo " this is the reference trace"
159 | if [ "${fail_count}" != "0" ]; then
160 | echo
161 | grep -10 -m 100 fail ${log}
162 | echo
163 | fi
164 | elif [ "${md5}" == "${refmd5}" ]; then
165 | echo -e " \e[32mPASS\e[97m: test trace matches reference trace"
166 | else
167 | if [ "${fail_count}" != "0" ]; then
168 | echo
169 | grep -10 -m 100 fail ${log}
170 | echo
171 | fi
172 | difcmd="diff ${reflog} ${log}"
173 | if (( size < MAXDIFFSIZE )); then
174 | diff_count=`${difcmd} | wc -l`
175 | echo -e " \e[31mFAIL\e[97m: test trace doesn't match reference trace; Diff Count: " ${diff_count}
176 | else
177 | echo -e " \e[31mFAIL\e[97m: test trace doesn't match reference trace; file too large too diff"
178 | fi
179 | echo " % ${difcmd}"
180 | fi
181 | echo
182 | done
183 | fi
184 | done
185 | done
186 |
--------------------------------------------------------------------------------
/fx2pipe/usb_io/usbdevice_fs.h:
--------------------------------------------------------------------------------
1 | /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
2 | /*****************************************************************************/
3 |
4 | /*
5 | * usbdevice_fs.h -- USB device file system.
6 | *
7 | * Copyright (C) 2000
8 | * Thomas Sailer (sailer@ife.ee.ethz.ch)
9 | *
10 | * This program is free software; you can redistribute it and/or modify
11 | * it under the terms of the GNU General Public License as published by
12 | * the Free Software Foundation; either version 2 of the License, or
13 | * (at your option) any later version.
14 | *
15 | * This program is distributed in the hope that it will be useful,
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | * GNU General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with this program; if not, write to the Free Software
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 | *
24 | * History:
25 | * 0.1 04.01.2000 Created
26 | */
27 |
28 | /*****************************************************************************/
29 |
30 | #ifndef _LINUX_USBDEVICE_FS_H
31 | #define _LINUX_USBDEVICE_FS_H
32 |
33 | #include
34 | #include
35 |
36 | /* --------------------------------------------------------------------- */
37 |
38 | /* usbdevfs ioctl codes */
39 |
40 | struct usbdevfs_ctrltransfer {
41 | __u8 bRequestType;
42 | __u8 bRequest;
43 | __u16 wValue;
44 | __u16 wIndex;
45 | __u16 wLength;
46 | __u32 timeout; /* in milliseconds */
47 | void *data;
48 | };
49 |
50 | struct usbdevfs_bulktransfer {
51 | unsigned int ep;
52 | unsigned int len;
53 | unsigned int timeout; /* in milliseconds */
54 | void *data;
55 | };
56 |
57 | struct usbdevfs_setinterface {
58 | unsigned int interface;
59 | unsigned int altsetting;
60 | };
61 |
62 | struct usbdevfs_disconnectsignal {
63 | unsigned int signr;
64 | void *context;
65 | };
66 |
67 | #define USBDEVFS_MAXDRIVERNAME 255
68 |
69 | struct usbdevfs_getdriver {
70 | unsigned int interface;
71 | char driver[USBDEVFS_MAXDRIVERNAME + 1];
72 | };
73 |
74 | struct usbdevfs_connectinfo {
75 | unsigned int devnum;
76 | unsigned char slow;
77 | };
78 |
79 | struct usbdevfs_conninfo_ex {
80 | __u32 size; /* Size of the structure from the kernel's */
81 | /* point of view. Can be used by userspace */
82 | /* to determine how much data can be */
83 | /* used/trusted. */
84 | __u32 busnum; /* USB bus number, as enumerated by the */
85 | /* kernel, the device is connected to. */
86 | __u32 devnum; /* Device address on the bus. */
87 | __u32 speed; /* USB_SPEED_* constants from ch9.h */
88 | __u8 num_ports; /* Number of ports the device is connected */
89 | /* to on the way to the root hub. It may */
90 | /* be bigger than size of 'ports' array so */
91 | /* userspace can detect overflows. */
92 | __u8 ports[7]; /* List of ports on the way from the root */
93 | /* hub to the device. Current limit in */
94 | /* USB specification is 7 tiers (root hub, */
95 | /* 5 intermediate hubs, device), which */
96 | /* gives at most 6 port entries. */
97 | };
98 |
99 | #define USBDEVFS_URB_SHORT_NOT_OK 0x01
100 | #define USBDEVFS_URB_ISO_ASAP 0x02
101 | #define USBDEVFS_URB_BULK_CONTINUATION 0x04
102 | #define USBDEVFS_URB_NO_FSBR 0x20 /* Not used */
103 | #define USBDEVFS_URB_ZERO_PACKET 0x40
104 | #define USBDEVFS_URB_NO_INTERRUPT 0x80
105 |
106 | #define USBDEVFS_URB_TYPE_ISO 0
107 | #define USBDEVFS_URB_TYPE_INTERRUPT 1
108 | #define USBDEVFS_URB_TYPE_CONTROL 2
109 | #define USBDEVFS_URB_TYPE_BULK 3
110 |
111 | struct usbdevfs_iso_packet_desc {
112 | unsigned int length;
113 | unsigned int actual_length;
114 | unsigned int status;
115 | };
116 |
117 | struct usbdevfs_urb {
118 | unsigned char type;
119 | unsigned char endpoint;
120 | int status;
121 | unsigned int flags;
122 | void *buffer;
123 | int buffer_length;
124 | int actual_length;
125 | int start_frame;
126 | union {
127 | int number_of_packets; /* Only used for isoc urbs */
128 | unsigned int stream_id; /* Only used with bulk streams */
129 | };
130 | int error_count;
131 | unsigned int signr; /* signal to be sent on completion,
132 | or 0 if none should be sent. */
133 | void *usercontext;
134 | struct usbdevfs_iso_packet_desc iso_frame_desc[0];
135 | };
136 |
137 | /* ioctls for talking directly to drivers */
138 | struct usbdevfs_ioctl {
139 | int ifno; /* interface 0..N ; negative numbers reserved */
140 | int ioctl_code; /* MUST encode size + direction of data so the
141 | * macros in give correct values */
142 | void *data; /* param buffer (in, or out) */
143 | };
144 |
145 | /* You can do most things with hubs just through control messages,
146 | * except find out what device connects to what port. */
147 | struct usbdevfs_hub_portinfo {
148 | char nports; /* number of downstream ports in this hub */
149 | char port [127]; /* e.g. port 3 connects to device 27 */
150 | };
151 |
152 | /* System and bus capability flags */
153 | #define USBDEVFS_CAP_ZERO_PACKET 0x01
154 | #define USBDEVFS_CAP_BULK_CONTINUATION 0x02
155 | #define USBDEVFS_CAP_NO_PACKET_SIZE_LIM 0x04
156 | #define USBDEVFS_CAP_BULK_SCATTER_GATHER 0x08
157 | #define USBDEVFS_CAP_REAP_AFTER_DISCONNECT 0x10
158 | #define USBDEVFS_CAP_MMAP 0x20
159 | #define USBDEVFS_CAP_DROP_PRIVILEGES 0x40
160 | #define USBDEVFS_CAP_CONNINFO_EX 0x80
161 | #define USBDEVFS_CAP_SUSPEND 0x100
162 |
163 | /* USBDEVFS_DISCONNECT_CLAIM flags & struct */
164 |
165 | /* disconnect-and-claim if the driver matches the driver field */
166 | #define USBDEVFS_DISCONNECT_CLAIM_IF_DRIVER 0x01
167 | /* disconnect-and-claim except when the driver matches the driver field */
168 | #define USBDEVFS_DISCONNECT_CLAIM_EXCEPT_DRIVER 0x02
169 |
170 | struct usbdevfs_disconnect_claim {
171 | unsigned int interface;
172 | unsigned int flags;
173 | char driver[USBDEVFS_MAXDRIVERNAME + 1];
174 | };
175 |
176 | struct usbdevfs_streams {
177 | unsigned int num_streams; /* Not used by USBDEVFS_FREE_STREAMS */
178 | unsigned int num_eps;
179 | unsigned char eps[];
180 | };
181 |
182 | /*
183 | * USB_SPEED_* values returned by USBDEVFS_GET_SPEED are defined in
184 | * linux/usb/ch9.h
185 | */
186 |
187 | #define USBDEVFS_CONTROL _IOWR('U', 0, struct usbdevfs_ctrltransfer)
188 | #define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32)
189 | #define USBDEVFS_BULK _IOWR('U', 2, struct usbdevfs_bulktransfer)
190 | #define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32)
191 | #define USBDEVFS_RESETEP _IOR('U', 3, unsigned int)
192 | #define USBDEVFS_SETINTERFACE _IOR('U', 4, struct usbdevfs_setinterface)
193 | #define USBDEVFS_SETCONFIGURATION _IOR('U', 5, unsigned int)
194 | #define USBDEVFS_GETDRIVER _IOW('U', 8, struct usbdevfs_getdriver)
195 | #define USBDEVFS_SUBMITURB _IOR('U', 10, struct usbdevfs_urb)
196 | #define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32)
197 | #define USBDEVFS_DISCARDURB _IO('U', 11)
198 | #define USBDEVFS_REAPURB _IOW('U', 12, void *)
199 | #define USBDEVFS_REAPURB32 _IOW('U', 12, __u32)
200 | #define USBDEVFS_REAPURBNDELAY _IOW('U', 13, void *)
201 | #define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, __u32)
202 | #define USBDEVFS_DISCSIGNAL _IOR('U', 14, struct usbdevfs_disconnectsignal)
203 | #define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32)
204 | #define USBDEVFS_CLAIMINTERFACE _IOR('U', 15, unsigned int)
205 | #define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int)
206 | #define USBDEVFS_CONNECTINFO _IOW('U', 17, struct usbdevfs_connectinfo)
207 | #define USBDEVFS_IOCTL _IOWR('U', 18, struct usbdevfs_ioctl)
208 | #define USBDEVFS_IOCTL32 _IOWR('U', 18, struct usbdevfs_ioctl32)
209 | #define USBDEVFS_HUB_PORTINFO _IOR('U', 19, struct usbdevfs_hub_portinfo)
210 | #define USBDEVFS_RESET _IO('U', 20)
211 | #define USBDEVFS_CLEAR_HALT _IOR('U', 21, unsigned int)
212 | #define USBDEVFS_DISCONNECT _IO('U', 22)
213 | #define USBDEVFS_CONNECT _IO('U', 23)
214 | #define USBDEVFS_CLAIM_PORT _IOR('U', 24, unsigned int)
215 | #define USBDEVFS_RELEASE_PORT _IOR('U', 25, unsigned int)
216 | #define USBDEVFS_GET_CAPABILITIES _IOR('U', 26, __u32)
217 | #define USBDEVFS_DISCONNECT_CLAIM _IOR('U', 27, struct usbdevfs_disconnect_claim)
218 | #define USBDEVFS_ALLOC_STREAMS _IOR('U', 28, struct usbdevfs_streams)
219 | #define USBDEVFS_FREE_STREAMS _IOR('U', 29, struct usbdevfs_streams)
220 | #define USBDEVFS_DROP_PRIVILEGES _IOW('U', 30, __u32)
221 | #define USBDEVFS_GET_SPEED _IO('U', 31)
222 | /*
223 | * Returns struct usbdevfs_conninfo_ex; length is variable to allow
224 | * extending size of the data returned.
225 | */
226 | #define USBDEVFS_CONNINFO_EX(len) _IOC(_IOC_READ, 'U', 32, len)
227 | #define USBDEVFS_FORBID_SUSPEND _IO('U', 33)
228 | #define USBDEVFS_ALLOW_SUSPEND _IO('U', 34)
229 | #define USBDEVFS_WAIT_FOR_RESUME _IO('U', 35)
230 |
231 | #endif /* _LINUX_USBDEVICE_FS_H */
232 |
--------------------------------------------------------------------------------
/fx2pipe/firmware/fx2pipe.c:
--------------------------------------------------------------------------------
1 | /*
2 | * firmware/fx2pipe.c
3 | *
4 | * FX2 pipe IO firmware.
5 | *
6 | * Copyright (c) 2006--2009 by Wolfgang Wieser ] wwieser (a) gmx <*> de [
7 | *
8 | * This file may be distributed and/or modified under the terms of the
9 | * GNU General Public License version 2 as published by the Free Software
10 | * Foundation. (See COPYING.GPL for details.)
11 | *
12 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14 | *
15 | */
16 |
17 | // Compile with sdcc!
18 |
19 | // Uncomment this to enable debug output at 9600 baud on PA0
20 | // #define SERIAL_DEBUG
21 |
22 | #define BAUD 9600
23 |
24 | #define ALLOCATE_EXTERN
25 | #include
26 |
27 | typedef unsigned char uint8;
28 | typedef unsigned int uint16; // int is 16 bit.
29 |
30 | // TRM states: (p.15-115)
31 | //
32 | // The minimum delay length is a function of the IFCLK and CLKOUT
33 | // (CPU Clock) frequencies, and is determined by the equation:
34 | //
35 | // MinNumberOfCPUCycles = ceil( 1.5 * ( ifclk_period / clkout_period + 1) );
36 | //
37 | // The required delay length is smallest when the CPU is running at its
38 | // slowest speed (12 MHz, 83.2ns/cycle) and IFCLK is running at its fastest
39 | // speed (48 MHz, 20.8 ns/cycle) --> 2 cycles.
40 | //
41 | // The longest delay is required when the CPU is running at its fastest
42 | // speed (48MHz, 20.8 ns/cycle) and IFCLK is running much slower
43 | // (e.g., 5.2 MHz, 192 ns/cycle) --> 16 cycles
44 | //
45 | // The most-typical EZ-USB configuration, IFCLK and CLKOUT both running at
46 | // 48 MHz, requires a minimum delay of 3 cycles.
47 | //
48 | // Hmm, but experimental results seem to contradict the above calculation.
49 | // E.g. with a 48MHz clock, 17 NOPs require more than 7MHz to work sometimes
50 | // and 10MHz to work reliably while we'd expect 5.2MHz to be more than
51 | // enough... (Wolfgang)
52 | #define NOP __asm nop __endasm
53 | #define SYNCDELAY \
54 | NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; \
55 | NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; \
56 | NOP
57 |
58 |
59 | #ifdef SERIAL_DEBUG
60 |
61 | #define BAUD_TICKS (4000000/BAUD)
62 |
63 | static void debug_putc(int c)
64 | {
65 | int i;
66 | int senddata = (c << 1) | 0x200;
67 | OEA |= 0x01;
68 | for (i = 0; i < 10; i++) {
69 | TH1 = (65536 - BAUD_TICKS) / 256;
70 | TL1 = (65536 - BAUD_TICKS) % 256;
71 | IOA = (IOA & 0xFE) | (senddata & 1);
72 | senddata >>= 1;
73 | while (TH1 > 128);
74 | }
75 | }
76 |
77 | static void debug_puthex1(int i)
78 | {
79 | i &= 0xf;
80 | debug_putc(i + (i < 10 ? '0' : 'A' - 10));
81 | }
82 |
83 |
84 | static void debug_puthex2(int i)
85 | {
86 | debug_puthex1(i >> 4);
87 | debug_puthex1(i);
88 | }
89 |
90 | static void debug_puts(char *s)
91 | {
92 | while (*s) {
93 | debug_putc(*s);
94 | s++;
95 | }
96 | }
97 |
98 | static void debug_init() {
99 | CPUCS = 0x12; // Clock the 8051 at 48MHz
100 | TMOD = 0x10; // Run T1 at 48MHz / 12 = 4MHz
101 | TCON |= 0x40; // Start T1
102 | }
103 |
104 | #else
105 |
106 | #define debug_put(...)
107 | #define debug_puts(...)
108 | #define debug_init(...)
109 |
110 | #endif
111 |
112 | // Initialize the FX2 in 16bit sync fifo mode.
113 | static void Initialize(void)
114 | {
115 | // Config is put at address 0x3000 by fx2pipe program at firmware
116 | // download.
117 | // NOTE: This is for FX2LP; the FX2 has fewer SRAM and so we cannot use
118 | // 0x3000 but rather 0x1000 or so.
119 | // Now we use 0x1000 to support both devices.
120 | __xdata char *cfg_data=(__xdata char*)0x1003;
121 | // First cfg_data must be 21 or 12 to be considered valid.
122 | char cfg_data_ok = (cfg_data[0]==0x12U || cfg_data[0]==0x21U);
123 |
124 | SYNCDELAY;
125 |
126 | // CPUCS: 0 0 PORTCSTB CLKSPD1 CLKSPD0 CLKINV CLKOE 8051RES 00000010
127 | // PORTCSTB=1: reads/writes to PORTC generate RD# and WR# strobes
128 | // CLKSPD1,0 = 8051 clock speed: 00=12, 01=24, 10=48, 11=X
129 | // CLKINV=1 to invert CLKOUT signal
130 | // CLKOE=1 to drive CLKOUT pin
131 | // 8051RES=1 to reset 8051
132 | // Want: 0001 0010 <-- 48MHz, output enabled.
133 | // 0000 0010 <-- 12MHz, output enabled.
134 | CPUCS = cfg_data_ok ? cfg_data[4] : 0x12; // 0x12
135 | SYNCDELAY;
136 |
137 | // a = 10; b = 11; c = 12; d = 13; e = 14; f = 15
138 |
139 | // Okay, the most important config register: (default: 10000000)
140 | // bit7: 1 = internal clocking of IFCLK; 0 = external
141 | // bit6: 0 = 30MHz; 1 = 48MHz
142 | // bit5: 1 = enable output to IFCLK
143 | // bit4: 1 = invert IFCLK
144 | // bit3: 1 = async mode; 0 = sync
145 | // bit2: 1 = drive GSTATE[0:2] on PORTE[0:2] (irrelevant for 56-pin package)
146 | // bit1,0: 00: ports; 01: reserved; 10: GPIF; 11: Slave FIFO (ext master),
147 | //IFCONFIG = 0x43; // 0100 0011 = 0x43 externally clocked sync mode
148 | //IFCONFIG = 0xcb; // 1100 1011 = 0xcb internally clocked async mode
149 | //IFCONFIG = 0xc3; // 1100 0011 = 0xc3 internally clocked sync mode (perf test)
150 | IFCONFIG = cfg_data_ok ? cfg_data[1] : 0xc3;
151 | SYNCDELAY;
152 |
153 | // Based on TRM and SSRP.
154 | REVCTL = 0x03; // See TRM...
155 | SYNCDELAY;
156 |
157 | // PORTACFG: FLAGD SLCS(*) 0 0 0 0 INT1 INT0
158 | PORTACFG = 0x00;
159 | SYNCDELAY; // maybe not needed
160 |
161 | // All default polarities: except SLWR,...
162 | if (cfg_data[1] & 0x10) {
163 | // SLWR active low, use the rising edge as the sample clock
164 | FIFOPINPOLAR=0x00;
165 | // this is selected if -ifclk=i is specified
166 | } else {
167 | // SLWR active high, use the falling edge as the sample clock
168 | // this is the default, and works forthe 6502
169 | FIFOPINPOLAR=0x04;
170 | }
171 | SYNCDELAY;
172 |
173 | // Reset...
174 | EP6CFG=0x00U; SYNCDELAY;
175 | EP2CFG=0x00U; SYNCDELAY;
176 | EP6FIFOCFG=0x00U; SYNCDELAY;
177 | EP2FIFOCFG=0x00U; SYNCDELAY;
178 | OEA=0x00U;
179 |
180 | if(cfg_data[0]==0x12U) /* INPUT: USB->HOST */
181 | {
182 | // Configure EP6 (IN):
183 | // EP6CFG:
184 | // 1 bit7: VALID: 1 = enable
185 | // 1 bit6: DIR: 1 = in; 0 = out
186 | // 10 bit5,4: TYPE1,0: 00 = ivalid; 01=isochronous; 10=bulk; 11=interrupt
187 | // 0 bit3: SIZE: 0 = 512 bytes; 1 = 1024 bytes
188 | // 0 bit2: 0
189 | // 10 bit1,0: BUF1,0: 00=quad; 01=; 10=double; 11=triple
190 | // Want: 1110 0010 (enabled, IN, BULK, double-buffered 512 bytes)
191 | EP6CFG = cfg_data[2]; // bulk: 0xe2 double-buffered; 0xe3 triple-; 0xe0 quad
192 | SYNCDELAY;
193 |
194 | // To be sure, clear and reset all FIFOs although
195 | // this is probably not strictly required.
196 | FIFORESET = 0x80; SYNCDELAY; // NAK all requests from host.
197 | FIFORESET = 0x02; SYNCDELAY; // Reset individual EP (2,4,6,8)
198 | FIFORESET = 0x04; SYNCDELAY;
199 | FIFORESET = 0x06; SYNCDELAY;
200 | FIFORESET = 0x08; SYNCDELAY;
201 | FIFORESET = 0x00; SYNCDELAY; // Resume normal operation.
202 |
203 | // EP6FIFOCFG:
204 | // bit7: 0
205 | // bit6: INFM6 See TRM 15-29 (p.351): Signal line one clock earlier.
206 | // bit5: OEP6
207 | // bit4: AUTOOUT 1 = enable
208 | // bit3: AUTOIN 1 = enable
209 | // bit2: ZEROLENIN 1 = enable (?)
210 | // bit1: 0
211 | // bit0: WORDWIDE 1 = 16bit (default)
212 | // Want: 0000 1101 -> 0x0d
213 | EP6FIFOCFG = cfg_data[3]; /*0x0d //&0xfe*/;
214 | SYNCDELAY;
215 |
216 | // This determines how much data is accumulated in the FIFOs before a
217 | // USB packet is committed. Use 512 bytes.
218 | // Not sure if we need the sync delays (WW).
219 | EP6AUTOINLENH = 0x02; // MSB
220 | SYNCDELAY;
221 | EP6AUTOINLENL = 0x00; // LSB
222 | SYNCDELAY;
223 |
224 | // SPECIAL VOODOO: Set the IO pins on port A:
225 | // 7, PKTEND, FIFOADR1, FIFOADR0, 3, SLOE, 1, 0
226 | // Z 1 1 0 Z 1 Z Z
227 | //OEA=0x74U; // 0111 0100
228 | //IOA=0x64U; // 0110 0100
229 | }
230 | else if(cfg_data[0]==0x21U) /* OUTPUT: HOST->USB */
231 | {
232 | // Configure EP2 (OUT):
233 | // EP2CFG:
234 | // 1 bit7: VALID: 1 = enable
235 | // 0 bit6: DIR: 1 = in; 0 = out
236 | // 10 bit5,4: TYPE1,0: 00 = ivalid; 01=isochronous; 10=bulk; 11=interrupt
237 | // 0 bit3: SIZE: 0 = 512 bytes; 1 = 1024 bytes
238 | // 0 bit2: 0
239 | // 10 bit1,0: BUF1,0: 00=quad; 01=; 10=double; 11=triple
240 | // Want: 1010 0010 (enabled, OUT, BULK, double-buffered 512 bytes)
241 | EP2CFG = cfg_data[2]; // bulk: 0xa2 double-buffered; 0xa3 triple-; 0xa0 quad
242 | SYNCDELAY;
243 |
244 | // To be sure, clear and reset all FIFOs although
245 | // this is probably not strictly required.
246 | FIFORESET = 0x80; SYNCDELAY; // NAK all requests from host.
247 | FIFORESET = 0x82; SYNCDELAY; // Reset individual EP (2,4,6,8)
248 | FIFORESET = 0x84; SYNCDELAY;
249 | FIFORESET = 0x86; SYNCDELAY;
250 | FIFORESET = 0x88; SYNCDELAY;
251 | FIFORESET = 0x00; SYNCDELAY; // Resume normal operation.
252 |
253 | // Arm ouput endpoint TRM p.348 ("prime the pump"):
254 | OUTPKTEND = 0x82; SYNCDELAY;
255 | OUTPKTEND = 0x82; SYNCDELAY;
256 | switch(cfg_data[2]&0x03U)
257 | { // Fall-through switch!
258 | case 0x00U: OUTPKTEND = 0x82; SYNCDELAY; // Quad-buffered.
259 | case 0x03U: OUTPKTEND = 0x82; SYNCDELAY; // Triple-buffered.
260 | }
261 |
262 | // EP2FIFOCFG:
263 | // bit7: 0
264 | // bit6: INFM2 See TRM 15-29 (p.351): Signal line one clock earlier.
265 | // bit5: OEP2
266 | // bit4: AUTOOUT 1 = enable
267 | // bit3: AUTOIN 1 = enable
268 | // bit2: ZEROLENIN 1 = enable (?)
269 | // bit1: 0
270 | // bit0: WORDWIDE 1 = 16bit (default)
271 | // Want: 0001 0001 -> 0x15
272 | EP2FIFOCFG = cfg_data[3]; /*0x11;*/
273 | SYNCDELAY;
274 |
275 | // SPECIAL VOODOO: Set the IO pins on port A:
276 | // 7, PKTEND, FIFOADR1, FIFOADR0, 3, SLOE, 1, 0
277 | // Z 1 0 0 Z 0 Z Z
278 | //OEA=0x74U; // 0111 0100
279 | //IOA=0x50U; // 0100 0000
280 | }
281 | }
282 |
283 |
284 | void main()
285 | {
286 |
287 | #ifdef SERIAL_DEBUG
288 | int i;
289 | __xdata char *cfg_data=(__xdata char*)0x1003;
290 | debug_init();
291 | debug_puts("Booted cfg=");
292 | for (i = 0; i< 5; i++) {
293 | debug_puthex2(cfg_data[i]);
294 | debug_putc(' ');
295 | }
296 | debug_puts("\r\n");
297 | #endif
298 | Initialize();
299 | #ifdef SERIAL_DEBUG
300 | debug_puts("Looping\r\n");
301 | #endif
302 | for(;;) {
303 | // Do nothing.
304 | #ifdef SERIAL_DEBUG
305 | debug_puts("ep2468stat=");
306 | debug_puthex2(EP2468STAT);
307 | debug_puts("\r\n");
308 | #endif
309 |
310 | }
311 | }
312 |
--------------------------------------------------------------------------------
/fx2pipe/fx2pipe/main.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * usb_io/main.cc
3 | *
4 | * FX2 pipe program main routine.
5 | *
6 | * Copyright (c) 2006--2009 by Wolfgang Wieser ] wwieser (a) gmx <*> de [
7 | *
8 | * This file may be distributed and/or modified under the terms of the
9 | * GNU General Public License version 2 as published by the Free Software
10 | * Foundation. (See COPYING.GPL for details.)
11 | *
12 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14 | *
15 | */
16 |
17 | #include "../oconfig.h"
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | #include "../fx2pipe/fx2pipe.h"
29 |
30 | #include
31 |
32 |
33 | volatile int caught_sigint=0;
34 |
35 | static void SigIntHandler(int)
36 | {
37 | ++caught_sigint;
38 | if(caught_sigint>5)
39 | {
40 | const char *msg=
41 | "fx2pipe: caught too many SIGINT; exiting ungracefully\n";
42 | write(2,msg,sizeof(msg));
43 | _exit(1);
44 | }
45 | }
46 |
47 |
48 | static void PrintHelp()
49 | {
50 | fprintf(stderr,
51 | "USAGE: fx2pipe [option|assignment]...\n"
52 | "Long options:\n"
53 | " --help print this\n"
54 | " --version print version information\n"
55 | "Short options: (Can be compined into single option)\n"
56 | " -i run in IN direction, i.e. read data from USB EP6 (default)\n"
57 | " -o run in OUT direction, i.e. write data to USB EP2\n"
58 | " -0 no stdio; send NULs / throw away read data (for timing)\n"
59 | " -8,-w use 8bit / 16bit (default) wide fifo bus on FX2 side\n"
60 | " -2,-3,-4 use double, triple or quad (default) buffered FX2 fifo\n"
61 | " -s,-a run in sync (default) / async slave fifo mode\n"
62 | " -O,-I shortcut for -o0, -i0, respectively\n"
63 | "Assignments: (Leading '-' can be left away)\n"
64 | " -d=NN use n-th (unconfigured) FX2 device (start with NN=0, default)\n"
65 | " -d=VID:PID[:N] use N-th device with specified VID and PID\n"
66 | // " -d=BUS/DEV use BUS/DEV (e.g. 003/047) as device\n"
67 | " -n=NNN stop after NNN bytes; suffix k,M,G for mult. with 2^10,20,30\n"
68 | " -bs=NNN set IO block size to NNN, max 16384 (default 16384)\n"
69 | " -ps=NN set pipeline size (number of URBs; default 16)\n"
70 | " -sched=P[,N] set scheduling policy P (\"fifo\" or \"rr\") and prio N\n"
71 | " -fw=PATH use specified firmware IHX file instead of built-in one\n"
72 | " omit path to not download any firmware (just reset device)\n"
73 | " -ifclk=[x|30[o]|48[o]][i] specify interface clock:\n"
74 | " x -> external; 30,48 -> internal clock 30/48MHz, suffix 'o'\n"
75 | " to enable output to IFCLK pin, 'i' to invert IFCLK\n"
76 | " -cko=[12|24|48][o|z][i] specify 8051 frequency in MHz (default: 48) and\n"
77 | " CLKOUT pin: output 'o' (default), tristate 'z', invert 'i'\n"
78 | "\n"
79 | "fx2pipe - pipe data in or out of an Cypress FX2 device (CY7C6801x[A])\n"
80 | " Copyright (c) 2006--2011 by Wolfgang Wieser; License: GPL\n");
81 | }
82 |
83 |
84 | int main(int argc,char **arg)
85 | {
86 | FX2Pipe p;
87 |
88 | int errors=0;
89 | int dir_spec=0;
90 | int fifo_width=2; // 1 or 2 (8 or 16 bits)
91 | int fifo_nbuf=4; // 2,3,4 for double, triple, quad buffered
92 | char fifo_mode='s';
93 | char ifclk_invert=0;
94 | char ifclk_speed=48; // 0 -> external; 30,48 -> internal 30/48 MHz
95 | char ifclk_output=0;
96 | char cko_speed=48;
97 | char cko_output=1;
98 | char cko_invert=0;
99 | for(int i=1; i1)
290 | {
291 | fprintf(stderr,"fx2pipe: more than one direction specification "
292 | "(-iIoO).\n");
293 | ++errors;
294 | }
295 |
296 | // FIXME: If fifo_width is 2, force even sizes!
297 | if(p.io_block_size<1 || p.io_block_size>16384)
298 | {
299 | fprintf(stderr,"fx2pipe: IO block size (bs) must be in "
300 | "range 1..16384, bs=%u is invalid\n",p.io_block_size);
301 | ++errors;
302 | }
303 |
304 | // Set up config for firmware:
305 | p.fc.FC_DIR = p.dir<0 ? 0x12U : 0x21U;
306 | p.fc.FC_CPUCS =
307 | ((cko_speed==12 ? 0U : cko_speed==24 ? 1U : 2U)<<3) |
308 | (cko_invert ? 0x04U : 0x00U) |
309 | (cko_output ? 0x02U : 0x00U);
310 | p.fc.FC_IFCONFIG =
311 | (ifclk_speed ? 0x80U : 0x00U) | // Internal (1) / external?
312 | (ifclk_speed==30 ? 0x00U : 0x40U) | // 30 (0) / 48 (1) MHz?
313 | (ifclk_output ? 0x20U : 0x00U) | // Enable (1) output to IFCLK?
314 | (ifclk_invert ? 0x10U : 0x00U) | // Invert (1) IFCLK?
315 | (fifo_mode=='a' ? 0x08U : 0x00U) | // Async (1) or sync (0) FIFO mode?
316 | 0x00U | // bit2 irrelevant for us...
317 | 0x03U; // bits 1,0 = 11 for slave FIFO mode
318 | if(p.dir<0)
319 | {
320 | // INPUT: USB->HOST
321 | p.fc.FC_EPCFG = 0xe0U; // 1110 00BB with BB = 2,3,4times buffered?
322 | p.fc.FC_EPFIFOCFG = 0x0cU; // 0000 110W (W = wordwide)
323 | }
324 | else
325 | {
326 | // OUTPUT: HOST->USB
327 | p.fc.FC_EPCFG = 0xa0U; // 1010 00BB with BB = 2,3,4times buffered?
328 | p.fc.FC_EPFIFOCFG = 0x10U; // 0001 000W (W = wordwide)
329 | }
330 | switch(fifo_nbuf)
331 | {
332 | case 2: p.fc.FC_EPCFG|=0x02U; break;
333 | case 3: p.fc.FC_EPCFG|=0x03U; break;
334 | case 4: break; // Do nothing.
335 | default: assert(0); break;
336 | }
337 | if(fifo_width==2)
338 | { p.fc.FC_EPFIFOCFG|=0x01U; }
339 |
340 | // Dump firmware config values:
341 | fprintf(stderr,"Firmware config: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
342 | (unsigned int)p.fc.FC_DIR, (unsigned int)p.fc.FC_IFCONFIG,
343 | (unsigned int)p.fc.FC_EPCFG, (unsigned int)p.fc.FC_EPFIFOCFG,
344 | (unsigned int)p.fc.FC_CPUCS );
345 |
346 | if(errors)
347 | { return(1); }
348 |
349 | // Install signal handler for SIGINT.
350 | struct sigaction sa;
351 | memset(&sa,0,sizeof(sa));
352 | sa.sa_handler=&SigIntHandler;
353 | sigaction(SIGINT,&sa,NULL);
354 |
355 | int ecode=0;
356 |
357 | ecode=p.run();
358 |
359 | return(ecode);
360 | }
361 |
--------------------------------------------------------------------------------
/fx2pipe/lib/Makefile.in:
--------------------------------------------------------------------------------
1 | # Makefile.in generated by automake 1.10.1 from Makefile.am.
2 | # @configure_input@
3 |
4 | # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
5 | # 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
6 | # This Makefile.in is free software; the Free Software Foundation
7 | # gives unlimited permission to copy and/or distribute it,
8 | # with or without modifications, as long as this notice is preserved.
9 |
10 | # This program is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without
12 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 | # PARTICULAR PURPOSE.
14 |
15 | @SET_MAKE@
16 |
17 | VPATH = @srcdir@
18 | pkgdatadir = $(datadir)/@PACKAGE@
19 | pkglibdir = $(libdir)/@PACKAGE@
20 | pkgincludedir = $(includedir)/@PACKAGE@
21 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
22 | install_sh_DATA = $(install_sh) -c -m 644
23 | install_sh_PROGRAM = $(install_sh) -c
24 | install_sh_SCRIPT = $(install_sh) -c
25 | INSTALL_HEADER = $(INSTALL_DATA)
26 | transform = $(program_transform_name)
27 | NORMAL_INSTALL = :
28 | PRE_INSTALL = :
29 | POST_INSTALL = :
30 | NORMAL_UNINSTALL = :
31 | PRE_UNINSTALL = :
32 | POST_UNINSTALL = :
33 | subdir = lib
34 | DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
35 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
36 | am__aclocal_m4_deps = $(top_srcdir)/configure.ac
37 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
38 | $(ACLOCAL_M4)
39 | mkinstalldirs = $(install_sh) -d
40 | CONFIG_HEADER = $(top_builddir)/config.h
41 | CONFIG_CLEAN_FILES =
42 | LIBRARIES = $(noinst_LIBRARIES)
43 | AR = ar
44 | ARFLAGS = cru
45 | lib_fx2pipe_supp_a_AR = $(AR) $(ARFLAGS)
46 | lib_fx2pipe_supp_a_LIBADD =
47 | am_lib_fx2pipe_supp_a_OBJECTS =
48 | lib_fx2pipe_supp_a_OBJECTS = $(am_lib_fx2pipe_supp_a_OBJECTS)
49 | DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
50 | COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
51 | $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
52 | CCLD = $(CC)
53 | LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
54 | SOURCES = $(lib_fx2pipe_supp_a_SOURCES)
55 | DIST_SOURCES = $(lib_fx2pipe_supp_a_SOURCES)
56 | ETAGS = etags
57 | CTAGS = ctags
58 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
59 | ACLOCAL = @ACLOCAL@
60 | AMTAR = @AMTAR@
61 | AUTOCONF = @AUTOCONF@
62 | AUTOHEADER = @AUTOHEADER@
63 | AUTOMAKE = @AUTOMAKE@
64 | AWK = @AWK@
65 | CC = @CC@
66 | CCDEPMODE = @CCDEPMODE@
67 | CFLAGS = @CFLAGS@
68 | CPP = @CPP@
69 | CPPFLAGS = @CPPFLAGS@
70 | CXX = @CXX@
71 | CXXDEPMODE = @CXXDEPMODE@
72 | CXXFLAGS = @CXXFLAGS@
73 | CYGPATH_W = @CYGPATH_W@
74 | DEFS = @DEFS@
75 | DEPDIR = @DEPDIR@
76 | ECHO_C = @ECHO_C@
77 | ECHO_N = @ECHO_N@
78 | ECHO_T = @ECHO_T@
79 | EGREP = @EGREP@
80 | EXEEXT = @EXEEXT@
81 | GREP = @GREP@
82 | INSTALL = @INSTALL@
83 | INSTALL_DATA = @INSTALL_DATA@
84 | INSTALL_PROGRAM = @INSTALL_PROGRAM@
85 | INSTALL_SCRIPT = @INSTALL_SCRIPT@
86 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
87 | LDFLAGS = @LDFLAGS@
88 | LIBOBJS = @LIBOBJS@
89 | LIBS = @LIBS@
90 | LTLIBOBJS = @LTLIBOBJS@
91 | MAKEINFO = @MAKEINFO@
92 | MKDIR_P = @MKDIR_P@
93 | OBJEXT = @OBJEXT@
94 | PACKAGE = @PACKAGE@
95 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
96 | PACKAGE_NAME = @PACKAGE_NAME@
97 | PACKAGE_STRING = @PACKAGE_STRING@
98 | PACKAGE_TARNAME = @PACKAGE_TARNAME@
99 | PACKAGE_VERSION = @PACKAGE_VERSION@
100 | PATH_SEPARATOR = @PATH_SEPARATOR@
101 | RANLIB = @RANLIB@
102 | SET_MAKE = @SET_MAKE@
103 | SHELL = @SHELL@
104 | STRIP = @STRIP@
105 | VERSION = @VERSION@
106 | abs_builddir = @abs_builddir@
107 | abs_srcdir = @abs_srcdir@
108 | abs_top_builddir = @abs_top_builddir@
109 | abs_top_srcdir = @abs_top_srcdir@
110 | ac_ct_CC = @ac_ct_CC@
111 | ac_ct_CXX = @ac_ct_CXX@
112 | am__include = @am__include@
113 | am__leading_dot = @am__leading_dot@
114 | am__quote = @am__quote@
115 | am__tar = @am__tar@
116 | am__untar = @am__untar@
117 | bindir = @bindir@
118 | build_alias = @build_alias@
119 | builddir = @builddir@
120 | datadir = @datadir@
121 | datarootdir = @datarootdir@
122 | docdir = @docdir@
123 | dvidir = @dvidir@
124 | exec_prefix = @exec_prefix@
125 | host_alias = @host_alias@
126 | htmldir = @htmldir@
127 | includedir = @includedir@
128 | infodir = @infodir@
129 | install_sh = @install_sh@
130 | libdir = @libdir@
131 | libexecdir = @libexecdir@
132 | localedir = @localedir@
133 | localstatedir = @localstatedir@
134 | mandir = @mandir@
135 | mkdir_p = @mkdir_p@
136 | oldincludedir = @oldincludedir@
137 | pdfdir = @pdfdir@
138 | prefix = @prefix@
139 | program_transform_name = @program_transform_name@
140 | psdir = @psdir@
141 | sbindir = @sbindir@
142 | sharedstatedir = @sharedstatedir@
143 | srcdir = @srcdir@
144 | sysconfdir = @sysconfdir@
145 | target_alias = @target_alias@
146 | top_build_prefix = @top_build_prefix@
147 | top_builddir = @top_builddir@
148 | top_srcdir = @top_srcdir@
149 | INCLUDES = -I. -I$(top_srcdir) -I$(top_builddir)
150 | noinst_LIBRARIES = lib_fx2pipe_supp.a
151 | lib_fx2pipe_supp_a_SOURCES = \
152 | linkedlist.h \
153 | linearqueue.h
154 |
155 | all: all-am
156 |
157 | .SUFFIXES:
158 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
159 | @for dep in $?; do \
160 | case '$(am__configure_deps)' in \
161 | *$$dep*) \
162 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
163 | && exit 0; \
164 | exit 1;; \
165 | esac; \
166 | done; \
167 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/Makefile'; \
168 | cd $(top_srcdir) && \
169 | $(AUTOMAKE) --gnu lib/Makefile
170 | .PRECIOUS: Makefile
171 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
172 | @case '$?' in \
173 | *config.status*) \
174 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
175 | *) \
176 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
177 | cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
178 | esac;
179 |
180 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
181 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
182 |
183 | $(top_srcdir)/configure: $(am__configure_deps)
184 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
185 | $(ACLOCAL_M4): $(am__aclocal_m4_deps)
186 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
187 |
188 | clean-noinstLIBRARIES:
189 | -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
190 | lib_fx2pipe_supp.a: $(lib_fx2pipe_supp_a_OBJECTS) $(lib_fx2pipe_supp_a_DEPENDENCIES)
191 | -rm -f lib_fx2pipe_supp.a
192 | $(lib_fx2pipe_supp_a_AR) lib_fx2pipe_supp.a $(lib_fx2pipe_supp_a_OBJECTS) $(lib_fx2pipe_supp_a_LIBADD)
193 | $(RANLIB) lib_fx2pipe_supp.a
194 |
195 | mostlyclean-compile:
196 | -rm -f *.$(OBJEXT)
197 |
198 | distclean-compile:
199 | -rm -f *.tab.c
200 |
201 | ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
202 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
203 | unique=`for i in $$list; do \
204 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
205 | done | \
206 | $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
207 | END { if (nonempty) { for (i in files) print i; }; }'`; \
208 | mkid -fID $$unique
209 | tags: TAGS
210 |
211 | TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
212 | $(TAGS_FILES) $(LISP)
213 | tags=; \
214 | here=`pwd`; \
215 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
216 | unique=`for i in $$list; do \
217 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
218 | done | \
219 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
220 | END { if (nonempty) { for (i in files) print i; }; }'`; \
221 | if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
222 | test -n "$$unique" || unique=$$empty_fix; \
223 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
224 | $$tags $$unique; \
225 | fi
226 | ctags: CTAGS
227 | CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
228 | $(TAGS_FILES) $(LISP)
229 | tags=; \
230 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
231 | unique=`for i in $$list; do \
232 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
233 | done | \
234 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
235 | END { if (nonempty) { for (i in files) print i; }; }'`; \
236 | test -z "$(CTAGS_ARGS)$$tags$$unique" \
237 | || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
238 | $$tags $$unique
239 |
240 | GTAGS:
241 | here=`$(am__cd) $(top_builddir) && pwd` \
242 | && cd $(top_srcdir) \
243 | && gtags -i $(GTAGS_ARGS) $$here
244 |
245 | distclean-tags:
246 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
247 |
248 | distdir: $(DISTFILES)
249 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
250 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
251 | list='$(DISTFILES)'; \
252 | dist_files=`for file in $$list; do echo $$file; done | \
253 | sed -e "s|^$$srcdirstrip/||;t" \
254 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
255 | case $$dist_files in \
256 | */*) $(MKDIR_P) `echo "$$dist_files" | \
257 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
258 | sort -u` ;; \
259 | esac; \
260 | for file in $$dist_files; do \
261 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
262 | if test -d $$d/$$file; then \
263 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
264 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
265 | cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
266 | fi; \
267 | cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
268 | else \
269 | test -f $(distdir)/$$file \
270 | || cp -p $$d/$$file $(distdir)/$$file \
271 | || exit 1; \
272 | fi; \
273 | done
274 | check-am: all-am
275 | check: check-am
276 | all-am: Makefile $(LIBRARIES)
277 | installdirs:
278 | install: install-am
279 | install-exec: install-exec-am
280 | install-data: install-data-am
281 | uninstall: uninstall-am
282 |
283 | install-am: all-am
284 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
285 |
286 | installcheck: installcheck-am
287 | install-strip:
288 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
289 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
290 | `test -z '$(STRIP)' || \
291 | echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
292 | mostlyclean-generic:
293 |
294 | clean-generic:
295 |
296 | distclean-generic:
297 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
298 |
299 | maintainer-clean-generic:
300 | @echo "This command is intended for maintainers to use"
301 | @echo "it deletes files that may require special tools to rebuild."
302 | clean: clean-am
303 |
304 | clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
305 |
306 | distclean: distclean-am
307 | -rm -f Makefile
308 | distclean-am: clean-am distclean-compile distclean-generic \
309 | distclean-tags
310 |
311 | dvi: dvi-am
312 |
313 | dvi-am:
314 |
315 | html: html-am
316 |
317 | info: info-am
318 |
319 | info-am:
320 |
321 | install-data-am:
322 |
323 | install-dvi: install-dvi-am
324 |
325 | install-exec-am:
326 |
327 | install-html: install-html-am
328 |
329 | install-info: install-info-am
330 |
331 | install-man:
332 |
333 | install-pdf: install-pdf-am
334 |
335 | install-ps: install-ps-am
336 |
337 | installcheck-am:
338 |
339 | maintainer-clean: maintainer-clean-am
340 | -rm -f Makefile
341 | maintainer-clean-am: distclean-am maintainer-clean-generic
342 |
343 | mostlyclean: mostlyclean-am
344 |
345 | mostlyclean-am: mostlyclean-compile mostlyclean-generic
346 |
347 | pdf: pdf-am
348 |
349 | pdf-am:
350 |
351 | ps: ps-am
352 |
353 | ps-am:
354 |
355 | uninstall-am:
356 |
357 | .MAKE: install-am install-strip
358 |
359 | .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
360 | clean-noinstLIBRARIES ctags distclean distclean-compile \
361 | distclean-generic distclean-tags distdir dvi dvi-am html \
362 | html-am info info-am install install-am install-data \
363 | install-data-am install-dvi install-dvi-am install-exec \
364 | install-exec-am install-html install-html-am install-info \
365 | install-info-am install-man install-pdf install-pdf-am \
366 | install-ps install-ps-am install-strip installcheck \
367 | installcheck-am installdirs maintainer-clean \
368 | maintainer-clean-generic mostlyclean mostlyclean-compile \
369 | mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
370 | uninstall-am
371 |
372 | # Tell versions [3.59,3.63) of GNU make to not export all variables.
373 | # Otherwise a system limit (for SysV at least) may be exceeded.
374 | .NOEXPORT:
375 |
--------------------------------------------------------------------------------
/fx2pipe/usb_io/wwusb.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * usb_io/wwusb.cc
3 | *
4 | * USB async low-level routines.
5 | *
6 | * Copyright (c) 2006 by Wolfgang Wieser ] wwieser (a) gmx <*> de [
7 | *
8 | * The idea behind this code is inspired from fusb_linux.cc from the GNU
9 | * radio project (Copyright 2003 Free Software Foundation, Inc.) and the
10 | * first version of the code was based on it.
11 | * However, this is a major re-write for the second version.
12 | *
13 | * This file may be distributed and/or modified under the terms of the
14 | * GNU General Public License version 2 as published by the Free Software
15 | * Foundation. (See COPYING.GPL for details.)
16 | *
17 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 | *
20 | */
21 |
22 | #include "wwusb.h"
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | #include
30 |
31 | // Initialize static data:
32 | int WWUSBDevice::URB::urb_serial_counter=1;
33 |
34 | #define DEBUG_ASYNC_IO 0
35 |
36 |
37 | // Totally evil and fragile extraction of file descriptor from
38 | // guts of libusb. They don't install usbi.h, which is what we'd need
39 | // to do this nicely.
40 | //
41 | // FIXME if everything breaks someday in the future, look here...
42 | static inline int fd_from_usb_dev_handle(usb_dev_handle *udh)
43 | {
44 | return( *((int*)udh) );
45 | }
46 |
47 | // This function is from SSRP: Actually, we don't need it any more.
48 | // Danger, big, fragile KLUDGE. The problem is that we want to be
49 | // able to get from a usb_dev_handle back to a usb_device, and the
50 | // right way to do this is buried in a non-installed include file.
51 | static inline struct usb_device *dev_handle_to_dev(usb_dev_handle *udh)
52 | {
53 | struct usb_dev_handle_kludge {
54 | int fd;
55 | struct usb_bus *bus;
56 | struct usb_device *device;
57 | };
58 |
59 | return(((struct usb_dev_handle_kludge *) udh)->device);
60 | }
61 |
62 | //==============================================================================
63 |
64 | struct usb_device *WWUSBDevice::USBFindDevice(int vendor,int product,int nth)
65 | {
66 | // We re-scan now to make sure not to miss devices which were plugged
67 | // in in the meantime...
68 | // FIXME: The only problem is that this may make our udev pointer invalid
69 | // if the corresponding device was unplugged in the mean time (?).
70 | // You may see crashes here...
71 | usb_find_busses();
72 | usb_find_devices();
73 |
74 | for(usb_bus *b=usb_busses; b; b=b->next)
75 | {
76 | for(struct usb_device *d=b->devices; d; d=d->next)
77 | {
78 | if(d->descriptor.idVendor==vendor &&
79 | d->descriptor.idProduct==product )
80 | {
81 | if(!nth--)
82 | { return(d); }
83 | }
84 | }
85 | }
86 |
87 | return(NULL);
88 | }
89 |
90 | struct usb_device *WWUSBDevice::USBFindDevice(const char *bus,const char *dev)
91 | {
92 | // We re-scan now to make sure not to miss devices which were plugged
93 | // in in the meantime...
94 | ::usb_find_busses();
95 | ::usb_find_devices();
96 |
97 | for(usb_bus *b=usb_busses; b; b=b->next)
98 | {
99 | if(strcmp(b->dirname,bus)) continue;
100 | for(struct usb_device *d=b->devices; d; d=d->next)
101 | {
102 | if(strcmp(d->filename,dev)) continue;
103 | return(d);
104 | }
105 | }
106 |
107 | return(NULL);
108 | }
109 |
110 | //==============================================================================
111 |
112 | WWUSBDevice::ErrorCode WWUSBDevice::_ErrorCodeRV(int e)
113 | {
114 | assert(e>=0);
115 | return((ErrorCode)e);
116 | }
117 |
118 |
119 | WWUSBDevice::ErrorCode WWUSBDevice::_DoConnect(struct usb_device *d)
120 | {
121 | if(udev || udh)
122 | { return(ECConnected); }
123 |
124 | udev=d;
125 | udh=::usb_open(udev);
126 | if(!udh)
127 | { udev=NULL; return(_ErrorCodeRV(errno)); }
128 |
129 | assert(dev_handle_to_dev(udh)==udev);
130 |
131 | return(ECSuccess);
132 | }
133 |
134 |
135 | WWUSBDevice::ErrorCode WWUSBDevice::connect(int vendor,int product,int nth)
136 | {
137 | if(udev || udh)
138 | { return(ECConnected); }
139 |
140 | struct usb_device *ud=USBFindDevice(vendor,product,nth);
141 | if(!ud)
142 | { return(ECNoSuchDevice); }
143 |
144 | return(_DoConnect(ud));
145 | }
146 |
147 |
148 | WWUSBDevice::ErrorCode WWUSBDevice::connect(const char *bus,const char *dev)
149 | {
150 | if(udev || udh)
151 | { return(ECConnected); }
152 |
153 | struct usb_device *ud=USBFindDevice(bus,dev);
154 | if(!ud)
155 | { return(ECNoSuchDevice); }
156 |
157 | return(_DoConnect(ud));
158 | }
159 |
160 |
161 | WWUSBDevice::ErrorCode WWUSBDevice::claim(int interface,int alt_interface)
162 | {
163 | if(!udh)
164 | { return(ECNotConnected); }
165 |
166 | if(interface>=0)
167 | {
168 | if(::usb_claim_interface(udh,/*interface=*/interface)<0)
169 | { return(_ErrorCodeRV(errno)); }
170 | }
171 |
172 | if(alt_interface>=0)
173 | {
174 | if(::usb_set_altinterface(udh,/*alt_interface=*/alt_interface)<0)
175 | { return(_ErrorCodeRV(errno)); }
176 | }
177 |
178 | return(ECSuccess);
179 | }
180 |
181 |
182 | void WWUSBDevice::CancelAllPendingURBs(bool also_delete)
183 | {
184 | int cnt=0;
185 | for(URB *_u=pending.last(); _u; cnt++)
186 | {
187 | URB *u=_u;
188 | _u=_u->prev;
189 |
190 | ErrorCode ec=_CancelURB(u);
191 | // We get errno=EINVAL when cancelling an URB which is already
192 | // completed but not yet reaped. Ignore that.
193 | if(ec && ec!=EINVAL)
194 | {
195 | fprintf(stderr,"Failed to cancel URB: ec=%d (%s)\n",
196 | ec,strerror(ec));
197 | // In case we get ENODEV (after a hot disconnect), the
198 | // URB was already killed in kernel space.
199 | if(ec==ENODEV)
200 | {
201 | pending.dequeue(u);
202 | --npending;
203 | DeleteURB(u);
204 | }
205 | }
206 | }
207 |
208 | if(cnt)
209 | { fprintf(stderr,"Cancelled %d pending URBs (npending=%d)%s",
210 | cnt,npending,(also_delete && udh) ? ", reaping..." : "\n"); }
211 |
212 | if(also_delete && udh)
213 | {
214 | // Reap as much as we can.
215 | int nreap=0;
216 | for(;;)
217 | {
218 | ErrorCode ec=ECSuccess;
219 | URB *u=_ReapURB(&ec,/*may_wait=*/0);
220 | if(u)
221 | { ++nreap; continue; }
222 | if(ec==ECNoURBAvail) break;
223 | // In all other cases, we break as well. Most notably
224 | // when we get ECNotConnected...
225 | break;
226 | }
227 |
228 | if(cnt)
229 | { fprintf(stderr," done reaping (%d): npending=%d\n",
230 | nreap,npending); }
231 | }
232 |
233 | if(also_delete)
234 | { assert(npending==0); }
235 | }
236 |
237 |
238 | WWUSBDevice::ErrorCode WWUSBDevice::disconnect()
239 | {
240 | // Cancel everything, free requests, close everything...
241 | CancelAllPendingURBs(/*also_delete=*/1);
242 |
243 | if(udh)
244 | { ::usb_close(udh); udh=NULL; }
245 | udev=NULL;
246 |
247 | return(ECSuccess);
248 | }
249 |
250 |
251 | WWUSBDevice::ErrorCode WWUSBDevice::_SubmitURB(URB *u)
252 | {
253 | #if DEBUG_ASYNC_IO
254 | fprintf(stderr,"S(%d) ",u->urb_serial);
255 | #endif
256 |
257 | usbdevfs_urb *dev_u=u;
258 | u->usercontext=u; // <-- This is just some "magic" for checks...
259 | int rv=ioctl(fd_from_usb_dev_handle(udh),USBDEVFS_SUBMITURB,dev_u);
260 | if(rv<0)
261 | { return(_ErrorCodeRV(errno)); }
262 |
263 | pending.append(u);
264 | ++npending;
265 | //fprintf(stderr,"<<%d>>",npending);
266 |
267 | return(ECSuccess);
268 | }
269 |
270 |
271 | WWUSBDevice::ErrorCode WWUSBDevice::_CancelURB(URB *u)
272 | {
273 | #if DEBUG_ASYNC_IO
274 | fprintf(stderr,"C(%d) ",u->urb_serial);
275 | #endif
276 |
277 | if(u->cancelled==2) return(ECSuccess);
278 |
279 | usbdevfs_urb *dev_u=u;
280 | int rv=ioctl(fd_from_usb_dev_handle(udh),USBDEVFS_DISCARDURB,dev_u);
281 | if(rv<0)
282 | {
283 | u->cancelled=1;
284 | return(_ErrorCodeRV(errno));
285 | }
286 |
287 | u->cancelled=2;
288 | return(ECSuccess);
289 | }
290 |
291 |
292 | WWUSBDevice::URB *WWUSBDevice::_ReapURB(ErrorCode *ec_rv,bool may_wait)
293 | {
294 | int fd=fd_from_usb_dev_handle(udh);
295 | usbdevfs_urb *dev_u=NULL;
296 | int reap_rv = may_wait ?
297 | ioctl(fd,USBDEVFS_REAPURB,&dev_u) :
298 | ioctl(fd,USBDEVFS_REAPURBNDELAY,&dev_u);
299 | int errn=errno;
300 |
301 | if(reap_rv<0)
302 | {
303 | if(errn==EAGAIN)
304 | {
305 | // Currently no URB to reap available.
306 | *ec_rv=ECNoURBAvail;
307 | }
308 | else if(errn==ENODEV)
309 | {
310 | fprintf(stderr,"USB hot disconnect... What'chew doin' dude?\n");
311 | *ec_rv=ECNotConnected;
312 | }
313 | else
314 | {
315 | *ec_rv=_ErrorCodeRV(errn);
316 | fprintf(stderr,"reap_rv=%d, errno=%s\n",reap_rv,strerror(errn));
317 | }
318 | return(NULL);
319 | }
320 |
321 | assert(dev_u);
322 | URB *u=static_cast(dev_u);
323 | assert(u->usercontext==u); // <-- Here's the magic check.
324 |
325 | // If this assert fails, you probably messed around with libusb...
326 | assert(pending.search(u));
327 | pending.dequeue(u);
328 | --npending; assert(npending>=0);
329 |
330 | #if DEBUG_ASYNC_IO
331 | fprintf(stderr,"R(%d) ",u->urb_serial);
332 | #endif
333 |
334 | if(u->status && !(u->status==-ENOENT && u->cancelled==2))
335 | {
336 | fprintf(stderr,"URB (just reaped) status=%d (%s), cancelled=%d\n",
337 | u->status,strerror(u->status),u->cancelled);
338 | }
339 |
340 | *ec_rv=ECSuccess;
341 | return(u);
342 | }
343 |
344 |
345 | WWUSBDevice::ErrorCode WWUSBDevice::_ResetEP(uchar dir_ep)
346 | {
347 | unsigned int ep=dir_ep;
348 | int rv=ioctl(fd_from_usb_dev_handle(udh),USBDEVFS_RESETEP,&ep);
349 | if(rv<0)
350 | {
351 | int errn=errno;
352 | fprintf(stderr,"Reset EP 0x%02x: %s\n",(int)ep,strerror(errn));
353 | _ErrorCodeRV(errn);
354 | }
355 | else { fprintf(stderr,"Reset EP 0x%02x: OK\n",(int)ep); }
356 |
357 | return(ECSuccess);
358 | }
359 |
360 |
361 | WWUSBDevice::ErrorCode WWUSBDevice::ProcessEvents(int max_delay)
362 | {
363 | if(!udh)
364 | { return(ECNotConnected); }
365 |
366 | int fd=fd_from_usb_dev_handle(udh);
367 | //fprintf(stderr,"fd=%d\n",fd);
368 |
369 | // First, see what we can get without waiting.
370 | bool gather_phase=1;
371 |
372 | ErrorCode ec=ECSuccess;
373 | int errn=0;
374 | for(;;)
375 | {
376 | if(!npending)
377 | { return(ECNoURBAvail); }
378 |
379 | //fprintf(stderr,"loop: gather_phase=%d\n",gather_phase);
380 | usbdevfs_urb *dev_u=NULL;
381 | bool may_wait;
382 | if(gather_phase || max_delay==0)
383 | { may_wait=0; }
384 | else if(max_delay>0)
385 | {
386 | struct pollfd pfd[1];
387 | pfd[0].fd=fd;
388 | pfd[0].events=POLLIN|POLLHUP;
389 | pfd[0].revents=0;
390 | int poll_rv=::poll(pfd,1,max_delay);
391 | // FIXME!!! This does not work!!!!!!!!!!!!!!
392 | fprintf(stderr,"fd=%d, poll_rv=%d, revents=0x%x \n",
393 | pfd[0].fd,poll_rv,pfd[0].revents);
394 | if(poll_rv<0)
395 | {
396 | fprintf(stderr,"poll: rv=%d (%s)\n",poll_rv,strerror(errno));
397 | // Actually, this may make the actual delay longer than
398 | // max_delay (e.g. by periodically sending a singal to
399 | // the process) but is not supposed to be a real problem.
400 | continue; // FIXME: This may be dangerous (except for EINTR).
401 | }
402 | else if(poll_rv==0)
403 | {
404 | // Timeout.
405 | ec=ECTimeout;
406 | break;
407 | }
408 | else
409 | { may_wait=0; }
410 | }
411 | else // max_delay<0.
412 | { may_wait=1; }
413 |
414 | URB *u=_ReapURB(&ec,may_wait);
415 | if(!u)
416 | {
417 | if(ec==ECNoURBAvail)
418 | {
419 | // Currently no URB to reap available.
420 | if((max_delay>0 && !gather_phase) ||
421 | (max_delay==0 && gather_phase) )
422 | {
423 | ec=ECTimeout;
424 | break;
425 | }
426 | gather_phase=0;
427 | continue;
428 | }
429 | else if(ec==ECNotConnected)
430 | { return(ECNotConnected); }
431 |
432 | gather_phase=0;
433 | break;
434 | }
435 |
436 | // Tell user.
437 | ErrorCode urv=URBNotify(u);
438 |
439 | // Now free the URB.
440 | DeleteURB(u);
441 |
442 | if(urv)
443 | {
444 | ec = urv==ECUserQuitFatal ? ECUserQuitFatal : ECUserQuit;
445 | break;
446 | }
447 | }
448 |
449 | return(ec);
450 | }
451 |
452 |
453 | WWUSBDevice::ErrorCode WWUSBDevice::URBNotify(URB *)
454 | {
455 | assert(!"Not overridden.");
456 | return(ECSuccess);
457 | }
458 |
459 |
460 | void WWUSBDevice::DeleteURB(URB *u)
461 | {
462 | // Hope that's right...
463 | delete u;
464 | }
465 |
466 |
467 | WWUSBDevice::WWUSBDevice() :
468 | udev(NULL),
469 | udh(NULL),
470 | pending(),
471 | npending(0)
472 | {
473 | // Nothing to do...
474 | }
475 |
476 | WWUSBDevice::~WWUSBDevice()
477 | {
478 | disconnect();
479 | }
480 |
481 | //------------------------------------------------------------------------------
482 |
483 | void WWUSBDevice::URB::_buffer_oops()
484 | {
485 | assert(buffer==NULL);
486 | }
487 |
--------------------------------------------------------------------------------
/fx2pipe/usb_io/wwusb.h:
--------------------------------------------------------------------------------
1 | /*
2 | * usb_io/wwusb.h
3 | *
4 | * USB async low-level routines.
5 | *
6 | * Copyright (c) 2006 by Wolfgang Wieser ] wwieser (a) gmx <*> de [
7 | *
8 | * This file may be distributed and/or modified under the terms of the
9 | * GNU General Public License version 2 as published by the Free Software
10 | * Foundation. (See COPYING.GPL for details.)
11 | *
12 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14 | *
15 | */
16 |
17 | #ifndef _INCLUDE_USBIO_WWUSB_H_
18 | #define _INCLUDE_USBIO_WWUSB_H_ 1
19 |
20 | #include "../oconfig.h"
21 | #include "../lib/linkedlist.h"
22 |
23 | #include
24 | #include
25 |
26 | #include "usbdevice_fs.h" /* usbdevfs_urb */
27 |
28 |
29 | typedef unsigned char uchar;
30 | struct usb_device;
31 |
32 | /*
33 | struct usbdevfs_urb {
34 | unsigned char type;
35 | unsigned char endpoint;
36 | int status;
37 | unsigned int flags;
38 | void __user *buffer;
39 | int buffer_length; // <-- Max: MAX_USBFS_BUFFER_SIZE=16384
40 | int actual_length;
41 | int start_frame;
42 | int number_of_packets;
43 | int error_count;
44 | unsigned int signr;
45 | void *usercontext;
46 | struct usbdevfs_iso_packet_desc iso_frame_desc[0];
47 | };
48 | */
49 |
50 | /**
51 | * \short USB Device representation.
52 | * \author Wolfgang Wieser ] wwieser (a) gmx <*> de [
53 | *
54 | * The WWUSBDevice represents an USB device which can have several endpoints
55 | * and communication in both directions (IN and OUT).
56 | *
57 | * The idea is to derive a class from this one and override some virtual
58 | * functions to actually implement USB communication.
59 | *
60 | * NOTE: You canNOT use libusb routines in order to talk to a device while
61 | * having it opened using WWUSBDevice. Even not if the libusb code is
62 | * talking to a different endpoint of the device. The reason is that
63 | * libusb is likely to reap URBs which were submitted by us and vice
64 | * versa. So, be sure to know what you're doing.
65 | *
66 | * Not thread-safe. Only one thread should to all the USB actions. Otherwise
67 | * a synchronisation layer must be added.
68 | *
69 | * Not "C++-safe", i.e. do not copy or assign; corresponding operators are
70 | * made private by purpose.
71 | */
72 | class WWUSBDevice
73 | {
74 | public:
75 | /// Error code enum.
76 | /// Negative codes are private codes; positive ones are errno values.
77 | enum ErrorCode
78 | {
79 | ECSuccess=0, ///< No error. You can rely on this being 0.
80 | ECConnected=-100, ///< (Already) connected.
81 | ECNotConnected, ///< Not connected to a device.
82 | ECNoSuchDevice, ///< No such USB device.
83 | ECFailure, ///< Unspecified failure.
84 | ECTimeout, ///< Timeout.
85 | ECUserQuit, ///< Event loop left by user request.
86 | ECUserQuitFatal, ///< Fatal version of ECUserQuit.
87 | ECNoURBAvail, ///< Internally used by _ReapURB().
88 | };
89 |
90 | /**
91 | * \short User request block base struct.
92 | *
93 | * URB handling is somewhat ciritcal since we want little overhead
94 | * and hence need to be careful with buffer allocation to avoid
95 | * spurious copying.
96 | *
97 | * So, it works as follows: URBs are allocated via operator new
98 | * and deleted via operator delete. URBs are always allocated from
99 | * user code and then get an apropriate buffer attached. Deallocation
100 | * from within WWUSBDevice is done via WWUSBDevice::DeleteURB() which
101 | * can be overridden to provide URB caching, see below. Note that
102 | * kernel copies the URB data buffer of OUT URBs upon submission so
103 | * buffer re-use is possible. The URB destructor must be able to
104 | * correctly deallocate an attached buffer so that the URB
105 | * cancellation code does not introducing a mem leak when deleting
106 | * a pending URB.
107 | *
108 | * Note that it is recommended to use URB caching to avoid
109 | * (de)allocation overhead. For that, implement custom operators
110 | * for new and delete: Operator new dequeues the memory chunk from
111 | * a list and operator delete will put it back (after the destructor
112 | * has been called). To make sure that the correct operators are
113 | * called, WWUSBDevice uses WWUSBDevice::DeleteURB() for URB deletion
114 | * which should be overridden with a "delete" statement first applying
115 | * the apropriate type cast.
116 | */
117 | struct URB : LinkedListBase, usbdevfs_urb
118 | {
119 | /// 0 -> not cancelled; 1 -> cancellation failed; 2 -> cancelled.
120 | int cancelled;
121 |
122 | /// For debugging: serial number.
123 | int urb_serial;
124 | static int urb_serial_counter;
125 |
126 | /// See destructor.
127 | void _buffer_oops();
128 |
129 | /**
130 | * \short URB constructor without buffer assignment.
131 | *
132 | * dir_ep is direction and endpoint (bit 7 = 0x80 set for IN).
133 | * Construcor will NUL out all the struct first.
134 | *
135 | * In order to allocate a new URB, use operator new or use
136 | * the URB cache (urbcache.h) which is most easily implemented
137 | * by overriding operators new and delete with URB cache's
138 | * get() and put() functions.
139 | */
140 | inline URB(uchar dir_ep,uchar _type=USBDEVFS_URB_TYPE_BULK) :
141 | LinkedListBase()
142 | {
143 | usbdevfs_urb *u=this; memset(u,0,sizeof(usbdevfs_urb));
144 | endpoint=dir_ep; type=_type; cancelled=0;
145 | urb_serial=urb_serial_counter++;
146 | }
147 | /// URB destructor of derived class MUST also free attached buffer.
148 | virtual inline ~URB()
149 | { if(buffer) _buffer_oops(); }
150 |
151 | // Get direction: -1 -> IN; +1 -> OUT.
152 | inline int dir() const
153 | { return((endpoint & 0x80) ? -1 : +1); }
154 | // Get endpoint.
155 | inline int ep() const
156 | { return(endpoint & 0x7f); }
157 | };
158 |
159 | /// Find n-th (nth) device with specified vendor and product ID.
160 | static struct usb_device *USBFindDevice(
161 | int vendor,int product,int nth=0);
162 | /// Find device with specified vendor and device number.
163 | static struct usb_device *USBFindDevice(
164 | const char *bus,const char *dev);
165 |
166 | protected:
167 | /// USB device descriptor from libusb.
168 | struct usb_device *udev;
169 | /// USB device handle from libusb.
170 | struct usb_dev_handle *udh;
171 |
172 | /**
173 | * \short Notification of URB completion.
174 | *
175 | * This is called when an URB got processed and was just reaped.
176 | *
177 | * The URB will be deleted (using DeleteURB()) after returning
178 | * from the call to URBNotify() (so you need to detach the URB
179 | * buffer in URBNotify() if you still need it afterwards to prevent
180 | * it from being free'd in DeleteURB()).
181 | *
182 | * The return value should normally be 0; use ECUserQuit or
183 | * ECUserQuitFatal to exit the event loop.
184 | */
185 | virtual ErrorCode URBNotify(URB *u);
186 |
187 | /// Delete an URB. Never uses delete directly; see URB for details.
188 | /// Default implementation will use operator delete directly.
189 | virtual void DeleteURB(URB *u);
190 |
191 | /**
192 | * \short Submit an URB.
193 | *
194 | * Call this to have an URB queued in the kernel.
195 | *
196 | * May be called from within URBNotify() but NOT with the
197 | * "original" URB (passed to URBNotify()).
198 | */
199 | ErrorCode SubmitURB(URB *u)
200 | { return(_SubmitURB(u)); }
201 | /**
202 | * \short Cancel a submitted URB.
203 | *
204 | * Used to get rid of an URB which may not yet be processed.
205 | *
206 | * May be called from within URBNotify() but NOT with the
207 | * "original" URB (passed to URBNotify()).
208 | *
209 | * NOTE: A canceled URB will still be reaped. So don't delete them
210 | * unless you close the device afterwards anyways.
211 | */
212 | ErrorCode CancelURB(URB *u)
213 | { return(_CancelURB(u)); }
214 |
215 | /**
216 | * \short Cancel all pending URBs.
217 | *
218 | * May be called from within URBNotify().
219 | *
220 | * If also_delete is set, the URBs are also reaped and deleted.
221 | * See CancelURB().
222 | */
223 | void CancelAllPendingURBs(bool also_delete=0);
224 |
225 | /**
226 | * \short Reap and URB.
227 | *
228 | * Will reap one URB (wait for it if may_wait it set, otherwise
229 | * return immediately) and remove it from the pending list.
230 | * Magic check is performed and errors are reported.
231 | *
232 | * Returns an URB or NULL.
233 | * If NULL, see *ec_rv for details; this may be an errno value or
234 | * ECNoURBAvail if currently no URB available (and may_wait was set
235 | * to 0), ECNotConnected if disconnected.
236 | */
237 | URB *_ReapURB(ErrorCode *ec_rv,bool may_wait);
238 |
239 | /// Reset endpoint (if needed).
240 | ErrorCode _ResetEP(uchar ep);
241 |
242 | protected:
243 | /// List of pending (i.e submitted but not yet completed) requests.
244 | LinkedList pending;
245 | /// Number of pending URBs.
246 | int npending;
247 |
248 | private:
249 | /// Internal function for error code "conversion".
250 | ErrorCode _ErrorCodeRV(int errno_val);
251 |
252 | /// Connect to the passed USB device.
253 | ErrorCode _DoConnect(struct usb_device *d);
254 |
255 | /// Submit URB and append it to pending on success. Usual return value.
256 | ErrorCode _SubmitURB(URB *u);
257 | /// Cancel the URB. This will NOT remove it from the pending list
258 | /// since cancelled URBs can still be reaped.
259 | ErrorCode _CancelURB(URB *u);
260 |
261 | private:
262 | /// Do not use.
263 | void operator=(const WWUSBDevice &);
264 | /// Do not use.
265 | WWUSBDevice(const WWUSBDevice &);
266 | public:
267 | /// Constructor creates a non-set-up device. Use connect().
268 | WWUSBDevice();
269 | /// Destructor. Will also disconnect.
270 | virtual ~WWUSBDevice();
271 |
272 | /// Get number of pending (not yet reaped) URBs.
273 | inline int NPending() const
274 | { return(npending); }
275 |
276 | /**
277 | * \short Connect to a (physical) USB device attached to the USB.
278 | *
279 | * If already connected, use disconnect() before.
280 | *
281 | * There are 2 versions available which differ only in the way
282 | * the device to connect is chosen, e.g. if the output of "lsusb"
283 | * is the following:
284 | * \code
285 | * Bus 006 Device 002: ID 04b4:8613 Cypress CY7C68013 EZ-USB...
286 | * \endcode
287 | * then you can use vendor=0x04b4, product=0x8613 or you can use
288 | * bus="006", dev="002". The latter has the advantage that if
289 | * two identical devices are plugged into the box, they can be
290 | * uniquely addressed while the former version will choose the
291 | * one listed first (nth=0) or second (nth=1), etc.
292 | *
293 | * Return codes:
294 | * ECSuccess\n
295 | * ECConnected (already connected to some device; disconnect() first)\n
296 | * ECNoSuchDevice (specified device is not present)\n
297 | */
298 | /// \{
299 | ErrorCode connect(int vendor,int product,int nth=0);
300 | ErrorCode connect(const char *bus,const char *dev);
301 | /// \}
302 |
303 | /**
304 | * \short Claim interface.
305 | *
306 | * Call after connect() to claim the specified interface (if>=0) and
307 | * use the alternate interface alt_interface (if >=0).
308 | */
309 | ErrorCode claim(int interface,int alt_interface);
310 |
311 | /**
312 | * \short Disconnect from device.
313 | *
314 | * This will also cancel all URBs and free them.
315 | *
316 | * Will return ECSuccess if not connected so it's safe to call
317 | * more often than needed.
318 | */
319 | ErrorCode disconnect();
320 |
321 | /**
322 | * \short Main (event) loop.
323 | *
324 | * Call this to have URBs reaped (URBNotify()).
325 | *
326 | * The loop will generally process as many URBs as possible.
327 | * Exiting the event loop can be achieved by returning 1 in
328 | * URBNotify().
329 | * If you set max_delay>=0, the function will also return as soon
330 | * as an URB reap request will block for more than max_delay msec.
331 | * If max_delay<0, the function may block infinitely.
332 | *
333 | * NOTE: max_delay is the max delay between URBs, NOT the max.
334 | * total delay spent in the function.
335 | *
336 | * Return value: \n
337 | * ECUserQuit: URBNotify() returned 1. \n
338 | * ECTimeout: max_delay timeout. \n
339 | * ECNotConnected: if disconnected in action \n
340 | * ECNoURBAvail: no more pending URBs \n
341 | * other errno codes
342 | */
343 | ErrorCode ProcessEvents(int max_delay);
344 | };
345 |
346 | #endif /* _INCLUDE_USBIO_WWUSB_H_ */
347 |
--------------------------------------------------------------------------------
/fx2pipe/missing:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 | # Common stub for a few missing GNU programs while installing.
3 |
4 | scriptversion=2009-04-28.21; # UTC
5 |
6 | # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
7 | # 2008, 2009 Free Software Foundation, Inc.
8 | # Originally by Fran,cois Pinard , 1996.
9 |
10 | # This program is free software; you can redistribute it and/or modify
11 | # it under the terms of the GNU General Public License as published by
12 | # the Free Software Foundation; either version 2, or (at your option)
13 | # any later version.
14 |
15 | # This program is distributed in the hope that it will be useful,
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | # GNU General Public License for more details.
19 |
20 | # You should have received a copy of the GNU General Public License
21 | # along with this program. If not, see .
22 |
23 | # As a special exception to the GNU General Public License, if you
24 | # distribute this file as part of a program that contains a
25 | # configuration script generated by Autoconf, you may include it under
26 | # the same distribution terms that you use for the rest of that program.
27 |
28 | if test $# -eq 0; then
29 | echo 1>&2 "Try \`$0 --help' for more information"
30 | exit 1
31 | fi
32 |
33 | run=:
34 | sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
35 | sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
36 |
37 | # In the cases where this matters, `missing' is being run in the
38 | # srcdir already.
39 | if test -f configure.ac; then
40 | configure_ac=configure.ac
41 | else
42 | configure_ac=configure.in
43 | fi
44 |
45 | msg="missing on your system"
46 |
47 | case $1 in
48 | --run)
49 | # Try to run requested program, and just exit if it succeeds.
50 | run=
51 | shift
52 | "$@" && exit 0
53 | # Exit code 63 means version mismatch. This often happens
54 | # when the user try to use an ancient version of a tool on
55 | # a file that requires a minimum version. In this case we
56 | # we should proceed has if the program had been absent, or
57 | # if --run hadn't been passed.
58 | if test $? = 63; then
59 | run=:
60 | msg="probably too old"
61 | fi
62 | ;;
63 |
64 | -h|--h|--he|--hel|--help)
65 | echo "\
66 | $0 [OPTION]... PROGRAM [ARGUMENT]...
67 |
68 | Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
69 | error status if there is no known handling for PROGRAM.
70 |
71 | Options:
72 | -h, --help display this help and exit
73 | -v, --version output version information and exit
74 | --run try to run the given command, and emulate it if it fails
75 |
76 | Supported PROGRAM values:
77 | aclocal touch file \`aclocal.m4'
78 | autoconf touch file \`configure'
79 | autoheader touch file \`config.h.in'
80 | autom4te touch the output file, or create a stub one
81 | automake touch all \`Makefile.in' files
82 | bison create \`y.tab.[ch]', if possible, from existing .[ch]
83 | flex create \`lex.yy.c', if possible, from existing .c
84 | help2man touch the output file
85 | lex create \`lex.yy.c', if possible, from existing .c
86 | makeinfo touch the output file
87 | tar try tar, gnutar, gtar, then tar without non-portable flags
88 | yacc create \`y.tab.[ch]', if possible, from existing .[ch]
89 |
90 | Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
91 | \`g' are ignored when checking the name.
92 |
93 | Send bug reports to ."
94 | exit $?
95 | ;;
96 |
97 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
98 | echo "missing $scriptversion (GNU Automake)"
99 | exit $?
100 | ;;
101 |
102 | -*)
103 | echo 1>&2 "$0: Unknown \`$1' option"
104 | echo 1>&2 "Try \`$0 --help' for more information"
105 | exit 1
106 | ;;
107 |
108 | esac
109 |
110 | # normalize program name to check for.
111 | program=`echo "$1" | sed '
112 | s/^gnu-//; t
113 | s/^gnu//; t
114 | s/^g//; t'`
115 |
116 | # Now exit if we have it, but it failed. Also exit now if we
117 | # don't have it and --version was passed (most likely to detect
118 | # the program). This is about non-GNU programs, so use $1 not
119 | # $program.
120 | case $1 in
121 | lex*|yacc*)
122 | # Not GNU programs, they don't have --version.
123 | ;;
124 |
125 | tar*)
126 | if test -n "$run"; then
127 | echo 1>&2 "ERROR: \`tar' requires --run"
128 | exit 1
129 | elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
130 | exit 1
131 | fi
132 | ;;
133 |
134 | *)
135 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
136 | # We have it, but it failed.
137 | exit 1
138 | elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
139 | # Could not run --version or --help. This is probably someone
140 | # running `$TOOL --version' or `$TOOL --help' to check whether
141 | # $TOOL exists and not knowing $TOOL uses missing.
142 | exit 1
143 | fi
144 | ;;
145 | esac
146 |
147 | # If it does not exist, or fails to run (possibly an outdated version),
148 | # try to emulate it.
149 | case $program in
150 | aclocal*)
151 | echo 1>&2 "\
152 | WARNING: \`$1' is $msg. You should only need it if
153 | you modified \`acinclude.m4' or \`${configure_ac}'. You might want
154 | to install the \`Automake' and \`Perl' packages. Grab them from
155 | any GNU archive site."
156 | touch aclocal.m4
157 | ;;
158 |
159 | autoconf*)
160 | echo 1>&2 "\
161 | WARNING: \`$1' is $msg. You should only need it if
162 | you modified \`${configure_ac}'. You might want to install the
163 | \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
164 | archive site."
165 | touch configure
166 | ;;
167 |
168 | autoheader*)
169 | echo 1>&2 "\
170 | WARNING: \`$1' is $msg. You should only need it if
171 | you modified \`acconfig.h' or \`${configure_ac}'. You might want
172 | to install the \`Autoconf' and \`GNU m4' packages. Grab them
173 | from any GNU archive site."
174 | files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
175 | test -z "$files" && files="config.h"
176 | touch_files=
177 | for f in $files; do
178 | case $f in
179 | *:*) touch_files="$touch_files "`echo "$f" |
180 | sed -e 's/^[^:]*://' -e 's/:.*//'`;;
181 | *) touch_files="$touch_files $f.in";;
182 | esac
183 | done
184 | touch $touch_files
185 | ;;
186 |
187 | automake*)
188 | echo 1>&2 "\
189 | WARNING: \`$1' is $msg. You should only need it if
190 | you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
191 | You might want to install the \`Automake' and \`Perl' packages.
192 | Grab them from any GNU archive site."
193 | find . -type f -name Makefile.am -print |
194 | sed 's/\.am$/.in/' |
195 | while read f; do touch "$f"; done
196 | ;;
197 |
198 | autom4te*)
199 | echo 1>&2 "\
200 | WARNING: \`$1' is needed, but is $msg.
201 | You might have modified some files without having the
202 | proper tools for further handling them.
203 | You can get \`$1' as part of \`Autoconf' from any GNU
204 | archive site."
205 |
206 | file=`echo "$*" | sed -n "$sed_output"`
207 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
208 | if test -f "$file"; then
209 | touch $file
210 | else
211 | test -z "$file" || exec >$file
212 | echo "#! /bin/sh"
213 | echo "# Created by GNU Automake missing as a replacement of"
214 | echo "# $ $@"
215 | echo "exit 0"
216 | chmod +x $file
217 | exit 1
218 | fi
219 | ;;
220 |
221 | bison*|yacc*)
222 | echo 1>&2 "\
223 | WARNING: \`$1' $msg. You should only need it if
224 | you modified a \`.y' file. You may need the \`Bison' package
225 | in order for those modifications to take effect. You can get
226 | \`Bison' from any GNU archive site."
227 | rm -f y.tab.c y.tab.h
228 | if test $# -ne 1; then
229 | eval LASTARG="\${$#}"
230 | case $LASTARG in
231 | *.y)
232 | SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
233 | if test -f "$SRCFILE"; then
234 | cp "$SRCFILE" y.tab.c
235 | fi
236 | SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
237 | if test -f "$SRCFILE"; then
238 | cp "$SRCFILE" y.tab.h
239 | fi
240 | ;;
241 | esac
242 | fi
243 | if test ! -f y.tab.h; then
244 | echo >y.tab.h
245 | fi
246 | if test ! -f y.tab.c; then
247 | echo 'main() { return 0; }' >y.tab.c
248 | fi
249 | ;;
250 |
251 | lex*|flex*)
252 | echo 1>&2 "\
253 | WARNING: \`$1' is $msg. You should only need it if
254 | you modified a \`.l' file. You may need the \`Flex' package
255 | in order for those modifications to take effect. You can get
256 | \`Flex' from any GNU archive site."
257 | rm -f lex.yy.c
258 | if test $# -ne 1; then
259 | eval LASTARG="\${$#}"
260 | case $LASTARG in
261 | *.l)
262 | SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
263 | if test -f "$SRCFILE"; then
264 | cp "$SRCFILE" lex.yy.c
265 | fi
266 | ;;
267 | esac
268 | fi
269 | if test ! -f lex.yy.c; then
270 | echo 'main() { return 0; }' >lex.yy.c
271 | fi
272 | ;;
273 |
274 | help2man*)
275 | echo 1>&2 "\
276 | WARNING: \`$1' is $msg. You should only need it if
277 | you modified a dependency of a manual page. You may need the
278 | \`Help2man' package in order for those modifications to take
279 | effect. You can get \`Help2man' from any GNU archive site."
280 |
281 | file=`echo "$*" | sed -n "$sed_output"`
282 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
283 | if test -f "$file"; then
284 | touch $file
285 | else
286 | test -z "$file" || exec >$file
287 | echo ".ab help2man is required to generate this page"
288 | exit $?
289 | fi
290 | ;;
291 |
292 | makeinfo*)
293 | echo 1>&2 "\
294 | WARNING: \`$1' is $msg. You should only need it if
295 | you modified a \`.texi' or \`.texinfo' file, or any other file
296 | indirectly affecting the aspect of the manual. The spurious
297 | call might also be the consequence of using a buggy \`make' (AIX,
298 | DU, IRIX). You might want to install the \`Texinfo' package or
299 | the \`GNU make' package. Grab either from any GNU archive site."
300 | # The file to touch is that specified with -o ...
301 | file=`echo "$*" | sed -n "$sed_output"`
302 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
303 | if test -z "$file"; then
304 | # ... or it is the one specified with @setfilename ...
305 | infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
306 | file=`sed -n '
307 | /^@setfilename/{
308 | s/.* \([^ ]*\) *$/\1/
309 | p
310 | q
311 | }' $infile`
312 | # ... or it is derived from the source name (dir/f.texi becomes f.info)
313 | test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
314 | fi
315 | # If the file does not exist, the user really needs makeinfo;
316 | # let's fail without touching anything.
317 | test -f $file || exit 1
318 | touch $file
319 | ;;
320 |
321 | tar*)
322 | shift
323 |
324 | # We have already tried tar in the generic part.
325 | # Look for gnutar/gtar before invocation to avoid ugly error
326 | # messages.
327 | if (gnutar --version > /dev/null 2>&1); then
328 | gnutar "$@" && exit 0
329 | fi
330 | if (gtar --version > /dev/null 2>&1); then
331 | gtar "$@" && exit 0
332 | fi
333 | firstarg="$1"
334 | if shift; then
335 | case $firstarg in
336 | *o*)
337 | firstarg=`echo "$firstarg" | sed s/o//`
338 | tar "$firstarg" "$@" && exit 0
339 | ;;
340 | esac
341 | case $firstarg in
342 | *h*)
343 | firstarg=`echo "$firstarg" | sed s/h//`
344 | tar "$firstarg" "$@" && exit 0
345 | ;;
346 | esac
347 | fi
348 |
349 | echo 1>&2 "\
350 | WARNING: I can't seem to be able to run \`tar' with the given arguments.
351 | You may want to install GNU tar or Free paxutils, or check the
352 | command line arguments."
353 | exit 1
354 | ;;
355 |
356 | *)
357 | echo 1>&2 "\
358 | WARNING: \`$1' is needed, and is $msg.
359 | You might have modified some files without having the
360 | proper tools for further handling them. Check the \`README' file,
361 | it often tells you about the needed prerequisites for installing
362 | this package. You may also peek at any GNU archive site, in case
363 | some other package would contain this missing \`$1' program."
364 | exit 1
365 | ;;
366 | esac
367 |
368 | exit 0
369 |
370 | # Local variables:
371 | # eval: (add-hook 'write-file-hooks 'time-stamp)
372 | # time-stamp-start: "scriptversion="
373 | # time-stamp-format: "%:y-%02m-%02d.%02H"
374 | # time-stamp-time-zone: "UTC"
375 | # time-stamp-end: "; # UTC"
376 | # End:
377 |
--------------------------------------------------------------------------------
/ftdi_async_mode/stream_test.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | static FILE *outputFile;
13 |
14 | static int exitRequested = 0;
15 | /*
16 | * sigintHandler --
17 | *
18 | * SIGINT handler, so we can gracefully exit when the user hits ctrl-C.
19 | */
20 |
21 | static void
22 | sigintHandler(int signum)
23 | {
24 | exitRequested = 1;
25 | }
26 |
27 | static void
28 | usage(const char *argv0)
29 | {
30 | fprintf(stderr,
31 | "Usage: %s [options...] \n"
32 | "Test streaming read from FT2232H\n"
33 | "[-P string] only look for product with given string\n"
34 | "\n"
35 | "If some filename is given, write data read to that file\n"
36 | "Progess information is printed each second\n"
37 | "Abort with ^C\n"
38 | "\n"
39 | "Options:\n"
40 | "\n"
41 | "Copyright (C) 2009 Micah Dowty \n"
42 | "Adapted for use with libftdi (C) 2010 Uwe Bonnes \n",
43 | argv0);
44 | exit(1);
45 | }
46 |
47 |
48 | static int readCallback(uint8_t *buffer, int length, FTDIProgressInfo *progress, void *userdata)
49 | {
50 | if (length)
51 | {
52 | if (outputFile)
53 | {
54 | if (fwrite(buffer, length, 1, outputFile) != 1)
55 | {
56 | perror("Write error");
57 | return 1;
58 | }
59 | }
60 | }
61 | if (progress)
62 | {
63 | fprintf(stderr, "%10.02fs total time %9.3f MiB captured %7.1f kB/s curr rate %7.1f kB/s totalrate\n",
64 | progress->totalTime,
65 | progress->current.totalBytes / (1024.0 * 1024.0),
66 | progress->currentRate / 1024.0,
67 | progress->totalRate / 1024.0
68 | );
69 | }
70 | return exitRequested ? 1 : 0;
71 | }
72 |
73 | typedef struct
74 | {
75 | FTDIStreamCallback *callback;
76 | void *userdata;
77 | int packetsize;
78 | int activity;
79 | int result;
80 | FTDIProgressInfo progress;
81 | } FTDIStreamState;
82 |
83 | /* Handle callbacks
84 | *
85 | * With Exit request, free memory and release the transfer
86 | *
87 | * state->result is only set when some error happens
88 | */
89 | static void
90 | ftdi_readstream_cb(struct libusb_transfer *transfer)
91 | {
92 | FTDIStreamState *state = transfer->user_data;
93 | int packet_size = state->packetsize;
94 |
95 | state->activity++;
96 | if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
97 | {
98 | int i;
99 | uint8_t *ptr = transfer->buffer;
100 | int length = transfer->actual_length;
101 | int numPackets = (length + packet_size - 1) / packet_size;
102 | int res = 0;
103 |
104 | for (i = 0; i < numPackets; i++)
105 | {
106 | int payloadLen;
107 | int packetLen = length;
108 |
109 | if (packetLen > packet_size)
110 | packetLen = packet_size;
111 |
112 | payloadLen = packetLen - 2;
113 | state->progress.current.totalBytes += payloadLen;
114 |
115 | res = state->callback(ptr + 2, payloadLen,
116 | NULL, state->userdata);
117 |
118 | ptr += packetLen;
119 | length -= packetLen;
120 | }
121 | if (res)
122 | {
123 | free(transfer->buffer);
124 | libusb_free_transfer(transfer);
125 | }
126 | else
127 | {
128 | transfer->status = -1;
129 | state->result = libusb_submit_transfer(transfer);
130 | }
131 | }
132 | else
133 | {
134 | fprintf(stderr, "unknown status %d\n",transfer->status);
135 | state->result = LIBUSB_ERROR_IO;
136 | }
137 | }
138 |
139 | /**
140 | Helper function to calculate (unix) time differences
141 |
142 | \param a timeval
143 | \param b timeval
144 | */
145 | static double
146 | TimevalDiff(const struct timeval *a, const struct timeval *b)
147 | {
148 | return (a->tv_sec - b->tv_sec) + 1e-6 * (a->tv_usec - b->tv_usec);
149 | }
150 |
151 | /**
152 | Streaming reading of data from the device
153 |
154 | Use asynchronous transfers in libusb-1.0 for high-performance
155 | streaming of data from a device interface back to the PC. This
156 | function continuously transfers data until either an error occurs
157 | or the callback returns a nonzero value. This function returns
158 | a libusb error code or the callback's return value.
159 |
160 | For every contiguous block of received data, the callback will
161 | be invoked.
162 |
163 | \param ftdi pointer to ftdi_context
164 | \param callback to user supplied function for one block of data
165 | \param userdata
166 | \param packetsPerTransfer number of packets per transfer
167 | \param numTransfers Number of transfers per callback
168 |
169 | */
170 |
171 | static int
172 | ftdi_readstream_async(struct ftdi_context *ftdi,
173 | FTDIStreamCallback *callback, void *userdata,
174 | int packetsPerTransfer, int numTransfers)
175 | {
176 | struct libusb_transfer **transfers;
177 | FTDIStreamState state = { callback, userdata, ftdi->max_packet_size, 1 };
178 | int bufferSize = packetsPerTransfer * ftdi->max_packet_size;
179 | int xferIndex;
180 | int err = 0;
181 |
182 | /* Only FT2232H and FT232H know about the synchronous FIFO Mode*/
183 | if ((ftdi->type != TYPE_2232H) && (ftdi->type != TYPE_232H))
184 | {
185 | fprintf(stderr,"Device doesn't support synchronous FIFO mode\n");
186 | return 1;
187 | }
188 |
189 | /* We don't know in what state we are, switch to reset*/
190 | if (ftdi_set_bitmode(ftdi, 0xff, BITMODE_RESET) < 0)
191 | {
192 | fprintf(stderr,"Can't reset mode\n");
193 | return 1;
194 | }
195 |
196 | /* Purge anything remaining in the buffers*/
197 | if (ftdi_usb_purge_buffers(ftdi) < 0)
198 | {
199 | fprintf(stderr,"Can't Purge\n");
200 | return 1;
201 | }
202 |
203 | /*
204 | * Set up all transfers
205 | */
206 |
207 | transfers = calloc(numTransfers, sizeof *transfers);
208 | if (!transfers) {
209 | err = LIBUSB_ERROR_NO_MEM;
210 | goto cleanup;
211 | }
212 |
213 | for (xferIndex = 0; xferIndex < numTransfers; xferIndex++)
214 | {
215 | struct libusb_transfer *transfer;
216 |
217 | transfer = libusb_alloc_transfer(0);
218 | transfers[xferIndex] = transfer;
219 | if (!transfer) {
220 | err = LIBUSB_ERROR_NO_MEM;
221 | goto cleanup;
222 | }
223 |
224 | libusb_fill_bulk_transfer(transfer, ftdi->usb_dev, ftdi->out_ep,
225 | malloc(bufferSize), bufferSize,
226 | ftdi_readstream_cb,
227 | &state, 0);
228 |
229 | if (!transfer->buffer) {
230 | err = LIBUSB_ERROR_NO_MEM;
231 | goto cleanup;
232 | }
233 |
234 | transfer->status = -1;
235 | err = libusb_submit_transfer(transfer);
236 | if (err)
237 | goto cleanup;
238 | }
239 |
240 | /* Start the transfers only when everything has been set up.
241 | * Otherwise the transfers start stuttering and the PC not
242 | * fetching data for several to several ten milliseconds
243 | * and we skip blocks
244 | */
245 | #if 0
246 | if (ftdi_set_bitmode(ftdi, 0xff, BITMODE_SYNCFF) < 0)
247 | {
248 | fprintf(stderr,"Can't set synch fifo mode: %s\n",
249 | ftdi_get_error_string(ftdi));
250 | goto cleanup;
251 | }
252 | #endif
253 |
254 | /*
255 | * Run the transfers, and periodically assess progress.
256 | */
257 |
258 | gettimeofday(&state.progress.first.time, NULL);
259 |
260 | do
261 | {
262 | FTDIProgressInfo *progress = &state.progress;
263 | const double progressInterval = 1.0;
264 | struct timeval timeout = { 0, ftdi->usb_read_timeout };
265 | struct timeval now;
266 |
267 | int err = libusb_handle_events_timeout(ftdi->usb_ctx, &timeout);
268 | if (err == LIBUSB_ERROR_INTERRUPTED)
269 | /* restart interrupted events */
270 | err = libusb_handle_events_timeout(ftdi->usb_ctx, &timeout);
271 | if (!state.result)
272 | {
273 | state.result = err;
274 | }
275 | if (state.activity == 0)
276 | state.result = 1;
277 | else
278 | state.activity = 0;
279 |
280 | // If enough time has elapsed, update the progress
281 | gettimeofday(&now, NULL);
282 | if (TimevalDiff(&now, &progress->current.time) >= progressInterval)
283 | {
284 | progress->current.time = now;
285 | progress->totalTime = TimevalDiff(&progress->current.time,
286 | &progress->first.time);
287 |
288 | if (progress->prev.totalBytes)
289 | {
290 | // We have enough information to calculate rates
291 |
292 | double currentTime;
293 |
294 | currentTime = TimevalDiff(&progress->current.time,
295 | &progress->prev.time);
296 |
297 | progress->totalRate =
298 | progress->current.totalBytes /progress->totalTime;
299 | progress->currentRate =
300 | (progress->current.totalBytes -
301 | progress->prev.totalBytes) / currentTime;
302 | }
303 |
304 | state.callback(NULL, 0, progress, state.userdata);
305 | progress->prev = progress->current;
306 |
307 | }
308 | } while (!state.result);
309 |
310 | /*
311 | * Cancel any outstanding transfers, and free memory.
312 | */
313 |
314 | cleanup:
315 | fprintf(stderr, "cleanup\n");
316 | if (transfers)
317 | free(transfers);
318 | if (err)
319 | return err;
320 | else
321 | return state.result;
322 | }
323 |
324 | int main(int argc, char **argv)
325 | {
326 | struct ftdi_context *ftdi;
327 | int err, c;
328 | FILE *of = NULL;
329 | char const *outfile = 0;
330 | outputFile =0;
331 | exitRequested = 0;
332 | char *descstring = NULL;
333 | int option_index;
334 | static struct option long_options[] = {{NULL},};
335 |
336 | while ((c = getopt_long(argc, argv, "P:n", long_options, &option_index)) !=- 1)
337 | switch (c)
338 | {
339 | case -1:
340 | break;
341 | case 'P':
342 | descstring = optarg;
343 | break;
344 | default:
345 | usage(argv[0]);
346 | }
347 |
348 | if (optind == argc - 1)
349 | {
350 | // Exactly one extra argument- a dump file
351 | outfile = argv[optind];
352 | }
353 | else if (optind < argc)
354 | {
355 | // Too many extra args
356 | usage(argv[0]);
357 | }
358 |
359 | if ((ftdi = ftdi_new()) == 0)
360 | {
361 | fprintf(stderr, "ftdi_new failed\n");
362 | return EXIT_FAILURE;
363 | }
364 |
365 | if (ftdi_set_interface(ftdi, INTERFACE_A) < 0)
366 | {
367 | fprintf(stderr, "ftdi_set_interface failed\n");
368 | ftdi_free(ftdi);
369 | return EXIT_FAILURE;
370 | }
371 |
372 | if (ftdi_usb_open_desc(ftdi, 0x0403, 0x6014, descstring, NULL) < 0)
373 | {
374 | fprintf(stderr,"Can't open ftdi device: %s\n",ftdi_get_error_string(ftdi));
375 | ftdi_free(ftdi);
376 | return EXIT_FAILURE;
377 | }
378 |
379 | /* A timeout value of 1 results in may skipped blocks */
380 | if(ftdi_set_latency_timer(ftdi, 2))
381 | {
382 | fprintf(stderr,"Can't set latency, Error %s\n",ftdi_get_error_string(ftdi));
383 | ftdi_usb_close(ftdi);
384 | ftdi_free(ftdi);
385 | return EXIT_FAILURE;
386 | }
387 |
388 | /* if(ftdi_usb_purge_rx_buffer(ftdi) < 0)
389 | {
390 | fprintf(stderr,"Can't rx purge\n",ftdi_get_error_string(ftdi));
391 | return EXIT_FAILURE;
392 | }*/
393 | if (outfile)
394 | if ((of = fopen(outfile,"w+")) == 0)
395 | fprintf(stderr,"Can't open logfile %s, Error %s\n", outfile, strerror(errno));
396 | if (of)
397 | if (setvbuf(of, NULL, _IOFBF , 1<<16) == 0)
398 | outputFile = of;
399 | signal(SIGINT, sigintHandler);
400 |
401 | err = ftdi_readstream_async(ftdi, readCallback, NULL, 8, 256);
402 | if (err < 0 && !exitRequested)
403 | exit(1);
404 |
405 | if (outputFile) {
406 | fclose(outputFile);
407 | outputFile = NULL;
408 | }
409 | fprintf(stderr, "Capture ended.\n");
410 |
411 | if (ftdi_set_bitmode(ftdi, 0xff, BITMODE_RESET) < 0)
412 | {
413 | fprintf(stderr,"Can't set synchronous fifo mode, Error %s\n",ftdi_get_error_string(ftdi));
414 | ftdi_usb_close(ftdi);
415 | ftdi_free(ftdi);
416 | return EXIT_FAILURE;
417 | }
418 | ftdi_usb_close(ftdi);
419 | ftdi_free(ftdi);
420 | signal(SIGINT, SIG_DFL);
421 | exit (0);
422 | }
423 |
--------------------------------------------------------------------------------
/fx2pipe/fx2pipe/fx2pipe.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * usb_io/fx2pipe.cc
3 | *
4 | * Cypress FX2 pipe IO main class.
5 | *
6 | * Copyright (c) 2006 by Wolfgang Wieser ] wwieser (a) gmx <*> de [
7 | *
8 | * This file may be distributed and/or modified under the terms of the
9 | * GNU General Public License version 2 as published by the Free Software
10 | * Foundation. (See COPYING.GPL for details.)
11 | *
12 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14 | *
15 | */
16 |
17 | #include "../fx2pipe/fx2pipe.h"
18 | //#include "../lib/databuffer.h"
19 |
20 | #include
21 | #include
22 | #include
23 | //#include
24 | //#include
25 | //#include
26 |
27 | #include
28 |
29 |
30 | // Initialize static data:
31 | URBCache FX2Pipe::MyURB::urb_cache(/*max_elem=*/256,
32 | /*elem_size=*/sizeof(FX2Pipe::MyURB));
33 |
34 |
35 | int FX2Pipe::_ConnectAndInitUSB()
36 | {
37 | // Be sure:
38 | _CleanupUSB();
39 |
40 | // Connect and init USB device.
41 | // FIXME: Support bus/device.
42 | FX2USBDevice::ErrorCode ec=FX2USBDevice::connect(
43 | /*initial_vendor=*/search_vid,/*initial_product=*/search_pid,
44 | /*n_th=*/n_th_usb_dev,
45 | /*firmware_path=*/firmware_hex_path,
46 | /*firmware_buf=*/fx2pipe_static_firmware,
47 | (const char*)&fc,sizeof(FirwareConfig),FirmwareConfigAdr);
48 | if(ec)
49 | {
50 | fprintf(stderr,"FX2 initialisation failure (ec=%d)\n",ec);
51 | return(1);
52 | }
53 |
54 | const int rx_interface=0;
55 | const int rx_altinterface=1; // alt interface: 1: bulk, 2: interrupt (?), see TRM
56 |
57 | ec=FX2USBDevice::claim(rx_interface,rx_altinterface);
58 | if(ec)
59 | {
60 | fprintf(stderr,"Failed to claim interface %d,%d: ec=%d\n",
61 | rx_interface,rx_altinterface,ec);
62 | return(2);
63 | }
64 |
65 | return(0);
66 | }
67 |
68 |
69 | void FX2Pipe::_CleanupUSB()
70 | {
71 | // NOTE: This function must be safe to be called several times
72 | // even when the USB is already shut down.
73 | FX2USBDevice::disconnect();
74 | FX2Pipe::MyURB::urb_cache.clear();
75 | }
76 |
77 |
78 | int FX2Pipe::_SubmitOneURB()
79 | {
80 | if(stdio_eof)
81 | { return(0); }
82 |
83 | size_t iobs=io_block_size;
84 | if(transfer_limit>=0 && transfer_limit-submitted_bytes=submitted_bytes);
87 | iobs=transfer_limit-submitted_bytes;
88 |
89 | stdio_eof=2;
90 | }
91 |
92 | if(!iobs)
93 | { return(0); }
94 |
95 | MyURB *u = new MyURB(dir<0 ? 0x86U/*EP6 IN*/ : 0x02U/*EP2 OUT*/);
96 | // FIXME: In the OUT case we don't need to allocate buffers all the time
97 | // since the content is copied by the kernel upon submission time.
98 | // FIXME: This means we don't need to zero out the buffer each time if
99 | // no_stdio is set.
100 | u->AllocBuffer(iobs);
101 |
102 | if(dir>0) // Write out to USB.
103 | {
104 | if(no_stdio)
105 | {
106 | u->actual_length=u->buffer_length;
107 | memset(u->buffer,0,u->actual_length);
108 |
109 | //slurped_bytes+=u->buffer_length;
110 | }
111 | else
112 | {
113 | char *raw_buf=(char*)u->buffer;
114 | size_t raw_size=u->buffer_length;
115 | u->actual_length=0;
116 | while(raw_size && !caught_sigint)
117 | {
118 | ssize_t rd=read(0,raw_buf,raw_size);
119 | if(rd>0)
120 | {
121 | assert(size_t(rd)<=raw_size);
122 | raw_size-=rd;
123 | raw_buf+=rd;
124 | u->actual_length+=rd;
125 | //slurped_bytes+=rd;
126 | }
127 | else if(rd<0)
128 | {
129 | if(errno==EINTR) continue;
130 | if(errno==EAGAIN) continue; // <-- SHOULD NOT HAPPEN!
131 | fprintf(stderr,"fx2pipe: read error: %s\n",
132 | strerror(errno));
133 | ++x_errors;
134 |
135 | delete u;
136 | return(1);
137 | }
138 | else if(!rd)
139 | {
140 | //fprintf(stderr,"fx2pipe: EOF on stdin\n");
141 | stdio_eof=1;
142 | break;
143 | }
144 | }
145 | // This is to be sure that the kernel uses the correct size.
146 | // And we as well further down...
147 | u->buffer_length=u->actual_length;
148 | }
149 | }
150 |
151 | if(u->buffer_length)
152 | {
153 | ErrorCode ec=SubmitURB(u);
154 | if(ec)
155 | {
156 | // This is a problem because we hereby lose one in the pipeline.
157 | // Let's see if this turns out to be a problem.
158 | fprintf(stderr,"OOPS: URB submission failed (ec=%d)\n",ec);
159 | return(1);
160 | }
161 |
162 | submitted_bytes+=u->buffer_length;
163 | }
164 | else
165 | { delete u; }
166 |
167 | return(0);
168 | }
169 |
170 |
171 | int FX2Pipe::_SubmitInitialURBs()
172 | {
173 | if(!udh) return(2);
174 |
175 | // We submit some URBs with specified iobs.
176 |
177 | fprintf(stderr,"Submitting max. %d URBs to fill pipeline... ",
178 | pipeline_size);
179 |
180 | gettimeofday(&starttime,NULL);
181 | last_update_time=starttime;
182 |
183 | for(int i=0; iprev;
202 |
203 | ErrorCode ec=CancelURB(u);
204 | // We get errno=EINVAL when cancelling an URB which is already
205 | // completed but not yet reaped. Ignore that.
206 | if(ec && ec!=EINVAL)
207 | { fprintf(stderr,"Failed to cancel (data) URB: ec=%d (%s)\n",
208 | ec,strerror(ec)); }
209 | }
210 | }
211 |
212 |
213 | void FX2Pipe::_DisplayTransferStatistics(const timeval *endtime,int final)
214 | {
215 | long long msec =
216 | 1000LL*(endtime->tv_sec-starttime.tv_sec) +
217 | (endtime->tv_usec-starttime.tv_usec+500)/1000;
218 | fprintf(stderr,
219 | "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
220 | "fx2pipe: %lld bytes in %lld.%03ds",
221 | (long long)transferred_bytes,
222 | (long long)(msec/1000),(int)(msec%1000));
223 | if(msec>10)
224 | {
225 | double bps = double(transferred_bytes)*1000.0 / double(msec);
226 | fprintf(stderr,
227 | " (avg %ld kb/s",
228 | (long)(bps/1024.0+0.5));
229 | }
230 | if(final)
231 | { fprintf(stderr,")\n"); }
232 | else
233 | {
234 | long lu_msec = 1000L*(endtime->tv_sec-last_update_time.tv_sec) +
235 | (endtime->tv_usec-last_update_time.tv_usec+500)/1000;
236 | long lu_bytes = (long)(transferred_bytes-last_update_transferred);
237 | double lu_bps = double(lu_bytes)*1000.0 / double(lu_msec);
238 | fprintf(stderr,
239 | ", curr %ld kb/s)",
240 | (long)(lu_bps/1024.0+0.5));
241 | }
242 | }
243 |
244 |
245 | int FX2Pipe::run()
246 | {
247 | fprintf(stderr,"IO loop running...\n");
248 |
249 | // LibUSB initialisation:
250 | usb_init();
251 | usb_find_busses();
252 | usb_find_devices();
253 |
254 | if(_ConnectAndInitUSB())
255 | { ++x_errors; return(1); }
256 |
257 | if(_SubmitInitialURBs())
258 | { ++x_errors; return(1); }
259 |
260 | // Set scheduler.
261 | if(schedule_policy!=SCHED_OTHER)
262 | {
263 | // Change scheduler.
264 | struct sched_param sp;
265 | memset(&sp,0,sizeof(sp));
266 | sp.sched_priority=schedule_priority;
267 | int rv=sched_setscheduler(0,schedule_policy,&sp);
268 | if(rv)
269 | {
270 | fprintf(stderr,"Failed to use realtime scheduling: %s\n",
271 | strerror(rv));
272 | schedule_policy=SCHED_OTHER;
273 | }
274 | }
275 |
276 | int must_break_loop=0; // 2 -> disconnect or other severe error.
277 | while(!must_break_loop)
278 | {
279 | ErrorCode ec=ProcessEvents(/*max_delay=*/-1);
280 | switch(ec)
281 | {
282 | case ECTimeout:
283 | break;
284 | case ECUserQuit:
285 | must_break_loop=1;
286 | break;
287 | case ECUserQuitFatal:
288 | // ECUserQuitFatal is for severe errors.
289 | ++x_errors;
290 | must_break_loop=2;
291 | break;
292 | case ECNotConnected:
293 | must_break_loop=2;
294 | break;
295 | case ECNoURBAvail:
296 | if(stdio_eof)
297 | { must_break_loop=1; }
298 | else
299 | { fprintf(stderr,
300 | "fx2pipe: OOPS no more URBs although not on EOF\n");
301 | ++x_errors; must_break_loop=2; }
302 | break;
303 | default:
304 | fprintf(stderr,"OOPS: ProcessEvents: ec=%d\n",ec);
305 | // FIXME: What should we do???
306 | break;
307 | }
308 | if(caught_sigint) must_break_loop=1;
309 |
310 | //write(1,"+",1);
311 | //fprintf(stderr,"+%d",npending);
312 | if(npending(_u);
344 | if(u->actual_length!=u->buffer_length
345 | || u->status || u->error_count || u->cancelled)
346 | {
347 | if(!(u->cancelled==2 && u->status==-ENOENT))
348 | { fprintf(stderr,"HMM: URB(%d): blen=%d/%d, status=%d, "
349 | "error count=%d, cancelled=%d\n",
350 | u->urb_serial,u->actual_length,u->buffer_length,
351 | u->status,u->error_count,u->cancelled); }
352 | }
353 |
354 | // Simply ignore cancelled URBs.
355 | if(u->cancelled)
356 | { return(ECSuccess); }
357 |
358 | if(u->status==-EPROTO)
359 | {
360 | if(++successive_error_urbs>pipeline_size+4)
361 | {
362 | fprintf(stderr,"Giving up after %d reaped URBs with errors.\n",
363 | successive_error_urbs);
364 | // Seems like it does not make sense to go on here.
365 | return(ECUserQuitFatal); // User quit.
366 | }
367 | }
368 | else
369 | { successive_error_urbs=0; }
370 |
371 | // FIXME: We don't handle frames with protocol error yet.
372 | if(u->status==0)
373 | {
374 | if(dir<0) // Read in from USB.
375 | {
376 | // In benchmarking mode, don't do anything actually.
377 | // Otherwise, write to stdout.
378 | if(no_stdio)
379 | {
380 | //slurped_bytes+=u->actual_length;
381 | transferred_bytes+=u->actual_length;
382 | }
383 | else
384 | {
385 | const char *raw_buf = (const char*)u->buffer;
386 | size_t raw_size = u->actual_length;
387 |
388 | //slurped_bytes+=u->actual_length;
389 |
390 | while(raw_size && !caught_sigint)
391 | {
392 | ssize_t wr=write(1,raw_buf,raw_size);
393 | if(wr>0)
394 | {
395 | assert(size_t(wr)<=raw_size);
396 | raw_size-=wr;
397 | raw_buf+=wr;
398 |
399 | transferred_bytes+=wr;
400 | }
401 | else if(wr<0)
402 | {
403 | if(errno==EINTR) continue;
404 | if(errno==EAGAIN) continue; // <-- SHOULD NOT HAPPEN!
405 | fprintf(stderr,"fx2pipe: write error: %s\n",
406 | strerror(errno));
407 | ++x_errors;
408 | return(ECUserQuit);
409 | }
410 | else if(!wr)
411 | {
412 | fprintf(stderr,"fx2pipe: EOF on stdout\n");
413 | return(ECUserQuit);
414 | }
415 | }
416 | }
417 | }
418 | else //if(dir>0) // Write out to USB.
419 | {
420 | // Data successfully written over USB.
421 | transferred_bytes+=u->actual_length;
422 | }
423 |
424 | //write(2,".",1);
425 | }
426 |
427 | {
428 | timeval curr_time;
429 | gettimeofday(&curr_time,NULL);
430 | long msec = 1000L*(curr_time.tv_sec-last_update_time.tv_sec) +
431 | (curr_time.tv_usec-last_update_time.tv_usec+500)/1000;
432 | if(msec>250)
433 | {
434 | _DisplayTransferStatistics(&curr_time,0);
435 | last_update_time=curr_time;
436 | last_update_transferred=transferred_bytes;
437 | }
438 | }
439 |
440 | if(caught_sigint)
441 | { return(ECUserQuit); }
442 |
443 | // For each reaped URB, we submit a new one to keep things running.
444 | if(_SubmitOneURB())
445 | { return(ECUserQuit); }
446 |
447 | return(ECSuccess);
448 | }
449 |
450 |
451 | void FX2Pipe::DeleteURB(URB *_u)
452 | {
453 | MyURB *u=static_cast(_u);
454 | delete u;
455 | }
456 |
457 |
458 | FX2Pipe::FX2Pipe() :
459 | FX2USBDevice(),
460 | successive_error_urbs(0),
461 | x_errors(0),
462 | //slurped_bytes(0),
463 | submitted_bytes(0),
464 | last_update_transferred(0),
465 | transferred_bytes(0),
466 | stdio_eof(0),
467 | n_th_usb_dev(0),
468 | search_vid(-1),
469 | search_pid(-1),
470 | transfer_limit(-1),
471 | io_block_size(16384),
472 | pipeline_size(16),
473 | dir(-1),
474 | no_stdio(0),
475 | schedule_policy(SCHED_OTHER),
476 | schedule_priority(0),
477 | firmware_hex_path(NULL)
478 | {
479 | memset(&starttime,0,sizeof(starttime));
480 | memset(&endtime,0,sizeof(endtime));
481 | memset(&last_update_time,0,sizeof(last_update_time));
482 | }
483 |
484 | FX2Pipe::~FX2Pipe()
485 | {
486 | _CleanupUSB();
487 | }
488 |
489 | //------------------------------------------------------------------------------
490 |
491 | void FX2Pipe::MyURB::AllocBuffer(size_t size)
492 | {
493 | buffer=malloc(size);
494 | if(!buffer)
495 | { fprintf(stderr,"URB buffer allocation failure (%u bytes)\n",size);
496 | abort(); }
497 | buffer_length=size;
498 | }
499 |
500 | FX2Pipe::MyURB::MyURB(uchar dir_ep,uchar _type) :
501 | FX2USBDevice::URB(dir_ep,_type)
502 | {
503 | }
504 |
505 | FX2Pipe::MyURB::~MyURB()
506 | {
507 | if(buffer)
508 | { free(buffer); buffer=NULL; }
509 | }
510 |
511 |
--------------------------------------------------------------------------------
/fx2pipe/usb_io/Makefile.in:
--------------------------------------------------------------------------------
1 | # Makefile.in generated by automake 1.10.1 from Makefile.am.
2 | # @configure_input@
3 |
4 | # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
5 | # 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
6 | # This Makefile.in is free software; the Free Software Foundation
7 | # gives unlimited permission to copy and/or distribute it,
8 | # with or without modifications, as long as this notice is preserved.
9 |
10 | # This program is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without
12 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 | # PARTICULAR PURPOSE.
14 |
15 | @SET_MAKE@
16 |
17 | VPATH = @srcdir@
18 | pkgdatadir = $(datadir)/@PACKAGE@
19 | pkglibdir = $(libdir)/@PACKAGE@
20 | pkgincludedir = $(includedir)/@PACKAGE@
21 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
22 | install_sh_DATA = $(install_sh) -c -m 644
23 | install_sh_PROGRAM = $(install_sh) -c
24 | install_sh_SCRIPT = $(install_sh) -c
25 | INSTALL_HEADER = $(INSTALL_DATA)
26 | transform = $(program_transform_name)
27 | NORMAL_INSTALL = :
28 | PRE_INSTALL = :
29 | POST_INSTALL = :
30 | NORMAL_UNINSTALL = :
31 | PRE_UNINSTALL = :
32 | POST_UNINSTALL = :
33 | subdir = usb_io
34 | DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
35 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
36 | am__aclocal_m4_deps = $(top_srcdir)/configure.ac
37 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
38 | $(ACLOCAL_M4)
39 | mkinstalldirs = $(install_sh) -d
40 | CONFIG_HEADER = $(top_builddir)/config.h
41 | CONFIG_CLEAN_FILES =
42 | LIBRARIES = $(noinst_LIBRARIES)
43 | AR = ar
44 | ARFLAGS = cru
45 | lib_usb_io_a_AR = $(AR) $(ARFLAGS)
46 | lib_usb_io_a_LIBADD =
47 | am_lib_usb_io_a_OBJECTS = wwusb.$(OBJEXT) fx2usb.$(OBJEXT) \
48 | urbcache.$(OBJEXT) cycfx2dev.$(OBJEXT)
49 | lib_usb_io_a_OBJECTS = $(am_lib_usb_io_a_OBJECTS)
50 | DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
51 | depcomp = $(SHELL) $(top_srcdir)/depcomp
52 | am__depfiles_maybe = depfiles
53 | CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
54 | $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
55 | CXXLD = $(CXX)
56 | CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
57 | -o $@
58 | COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
59 | $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
60 | CCLD = $(CC)
61 | LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
62 | SOURCES = $(lib_usb_io_a_SOURCES)
63 | DIST_SOURCES = $(lib_usb_io_a_SOURCES)
64 | ETAGS = etags
65 | CTAGS = ctags
66 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
67 | ACLOCAL = @ACLOCAL@
68 | AMTAR = @AMTAR@
69 | AUTOCONF = @AUTOCONF@
70 | AUTOHEADER = @AUTOHEADER@
71 | AUTOMAKE = @AUTOMAKE@
72 | AWK = @AWK@
73 | CC = @CC@
74 | CCDEPMODE = @CCDEPMODE@
75 | CFLAGS = @CFLAGS@
76 | CPP = @CPP@
77 | CPPFLAGS = @CPPFLAGS@
78 | CXX = @CXX@
79 | CXXDEPMODE = @CXXDEPMODE@
80 | CXXFLAGS = @CXXFLAGS@
81 | CYGPATH_W = @CYGPATH_W@
82 | DEFS = @DEFS@
83 | DEPDIR = @DEPDIR@
84 | ECHO_C = @ECHO_C@
85 | ECHO_N = @ECHO_N@
86 | ECHO_T = @ECHO_T@
87 | EGREP = @EGREP@
88 | EXEEXT = @EXEEXT@
89 | GREP = @GREP@
90 | INSTALL = @INSTALL@
91 | INSTALL_DATA = @INSTALL_DATA@
92 | INSTALL_PROGRAM = @INSTALL_PROGRAM@
93 | INSTALL_SCRIPT = @INSTALL_SCRIPT@
94 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
95 | LDFLAGS = @LDFLAGS@
96 | LIBOBJS = @LIBOBJS@
97 | LIBS = @LIBS@
98 | LTLIBOBJS = @LTLIBOBJS@
99 | MAKEINFO = @MAKEINFO@
100 | MKDIR_P = @MKDIR_P@
101 | OBJEXT = @OBJEXT@
102 | PACKAGE = @PACKAGE@
103 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
104 | PACKAGE_NAME = @PACKAGE_NAME@
105 | PACKAGE_STRING = @PACKAGE_STRING@
106 | PACKAGE_TARNAME = @PACKAGE_TARNAME@
107 | PACKAGE_VERSION = @PACKAGE_VERSION@
108 | PATH_SEPARATOR = @PATH_SEPARATOR@
109 | RANLIB = @RANLIB@
110 | SET_MAKE = @SET_MAKE@
111 | SHELL = @SHELL@
112 | STRIP = @STRIP@
113 | VERSION = @VERSION@
114 | abs_builddir = @abs_builddir@
115 | abs_srcdir = @abs_srcdir@
116 | abs_top_builddir = @abs_top_builddir@
117 | abs_top_srcdir = @abs_top_srcdir@
118 | ac_ct_CC = @ac_ct_CC@
119 | ac_ct_CXX = @ac_ct_CXX@
120 | am__include = @am__include@
121 | am__leading_dot = @am__leading_dot@
122 | am__quote = @am__quote@
123 | am__tar = @am__tar@
124 | am__untar = @am__untar@
125 | bindir = @bindir@
126 | build_alias = @build_alias@
127 | builddir = @builddir@
128 | datadir = @datadir@
129 | datarootdir = @datarootdir@
130 | docdir = @docdir@
131 | dvidir = @dvidir@
132 | exec_prefix = @exec_prefix@
133 | host_alias = @host_alias@
134 | htmldir = @htmldir@
135 | includedir = @includedir@
136 | infodir = @infodir@
137 | install_sh = @install_sh@
138 | libdir = @libdir@
139 | libexecdir = @libexecdir@
140 | localedir = @localedir@
141 | localstatedir = @localstatedir@
142 | mandir = @mandir@
143 | mkdir_p = @mkdir_p@
144 | oldincludedir = @oldincludedir@
145 | pdfdir = @pdfdir@
146 | prefix = @prefix@
147 | program_transform_name = @program_transform_name@
148 | psdir = @psdir@
149 | sbindir = @sbindir@
150 | sharedstatedir = @sharedstatedir@
151 | srcdir = @srcdir@
152 | sysconfdir = @sysconfdir@
153 | target_alias = @target_alias@
154 | top_build_prefix = @top_build_prefix@
155 | top_builddir = @top_builddir@
156 | top_srcdir = @top_srcdir@
157 | INCLUDES = -I. -I$(top_srcdir) -I$(top_builddir)
158 | noinst_LIBRARIES = lib_usb_io.a
159 | lib_usb_io_a_SOURCES = \
160 | wwusb.h wwusb.cc \
161 | fx2usb.h fx2usb.cc \
162 | urbcache.h urbcache.cc \
163 | cycfx2dev.h cycfx2dev.cc
164 |
165 | all: all-am
166 |
167 | .SUFFIXES:
168 | .SUFFIXES: .cc .o .obj
169 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
170 | @for dep in $?; do \
171 | case '$(am__configure_deps)' in \
172 | *$$dep*) \
173 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
174 | && exit 0; \
175 | exit 1;; \
176 | esac; \
177 | done; \
178 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu usb_io/Makefile'; \
179 | cd $(top_srcdir) && \
180 | $(AUTOMAKE) --gnu usb_io/Makefile
181 | .PRECIOUS: Makefile
182 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
183 | @case '$?' in \
184 | *config.status*) \
185 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
186 | *) \
187 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
188 | cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
189 | esac;
190 |
191 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
192 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
193 |
194 | $(top_srcdir)/configure: $(am__configure_deps)
195 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
196 | $(ACLOCAL_M4): $(am__aclocal_m4_deps)
197 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
198 |
199 | clean-noinstLIBRARIES:
200 | -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
201 | lib_usb_io.a: $(lib_usb_io_a_OBJECTS) $(lib_usb_io_a_DEPENDENCIES)
202 | -rm -f lib_usb_io.a
203 | $(lib_usb_io_a_AR) lib_usb_io.a $(lib_usb_io_a_OBJECTS) $(lib_usb_io_a_LIBADD)
204 | $(RANLIB) lib_usb_io.a
205 |
206 | mostlyclean-compile:
207 | -rm -f *.$(OBJEXT)
208 |
209 | distclean-compile:
210 | -rm -f *.tab.c
211 |
212 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cycfx2dev.Po@am__quote@
213 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fx2usb.Po@am__quote@
214 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/urbcache.Po@am__quote@
215 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wwusb.Po@am__quote@
216 |
217 | .cc.o:
218 | @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
219 | @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
220 | @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
221 | @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
222 | @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
223 |
224 | .cc.obj:
225 | @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
226 | @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
227 | @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
228 | @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
229 | @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
230 |
231 | ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
232 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
233 | unique=`for i in $$list; do \
234 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
235 | done | \
236 | $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
237 | END { if (nonempty) { for (i in files) print i; }; }'`; \
238 | mkid -fID $$unique
239 | tags: TAGS
240 |
241 | TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
242 | $(TAGS_FILES) $(LISP)
243 | tags=; \
244 | here=`pwd`; \
245 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
246 | unique=`for i in $$list; do \
247 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
248 | done | \
249 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
250 | END { if (nonempty) { for (i in files) print i; }; }'`; \
251 | if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
252 | test -n "$$unique" || unique=$$empty_fix; \
253 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
254 | $$tags $$unique; \
255 | fi
256 | ctags: CTAGS
257 | CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
258 | $(TAGS_FILES) $(LISP)
259 | tags=; \
260 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
261 | unique=`for i in $$list; do \
262 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
263 | done | \
264 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
265 | END { if (nonempty) { for (i in files) print i; }; }'`; \
266 | test -z "$(CTAGS_ARGS)$$tags$$unique" \
267 | || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
268 | $$tags $$unique
269 |
270 | GTAGS:
271 | here=`$(am__cd) $(top_builddir) && pwd` \
272 | && cd $(top_srcdir) \
273 | && gtags -i $(GTAGS_ARGS) $$here
274 |
275 | distclean-tags:
276 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
277 |
278 | distdir: $(DISTFILES)
279 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
280 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
281 | list='$(DISTFILES)'; \
282 | dist_files=`for file in $$list; do echo $$file; done | \
283 | sed -e "s|^$$srcdirstrip/||;t" \
284 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
285 | case $$dist_files in \
286 | */*) $(MKDIR_P) `echo "$$dist_files" | \
287 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
288 | sort -u` ;; \
289 | esac; \
290 | for file in $$dist_files; do \
291 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
292 | if test -d $$d/$$file; then \
293 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
294 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
295 | cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
296 | fi; \
297 | cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
298 | else \
299 | test -f $(distdir)/$$file \
300 | || cp -p $$d/$$file $(distdir)/$$file \
301 | || exit 1; \
302 | fi; \
303 | done
304 | check-am: all-am
305 | check: check-am
306 | all-am: Makefile $(LIBRARIES)
307 | installdirs:
308 | install: install-am
309 | install-exec: install-exec-am
310 | install-data: install-data-am
311 | uninstall: uninstall-am
312 |
313 | install-am: all-am
314 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
315 |
316 | installcheck: installcheck-am
317 | install-strip:
318 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
319 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
320 | `test -z '$(STRIP)' || \
321 | echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
322 | mostlyclean-generic:
323 |
324 | clean-generic:
325 |
326 | distclean-generic:
327 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
328 |
329 | maintainer-clean-generic:
330 | @echo "This command is intended for maintainers to use"
331 | @echo "it deletes files that may require special tools to rebuild."
332 | clean: clean-am
333 |
334 | clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
335 |
336 | distclean: distclean-am
337 | -rm -rf ./$(DEPDIR)
338 | -rm -f Makefile
339 | distclean-am: clean-am distclean-compile distclean-generic \
340 | distclean-tags
341 |
342 | dvi: dvi-am
343 |
344 | dvi-am:
345 |
346 | html: html-am
347 |
348 | info: info-am
349 |
350 | info-am:
351 |
352 | install-data-am:
353 |
354 | install-dvi: install-dvi-am
355 |
356 | install-exec-am:
357 |
358 | install-html: install-html-am
359 |
360 | install-info: install-info-am
361 |
362 | install-man:
363 |
364 | install-pdf: install-pdf-am
365 |
366 | install-ps: install-ps-am
367 |
368 | installcheck-am:
369 |
370 | maintainer-clean: maintainer-clean-am
371 | -rm -rf ./$(DEPDIR)
372 | -rm -f Makefile
373 | maintainer-clean-am: distclean-am maintainer-clean-generic
374 |
375 | mostlyclean: mostlyclean-am
376 |
377 | mostlyclean-am: mostlyclean-compile mostlyclean-generic
378 |
379 | pdf: pdf-am
380 |
381 | pdf-am:
382 |
383 | ps: ps-am
384 |
385 | ps-am:
386 |
387 | uninstall-am:
388 |
389 | .MAKE: install-am install-strip
390 |
391 | .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
392 | clean-noinstLIBRARIES ctags distclean distclean-compile \
393 | distclean-generic distclean-tags distdir dvi dvi-am html \
394 | html-am info info-am install install-am install-data \
395 | install-data-am install-dvi install-dvi-am install-exec \
396 | install-exec-am install-html install-html-am install-info \
397 | install-info-am install-man install-pdf install-pdf-am \
398 | install-ps install-ps-am install-strip installcheck \
399 | installcheck-am installdirs maintainer-clean \
400 | maintainer-clean-generic mostlyclean mostlyclean-compile \
401 | mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
402 | uninstall-am
403 |
404 | # Tell versions [3.59,3.63) of GNU make to not export all variables.
405 | # Otherwise a system limit (for SysV at least) may be exceeded.
406 | .NOEXPORT:
407 |
--------------------------------------------------------------------------------