From e1265fa32837f457ee2c2fa259d12c9545af4bbf Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Mon, 27 Apr 2015 02:28:57 +0200 Subject: First stand-alone ipecamera implementation --- .bzrignore | 26 +- BUGS | 18 - CMakeLists.txt | 79 +- NOTES | 311 -- ToDo | 22 - apps/CMakeLists.txt | 19 - apps/check_counter.c | 45 - apps/compare_to_value.c | 66 - apps/heb_strip_bad_values.c | 98 - apps/lorenzo_ipedma_test.c | 749 ----- apps/pio_test.c | 96 - apps/xilinx.c | 225 -- base.c | 684 +++++ base.h | 24 + cli.c | 3101 -------------------- cmosis.c | 216 ++ cmosis.h | 9 + common.mk | 61 - data.c | 287 ++ data.h | 6 + default.c | 34 - default.h | 9 - dma.c | 327 --- dma.h | 52 - dma/CMakeLists.txt | 9 - dma/ipe.c | 541 ---- dma/ipe.h | 42 - dma/ipe_private.h | 59 - dma/ipe_registers.h | 44 - dma/nwl.c | 139 - dma/nwl.h | 46 - dma/nwl_defines.h | 145 - dma/nwl_engine.c | 318 -- dma/nwl_engine.h | 12 - dma/nwl_engine_buffers.h | 412 --- dma/nwl_irq.c | 119 - dma/nwl_irq.h | 10 - dma/nwl_loopback.c | 255 -- dma/nwl_loopback.h | 7 - dma/nwl_private.h | 67 - dma/nwl_register.c | 77 - dma/nwl_register.h | 97 - driver/Makefile | 49 - driver/base.c | 676 ----- driver/base.h | 85 - driver/common.h | 108 - driver/compat.h | 198 -- driver/config.h | 23 - driver/int.c | 258 -- driver/int.h | 9 - driver/ioctl.c | 471 --- driver/ioctl.h | 5 - driver/kmem.c | 657 ----- driver/kmem.h | 9 - driver/pciDriver.h | 217 -- driver/sysfs.c | 308 -- driver/sysfs.h | 23 - driver/umem.c | 438 --- driver/umem.h | 5 - error.c | 27 - error.h | 34 - event.c | 450 --- event.h | 69 - events.c | 160 + events.h | 5 + ipecamera.h | 39 + ipecamera/CMakeLists.txt | 12 - ipecamera/data.c | 287 -- ipecamera/data.h | 6 - ipecamera/events.c | 160 - ipecamera/events.h | 5 - ipecamera/ipecamera.c | 695 ----- ipecamera/ipecamera.h | 38 - ipecamera/model.c | 211 -- ipecamera/model.h | 180 -- ipecamera/private.h | 151 - ipecamera/public.h | 25 - ipecamera/reader.c | 273 -- ipecamera/reader.h | 8 - irq.c | 55 - irq.h | 5 - kapture/CMakeLists.txt | 9 - kapture/kapture.c | 62 - kapture/kapture.h | 6 - kapture/model.h | 81 - kapture/private.h | 10 - kernel.h | 81 - kmem.c | 310 -- kmem.h | 80 - misc/50-pcidriver.rules | 1 - model.c | 195 ++ model.h | 18 + pci.c | 473 --- pci.h | 85 - pcilib.h | 380 --- pcilib_types.h | 44 - pcitool/CMakeLists.txt | 8 - pcitool/formaters.c | 47 - pcitool/formaters.h | 12 - pcitool/sysinfo.c | 172 -- pcitool/sysinfo.h | 7 - private.h | 155 + reader.c | 269 ++ reader.h | 8 + register.c | 362 --- register.h | 14 - tests/autotrigger.sh | 19 + tests/debug/incomplete.sh | 38 + tests/dma/debug/test-iommu.sh | 19 - tests/dma/ipe/bench.sh | 40 - tests/dma/nwl/bench.sh | 30 - tests/dma/nwl/cleanup.sh | 13 - tests/dma/xilinx/xilinx_dma.sh | 121 - tests/dma/xilinx/xilinx_dma_static_mem.sh | 117 - tests/dump_file.sh | 3 - tests/grab.sh | 24 - tests/heb/DataTaking.sh | 96 - tests/heb/cfg/BoardOFF.sh | 11 - tests/heb/cfg/BoardOn.sh | 57 - tests/heb/cfg/README | 11 - tests/heb/cfg/Set_ADC_1_Delay.sh | 10 - tests/heb/cfg/Set_ADC_2_Delay.sh | 10 - tests/heb/cfg/Set_ADC_3_Delay.sh | 10 - tests/heb/cfg/Set_ADC_4_Delay.sh | 11 - tests/heb/cfg/Set_Default.sh | 30 - tests/heb/cfg/Set_Delay_chip.sh | 11 - tests/heb/cfg/Set_FPGA_clock_delay.sh | 10 - tests/heb/cfg/Set_TH_Delay.sh | 10 - tests/heb/debug/debug.sh | 45 - tests/heb/debug/request_data.sh | 27 - tests/ipecamera/autotrigger.sh | 18 - tests/ipecamera/bench.sh | 34 - tests/ipecamera/cfg/Reset_Init_all_reg_10bit.sh | 326 -- .../ipecamera/cfg/Reset_Init_all_reg_10bit_4Mp.sh | 325 -- tests/ipecamera/cfg/Reset_Init_all_reg_11bit.sh | 318 -- tests/ipecamera/cfg/Reset_Init_all_reg_12bit.sh | 323 -- tests/ipecamera/debug/incomplete.sh | 37 - tests/ipecamera/frame.sh | 36 - tests/ipecamera/frame_req.sh | 27 - tests/ipecamera/grab-hwtrigger.sh | 20 - tests/ipecamera/stimuli.sh | 30 - tests/ipecamera/tests/loopback-test.sh | 87 - tests/ipecamera/tests/run-and-decode-test.sh | 103 - tests/new_device.sh | 3 - tools.c | 354 --- tools.h | 46 - 146 files changed, 2153 insertions(+), 18993 deletions(-) delete mode 100644 BUGS delete mode 100644 NOTES delete mode 100644 ToDo delete mode 100644 apps/CMakeLists.txt delete mode 100644 apps/check_counter.c delete mode 100644 apps/compare_to_value.c delete mode 100644 apps/heb_strip_bad_values.c delete mode 100644 apps/lorenzo_ipedma_test.c delete mode 100644 apps/pio_test.c delete mode 100644 apps/xilinx.c create mode 100644 base.c create mode 100644 base.h delete mode 100644 cli.c create mode 100644 cmosis.c create mode 100644 cmosis.h delete mode 100644 common.mk create mode 100644 data.c create mode 100644 data.h delete mode 100644 default.c delete mode 100644 default.h delete mode 100644 dma.c delete mode 100644 dma.h delete mode 100644 dma/CMakeLists.txt delete mode 100644 dma/ipe.c delete mode 100644 dma/ipe.h delete mode 100644 dma/ipe_private.h delete mode 100644 dma/ipe_registers.h delete mode 100644 dma/nwl.c delete mode 100644 dma/nwl.h delete mode 100644 dma/nwl_defines.h delete mode 100644 dma/nwl_engine.c delete mode 100644 dma/nwl_engine.h delete mode 100644 dma/nwl_engine_buffers.h delete mode 100644 dma/nwl_irq.c delete mode 100644 dma/nwl_irq.h delete mode 100644 dma/nwl_loopback.c delete mode 100644 dma/nwl_loopback.h delete mode 100644 dma/nwl_private.h delete mode 100644 dma/nwl_register.c delete mode 100644 dma/nwl_register.h delete mode 100644 driver/Makefile delete mode 100644 driver/base.c delete mode 100644 driver/base.h delete mode 100644 driver/common.h delete mode 100644 driver/compat.h delete mode 100644 driver/config.h delete mode 100644 driver/int.c delete mode 100644 driver/int.h delete mode 100644 driver/ioctl.c delete mode 100644 driver/ioctl.h delete mode 100644 driver/kmem.c delete mode 100644 driver/kmem.h delete mode 100644 driver/pciDriver.h delete mode 100644 driver/sysfs.c delete mode 100644 driver/sysfs.h delete mode 100644 driver/umem.c delete mode 100644 driver/umem.h delete mode 100644 error.c delete mode 100644 error.h delete mode 100644 event.c delete mode 100644 event.h create mode 100644 events.c create mode 100644 events.h create mode 100644 ipecamera.h delete mode 100644 ipecamera/CMakeLists.txt delete mode 100644 ipecamera/data.c delete mode 100644 ipecamera/data.h delete mode 100644 ipecamera/events.c delete mode 100644 ipecamera/events.h delete mode 100644 ipecamera/ipecamera.c delete mode 100644 ipecamera/ipecamera.h delete mode 100644 ipecamera/model.c delete mode 100644 ipecamera/model.h delete mode 100644 ipecamera/private.h delete mode 100644 ipecamera/public.h delete mode 100644 ipecamera/reader.c delete mode 100644 ipecamera/reader.h delete mode 100644 irq.c delete mode 100644 irq.h delete mode 100644 kapture/CMakeLists.txt delete mode 100644 kapture/kapture.c delete mode 100644 kapture/kapture.h delete mode 100644 kapture/model.h delete mode 100644 kapture/private.h delete mode 100644 kernel.h delete mode 100644 kmem.c delete mode 100644 kmem.h delete mode 100644 misc/50-pcidriver.rules create mode 100644 model.c create mode 100644 model.h delete mode 100644 pci.c delete mode 100644 pci.h delete mode 100644 pcilib.h delete mode 100644 pcilib_types.h delete mode 100644 pcitool/CMakeLists.txt delete mode 100644 pcitool/formaters.c delete mode 100644 pcitool/formaters.h delete mode 100644 pcitool/sysinfo.c delete mode 100644 pcitool/sysinfo.h create mode 100644 private.h create mode 100644 reader.c create mode 100644 reader.h delete mode 100644 register.c delete mode 100644 register.h create mode 100755 tests/autotrigger.sh create mode 100755 tests/debug/incomplete.sh delete mode 100755 tests/dma/debug/test-iommu.sh delete mode 100755 tests/dma/ipe/bench.sh delete mode 100755 tests/dma/nwl/bench.sh delete mode 100755 tests/dma/nwl/cleanup.sh delete mode 100755 tests/dma/xilinx/xilinx_dma.sh delete mode 100755 tests/dma/xilinx/xilinx_dma_static_mem.sh delete mode 100755 tests/dump_file.sh delete mode 100755 tests/grab.sh delete mode 100755 tests/heb/DataTaking.sh delete mode 100755 tests/heb/cfg/BoardOFF.sh delete mode 100755 tests/heb/cfg/BoardOn.sh delete mode 100644 tests/heb/cfg/README delete mode 100755 tests/heb/cfg/Set_ADC_1_Delay.sh delete mode 100755 tests/heb/cfg/Set_ADC_2_Delay.sh delete mode 100755 tests/heb/cfg/Set_ADC_3_Delay.sh delete mode 100755 tests/heb/cfg/Set_ADC_4_Delay.sh delete mode 100755 tests/heb/cfg/Set_Default.sh delete mode 100755 tests/heb/cfg/Set_Delay_chip.sh delete mode 100755 tests/heb/cfg/Set_FPGA_clock_delay.sh delete mode 100755 tests/heb/cfg/Set_TH_Delay.sh delete mode 100755 tests/heb/debug/debug.sh delete mode 100755 tests/heb/debug/request_data.sh delete mode 100755 tests/ipecamera/autotrigger.sh delete mode 100755 tests/ipecamera/bench.sh delete mode 100755 tests/ipecamera/cfg/Reset_Init_all_reg_10bit.sh delete mode 100755 tests/ipecamera/cfg/Reset_Init_all_reg_10bit_4Mp.sh delete mode 100755 tests/ipecamera/cfg/Reset_Init_all_reg_11bit.sh delete mode 100755 tests/ipecamera/cfg/Reset_Init_all_reg_12bit.sh delete mode 100755 tests/ipecamera/debug/incomplete.sh delete mode 100755 tests/ipecamera/frame.sh delete mode 100755 tests/ipecamera/frame_req.sh delete mode 100755 tests/ipecamera/grab-hwtrigger.sh delete mode 100755 tests/ipecamera/stimuli.sh delete mode 100755 tests/ipecamera/tests/loopback-test.sh delete mode 100755 tests/ipecamera/tests/run-and-decode-test.sh delete mode 100755 tests/new_device.sh delete mode 100644 tools.c delete mode 100644 tools.h diff --git a/.bzrignore b/.bzrignore index 6fe7019..164f343 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1,27 +1,5 @@ -*.cmd -pciDriver.ko -pciDriver.mod.c -pci.d -tools.d -modules.order -Module.symvers -./pci -.tmp_versions -cli.d -ipecamera.d -pci.d -tools.d -*.d -CMakeCache.txt CMakeFiles -cmake_install.cmake Makefile -*.so.* +cmake_install.cmake +CMakeCache.txt install_manifest.txt -apps/xilinx -apps/pio_test -apps/compare_to_value -apps/heb_strip_bad_values -*.out -apps/check_counter -apps/lorenzo_ipedma_test diff --git a/BUGS b/BUGS deleted file mode 100644 index 35b5e65..0000000 --- a/BUGS +++ /dev/null @@ -1,18 +0,0 @@ -IPECamera Hardware Bugs -======================= - 1. Strange sequence writting CMOSIS registers - 2. Extra 8 byte padding in the end of frames - 3. Solve the conflict between DMA packet_length register and FPGA registers - 4. Some frame requests are lost - -Incomplete Frames ------------------ - If I'm trying to stream the data, the camera from time to time returns - incomplete frames. The provided part of the frame is coherent. But instead - of at least 3063824 bytes (just full frame without padding, normally I get - more due to the padding) I get only 3063808 bytes. This number 3063808 looks - like to be constant. - - If I send another frame request, however, it looks I got the missing data with - the next frame. - diff --git a/CMakeLists.txt b/CMakeLists.txt index a761acb..f8ccdc2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,81 +1,40 @@ -project(pcitool) +project(ipecamera) -set(PCILIB_VERSION "0.1.0") -set(PCILIB_ABI_VERSION "1") +set(IPECAMERA_VERSION "0.0.1") +set(IPECAMERA_ABI_VERSION "0") cmake_minimum_required(VERSION 2.6) - -set(DISABLE_PCITOOL FALSE CACHE BOOL "Build only the library") - +list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") find_package(PkgConfig REQUIRED) find_package(Threads REQUIRED) +pkg_check_modules(UFODECODE ufodecode>=0.3 REQUIRED) -#Check in sibling directory -pkg_check_modules(UFODECODE ufodecode>=0.2 REQUIRED) - -if (NOT DISABLE_PCITOOL) - pkg_check_modules(FASTWRITER fastwriter REQUIRED) -endif (NOT DISABLE_PCITOOL) - -set(HEADERS pcilib.h pci.h register.h kmem.h irq.h dma.h event.h default.h tools.h error.h) -add_definitions("-fPIC --std=c99 -Wall -O2") -#add_definitions("-fPIC --std=c99 -Wall -O2 -pthread") - -add_subdirectory(dma) -add_subdirectory(ipecamera) -add_subdirectory(kapture) -add_subdirectory(pcitool) -add_subdirectory(apps) +pkg_check_modules(PCILIB pcitool>=0.2 REQUIRED) +exec_program("pkg-config --variable=plugindir pcitool" OUTPUT_VARIABLE PCILIB_PLUGIN_DIR) include_directories( - ${FASTWRITER_INCLUDE_DIRS} + ${CMAKE_SOURCE_DIR} + ${UFODECODE_INCLUDE_DIRS} + ${PCILIB_INCLUDE_DIRS} ) link_directories( - ${FASTWRITER_LIBRARY_DIRS} ${UFODECODE_LIBRARY_DIRS} + ${PCILIB_LIBRARY_DIRS} ) -add_library(pcilib SHARED pci.c register.c kmem.c irq.c dma.c event.c default.c tools.c error.c) -target_link_libraries(pcilib dma ipecamera kapture ${CMAKE_THREAD_LIBS_INIT} ${UFODECODE_LIBRARIES} ) -add_dependencies(pcilib dma ipecamera) - -set_target_properties(pcilib PROPERTIES - VERSION ${PCILIB_VERSION} - SOVERSION ${PCILIB_ABI_VERSION} -# LINK_FLAGS "-pthread" -# LINK_FLAGS "-pthread -Wl,--whole-archive,dma/libdma.a,ipecamera/libipecamera.a,--no-whole-archive" -) +set(HEADERS ${HEADERS} model.h cmosis.h base.h reader.h events.h data.h private.h ipecamera.h) -if (NOT DISABLE_PCITOOL) - add_executable(pci cli.c) - add_dependencies(pci pcitool) - target_link_libraries(pci pcilib pcitool ${FASTWRITER_LIBRARIES}) - set_target_properties(pci PROPERTIES - LINK_FLAGS ${CMAKE_THREAD_LIBS_INIT} - ) -endif (NOT DISABLE_PCITOOL) +add_library(ipecamera SHARED model.c cmosis.c base.c reader.c events.c data.c) -#set_target_properties(pci PROPERTIES -# LINK_FLAGS "-Wl,pcitool/libpcitool.a" -#) +target_link_libraries(ipecamera ${PCILIB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) -if(NOT DEFINED BIN_INSTALL_DIR) - set(BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin") -endif(NOT DEFINED BIN_INSTALL_DIR) - - -install(TARGETS pcilib - LIBRARY DESTINATION lib${LIB_SUFFIX} +install(FILES ipecamera.h + DESTINATION include ) -if (NOT DISABLE_PCITOOL) - install(TARGETS pci - DESTINATION ${BIN_INSTALL_DIR} - ) -endif (NOT DISABLE_PCITOOL) - -install(FILES pcilib.h - DESTINATION include +install(TARGETS ipecamera + DESTINATION ${PCILIB_PLUGIN_DIR} ) + diff --git a/NOTES b/NOTES deleted file mode 100644 index d87bbfc..0000000 --- a/NOTES +++ /dev/null @@ -1,311 +0,0 @@ -Memory Addressing -================= - There is 3 types of addresses: virtual, physical, and bus. For DMA a bus - address is used. However, on x86 physical and bus addresses are the same (on - other architectures it is not guaranteed). Anyway, this assumption is still - used by xdma driver, it uses phiscal address for DMA access. I have ported - in the same way. Now, we need to provide additionaly bus-addresses in kmem - abstraction and use it in NWL DMA implementation. - -DMA Access Synchronization -========================== - - At driver level, few types of buffers are supported: - * SIMPLE - non-reusable buffers, the use infomation can be used for cleanup - after crashed applications. - * EXCLUSIVE - reusable buffers which can be mmaped by a single appliction - only. There is two modes of these buffers: - + Buffers in a STANDARD mode are created for a single DMA operation and - if such buffer is detected while trying to reuse, the last operation - has failed and reset is needed. - + Buffers in a PERSISTENT mode are preserved between invocations of - control application and cleaned up only after the PERSISTENT flag is - removed - * SHARED - reusable buffers shared by multiple processes. Not really - needed at the moment. - - KMEM_FLAG_HW - indicates that buffer can be used by hardware, acually this - means that DMA will be enabled afterwards. The driver is not able to check - if it really was enable and therefore will block any attempt to release - buffer until KMEM_HW_FLAG is passed to kmem_free routine as well. The later - should only called with KMEM_HW_FLAG after the DMA engine is stopped. Then, - the driver can be realesd by kmem_free if ref count reaches 0. - - KMEM_FLAG_EXCLUSIVE - prevents multiple processes mmaping the buffer - simultaneously. This is used to prevent multiple processes use the same - DMA engine at the same time. When passed to kmem_free, allows to clean - buffers with lost clients even for shared buffers. - - KMEM_FLAG_REUSE - requires reuse of existing buffer. If reusable buffer is - found (non-reusable buffers, i.e. allocated without KMEM_FLAG_REUSE are - ignored), it is returned instead of allocation. Three types of usage - counters are used. At moment of allocation, the HW reference is set if - neccessary. The usage counter is increased by kmem_alloc function and - decreased by kmem_free. Finally, the reference is obtained at returned - during mmap/munmap. So, on kmem_free, we do not clean - a) buffers with reference count above zero or hardware reference set. - REUSE flag should be supplied, overwise the error is returned - b) PERSISTENT buffer. REUSE flash should be supplied, overwise the - error is returned - c) non-exclusive buffers with usage counter above zero (For exclusive - buffer the value of usage counter above zero just means that application - have failed without cleaning buffers first. There is no easy way to - detect that for shared buffers, so it is left as manual operation in - this case) - d) any buffer if KMEM_FLAG_REUSE was provided to function - During module unload, only buffers with references can prevent cleanup. In - this case the only possiblity to free the driver is to call kmem_free - passing FORCE flags. - - KMEM_FLAG_PERSISTENT - if passed to allocation routine, changes mode of - buffer to PERSISTENT, if passed to free routine, vice-versa changes mode - of buffer to NORMAL. Basically, if we call 'pci --dma-start' this flag - should be passed to alloc and if we call 'pci --dma-stop' it should be - passed to free. In other case, the flag should not be present. - - If application crashed, the munmap while be still called cleaning software - references. However, the hardware reference will stay since it is not clear - if hardware channel was closed or not. To lift hardware reference, the - application can be re-executed (or dma_stop called, for instance). - * If there is no hardware reference, the buffers will be reused by next - call to application and for EXCLUSIVE buffer cleaned at the end. For SHARED - buffers they will be cleaned during module cleanup only (no active - references). - * The buffer will be reused by next call which can result in wrong behaviour - if buffer left in incoherent stage. This should be handled on upper level. - - - At pcilib/kmem level synchronization of multiple buffers is performed - * The HW reference and following modes should be consistent between member - parts: REUSABLE, PERSISTENT, EXCLUSIVE (only HW reference and PERSISTENT - mode should be checked, others are handled on dirver level) - * It is fine if only part of buffers are reused and others are newly - allocated. However, on higher level this can be checked and resulting - in failure. - - Treatment of inconsistencies: - * Buffers are in PRESISTENT mode, but newly allocated, OK - * Buffers are reused, but are not in PERSISTENT mode (for EXCLUSIVE buffers - this means that application has crashed during the last execution), OK - * Some of buffers are reused (not just REUSABLE, but actually reused), - others - not, OK until - a) either PERSISTENT flag is set or reused buffers are non-PERSISTENT - b) either HW flag is set or reused buffers does not hold HW reference - * PERSISTENT mode inconsistency, FAIL (even if we are going to set - PERSISTENT mode anyway) - * HW reference inconsistency, FAIL (even if we are going to set - HW flag anyway) - - On allocation error at some of the buffer, call clean routine and - * Preserve PERSISTENT mode and HW reference if buffers held them before - unsuccessful kmem initialization. Until the last failed block, the blocks - of kmem should be consistent. The HW/PERSISTENT flags should be removed - if all reused blocks were in HW/PERSISTENT mode. The last block needs - special treatment. The flags may be removed for the block if it was - HW/PERSISTENT state (and others not). - * Remove REUSE flag, we want to clean if allowed by current buffer status - * EXCLUSIVE flag is not important for kmem_free routine. - - - At DMA level - There is 4 components of DMA access: - * DMA engine enabled/disabled - * DMA engine IRQs enabled/disabled - always enabled at startup - * Memory buffers - * Ring start/stop pointers - - To prevent multiple processes accessing DMA engine in parallel, the first - action is buffer initialization which will fail if buffers already used - * Always with REUSE, EXCLUSIVE, and HW flags - * Optionally with PERSISTENT flag (if DMA_PERSISTENT flag is set) - If another DMA app is running, the buffer allocation will fail (no dma_stop - is executed in this case) - - Depending on PRESERVE flag, kmem_free will be called with REUSE flag - keeping buffer in memory (this is redundant since HW flag is enough) or HW - flag indicating that DMA engine is stopped and buffer could be cleaned. - PERSISTENT flag is defined by DMA_PERSISTENT flag passed to stop routine. - - PRESERVE flag is enforced if DMA_PERSISTENT is not passed to dma_stop - routine and either it: - a) Explicitely set by DMA_PERMANENT flag passed to dma_start - function - b) Implicitely set if DMA engine is already enabled during dma_start, - all buffers are reused, and are in persistent mode. - If PRESERVE flag is on, the engine will not be stopped at the end of - execution (and buffers will stay because of HW flag). - - If buffers are reused and are already in PERSISTENT mode, DMA engine was on - before dma_start (PRESERVE flag is ignored, because it can be enforced), - ring pointers are calculated from LAST_BD and states of ring elements. - If previous application crashed (i.e. buffers may be corrupted). Two - cases are possible: - * If during the call buffers were in non-PERSISTENT mode, it can be - easily detected - buffers are reused, but are not in PERSISTENT mode - (or at least was not before we set them to). In this case we just - reinitialize all buffers. - * If during the call buffers were in PERSISTENT mode, it is up to - user to check their consistency and restart DMA engine.] - - IRQs are enabled and disabled at each call - -DMA Reads -========= -standard: default reading mode, reads a single full packet -multipacket: reads all available packets -waiting multipacket: reads all available packets, after finishing the - last one waiting if new data arrives -exact read: read exactly specified number of bytes (should be - only supported if it is multiple of packets, otherwise - error should be returned) -ignore packets: autoterminate each buffer, depends on engine - configuration - - To handle differnt cases, the value returned by callback function instructs -the DMA library how long to wait for the next data to appear before timing -out. The following variants are possible: -terminate: just bail out -check: no timeout, just check if there is data, otherwise - terminate -timeout: standard DMA timeout, normaly used while receiving - fragments of packet: in this case it is expected - that device has already prepared data and only - the performance of DMA engine limits transfer speed -wait: wait until the data is prepared by the device, this - timeout is specified as argument to the dma_stream - function (standard DMA timeout is used by default) - - first | new_pkt | bufer - -------------------------- -standard wait | term | timeout -multiple packets wait | check | timeout - DMA_READ_FLAG_MULTIPACKET -waiting multipacket wait | wait | timeout - DMA_READ_FLAG_WAIT -exact wait | wait/term | timeout - limited by size parameter -ignore packets wait | wait/check| wait/check - just autoterminated - -Shall we do a special handling in case of overflow? - - -Buffering -========= - The DMA addresses are limited to 32 bits (~4GB for everything). This means we - can't really use DMA pages are sole buffers. Therefore, a second thread, with - a realtime scheduling policy if possible, will be spawned and will copy the - data from the DMA pages into the allocated buffers. On expiration of duration - or number of events set by autostop call, this thread will be stopped but - processing in streaming mode will continue until all copyied data is passed - to the callbacks. - - To avoid stalls, the IPECamera requires data to be read continuously read out. - For this reason, there is no locks in the readout thread. It will simplify - overwrite the old frames if data is not copied out timely. To handle this case - after getting the data and processing it, the calling application should use - return_data function and check return code. This function may return error - indicating that the data was overwritten meanwhile. Hence, the data is - corrupted and shoud be droped by the application. The copy_data function - performs this check and user application can be sure it get coherent data - in this case. - - There is a way to avoid this problem. For raw data, the rawdata callback - can be requested. This callback blocks execution of readout thread and - data may be treated safely by calling application. However, this may - cause problems to electronics. Therefore, only memcpy should be performed - on the data normally. - - The reconstructed data, however, may be safely accessed. As described above, - the raw data will be continuously overwritten by the reader thread. However, - reconstructed data, upon the get_data call, will be protected by the mutex. - - -Register Access Synchronization -=============================== - We need to serialize access to the registers by the different running - applications and handle case when registers are accessed indirectly by - writting PCI BARs (DMA implementations, for instance). - - - Module-assisted locking: - * During initialization the locking context is created (which is basicaly - a kmem_handle of type LOCK_PAGE. - * This locking context is passed to the kernel module along with lock type - (LOCK_BANK) and lock item (BANK ADDRESS). If lock context is already owns - lock on the specified bank, just reference number is increased, otherwise - we are trying to obtain new lock. - * Kernel module just iterates over all registered lock pages and checks if - any holds the specified lock. if not, the lock is obtained and registered - in the our lock page. - * This allows to share access between multiple threads of single application - (by using the same lock page) or protect (by using own lock pages by each of - the threads) - * Either on application cleanup or if application crashed, the memory mapping - of lock page is removed and, hence, locks are freed. - - - Multiple-ways of accessing registers - Because of reference counting, we can successfully obtain locks multiple - times if necessary. The following locks are protecting register access: - a) Global register_read/write lock bank before executing implementation - b) DMA bank is locked by global DMA functions. So we can access the - registers using plain PCI bar read/write. - c) Sequence of register operations can be protected with pcilib_lock_bank - function - Reading raw register space or PCI bank is not locked. - * Ok. We can detect banks which will be affected by PCI read/write and - lock them. But shall we do it? - -Register/DMA Configuration -========================== - - XML description of registers - - Formal XML-based (or non XML-based) language for DMA implementation. - a) Writting/Reading register values - b) Wait until = on = report error - c) ... ? - -IRQ Handling -============ - IRQ types: DMA IRQ, Event IRQ, other types - IRQ hardware source: To allow purely user-space implementation, as general - rule, only a single (standard) source should be used. - IRQ source: The dma/event engines, however, may detail this hardware source - and produce real IRQ source basing on the values of registers. For example, - for DMA IRQs the source may present engine number and for Event IRQs the - source may present event type. - - Only types can be enabled or disabled. The sources are enabled/disabled - by enabling/disabling correspondent DMA engines or Event types. The expected - workflow is following: - * We enabling IRQs in user-space (normally setting some registers). Normally, - just an Event IRQs, the DMA if necessary will be managed by DMA engine itself. - * We waiting for standard IRQ from hardware (driver) - * In the user space, we are checking registers to find out the real source - of IRQ (driver reports us just hardware source), generating appropriate - events, and acknowledge IRQ. This is dependent on implementation and should - be managed inside event API. - - I.e. the driver implements just two methods pcilib_wait_irq(hw_source), - pcilib_clear_irq(hw_source). Only a few hardware IRQ sources are defined. - In most cirstumances, the IRQ_SOURCE_DEFAULT is used. - - The DMA engine may provide 3 additional methods, to enable, disable, - and acknowledge IRQ. - - ... To be decided in details upon the need... - -Updating Firmware -================= - - JTag should be connected to USB connector on the board (next to Ethernet) - - The computer should be tourned off and on before programming - - The environment variable should be loaded - . /home/uros/.bashrc - - The application is called 'impact' - No project is needed, cancel initial proposals (No/Cancel) - Double-click on "Boundary Scan" - Right click in the right window and select "Init Chain" - We don't want to select bit file now (Yes and, then, click Cancel) - Right click on second (right) item and choose "Assign new CF file" - Select a bit file. Answer No, we don't want to attach SPI to SPI Prom - Select xv6vlx240t and program it - - Shutdown and start computer - - Firmware are in - v.2: /home/uros/Repo/UFO2_last_good_version_UFO2.bit - v.3: /home/uros/Repo/UFO3 - Step5 - best working revision - Step6 - last revision - - \ No newline at end of file diff --git a/ToDo b/ToDo deleted file mode 100644 index c695a9a..0000000 --- a/ToDo +++ /dev/null @@ -1,22 +0,0 @@ -High Priority (we would need it for IPE Camera) -============= - 1. Serialize access to the registers across applications - 2. Protect kmem_entries in the driver using spinlock - 3. Implement pcilib_configure_autotrigger - -Normal Priority (it would make just few things a bit easier) -=============== - 1. Implement software registers (stored in kernel-memory) - 2. Support FIFO reads/writes from/to registers - 3. Provide OR and AND operations on registers in cli - 4. Support writting a data from a binary file in cli - 5. Use bus-addresses instead of physcial addresses for DMA - -Low Priority (only as generalization for other projects) -============ - 1. XML configurations describing registers (and DMA engines?) - 2. Access register/bank lookups using hash tables - 3. Support for Network Registers and Network DMA - 4. Define a syntax for register dependencies / delays (?) - 5. Use pthread_condition_t instead of polling - diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt deleted file mode 100644 index 24457e3..0000000 --- a/apps/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -include_directories( - ${CMAKE_SOURCE_DIR} -) - -link_directories(${UFODECODE_LIBRARY_DIRS}) - -add_executable(xilinx xilinx.c) -target_link_libraries(xilinx pcilib rt) - -add_executable(lorenzo_ipedma_test lorenzo_ipedma_test.c) -target_link_libraries(lorenzo_ipedma_test pcilib rt) - -add_executable(pio_test pio_test.c) -target_link_libraries(pio_test pcilib rt) - -add_executable(compare_to_value compare_to_value.c) - -add_executable(heb_strip_bad_values heb_strip_bad_values.c) -add_executable(check_counter check_counter.c) diff --git a/apps/check_counter.c b/apps/check_counter.c deleted file mode 100644 index b19b7d0..0000000 --- a/apps/check_counter.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include -#include - -int main(int argc, char *argv[]) { - int block = 0; - uint32_t value = 0; - uint32_t buf[1024]; - - if (argc < 2) { - printf("Usage:\n\t\t%s \n", argv[0]); - exit(0); - } - - FILE *f = fopen(argv[1], "r"); - if (!f) { - printf("Failed to open file %s\n", argv[1]); - exit(1); - } - - - while (!feof(f)) { - int i, n = fread(buf, 4, 1024, f); - - if (block) i = 0; - else { - i = 1; - value = (buf[0]); - } - - for (; i < n; i++) { - if ((buf[i]) != ++value) { - printf("Pos %lx (Block %i, dword %i) expected %x, but got %x\n", block * 4096 + i * 4, block, i, value, (buf[i])); - exit(1); - } - } - - if (n) block++; - } - - fclose(f); - - printf("Checked %i blocks. All is fine\n", block); - return 0; -} diff --git a/apps/compare_to_value.c b/apps/compare_to_value.c deleted file mode 100644 index 75ad353..0000000 --- a/apps/compare_to_value.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include - -int main(int argc, char *argv[]) { - long i, j, size, num; - size_t count = 0, total = 0; - int offset = 0, toread = 1, toskip = 0; - uint32_t value; - uint32_t *buf; - - if ((argc != 4)&&(argc != 7)) { - printf("Usage: %s [offset_dwords read_dwords skip_dwords] \n", argv[0]); - exit(0); - } - - FILE *f = fopen(argv[1], "r"); - if (!f) { - printf("Can't open %s\n", argv[1]); - exit(1); - } - - size = atol(argv[2]); - if (size <= 0) { - printf("Can't parse size %s\n", argv[2]); - exit(1); - } - - if (sscanf(argv[3], "%x", &value) != 1) { - printf("Can't parse register %s\n", argv[3]); - exit(1); - } - - buf = malloc(size * sizeof(uint32_t)); - if (!buf) { - printf("Can't allocate %lu bytes of memory\n", size * sizeof(uint32_t)); - exit(1); - } - - if (argc == 7) { - offset = atoi(argv[4]); - toread = atoi(argv[5]); - toskip = atoi(argv[6]); - } - - - num = fread(buf, 4, size, f); - if (num != size) { - printf("Only %lu of %lu dwords in the file\n", num, size); - exit(1); - } - fclose(f); - - for (i = offset; i < size; i += toskip) { - for (j = 0; j < toread; j++, i++) { - total++; - if (buf[i] != value) { - count++; - } - } - } - free(buf); - - printf("%lu of %lu is wrong\n", count, total); - return 0; -} diff --git a/apps/heb_strip_bad_values.c b/apps/heb_strip_bad_values.c deleted file mode 100644 index e04a53c..0000000 --- a/apps/heb_strip_bad_values.c +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#include -#include -#include -#include - -int main(int argc, char *argv[]) { - long i, num; - size_t count = 0, total = 0, size; - int offset = 3, toread = 1, toskip = 3; - uint32_t value; - uint32_t *buf; - uint32_t expected = 0; - uint32_t blocks = 0, status_good = 0; - - char fixed[4096]; - struct stat st_buf; - - if ((argc != 2)&&(argc != 5)) { - printf("Usage: %s [offset_dwords read_dwords skip_dwords] \n", argv[0]); - exit(0); - } - - FILE *f = fopen(argv[1], "r"); - if (!f) { - printf("Can't open %s\n", argv[1]); - exit(1); - } - - stat(argv[1], &st_buf); - size = st_buf.st_size / sizeof(uint32_t); - - - buf = malloc(size * sizeof(uint32_t)); - if (!buf) { - printf("Can't allocate %lu bytes of memory\n", size * sizeof(uint32_t)); - exit(1); - } - - if (argc == 5) { - offset = atoi(argv[2]); - toread = atoi(argv[3]); - toskip = atoi(argv[4]); - } - - - num = fread(buf, 4, size, f); - if (num != size) { - printf("Failed to read %lu dwords, only %lu read\n", size, num); - exit(1); - } - fclose(f); - - sprintf(fixed, "%s.fixed", argv[1]); - f = fopen(fixed, "w"); - if (!f) { - printf("Failed to open %s for output\n", fixed); - exit(1); - } - - expected = (buf[offset]>>24) + 2; - for (i = 1; i < size; i += (toread + toskip)) { - total++; - - value = buf[i + offset] >> 24; -// printf("0x%lx: value (%lx) = expected (%lx)\n", i + offset, value, expected); - if (value == expected) { - if (!status_good) { - status_good = 1; - blocks++; - } - fwrite(&buf[i], 4, toread + toskip, f); - expected += 2; - if (expected == 0xb8) - expected = 0; - } else if ((!status_good)&&(value == 0)&&((i + toread + toskip)< size)) { - value = buf[i + offset + toread + toskip] >> 24; - if (value == 2) { - status_good = 1; - blocks++; - fwrite(&buf[i], 4, toread + toskip, f); - expected = 2; - } else { - count++; - } - } else { - printf("0x%lx: value (%x) = expected (%x)\n", (i + offset)*sizeof(uint32_t), value, expected); - status_good = 0; - count++; - } - } - fclose(f); - free(buf); - - printf("%lu of %lu is wrong\n", count, total); - return 0; -} diff --git a/apps/lorenzo_ipedma_test.c b/apps/lorenzo_ipedma_test.c deleted file mode 100644 index 3802e78..0000000 --- a/apps/lorenzo_ipedma_test.c +++ /dev/null @@ -1,749 +0,0 @@ -#define _POSIX_C_SOURCE 199309L -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pcilib.h" -#include "irq.h" -#include "kmem.h" - -//#include -//#include - - -#define DEVICE "/dev/fpga0" - -#define BAR PCILIB_BAR0 -#define USE_RING PCILIB_KMEM_USE(PCILIB_KMEM_USE_USER, 1) -#define USE PCILIB_KMEM_USE(PCILIB_KMEM_USE_USER, 2) -//#define STATIC_REGION 0x80000000 // to reserve 512 MB at the specified address, add "memmap=512M$2G" to kernel parameters - -#define BUFFERS 128 -#define ITERATIONS 1000 -#define DESC_THRESHOLD BUFFERS/8 // Lorenzo: after how many desc the FPGA must update the "written descriptor counter" in PC mem - // if set to 0, the update only happens when INT is received - -#define HUGE_PAGE 1 // number of pages per huge page -#define TLP_SIZE 32 // TLP SIZE = 64 for 256B payload, 32 for 128B payload -#define PAGE_SIZE 4096 // other values are not supported in the kernel - -//#define USE_64 // Lorenzo: use 64bit addressing - -//#define DUAL_CORE // Lorenzo: DUAL Core - -//#define SHARED_MEMORY // Lorenzo: Test for fast GUI - -#define CHECK_READY // Lorenzo: Check if PCI-Express is ready by reading 0x0 -#define CHECK_RESULTS // Lorenzo: Check if data received is ok (only for counter!) -//#define PRINT_RESULTS // Lorenzo: Save the received data in "data.out" -//#define EXIT_ON_EMPTY // Lorenzo: Exit if an "empty_detected" signal is received - -//#define HEB // Lorenzo: Testing HEB -//#define SWITCH_GENERATOR // Lorenzo: Testing HEB -> Turn data gen on/off - -//#define TEST_DDR // Lorenzo: Testing DDR - -#define TIMEOUT 1000000 - - - -/* IRQs are slow for some reason. REALTIME mode is slower. Adding delays does not really help, - otherall we have only 3 checks in average. Check ready seems to be not needed and adds quite - much extra time */ - -//#define USE_IRQ -//#define REALTIME -//#define ADD_DELAYS - - -#define FPGA_CLOCK 250 // Lorenzo: in MHz ! - - - -//#define WR(addr, value) { val = value; pcilib_write(pci, BAR, addr, sizeof(val), &val); } -//#define RD(addr, value) { pcilib_read(pci, BAR, addr, sizeof(val), &val); value = val; } -#define WR(addr, value) { *(uint32_t*)(bar + addr + offset) = value; } -#define RD(addr, value) { value = *(uint32_t*)(bar + addr + offset); } - -// ************************************************************************************** -// Progress BAR -// Process has done x out of n rounds, -// and we want a bar of width w and resolution r. - static inline void loadBar(int x, int n, int r, int w) - { - // Only update r times. - if ( x % (n/r +1) != 0 ) return; - - // Calculuate the ratio of complete-to-incomplete. - float ratio = x/(float)n; - int c = ratio * w; - - // Show the percentage complete. - printf("%3d%% [", (int)(ratio*100) ); - - // Show the load bar. - for (x=0; x 999999999) { - wait.tv_sec += 1; - wait.tv_nsec = 1000000000 - wait.tv_nsec; - } - - do { - clock_gettime(CLOCK_REALTIME, &tv); - } while ((wait.tv_sec > tv.tv_sec)||((wait.tv_sec == tv.tv_sec)&&(wait.tv_nsec > tv.tv_nsec))); -} - - -// ************************************************************************************** -int main() { - - - - int err; - long i, j, k; - int mem_diff; - pcilib_t *pci; - pcilib_kmem_handle_t *kdesc; - pcilib_kmem_handle_t *kbuf; - struct timeval start, end; - size_t run_time, size; - long long int size_mb; - void* volatile bar; - uintptr_t bus_addr[BUFFERS]; - uintptr_t kdesc_bus; - volatile uint32_t *desc; - typedef volatile uint32_t *Tbuf; - Tbuf ptr[BUFFERS]; - int switch_generator = 0; - - float performance, perf_counter; - pcilib_bar_t bar_tmp = BAR; - uintptr_t offset = 0; - - unsigned int temp; - int iterations_completed, buffers_filled; - - -// int shmid; - - - printf("\n\n**** **** **** KIT-DMA TEST **** **** ****\n\n"); - - size = ITERATIONS * BUFFERS * HUGE_PAGE * PAGE_SIZE; - size_mb = ITERATIONS * BUFFERS * HUGE_PAGE * 4 / 1024; - printf("Total size of memory buffer: \t %.3lf GBytes\n", (float)size_mb/1024 ); - printf("Using %d Buffers with %d iterations\n\n", BUFFERS, ITERATIONS ); - -#ifdef ADD_DELAYS - long rpt = 0, rpt2 = 0; - size_t best_time; - best_time = 1000000000L * HUGE_PAGE * PAGE_SIZE / (4L * 1024 * 1024 * 1024); -#endif /* ADD_DELAYS */ - - - pcilib_kmem_flags_t flags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT|PCILIB_KMEM_FLAG_EXCLUSIVE/*|PCILIB_KMEM_FLAG_REUSE*/; // Lorenzo: if REUSE = 1, the re-allocation fails! - pcilib_kmem_flags_t free_flags = PCILIB_KMEM_FLAG_HARDWARE/*|PCILIB_KMEM_FLAG_EXCLUSIVE|PCILIB_KMEM_FLAG_REUSE*/; - pcilib_kmem_flags_t clean_flags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT|PCILIB_KMEM_FLAG_EXCLUSIVE; - - pci = pcilib_open(DEVICE, PCILIB_MODEL_DETECT); - if (!pci) fail("pcilib_open"); - - bar = pcilib_map_bar(pci, BAR); - if (!bar) { - pcilib_close(pci); - fail("map bar"); - } - - pcilib_detect_address(pci, &bar_tmp, &offset, 1); - - pcilib_enable_irq(pci, PCILIB_IRQ_TYPE_ALL, 0); - pcilib_clear_irq(pci, PCILIB_IRQ_SOURCE_DEFAULT); - - pcilib_clean_kernel_memory(pci, USE, clean_flags); - pcilib_clean_kernel_memory(pci, USE_RING, clean_flags); - - kdesc = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_CONSISTENT, 1, 128, 4096, USE_RING, flags); - kdesc_bus = pcilib_kmem_get_block_ba(pci, kdesc, 0); - desc = (uint32_t*)pcilib_kmem_get_block_ua(pci, kdesc, 0); - memset((void*)desc, 0, 5*sizeof(uint32_t)); - -#ifdef REALTIME - pid_t pid; - struct sched_param sched = {0}; - - pid = getpid(); - sched.sched_priority = sched_get_priority_min(SCHED_FIFO); - if (sched_setscheduler(pid, SCHED_FIFO, &sched)) - printf("Warning: not able to get real-time priority\n"); -#endif /* REALTIME */ - - // ****************************************************************** - // **** MEM: check 4k boundary ***** - // ****************************************************************** - - do { - printf("* Allocating KMem, "); -#ifdef STATIC_REGION - kbuf = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_REGION_C2S, BUFFERS, HUGE_PAGE * PAGE_SIZE, STATIC_REGION, USE, flags); -#else - kbuf = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_DMA_C2S_PAGE, BUFFERS, HUGE_PAGE * PAGE_SIZE, 4096, USE, flags); -#endif - - if (!kbuf) { - printf("KMem allocation failed\n"); - exit(0); - } - - // Pointers for Virtualized Mem - for (j = 0; j < BUFFERS; j++) { - ptr[j] = (volatile uint32_t*)pcilib_kmem_get_block_ua(pci, kbuf, j); - memset((ptr[j]), 0, HUGE_PAGE * PAGE_SIZE); - } - - err = 0; - - // Check if HW addresses satisfy 4k boundary condition, if not -> free (!!) and reallocate memory - printf("4k boundary test: "); - for (j = 0; j < BUFFERS; j++) { - temp = (((unsigned int)pcilib_kmem_get_block_ba(pci, kbuf, j)) % 4096); - //printf("%u", temp); - if (temp != 0) { - err = 1; - } - } - if (err == 1) { - pcilib_clean_kernel_memory(pci, USE, clean_flags); - pcilib_clean_kernel_memory(pci, USE_RING, clean_flags); - pcilib_free_kernel_memory(pci, kbuf, free_flags); - printf("failed \xE2\x9C\x98\n"); - } - else printf("passed \xE2\x9C\x93\n"); - - } while (err == 1); - - - // ****************************************************************** - // **** Allocate RAM buffer Memory ***** - // ****************************************************************** - - FILE * Output; - FILE * error_log; - -#ifdef CHECK_RESULTS - - uint32_t *temp_data[ITERATIONS][BUFFERS]; - - for (j=0; j < ITERATIONS; j++) { - for (i=0; i < BUFFERS; i++) { - temp_data[j][i] = (uint32_t *)malloc(HUGE_PAGE*PAGE_SIZE); - if (temp_data[j][i] == 0) { - printf("******* Error: could not allocate memory! ********\n"); - exit(0); - } - memset((void*)(temp_data[j][i]), 0, HUGE_PAGE * PAGE_SIZE); - } - } -#endif - -#ifdef SHARED_MEMORY - // give your shared memory an id, anything will do - key_t key = 123456; - char *shared_memory; - - // Setup shared memory, 11 is the size -/* if ((shmid = shmget(key, HUGE_PAGE*PAGE_SIZE, IPC_CREAT | 0666)) < 0) - { - printf("Error getting shared memory id"); - exit(1); - } - - // Attached shared memory - if ((shared_memory = shmat(shmid, NULL, 0)) == (char *) -1) - { - printf("Error attaching shared memory id"); - exit(1); - } - printf("* Shared memory created... Id:\t %d\n", key); - //////////////// SHARED MEMORY TEST */ -#endif - - Output = fopen ("data.out", "w"); - fclose(Output); - - error_log = fopen ("error_log.txt", "w"); - fclose(error_log); - - // ************************************* - Output = fopen("data.txt", "w"); - fclose(Output); - - // ****************************************************************** - // **** PCIe TEST ***** - // ****************************************************************** - - // Reset DMA - printf("* DMA: Reset...\n"); - WR(0x00, 0x1); - usleep(100000); - WR(0x00, 0x0); - usleep(100000); - -#ifdef CHECK_READY - printf("* PCIe: Testing..."); - RD(0x0, err); - if (err != 335746816) { - printf("\xE2\x9C\x98\n PCIe not ready!\n"); - exit(0); - } else { - printf("\xE2\x9C\x93 \n"); - } -#endif - - - // ****************************************************************** - // **** DMA CONFIGURATION ***** - // ****************************************************************** - - - printf("* DMA: Start Data Generator...\n"); - WR(0x04, 0x10) // Start data generator - - printf("* DMA: Send Data Fill Pattern 55aa55aa\n"); - WR(0x14, 0xbeef); - - printf("* DMA: Send Data Amount\n"); -#ifdef DUAL_CORE - WR(0x10, (HUGE_PAGE * (PAGE_SIZE / (4 * TLP_SIZE)))/2); -#else - WR(0x10, (HUGE_PAGE * (PAGE_SIZE / (4 * TLP_SIZE)))); -#endif - - printf("* DMA: Running mode: "); -#ifdef USE_64 - if (TLP_SIZE == 64) - { - WR(0x0C, 0x80040); - printf ("64bit - 256B Payload\n"); - } - else if (TLP_SIZE == 32) - { - WR(0x0C, 0x80020); - printf ("64bit - 128B Payload\n"); - } -#else - if (TLP_SIZE == 64) - { - WR(0x0C, 0x0040); - printf ("32bit - 256B Payload\n"); - } - else if (TLP_SIZE == 32) - { - WR(0x0C, 0x0020); - printf ("32bit - 128B Payload\n"); - } -#endif - - printf("* DMA: Reset Desc Memory...\n"); - WR(0x5C, 0x00); // RST Desc Memory - - //printf("Writing SW Read Descriptor\n"); - WR(0x58, BUFFERS-1); - //WR(0x58, 0x01); - - //printf("Writing the Descriptor Threshold\n"); - WR(0x60, DESC_THRESHOLD); - - //printf("Writing HW write Descriptor Address: %lx\n", kdesc_bus); - WR(0x54, kdesc_bus); - usleep(100000); - - printf("* DMA: Writing Descriptors\n"); - for (j = 0; j < BUFFERS; j++ ) { - bus_addr[j] = pcilib_kmem_get_block_ba(pci, kbuf, j); - // LEAVE THIS DELAY???!?!?!?! - usleep(1000); - printf("Writing descriptor num. %ld: \t %08lx \r", j, bus_addr[j]); - WR(0x50, bus_addr[j]); - } - - // ****************************************************************** - // **** HEB CONFIGURATION ***** - // ****************************************************************** -#ifdef HEB - - - printf("* DDR REGISTERS: AXI_BUF_SIZE \n"); - WR(0x9130, 0x1000); - - usleep(100000); - - printf("* HEB: Control \n"); - WR(0x9040, 0x00000001); - - usleep(100000); - - printf("* HEB: Control \n"); - WR(0x9040, 0x00000004); - - usleep(100000); - - printf("* HEB: Control \n"); - WR(0x9040, 0x00000000); - - usleep(100000); - - printf("* HEB: Writing Total Orbit Num\n"); - WR(0x9020, 0x2000); - - printf("* HEB: Orbit Skip Num h9028\n"); - WR(0x9028, 0x4); - - //printf("* HEB: LVDS_DELAY h9080\n"); - //WR(0x9080, 0x10101010); - - //printf("* HEB: Delay ADCs \n"); - //WR(0x9088, 0x001); - //WR(0x9090, 0x001); - //WR(0x9094, 0x001); - //WR(0x9098, 0x001); - - //printf("* HEB: Delay TH \n"); - //WR(0x90a0, 0x005); - - //printf("* HEB: Delay_FPGA_reg \n"); - //WR(0x90a8, 0x006); - - //printf("* HEB: Control \n"); - //WR(0x9040, 0x40000000); - - //usleep(1000000); - - printf("* HEB: Control \n"); - WR(0x9040, 0x40000bf0); - - usleep(100000); - - printf("* HEB: Control \n"); - WR(0x9040, 0x400003f0); - - usleep(100000); - - printf("* HEB: Control \n"); - WR(0x9040, 0x480007F0); - - usleep(100000); - - printf("* HEB: Control \n"); - WR(0x9040, 0x48000FF0); - - -#endif - - // ****************************************************************** - // **** TEST DDR conf ***** - // ****************************************************************** -#ifdef TEST_DDR - - - printf("* DDR: AXI_BUF_SIZE_ADDR: 4k\n"); - WR(0x9010, 0x04000); - - printf("* DDR: Control \n"); - WR(0x9000, 0x000000F); - - usleep(100000); - WR(0x9000, 0x00000008); - usleep(100000); - WR(0x9000, 0x08000008); - - usleep(50000); - - printf("* DDR: Control \n"); - WR(0x9000, 0x08000208); - - -#endif - - // ****************************************************************** - // **** START DMA ***** - // ****************************************************************** - - //printf ("\n ---- Press ENTER to start DMA ---- \n"); - //getchar(); - - printf("* DMA: Start \n"); - WR(0x04, 0x1f); - gettimeofday(&start, NULL); - - // ****************************************************************** - // **** Handshaking DMA ***** - // ****************************************************************** - - uint32_t curptr = 0, hwptr; - uint32_t curbuf = 0; - int empty = 0; - i = 0; - - - while (i < ITERATIONS) { - j = 0; - // printf("\ndesc0: %lx", htonl(desc[0])); - // printf("\ndesc1: %lx", htonl(desc[1])); - // printf("\ndesc2: %lx", htonl(desc[2])); - // printf("\ndesc3: %lx", htonl(desc[3])); - // printf("\ndesc4: %lx", htonl(desc[4])); - // printf("\ndesc5: %lx", htonl(desc[5])); - //printf("Iteration: %li of %li \r", i+1, ITERATIONS); - //loadBar(i+1, ITERATIONS, ITERATIONS, 30); - // printf("\nhwptr: %zu", hwptr); - // printf("\ncurptr: %zu", curptr); - - do { -#ifdef USE_64 - hwptr = htonl(desc[3]); -#else // 32-bit - hwptr = htonl(desc[4]); -#endif - j++; - //printf("\rcurptr: %lx \t \t hwptr: %lx", curptr, hwptr); - } while (hwptr == curptr); - - do { - pcilib_kmem_sync_block(pci, kbuf, PCILIB_KMEM_SYNC_FROMDEVICE, curbuf); -#ifdef CHECK_RESULTS - memcpy(temp_data[i][curbuf], ptr[curbuf], 4096); -#endif -#ifdef SHARED_MEMORY - memcpy(shared_memory, ptr[curbuf], 4096); -#endif - //printf("\ncurbuf: %08x", curbuf); - //printf("\nbus_addr[curbuf]\n: %08x",bus_addr[curbuf]); - // for (k = 0; k < 63; k++){ - // if (k%16 == 0) printf("\n# %d # :", k); - // printf(" %08x", ptr[curbuf][k]); - // } - //pcilib_kmem_sync_block(pci, kbuf, PCILIB_KMEM_SYNC_TODEVICE, curbuf); - curbuf++; - if (curbuf == BUFFERS) { - i++; - curbuf = 0; -#ifdef SWITCH_GENERATOR - if (switch_generator == 1) { - switch_generator = 0; - WR(0x9040, 0x100007F0); - } else { - WR(0x9040, 0x180007F0); - switch_generator = 1; - } -#endif - if (i >= ITERATIONS) break; - //if (i >= (ITERATIONS - 4) ) WR(0x04, 0x0f); - } - } while (bus_addr[curbuf] != hwptr); - -#ifdef EXIT_ON_EMPTY -#ifdef USE_64 - if (desc[1] != 0) -#else // 32bit - if (desc[2] != 0) -#endif - { - if (bus_addr[curbuf] == hwptr) { - empty = 1; - break; - } - } -#endif - - WR(0x58, curbuf + 1); - //printf("WR %d\n", curbuf + 1); - //printf("%u (%lu)\n", curbuf, j); - curptr = hwptr; - - } - - - - // ****************************************************************** - // **** Read performance and stop DMA ******* - // ****************************************************************** - - gettimeofday(&end, NULL); - WR(0x04, 0x00); - WR(0x01, 0x00); - RD(0x28, perf_counter); - - - - iterations_completed = i; - buffers_filled = curbuf; - if (empty) printf("* DMA: Empty FIFO! Last iteration: %li of %li\n", i+1, ITERATIONS); - printf ("* DMA: Stop\n\n"); - -#ifdef CHECK_RESULTS - printf ("First value:\t %08x\n", temp_data[0][0][0]); - printf ("Last value:\t %08x\n\n", temp_data[ITERATIONS-1][BUFFERS-1][(PAGE_SIZE/4)-4]); -#endif - - // ****************************************************************** - // **** Performance ******* - // ****************************************************************** - printf("Iterations done: %d\n", iterations_completed); - printf("Buffers filled on last iteration: %d\n", buffers_filled); - - - run_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); - size = (long long int) (( BUFFERS * (iterations_completed) + buffers_filled) * HUGE_PAGE * PAGE_SIZE); - size_mb = (long long int) (( BUFFERS * (iterations_completed) + buffers_filled) * HUGE_PAGE * 4 / 1024); - printf("Performance: transfered %zu Mbytes in %zu us using %d buffers\n", (size_mb), run_time, BUFFERS); - //printf("Buffers: \t %d \n", BUFFERS); - //printf("Buf_Size: \t %d \n", PAGE_SIZE); - //printf("Perf_counter: \t %f \n", perf_counter); - performance = ((size_mb * FPGA_CLOCK * 1000000)/(perf_counter*256)); - printf("DMA perf counter:\t%d\n", (int)perf_counter); - printf("DMA side:\t\t%.3lf MB/s\n", performance); - printf("PC side:\t\t%.3lf MB/s\n\n", 1000000. * size_mb / run_time ); - - // ****************************************************************** - // **** Read Data ******* - // ****************************************************************** - - - #ifdef PRINT_RESULTS - printf("Writing Data to HDD... \n"); - for (i=0; i < iterations_completed; i++) { - for (j=0; j < BUFFERS; j++) - { - Output = fopen("data.out", "a"); - fwrite(temp_data[i][j], 4096, 1, Output); - fclose(Output); - } - loadBar(i+1, ITERATIONS, ITERATIONS, 30); - } - // Save last partially filled iteration - for (j=0; j < buffers_filled; j++) - { - Output = fopen("data.out", "a"); - fwrite(temp_data[iterations_completed][j], 4096, 1, Output); - fclose(Output); - } - printf("Data saved in data.out. \n"); - #endif - - #ifdef CHECK_RESULTS - err = 0; - error_log = fopen ("error_log.txt", "a"); - printf("\nChecking data ...\n"); - for (i=0; i < iterations_completed; i++) { - for (j = 0; j < BUFFERS; j++) { - for (k = 0; k < 1024 ; k++) - { - mem_diff = ((uint32_t)temp_data[i][j][k] - (uint32_t)temp_data[i][j][k+1]); - //if ((mem_diff == 1) || (mem_diff == (-7)) || (k == 1023) ) - if ((mem_diff == -1) || (k == 1023) ) - {;} - else { - fprintf(error_log, "Error in: \t IT %li \t BUF : %li \t OFFSET: %li \t | %08x --> %08x - DIFF: %d \n", i, j, k, temp_data[i][j][k], temp_data[i][j][k+1], mem_diff); - err++; - } - } - if (j != BUFFERS-1) { - // Check first and Last - mem_diff = (uint32_t)(temp_data[i][j+1][0] - temp_data[i][j][1023]); - if (mem_diff == (1)) - {;} - else { - fprintf(error_log, "Error_2 in: \t IT %li \t BUF : %li \t OFFSET: %li \t | %08x --> %08x - DIFF: %d \n", i, j, k, temp_data[i][j+1][0], temp_data[i][j][1023], mem_diff); - err++; - } - } - - } - loadBar(i+1, ITERATIONS, ITERATIONS, 30); - } - for (j = 0; j < buffers_filled; j++) { - for (k = 0; k < 1024 ; k++) - { - mem_diff = ((uint32_t)temp_data[iterations_completed][j][k] - (uint32_t)temp_data[iterations_completed][j][k+1]); - if ((mem_diff == -1) || (k == 1023) ) - {;} - else { - fprintf(error_log, "Error in: \t IT %li \t BUF : %li \t OFFSET: %li \t | %08x --> %08x - DIFF: %d \n", iterations_completed, j, k, temp_data[iterations_completed][j][k], temp_data[iterations_completed][j][k+1], mem_diff); - err++; - } - } - if (j != buffers_filled-1) { - // Check first and Last - mem_diff = (uint32_t)(temp_data[i][j+1][0] - temp_data[i][j][1023]); - if (mem_diff == (1)) - {;} - else { - fprintf(error_log, "Error_2 in: \t IT %li \t BUF : %li \t OFFSET: %li \t | %08x --> %08x - DIFF: %d \n", iterations_completed, j, k, temp_data[iterations_completed][j+1][0], temp_data[iterations_completed][j][1023], mem_diff); - err++; - } - } - } - if (err != 0) printf("\rChecking data: \xE2\x9C\x98 %d errors found \n See \"error_log.txt\" for details \n\n", err); - else printf("\rChecking data: \xE2\x9C\x93 no errors found \n\n"); - fclose(error_log); - #endif - - - // *********** Free Memory -#ifdef CHECK_RESULTS - for (i=0; i < ITERATIONS; i++) { - for (j=0; j < BUFFERS; j++) - { - free(temp_data[i][j]); - } - } -#endif CHECK_RESULTS - - pcilib_free_kernel_memory(pci, kbuf, free_flags); - pcilib_free_kernel_memory(pci, kdesc, free_flags); - pcilib_disable_irq(pci, 0); - pcilib_unmap_bar(pci, BAR, bar); - pcilib_close(pci); - -// shmdt(shmid); -// shmctl(shmid, IPC_RMID, NULL); - -} diff --git a/apps/pio_test.c b/apps/pio_test.c deleted file mode 100644 index 84439ee..0000000 --- a/apps/pio_test.c +++ /dev/null @@ -1,96 +0,0 @@ -#define _BSD_SOURCE -#define _POSIX_C_SOURCE 199309L -#include -#include -#include -#include -#include -#include -#include - -#include "pcilib.h" -#include "irq.h" -#include "kmem.h" - -#define DEVICE "/dev/fpga0" -//#define REALTIME - -#define BAR PCILIB_BAR0 -#define BITS 32 -#define MASK ((1ll << BITS) - 1) - - -#define WR(addr, value) { *(uint32_t*)(bar + addr) = value; } -#define RD(addr, value) { value = *(uint32_t*)(bar + addr); } - -unsigned long long bits[BITS]; - -int main(int argc, char *argv[]) { - uint32_t i, j; - pcilib_t *pci; - uint32_t reg, value, diff, errors; - void* volatile bar; - - unsigned long long attempts = 0, failures = 0; - - if (argc < 2) { - printf("Usage: %s \n", argv[0]); - exit(0); - } - - if (sscanf(argv[1], "%x", ®) != 1) { - printf("Can't parse register %s\n", argv[1]); - exit(1); - } - -#ifdef REALTIME - pid_t pid; - struct sched_param sched = {0}; - - pid = getpid(); - sched.sched_priority = sched_get_priority_min(SCHED_FIFO); - if (sched_setscheduler(pid, SCHED_FIFO, &sched)) - printf("Warning: not able to get real-time priority\n"); -#endif /* REALTIME */ - - pci = pcilib_open(DEVICE, PCILIB_MODEL_DETECT); - if (!pci) { - printf("pcilib_open\n"); - exit(1); - } - - bar = pcilib_map_bar(pci, BAR); - if (!bar) { - pcilib_close(pci); - printf("map bar\n"); - exit(1); - } - - for (i = 0; 1; i++) { - WR(reg, (i%MASK)); - RD(reg, value); - - attempts++; - if (value != (i%MASK)) { - failures++; - - diff = value ^ (i%MASK); - for (errors = 0, j = 0; j < BITS; j++) - if (diff&(1< -#include -#include -#include -#include -#include -#include -#include - -#include "pcilib.h" -#include "irq.h" -#include "kmem.h" - -#define DEVICE "/dev/fpga0" -#define BAR PCILIB_BAR0 -#define USE PCILIB_KMEM_USE(PCILIB_KMEM_USE_USER, 1) -#define STATIC_REGION 0x80000000 // to reserve 512 MB at the specified address, add "memmap=512M$2G" to kernel parameters -#define BUFFERS 1 -#define ITERATIONS 100 -#define TLP_SIZE 64 -#define HUGE_PAGE 4096 // number of pages per huge page -#define PAGE_SIZE 4096 // other values are not supported in the kernel -#define TIMEOUT 100000 - -/* IRQs are slow for some reason. REALTIME mode is slower. Adding delays does not really help, -otherall we have only 3 checks in average. Check ready seems to be not needed and adds quite -much extra time */ -#define USE_IRQ -//#define CHECK_READY -//#define REALTIME -//#define ADD_DELAYS -#define CHECK_RESULT - -//#define WR(addr, value) { val = value; pcilib_write(pci, BAR, addr, sizeof(val), &val); } -//#define RD(addr, value) { pcilib_read(pci, BAR, addr, sizeof(val), &val); value = val; } -#define WR(addr, value) { *(uint32_t*)(bar + addr + offset) = value; } -#define RD(addr, value) { value = *(uint32_t*)(bar + addr + offset); } - -static void fail(const char *msg, ...) { - va_list va; - - va_start(va, msg); - vprintf(msg, va); - va_end(va); - printf("\n"); - - exit(-1); -} - -void hpsleep(size_t ns) { - struct timespec wait, tv; - - clock_gettime(CLOCK_REALTIME, &wait); - - wait.tv_nsec += ns; - if (wait.tv_nsec > 999999999) { - wait.tv_sec += 1; - wait.tv_nsec = 1000000000 - wait.tv_nsec; - } - - do { - clock_gettime(CLOCK_REALTIME, &tv); - } while ((wait.tv_sec > tv.tv_sec)||((wait.tv_sec == tv.tv_sec)&&(wait.tv_nsec > tv.tv_nsec))); -} - - -int main() { - int err; - long i, j; - pcilib_t *pci; - pcilib_kmem_handle_t *kbuf; - uint32_t status; - struct timeval start, end; - size_t size, run_time; - void* volatile bar; - uintptr_t bus_addr[BUFFERS]; - - pcilib_bar_t bar_tmp = BAR; - uintptr_t offset = 0; - - pcilib_kmem_flags_t clean_flags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT|PCILIB_KMEM_FLAG_EXCLUSIVE; - -#ifdef ADD_DELAYS - long rpt = 0, rpt2 = 0; - size_t best_time; - best_time = 1000000000L * HUGE_PAGE * PAGE_SIZE / (4L * 1024 * 1024 * 1024); -#endif /* ADD_DELAYS */ - -#ifdef REALTIME - pid_t pid; - struct sched_param sched = {0}; - - pid = getpid(); - sched.sched_priority = sched_get_priority_min(SCHED_FIFO); - if (sched_setscheduler(pid, SCHED_FIFO, &sched)) - printf("Warning: not able to get real-time priority\n"); -#endif /* REALTIME */ - - pci = pcilib_open(DEVICE, PCILIB_MODEL_DETECT); - if (!pci) fail("pcilib_open"); - - bar = pcilib_map_bar(pci, BAR); - if (!bar) { - pcilib_close(pci); - fail("map bar"); - } - - pcilib_detect_address(pci, &bar_tmp, &offset, 1); - - // Reset - WR(0x00, 1) - usleep(1000); - WR(0x00, 0) - - pcilib_enable_irq(pci, PCILIB_IRQ_TYPE_ALL, 0); - pcilib_clear_irq(pci, PCILIB_IRQ_SOURCE_DEFAULT); - - pcilib_clean_kernel_memory(pci, USE, clean_flags); - -#ifdef STATIC_REGION - kbuf = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_REGION_C2S, BUFFERS, HUGE_PAGE * PAGE_SIZE, STATIC_REGION, USE, 0); -#else /* STATIC_REGION */ - kbuf = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_DMA_C2S_PAGE, BUFFERS, HUGE_PAGE * PAGE_SIZE, 4096, USE, 0); -#endif /* STATIC_REGION */ - - if (!kbuf) { - printf("KMem allocation failed\n"); - exit(0); - } - - -#ifdef CHECK_RESULT - volatile uint32_t *ptr0 = pcilib_kmem_get_block_ua(pci, kbuf, 0); - - memset((void*)ptr0, 0, (HUGE_PAGE * PAGE_SIZE)); - - for (i = 0; i < (HUGE_PAGE * PAGE_SIZE / 4); i++) { - if (ptr0[i] != 0) break; - } - if (i < (HUGE_PAGE * PAGE_SIZE / 4)) { - printf("Initialization error in position %lu, value = %x\n", i * 4, ptr0[i]); - } -#endif /* CHECK_RESULT */ - - WR(0x04, 0) - WR(0x0C, TLP_SIZE) - WR(0x10, (HUGE_PAGE * (PAGE_SIZE / (4 * TLP_SIZE)))) - WR(0x14, 0x13131313) - - for (j = 0; j < BUFFERS; j++ ) { - bus_addr[j] = pcilib_kmem_get_block_ba(pci, kbuf, j); - } - - gettimeofday(&start, NULL); - - for (i = 0; i < ITERATIONS; i++) { - for (j = 0; j < BUFFERS; j++ ) { -// uintptr_t ba = pcilib_kmem_get_block_ba(pci, kbuf, j); -// WR(0x08, ba) - WR(0x08, bus_addr[j]); - WR(0x04, 0x01) - -#ifdef USE_IRQ - err = pcilib_wait_irq(pci, PCILIB_IRQ_SOURCE_DEFAULT, TIMEOUT, NULL); - if (err) printf("Timeout waiting for IRQ, err: %i\n", err); - - RD(0x04, status); - if ((status&0xFFFF) != 0x101) printf("Invalid status %x\n", status); -// WR(0x04, 0x00); -#else /* USE_IRQ */ -# ifdef ADD_DELAYS -// hpsleep(best_time); - do { - rpt++; - RD(0x04, status); - } while (status != 0x101); -# else /* ADD_DELAYS */ - do { - RD(0x04, status); - } while (status != 0x101); -# endif /* ADD_DELAYS */ -#endif /* USE_IRQ */ - - WR(0x00, 1) -#ifdef CHECK_READY - do { - rpt2++; - RD(0x04, status); - } while (status != 0); -#endif /* CHECK_READY */ - WR(0x00, 0) - } - } - gettimeofday(&end, NULL); - -#ifdef CHECK_RESULT - pcilib_kmem_sync_block(pci, kbuf, PCILIB_KMEM_SYNC_FROMDEVICE, 0); - - for (i = 0; i < (HUGE_PAGE * PAGE_SIZE / 4); i++) { -// printf("%lx ", ptr0[i]); - if (ptr0[i] != 0x13131313) break; - } - if (i < (HUGE_PAGE * PAGE_SIZE / 4)) { - printf("Error in position %lu, value = %x\n", i * 4, ptr0[i]); - } -#endif /* CHECK_RESULT */ - - pcilib_free_kernel_memory(pci, kbuf, 0); - pcilib_disable_irq(pci, 0); - pcilib_unmap_bar(pci, BAR, bar); - pcilib_close(pci); - - run_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); - size = (long long int)ITERATIONS * BUFFERS * HUGE_PAGE * PAGE_SIZE; - - printf("%.3lf GB/s: transfered %zu bytes in %zu us using %u buffers\n", 1000000. * size / run_time / 1024 / 1024 / 1024, size, run_time, BUFFERS); - -# ifdef ADD_DELAYS - printf("Repeats: %lf, %lf\n",1. * rpt / (ITERATIONS * BUFFERS), 1. * rpt2 / (ITERATIONS * BUFFERS)); -#endif /* USE_IRQ */ - - -} diff --git a/base.c b/base.c new file mode 100644 index 0000000..3d06bf3 --- /dev/null +++ b/base.c @@ -0,0 +1,684 @@ +#define _IPECAMERA_IMAGE_C +#define _BSD_SOURCE +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "private.h" +#include "model.h" +#include "reader.h" +#include "events.h" +#include "data.h" + + +#define FIND_REG(var, bank, name) \ + ctx->var = pcilib_find_register(pcilib, bank, name); \ + if (ctx->var == PCILIB_REGISTER_INVALID) { \ + err = PCILIB_ERROR_NOTFOUND; \ + pcilib_error("Unable to find a %s register", name); \ + } + + +#define GET_REG(reg, var) \ + if (!err) { \ + err = pcilib_read_register_by_id(pcilib, ctx->reg, &var); \ + if (err) { \ + pcilib_error("Error reading %s register", model_info->registers[ctx->reg].name); \ + } \ + } + +#define SET_REG(reg, val) \ + if (!err) { \ + err = pcilib_write_register_by_id(pcilib, ctx->reg, val); \ + if (err) { \ + pcilib_error("Error writting %s register", model_info->registers[ctx->reg].name); \ + } \ + } + +#define CHECK_REG(reg, check) \ + if (!err) { \ + err = pcilib_read_register_by_id(pcilib, ctx->reg, &value); \ + if (err) { \ + pcilib_error("Error reading %s register", model_info->registers[ctx->reg].name); \ + } \ + if (value != check) { \ + pcilib_error("Unexpected value (0x%lx) of register %s", value, model_info->registers[ctx->reg].name); \ + err = PCILIB_ERROR_INVALID_DATA; \ + } \ + } + +#define CHECK_STATUS() + //CHECK_REG(status_reg, IPECAMERA_GET_EXPECTED_STATUS(ctx)) + +#define CHECK_VALUE(value, val) \ + if ((!err)&&(value != val)) { \ + pcilib_error("Unexpected value (0x%x) in data stream (0x%x is expected)", value, val); \ + err = PCILIB_ERROR_INVALID_DATA; \ + } + +#define CHECK_FLAG(flag, check, ...) \ + if ((!err)&&(!(check))) { \ + pcilib_error("Unexpected value (0x%x) of " flag, __VA_ARGS__); \ + err = PCILIB_ERROR_INVALID_DATA; \ + } + + +pcilib_context_t *ipecamera_init(pcilib_t *pcilib) { + int err = 0; + + const pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib); + + ipecamera_t *ctx = malloc(sizeof(ipecamera_t)); + + if (ctx) { + pcilib_register_value_t value; + + memset(ctx, 0, sizeof(ipecamera_t)); + + ctx->buffer_size = IPECAMERA_DEFAULT_BUFFER_SIZE; + ctx->dim.bpp = sizeof(ipecamera_pixel_t) * 8; + + // We need DMA engine initialized to resolve DMA registers +// FIND_REG(packet_len_reg, "fpga", "xrawdata_packet_length"); + + FIND_REG(status_reg, "fpga", "status"); + FIND_REG(control_reg, "fpga", "control"); + + FIND_REG(status2_reg, "fpga", "status2"); + FIND_REG(status3_reg, "fpga", "status3"); + + FIND_REG(n_lines_reg, "cmosis", "cmosis_number_lines"); + FIND_REG(line_reg, "cmosis", "cmosis_start1"); + FIND_REG(exposure_reg, "cmosis", "cmosis_exp_time"); + FIND_REG(flip_reg, "cmosis", "cmosis_image_flipping"); + + FIND_REG(firmware_version_reg, "fpga", "firmware_version"); + FIND_REG(adc_resolution_reg, "fpga", "adc_resolution"); + FIND_REG(output_mode_reg, "fpga", "output_mode"); + + FIND_REG(max_frames_reg, "fpga", "ddr_max_frames"); + FIND_REG(num_frames_reg, "fpga", "ddr_num_frames"); + + + GET_REG(firmware_version_reg, value); + switch (value) { + case 5: + ctx->firmware = value; + break; + default: + ctx->firmware = 5; + pcilib_warning("Unsupported version of firmware (%lu)", value); + } + +#ifdef IPECAMERA_BUG_POSTPONED_READ + GET_REG(max_frames_reg, value); + if ((value + IPECAMERA_RESERVE_BUFFERS + 3) > ctx->buffer_size) { + ctx->buffer_size = (value + 1) + IPECAMERA_RESERVE_BUFFERS + 2; + } +#endif /* IPECAMERA_BUG_POSTPONED_READ */ + + + ctx->rdma = PCILIB_DMA_ENGINE_INVALID; + ctx->wdma = PCILIB_DMA_ENGINE_INVALID; + + if (err) { + free(ctx); + return NULL; + } + } + + return (pcilib_context_t*)ctx; +} + +void ipecamera_free(pcilib_context_t *vctx) { + if (vctx) { + ipecamera_t *ctx = (ipecamera_t*)vctx; + ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); + free(ctx); + } +} + +pcilib_dma_context_t *ipecamera_init_dma(pcilib_context_t *vctx) { + ipecamera_t *ctx = (ipecamera_t*)vctx; + + const pcilib_model_description_t *model_info = pcilib_get_model_description(vctx->pcilib); + if ((!model_info->dma)||(!model_info->dma->api)||(!model_info->dma->api->init)) { + pcilib_error("The DMA engine is not configured in model"); + return NULL; + } + + if (ctx->firmware) { + return model_info->dma->api->init(vctx->pcilib, NULL, NULL); + } else { + return model_info->dma->api->init(vctx->pcilib, "pci", NULL); + } +} + + +int ipecamera_set_buffer_size(ipecamera_t *ctx, int size) { + if (ctx->started) { + pcilib_error("Can't change buffer size while grabbing"); + return PCILIB_ERROR_INVALID_REQUEST; + } + + if (size < 2) { + pcilib_error("The buffer size is too small"); + return PCILIB_ERROR_INVALID_REQUEST; + } + + if (((size^(size-1)) < size) < size) { + pcilib_error("The buffer size is not power of 2"); + } + + ctx->buffer_size = size; + + return 0; +} + +int ipecamera_reset(pcilib_context_t *vctx) { + int err = 0; + ipecamera_t *ctx = (ipecamera_t*)vctx; + pcilib_t *pcilib = vctx->pcilib; + + pcilib_register_t control, status; + pcilib_register_value_t value; + + if (!ctx) { + pcilib_error("IPECamera imaging is not initialized"); + return PCILIB_ERROR_NOTINITIALIZED; + } + + if (!ctx->firmware) { + pcilib_warning("Unsupported version of firmware (%lu)", ctx->firmware); + return 0; + } + + pcilib = vctx->pcilib; + control = ctx->control_reg; + status = ctx->status_reg; + + // Set Reset bit to CMOSIS + err = pcilib_write_register_by_id(pcilib, control, 0x1e4); + if (err) { + pcilib_error("Error setting FPGA reset bit"); + return err; + } + usleep(IPECAMERA_SLEEP_TIME); + + // Remove Reset bit to CMOSIS + err = pcilib_write_register_by_id(pcilib, control, 0x1e1); + if (err) { + pcilib_error("Error reseting FPGA reset bit"); + return err; + } + usleep(IPECAMERA_SLEEP_TIME); + + // Special settings for CMOSIS v.2 + value = 01; err = pcilib_write_register_space(pcilib, "cmosis", 115, 1, &value); + if (err) { + pcilib_error("Error setting CMOSIS configuration"); + return err; + } + usleep(IPECAMERA_SLEEP_TIME); + + value = 07; err = pcilib_write_register_space(pcilib, "cmosis", 82, 1, &value); + if (err) { + pcilib_error("Error setting CMOSIS configuration"); + return err; + } + usleep(IPECAMERA_SLEEP_TIME); + + // Set default parameters + err = pcilib_write_register_by_id(pcilib, control, IPECAMERA_IDLE); + if (err) { + pcilib_error("Error bringing FPGA in default mode"); + return err; + } + + usleep(10000); + + + CHECK_STATUS(); + if (err) { + err = pcilib_read_register_by_id(pcilib, status, &value); + + if (err) pcilib_error("Error reading status register"); + else pcilib_error("Camera returns unexpected status (status: %lx)", value); + + return PCILIB_ERROR_VERIFY; + } + + // DS: Get rid of pending DMA data + + return 0; +} + + +int ipecamera_start(pcilib_context_t *vctx, pcilib_event_t event_mask, pcilib_event_flags_t flags) { + int i; + int err = 0; + + ipecamera_t *ctx = (ipecamera_t*)vctx; + pcilib_t *pcilib = vctx->pcilib; + pcilib_register_value_t value; + + const pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib); + + pthread_attr_t attr; + struct sched_param sched; + + if (!ctx) { + pcilib_error("IPECamera imaging is not initialized"); + return PCILIB_ERROR_NOTINITIALIZED; + } + + if (!ctx->firmware) { + pcilib_error("Unsupported version of firmware (%lu)", ctx->firmware); + return PCILIB_ERROR_INVALID_REQUEST; + } + + if (ctx->started) { + pcilib_error("IPECamera grabbing is already started"); + return PCILIB_ERROR_INVALID_REQUEST; + } + + ctx->event_id = 0; + ctx->preproc_id = 0; + ctx->reported_id = 0; + ctx->buffer_pos = 0; + ctx->parse_data = (flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY)?0:1; + ctx->cur_size = 0; + + ctx->dim.width = IPECAMERA_WIDTH; + ctx->dim.height = IPECAMERA_MAX_LINES; +// GET_REG(n_lines_reg, ctx->dim.height); + + GET_REG(output_mode_reg, value); + switch (value) { + case IPECAMERA_MODE_16_CHAN_IO: + ctx->cmosis_outputs = 16; + break; + case IPECAMERA_MODE_4_CHAN_IO: + ctx->cmosis_outputs = 4; + break; + default: + pcilib_error("IPECamera reporting invalid output_mode 0x%lx", value); + return PCILIB_ERROR_INVALID_STATE; + } + + ipecamera_compute_buffer_size(ctx, ctx->dim.height); + + ctx->raw_size = ctx->cur_raw_size; + ctx->full_size = ctx->cur_full_size; + ctx->padded_size = ctx->cur_padded_size; + + ctx->image_size = ctx->dim.width * ctx->dim.height; + + + GET_REG(max_frames_reg, value); + ctx->max_frames = value; + + ctx->buffer = malloc(ctx->padded_size * ctx->buffer_size); + if (!ctx->buffer) { + ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); + pcilib_error("Unable to allocate ring buffer (%lu bytes)", ctx->padded_size * ctx->buffer_size); + return PCILIB_ERROR_MEMORY; + } + + ctx->image = (ipecamera_pixel_t*)malloc(ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t)); + if (!ctx->image) { + ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); + pcilib_error("Unable to allocate image buffer (%lu bytes)", ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t)); + return PCILIB_ERROR_MEMORY; + } + + ctx->cmask = malloc(ctx->dim.height * ctx->buffer_size * sizeof(ipecamera_change_mask_t)); + if (!ctx->cmask) { + ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); + pcilib_error("Unable to allocate change-mask buffer"); + return PCILIB_ERROR_MEMORY; + } + + ctx->frame = (ipecamera_frame_t*)malloc(ctx->buffer_size * sizeof(ipecamera_frame_t)); + if (!ctx->frame) { + ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); + pcilib_error("Unable to allocate frame-info buffer"); + return PCILIB_ERROR_MEMORY; + } + + memset(ctx->frame, 0, ctx->buffer_size * sizeof(ipecamera_frame_t)); + + for (i = 0; i < ctx->buffer_size; i++) { + err = pthread_rwlock_init(&ctx->frame[i].mutex, NULL); + if (err) break; + } + + ctx->frame_mutex_destroy = i; + + if (err) { + ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); + pcilib_error("Initialization of rwlock mutexes for frame synchronization has failed"); + return PCILIB_ERROR_FAILED; + } + + ctx->ipedec = ufo_decoder_new(ctx->dim.height, ctx->dim.width, NULL, 0); + if (!ctx->ipedec) { + ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); + pcilib_error("Unable to initialize IPECamera decoder library"); + return PCILIB_ERROR_FAILED; + } + + if (!err) { + ctx->rdma = pcilib_find_dma_by_addr(vctx->pcilib, PCILIB_DMA_FROM_DEVICE, IPECAMERA_DMA_ADDRESS); + if (ctx->rdma == PCILIB_DMA_ENGINE_INVALID) { + err = PCILIB_ERROR_NOTFOUND; + pcilib_error("The C2S channel of IPECamera DMA Engine (%u) is not found", IPECAMERA_DMA_ADDRESS); + } else { + err = pcilib_start_dma(vctx->pcilib, ctx->rdma, PCILIB_DMA_FLAGS_DEFAULT); + if (err) { + ctx->rdma = PCILIB_DMA_ENGINE_INVALID; + pcilib_error("Failed to initialize C2S channel of IPECamera DMA Engine (%u)", IPECAMERA_DMA_ADDRESS); + } + } + } + +/* + if (!err) { + ctx->wdma = pcilib_find_dma_by_addr(vctx->pcilib, PCILIB_DMA_TO_DEVICE, IPECAMERA_DMA_ADDRESS); + if (ctx->wdma == PCILIB_DMA_ENGINE_INVALID) { + err = PCILIB_ERROR_NOTFOUND; + pcilib_error("The S2C channel of IPECamera DMA Engine (%u) is not found", IPECAMERA_DMA_ADDRESS); + } else { + err = pcilib_start_dma(vctx->pcilib, ctx->wdma, PCILIB_DMA_FLAGS_DEFAULT); + if (err) { + ctx->wdma = PCILIB_DMA_ENGINE_INVALID; + pcilib_error("Failed to initialize S2C channel of IPECamera DMA Engine (%u)", IPECAMERA_DMA_ADDRESS); + } + } + } +*/ + +/* + SET_REG(packet_len_reg, IPECAMERA_DMA_PACKET_LENGTH); +*/ + + if (err) { + ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); + return err; + } + + // Clean DMA +#ifndef IPECAMERA_BUG_POSTPONED_READ + err = pcilib_skip_dma(vctx->pcilib, ctx->rdma); + if (err) { + ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); + pcilib_error("Can't start grabbing, device continuously writes unexpected data using DMA engine"); + return err; + } +#endif /* ! IPECAMERA_BUG_POSTPONED_READ */ + + if (vctx->params.autostop.duration) { + gettimeofday(&ctx->autostop.timestamp, NULL); + ctx->autostop.timestamp.tv_usec += vctx->params.autostop.duration % 1000000; + if (ctx->autostop.timestamp.tv_usec > 999999) { + ctx->autostop.timestamp.tv_sec += 1 + vctx->params.autostop.duration / 1000000; + ctx->autostop.timestamp.tv_usec -= 1000000; + } else { + ctx->autostop.timestamp.tv_sec += vctx->params.autostop.duration / 1000000; + } + } + + if (vctx->params.autostop.max_events) { + ctx->autostop.evid = vctx->params.autostop.max_events; + } + + if ((ctx->parse_data)&&(flags&PCILIB_EVENT_FLAG_PREPROCESS)) { + ctx->n_preproc = pcilib_get_cpu_count(); + + // it would be greate to detect hyperthreading cores and ban them + switch (ctx->n_preproc) { + case 1: break; + case 2 ... 3: ctx->n_preproc -= 1; break; + default: ctx->n_preproc -= 2; break; + } + + if ((vctx->params.parallel.max_threads)&&(vctx->params.parallel.max_threads < ctx->n_preproc)) + ctx->n_preproc = vctx->params.parallel.max_threads; + + ctx->preproc = (ipecamera_preprocessor_t*)malloc(ctx->n_preproc * sizeof(ipecamera_preprocessor_t)); + if (!ctx->preproc) { + ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); + pcilib_error("Unable to allocate memory for preprocessor contexts"); + return PCILIB_ERROR_MEMORY; + } + + memset(ctx->preproc, 0, ctx->n_preproc * sizeof(ipecamera_preprocessor_t)); + + err = pthread_mutex_init(&ctx->preproc_mutex, NULL); + if (err) { + ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); + pcilib_error("Failed to initialize event mutex"); + return PCILIB_ERROR_FAILED; + } + ctx->preproc_mutex_destroy = 1; + + + ctx->run_preprocessors = 1; + for (i = 0; i < ctx->n_preproc; i++) { + ctx->preproc[i].i = i; + ctx->preproc[i].ipecamera = ctx; + err = pthread_create(&ctx->preproc[i].thread, NULL, ipecamera_preproc_thread, ctx->preproc + i); + if (err) { + err = PCILIB_ERROR_FAILED; + break; + } else { + ctx->preproc[i].started = 1; + } + } + + if (err) { + ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); + pcilib_error("Failed to schedule some of the preprocessor threads"); + return err; + } + } else { + ctx->n_preproc = 0; + } + + ctx->started = 1; + ctx->run_reader = 1; + + pthread_attr_init(&attr); + + if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) { + pcilib_warning("Can't schedule a real-time thread, you may consider running as root"); + } else { + sched.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1; // Let 1 priority for something really critcial + pthread_attr_setschedparam(&attr, &sched); + } + + if (pthread_create(&ctx->rthread, &attr, &ipecamera_reader_thread, (void*)ctx)) { + ctx->started = 0; + ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); + err = PCILIB_ERROR_FAILED; + } + + pthread_attr_destroy(&attr); + + return err; +} + + +int ipecamera_stop(pcilib_context_t *vctx, pcilib_event_flags_t flags) { + int i; + int err; + void *retcode; + ipecamera_t *ctx = (ipecamera_t*)vctx; + + if (!ctx) { + pcilib_error("IPECamera imaging is not initialized"); + return PCILIB_ERROR_NOTINITIALIZED; + } + + if (flags&PCILIB_EVENT_FLAG_STOP_ONLY) { + ctx->run_reader = 0; + return 0; + } + + if (ctx->started) { + ctx->run_reader = 0; + err = pthread_join(ctx->rthread, &retcode); + if (err) pcilib_error("Error joining the reader thread"); + } + + if (ctx->preproc) { + ctx->run_preprocessors = 0; + + for (i = 0; i < ctx->n_preproc; i++) { + if (ctx->preproc[i].started) { + pthread_join(ctx->preproc[i].thread, &retcode); + ctx->preproc[i].started = 0; + } + } + + if (ctx->preproc_mutex_destroy) { + pthread_mutex_destroy(&ctx->preproc_mutex); + ctx->preproc_mutex_destroy = 0; + } + + free(ctx->preproc); + ctx->preproc = NULL; + } + + if (ctx->frame_mutex_destroy) { + for (i = 0; i < ctx->frame_mutex_destroy; i++) { + pthread_rwlock_destroy(&ctx->frame[i].mutex); + } + ctx->frame_mutex_destroy = 0; + } + + + if (ctx->wdma != PCILIB_DMA_ENGINE_INVALID) { + pcilib_stop_dma(vctx->pcilib, ctx->wdma, PCILIB_DMA_FLAGS_DEFAULT); + ctx->wdma = PCILIB_DMA_ENGINE_INVALID; + } + + if (ctx->rdma != PCILIB_DMA_ENGINE_INVALID) { + pcilib_stop_dma(vctx->pcilib, ctx->rdma, PCILIB_DMA_FLAGS_DEFAULT); + ctx->rdma = PCILIB_DMA_ENGINE_INVALID; + } + + while (ctx->streaming) { + usleep(IPECAMERA_NOFRAME_SLEEP); + } + + if (ctx->ipedec) { + ufo_decoder_free(ctx->ipedec); + ctx->ipedec = NULL; + } + + if (ctx->frame) { + free(ctx->frame); + ctx->frame = NULL; + } + + if (ctx->cmask) { + free(ctx->cmask); + ctx->cmask = NULL; + } + + if (ctx->image) { + free(ctx->image); + ctx->image = NULL; + } + + if (ctx->buffer) { + free(ctx->buffer); + ctx->buffer = NULL; + } + + + memset(&ctx->autostop, 0, sizeof(ipecamera_autostop_t)); + + ctx->event_id = 0; + ctx->reported_id = 0; + ctx->buffer_pos = 0; + ctx->started = 0; + + return 0; +} + + +int ipecamera_trigger(pcilib_context_t *vctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) { + int err = 0; + pcilib_register_value_t value; + + ipecamera_t *ctx = (ipecamera_t*)vctx; + pcilib_t *pcilib = vctx->pcilib; + + const pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib); + + if (!ctx) { + pcilib_error("IPECamera imaging is not initialized"); + return PCILIB_ERROR_NOTINITIALIZED; + } + + if (!ctx->firmware) { + pcilib_error("Unsupported version of firmware (%lu)", ctx->firmware); + return PCILIB_ERROR_INVALID_REQUEST; + } + + pcilib_sleep_until_deadline(&ctx->next_trigger); +/* + GET_REG(num_frames_reg, value); + if (value == ctx->max_frames) { + return PCILIB_ERROR_BUSY; + } +*/ + + GET_REG(status2_reg, value); + if (value&0x40000000) { +// printf("%x\n", value); +// GET_REG(status3_reg, value); +// printf("3: %x\n", value); +// GET_REG(status_reg, value); +// printf("1: %x\n", value); + +#ifdef IPECAMERA_TRIGGER_WAIT_IDLE + if (IPECAMERA_TRIGGER_WAIT_IDLE) { + struct timeval deadline; + pcilib_calc_deadline(&deadline, IPECAMERA_TRIGGER_WAIT_IDLE); + do { + usleep(IPECAMERA_READ_STATUS_DELAY); + GET_REG(status2_reg, value); + } while ((value&0x40000000)&&(pcilib_calc_time_to_deadline(&deadline) > 0)); + } + if (value&0x40000000) +#endif /* IPECAMERA_TRIGGER_WAIT_IDLE */ + return PCILIB_ERROR_BUSY; + } + + GET_REG(control_reg, value); + SET_REG(control_reg, value|IPECAMERA_FRAME_REQUEST); + usleep(IPECAMERA_WAIT_FRAME_RCVD_TIME); + //DS: CHECK_REG(status_reg, IPECAMERA_EXPECTED_STATUS); + SET_REG(control_reg, value); + + // We need to compute it differently, on top of that add exposure time and the time FPGA takes to read frame from CMOSIS + pcilib_calc_deadline(&ctx->next_trigger, IPECAMERA_NEXT_FRAME_DELAY); + + return 0; +} diff --git a/base.h b/base.h new file mode 100644 index 0000000..beb3e1f --- /dev/null +++ b/base.h @@ -0,0 +1,24 @@ +#ifndef _IPECAMERA_BASE_H +#define _IPECAMERA_BASE_H + +#include + +#include +#include "ipecamera.h" + +pcilib_context_t *ipecamera_init(pcilib_t *pcilib); +void ipecamera_free(pcilib_context_t *ctx); + +pcilib_dma_context_t *ipecamera_init_dma(pcilib_context_t *ctx); + +int ipecamera_reset(pcilib_context_t *ctx); +int ipecamera_start(pcilib_context_t *ctx, pcilib_event_t event_mask, pcilib_event_flags_t flags); +int ipecamera_stop(pcilib_context_t *ctx, pcilib_event_flags_t flags); +int ipecamera_trigger(pcilib_context_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data); +int ipecamera_stream(pcilib_context_t *vctx, pcilib_event_callback_t callback, void *user); +int ipecamera_next_event(pcilib_context_t *vctx, pcilib_timeout_t timeout, pcilib_event_id_t *evid, size_t info_size, pcilib_event_info_t *info); + +int ipecamera_get(pcilib_context_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size, void **buf); +int ipecamera_return(pcilib_context_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, void *data); + +#endif /* _IPECAMERA_BASE_H */ diff --git a/cli.c b/cli.c deleted file mode 100644 index 052bb3b..0000000 --- a/cli.c +++ /dev/null @@ -1,3101 +0,0 @@ -#define _POSIX_C_SOURCE 200112L -#define _BSD_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include "pcitool/sysinfo.h" -#include "pcitool/formaters.h" - -//#include "pci.h" -#include "tools.h" -#include "kernel.h" -#include "error.h" - -/* defines */ -#define MAX_KBUF 14 -//#define BIGBUFSIZE (512*1024*1024) -#define BIGBUFSIZE (1024*1024) - - -#define DEFAULT_FPGA_DEVICE "/dev/fpga0" - -#define LINE_WIDTH 80 -#define SEPARATOR_WIDTH 2 -#define BLOCK_SEPARATOR_WIDTH 2 -#define BLOCK_SIZE 8 -#define BENCHMARK_ITERATIONS 128 -#define STATUS_MESSAGE_INTERVAL 5 /* seconds */ - - -#define isnumber pcilib_isnumber -#define isxnumber pcilib_isxnumber -#define isnumber_n pcilib_isnumber_n -#define isxnumber_n pcilib_isxnumber_n - -typedef uint8_t access_t; - -typedef enum { - GRAB_MODE_GRAB = 1, - GRAB_MODE_TRIGGER = 2 -} GRAB_MODE; - -typedef enum { - MODE_INVALID, - MODE_INFO, - MODE_LIST, - MODE_BENCHMARK, - MODE_READ, - MODE_READ_REGISTER, - MODE_WRITE, - MODE_WRITE_REGISTER, - MODE_RESET, - MODE_GRAB, - MODE_START_DMA, - MODE_STOP_DMA, - MODE_LIST_DMA, - MODE_LIST_DMA_BUFFERS, - MODE_READ_DMA_BUFFER, - MODE_ENABLE_IRQ, - MODE_DISABLE_IRQ, - MODE_ACK_IRQ, - MODE_WAIT_IRQ, - MODE_ALLOC_KMEM, - MODE_LIST_KMEM, - MODE_READ_KMEM, - MODE_FREE_KMEM -} MODE; - -typedef enum { - ACCESS_BAR, - ACCESS_DMA, - ACCESS_FIFO, - ACCESS_CONFIG -} ACCESS_MODE; - -typedef enum { - FLAG_MULTIPACKET = 1, - FLAG_WAIT = 2 -} FLAGS; - - -typedef enum { - FORMAT_DEFAULT = 0, - FORMAT_RAW, - FORMAT_HEADER, - FORMAT_RINGFS -} FORMAT; - -typedef enum { - PARTITION_UNKNOWN, - PARTITION_RAW, - PARTITION_EXT4, - PARTITION_NULL -} PARTITION; - -typedef enum { - OPT_DEVICE = 'd', - OPT_MODEL = 'm', - OPT_BAR = 'b', - OPT_ACCESS = 'a', - OPT_ENDIANESS = 'e', - OPT_SIZE = 's', - OPT_OUTPUT = 'o', - OPT_TIMEOUT = 't', - OPT_INFO = 'i', - OPT_LIST = 'l', - OPT_READ = 'r', - OPT_WRITE = 'w', - OPT_GRAB = 'g', - OPT_QUIETE = 'q', - OPT_HELP = 'h', - OPT_RESET = 128, - OPT_BENCHMARK, - OPT_TRIGGER, - OPT_DATA_TYPE, - OPT_EVENT, - OPT_TRIGGER_RATE, - OPT_TRIGGER_TIME, - OPT_RUN_TIME, - OPT_FORMAT, - OPT_BUFFER, - OPT_THREADS, - OPT_LIST_DMA, - OPT_LIST_DMA_BUFFERS, - OPT_READ_DMA_BUFFER, - OPT_START_DMA, - OPT_STOP_DMA, - OPT_ENABLE_IRQ, - OPT_DISABLE_IRQ, - OPT_ACK_IRQ, - OPT_WAIT_IRQ, - OPT_ITERATIONS, - OPT_ALLOC_KMEM, - OPT_LIST_KMEM, - OPT_FREE_KMEM, - OPT_READ_KMEM, - OPT_BLOCK_SIZE, - OPT_ALIGNMENT, - OPT_TYPE, - OPT_FORCE, - OPT_VERIFY, - OPT_WAIT, - OPT_MULTIPACKET, - OPT_VERBOSE -} OPTIONS; - -static struct option long_options[] = { - {"device", required_argument, 0, OPT_DEVICE }, - {"model", required_argument, 0, OPT_MODEL }, - {"bar", required_argument, 0, OPT_BAR }, - {"access", required_argument, 0, OPT_ACCESS }, - {"endianess", required_argument, 0, OPT_ENDIANESS }, - {"size", required_argument, 0, OPT_SIZE }, - {"output", required_argument, 0, OPT_OUTPUT }, - {"timeout", required_argument, 0, OPT_TIMEOUT }, - {"iterations", required_argument, 0, OPT_ITERATIONS }, - {"info", no_argument, 0, OPT_INFO }, - {"list", no_argument, 0, OPT_LIST }, - {"reset", no_argument, 0, OPT_RESET }, - {"benchmark", optional_argument, 0, OPT_BENCHMARK }, - {"read", optional_argument, 0, OPT_READ }, - {"write", optional_argument, 0, OPT_WRITE }, - {"grab", optional_argument, 0, OPT_GRAB }, - {"trigger", optional_argument, 0, OPT_TRIGGER }, - {"data", required_argument, 0, OPT_DATA_TYPE }, - {"event", required_argument, 0, OPT_EVENT }, - {"run-time", required_argument, 0, OPT_RUN_TIME }, - {"trigger-rate", required_argument, 0, OPT_TRIGGER_RATE }, - {"trigger-time", required_argument, 0, OPT_TRIGGER_TIME }, - {"format", required_argument, 0, OPT_FORMAT }, - {"buffer", optional_argument, 0, OPT_BUFFER }, - {"threads", optional_argument, 0, OPT_THREADS }, - {"start-dma", required_argument, 0, OPT_START_DMA }, - {"stop-dma", optional_argument, 0, OPT_STOP_DMA }, - {"list-dma-engines", no_argument, 0, OPT_LIST_DMA }, - {"list-dma-buffers", required_argument, 0, OPT_LIST_DMA_BUFFERS }, - {"read-dma-buffer", required_argument, 0, OPT_READ_DMA_BUFFER }, - {"enable-irq", optional_argument, 0, OPT_ENABLE_IRQ }, - {"disable-irq", optional_argument, 0, OPT_DISABLE_IRQ }, - {"acknowledge-irq", optional_argument, 0, OPT_ACK_IRQ }, - {"wait-irq", optional_argument, 0, OPT_WAIT_IRQ }, - {"list-kernel-memory", optional_argument, 0, OPT_LIST_KMEM }, - {"read-kernel-memory", required_argument, 0, OPT_READ_KMEM }, - {"alloc-kernel-memory", required_argument, 0, OPT_ALLOC_KMEM }, - {"free-kernel-memory", required_argument, 0, OPT_FREE_KMEM }, - {"type", required_argument, 0, OPT_TYPE }, - {"block-size", required_argument, 0, OPT_BLOCK_SIZE }, - {"alignment", required_argument, 0, OPT_ALIGNMENT }, - {"quiete", no_argument, 0, OPT_QUIETE }, - {"verbose", optional_argument, 0, OPT_VERBOSE }, - {"force", no_argument, 0, OPT_FORCE }, - {"verify", no_argument, 0, OPT_VERIFY }, - {"multipacket", no_argument, 0, OPT_MULTIPACKET }, - {"wait", no_argument, 0, OPT_WAIT }, - {"help", no_argument, 0, OPT_HELP }, - { 0, 0, 0, 0 } -}; - - -void Usage(int argc, char *argv[], const char *format, ...) { - if (format) { - va_list ap; - - va_start(ap, format); - printf("Error %i: ", errno); - vprintf(format, ap); - printf("\n"); - va_end(ap); - - printf("\n"); - } - - - printf( -"Usage:\n" -" %s [options] [hex data]\n" -" Modes:\n" -" -i - Device Info\n" -" -l[l] - List (detailed) Data Banks & Registers\n" -" -r - Read Data/Register\n" -" -w - Write Data/Register\n" -" --benchmark - Performance Evaluation\n" -" --reset - Reset board\n" -" --help - Help message\n" -"\n" -" Event Modes:\n" -" --trigger [event] - Trigger Events\n" -" -g [event] - Grab Events\n" -"\n" -" IRQ Modes:\n" -" --enable-irq [type] - Enable IRQs\n" -" --disable-irq [type] - Disable IRQs\n" -" --acknowledge-irq - Clean IRQ queue\n" -" --wait-irq - Wait for IRQ\n" - -" DMA Modes:\n" -" --start-dma [r|w] - Start specified DMA engine\n" -" --stop-dma [num[r|w]] - Stop specified engine or DMA subsystem\n" -" --list-dma-engines - List active DMA engines\n" -" --list-dma-buffers - List buffers for specified DMA engine\n" -" --read-dma-buffer - Read the specified buffer\n" -"\n" -" Kernel Modes:\n" -" --list-kernel-memory [use] - List kernel buffers\n" -" --read-kernel-memory - Read the specified block of the kernel memory\n" -" block is specified as: use:block_number\n" -" --alloc-kernel-memory - Allocate kernel buffers (DANGEROUS)\n" -" --free-kernel-memory - Cleans lost kernel space buffers (DANGEROUS)\n" -" dma - Remove all buffers allocated by DMA subsystem\n" -" #number - Remove all buffers with the specified use id\n" -"\n" -" Addressing:\n" -" -d - FPGA device (/dev/fpga0)\n" -" -m - Memory model (autodetected)\n" -" pci - Plain\n" -" ipecamera - IPE Camera\n" -" -b - PCI bar, Register bank, or DMA channel\n" -"\n" -" Options:\n" -" -s - Number of words (default: 1)\n" -" -a [fifo|dma|config] - Access type and bits per word (default: 32)\n" -" -e - Endianess Little/Big (default: host)\n" -" -o - Append output to file (default: stdout)\n" -" -t - Timeout in microseconds\n" -" --check - Verify write operations\n" -"\n" -" Event Options:\n" -" --event - Specifies event for trigger and grab modes\n" -" --data - Data type to request for the events\n" -" --run-time - Limit time to grab/trigger events\n" -" -t - Timeout to stop if no events triggered\n" -" --trigger-rate - Generate tps triggers per second\n" -" --trigger-time - Specifies delay between triggers (us)\n" -" -s - Number of events to grab and trigger\n" -" --format [type] - Specifies how event data should be stored\n" -" raw - Just write all events sequentially\n" -" add_header - Prefix events with 512 bit header:\n" -" event(64), data(64), nope(64), size(64)\n" -" seqnum(64), offset(64), timestamp(128)\n" -//" ringfs - Write to RingFS\n" -" --buffer [size] - Request data buffering, size in MB\n" -" --threads [num] - Allow multithreaded processing\n" -"\n" -" DMA Options:\n" -" --multipacket - Read multiple packets\n" -" --wait - Wait until data arrives\n" -"\n" -" Kernel Options:\n" -" --type - Type of kernel memory to allocate\n" -" consistent - Consistent memory\n" -" s2c - DMA S2C (write) memory\n" -" c2s - DMA C2S (read) memory\n" -" --page-size - Size of kernel buffer in bytes (default: page)\n" -" -s - Number of buffers to allocate (default: 1)\n" -" --allignment - Buffer alignment (default: page)\n" -"\n" -" Information:\n" -" --verbose [level] - Announce details of ongoing operations\n" -" -q - Quiete mode (suppress warnings)\n" -"\n" -" Data:\n" -" Data can be specified as sequence of hexdecimal number or\n" -" a single value prefixed with '*'. In this case it will be\n" -" replicated the specified amount of times\n" -"\n\n", -argv[0]); - - exit(0); -} - -static int StopFlag = 0; - -static void signal_exit_handler(int signo) { - if (++StopFlag > 2) - exit(-1); -} - - -void Error(const char *format, ...) { - va_list ap; - - va_start(ap, format); - printf("Error %i: ", errno); - vprintf(format, ap); - if (errno) printf("\n errno: %s", strerror(errno)); - printf("\n\n"); - va_end(ap); - - exit(-1); -} - -void Silence(const char *format, ...) { -} - -void List(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, int details) { - int i,j; - pcilib_register_bank_description_t *banks; - pcilib_register_description_t *registers; - pcilib_event_description_t *events; - pcilib_event_data_type_description_t *types; - - const pcilib_board_info_t *board_info = pcilib_get_board_info(handle); - const pcilib_dma_info_t *dma_info = pcilib_get_dma_info(handle); - - for (i = 0; i < PCILIB_MAX_BANKS; i++) { - if (board_info->bar_length[i] > 0) { - printf(" BAR %d - ", i); - - switch ( board_info->bar_flags[i]&IORESOURCE_TYPE_BITS) { - case IORESOURCE_IO: printf(" IO"); break; - case IORESOURCE_MEM: printf("MEM"); break; - case IORESOURCE_IRQ: printf("IRQ"); break; - case IORESOURCE_DMA: printf("DMA"); break; - } - - if (board_info->bar_flags[i]&IORESOURCE_MEM_64) printf("64"); - else printf("32"); - - printf(", Start: 0x%08lx, Length: 0x%8lx, Flags: 0x%08lx\n", board_info->bar_start[i], board_info->bar_length[i], board_info->bar_flags[i] ); - } - } - printf("\n"); - - if ((dma_info)&&(dma_info->engines)) { - printf("DMA Engines: \n"); - for (i = 0; dma_info->engines[i]; i++) { - pcilib_dma_engine_description_t *engine = dma_info->engines[i]; - printf(" DMA %2d ", engine->addr); - switch (engine->direction) { - case PCILIB_DMA_FROM_DEVICE: - printf("C2S"); - break; - case PCILIB_DMA_TO_DEVICE: - printf("S2C"); - break; - case PCILIB_DMA_BIDIRECTIONAL: - printf("BI "); - break; - } - printf(" - Type: "); - switch (engine->type) { - case PCILIB_DMA_TYPE_BLOCK: - printf("Block"); - break; - case PCILIB_DMA_TYPE_PACKET: - printf("Packet"); - break; - default: - printf("Unknown"); - } - - printf(", Address Width: %02lu bits\n", engine->addr_bits); - } - printf("\n"); - } - - if ((bank)&&(bank != (char*)-1)) banks = NULL; - else banks = model_info->banks; - - if (banks) { - printf("Banks: \n"); - for (i = 0; banks[i].access; i++) { - printf(" 0x%02x %s", banks[i].addr, banks[i].name); - if ((banks[i].description)&&(banks[i].description[0])) { - printf(": %s", banks[i].description); - } - printf("\n"); - } - printf("\n"); - } - - if (bank == (char*)-1) registers = NULL; - else registers = model_info->registers; - - if (registers) { - pcilib_register_bank_addr_t bank_addr = 0; - if (bank) { - pcilib_register_bank_t bank_id = pcilib_find_bank(handle, bank); - pcilib_register_bank_description_t *b = model_info->banks + bank_id; - - bank_addr = b->addr; - if (b->description) printf("%s:\n", b->description); - else if (b->name) printf("Registers of bank %s:\n", b->name); - else printf("Registers of bank 0x%x:\n", b->addr); - } else { - printf("Registers: \n"); - } - for (i = 0; registers[i].bits; i++) { - const char *mode; - - if ((bank)&&(registers[i].bank != bank_addr)) continue; - if (registers[i].type == PCILIB_REGISTER_BITS) { - if (!details) continue; - - if (registers[i].bits > 1) { - printf(" [%2u:%2u] - %s\n", registers[i].offset, registers[i].offset + registers[i].bits, registers[i].name); - } else { - printf(" [ %2u] - %s\n", registers[i].offset, registers[i].name); - } - - continue; - } - - if (registers[i].mode == PCILIB_REGISTER_RW) mode = "RW"; - else if (registers[i].mode == PCILIB_REGISTER_R) mode = "R "; - else if (registers[i].mode == PCILIB_REGISTER_W) mode = " W"; - else mode = " "; - - printf(" 0x%02x (%2i %s) %s", registers[i].addr, registers[i].bits, mode, registers[i].name); - if ((details > 0)&&(registers[i].description)&&(registers[i].description[0])) { - printf(": %s", registers[i].description); - } - printf("\n"); - - } - printf("\n"); - } - - if (bank == (char*)-1) events = NULL; - else { - events = model_info->events; - types = model_info->data_types; - } - - if (events) { - printf("Events: \n"); - for (i = 0; events[i].name; i++) { - printf(" %s", events[i].name); - if ((events[i].description)&&(events[i].description[0])) { - printf(": %s", events[i].description); - } - - if (types) { - for (j = 0; types[j].name; j++) { - if (types[j].evid & events[i].evid) { - printf("\n %s", types[j].name); - if ((types[j].description)&&(types[j].description[0])) { - printf(": %s", types[j].description); - } - } - } - } - } - printf("\n"); - } -} - -void Info(pcilib_t *handle, pcilib_model_description_t *model_info) { - const pcilib_board_info_t *board_info = pcilib_get_board_info(handle); - - printf("Vendor: %x, Device: %x, Bus: %x, Slot: %x, Function: %x\n", board_info->vendor_id, board_info->device_id, board_info->bus, board_info->slot, board_info->func); - printf(" Interrupt - Pin: %i, Line: %i\n", board_info->interrupt_pin, board_info->interrupt_line); - List(handle, model_info, (char*)-1, 0); -} - - -#define BENCH_MAX_DMA_SIZE 4 * 1024 * 1024 -#define BENCH_MAX_FIFO_SIZE 1024 * 1024 - -int Benchmark(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma, pcilib_bar_t bar, uintptr_t addr, size_t n, access_t access, size_t iterations) { - int err; - int i, j, errors; - void *data, *buf, *check; - void *fifo = NULL; - struct timeval start, end; - unsigned long time; - size_t size, min_size, max_size; - double mbs_in, mbs_out, mbs; - size_t irqs; - - const pcilib_board_info_t *board_info = pcilib_get_board_info(handle); - - if (mode == ACCESS_CONFIG) - Error("No benchmarking of configuration space acess is allowed"); - - if (mode == ACCESS_DMA) { - if (n) { - min_size = n * access; - max_size = n * access; - } else { - min_size = 1024; - max_size = BENCH_MAX_DMA_SIZE; - } - - for (size = min_size; size <= max_size; size *= 4) { - mbs_in = pcilib_benchmark_dma(handle, dma, addr, size, iterations, PCILIB_DMA_FROM_DEVICE); - mbs_out = pcilib_benchmark_dma(handle, dma, addr, size, iterations, PCILIB_DMA_TO_DEVICE); - mbs = pcilib_benchmark_dma(handle, dma, addr, size, iterations, PCILIB_DMA_BIDIRECTIONAL); - err = pcilib_wait_irq(handle, 0, 0, &irqs); - if (err) irqs = 0; - - printf("%8zu KB - ", size / 1024); - - printf("RW: "); - if (mbs < 0) printf("failed ... "); - else printf("%8.2lf MB/s", mbs); - - printf(", R: "); - if (mbs_in < 0) printf("failed ... "); - else printf("%8.2lf MB/s", mbs_in); - - printf(", W: "); - if (mbs_out < 0) printf("failed ... "); - else printf("%8.2lf MB/s", mbs_out); - - if (irqs) { - printf(", IRQs: %lu", irqs); - } - - printf("\n"); - } - - return 0; - } - - if (bar == PCILIB_BAR_INVALID) { - unsigned long maxlength = 0; - - - for (i = 0; i < PCILIB_MAX_BANKS; i++) { - if ((addr >= board_info->bar_start[i])&&((board_info->bar_start[i] + board_info->bar_length[i]) >= (addr + access))) { - bar = i; - break; - } - - if (board_info->bar_length[i] > maxlength) { - maxlength = board_info->bar_length[i]; - bar = i; - } - } - - if (bar < 0) Error("Data banks are not available"); - } - - if (n) { - if ((mode == ACCESS_BAR)&&(n * access > board_info->bar_length[bar])) Error("The specified size (%i) exceeds the size of bar (%i)", n * access, board_info->bar_length[bar]); - - min_size = n * access; - max_size = n * access; - } else { - min_size = access; - if (mode == ACCESS_BAR) max_size = board_info->bar_length[bar]; - else max_size = BENCH_MAX_FIFO_SIZE; - } - - err = posix_memalign( (void**)&buf, 256, max_size ); - if (!err) err = posix_memalign( (void**)&check, 256, max_size ); - if ((err)||(!buf)||(!check)) Error("Allocation of %i bytes of memory have failed", max_size); - - data = pcilib_map_bar(handle, bar); - if (!data) Error("Can't map bar %i", bar); - - if (mode == ACCESS_FIFO) { - fifo = data + (addr - board_info->bar_start[bar]) + (board_info->bar_start[bar] & pcilib_get_page_mask()); -// pcilib_resolve_register_address(handle, bar, addr); - if (!fifo) Error("Can't resolve address (%lx) in bar (%u)", addr, bar); - } - - if (mode == ACCESS_FIFO) - printf("Transfer time (Bank: %i, Fifo: %lx):\n", bar, addr); - else - printf("Transfer time (Bank: %i):\n", bar); - - for (size = min_size ; size < max_size; size *= 8) { - gettimeofday(&start,NULL); - if (mode == ACCESS_BAR) { - for (i = 0; i < BENCHMARK_ITERATIONS; i++) { - pcilib_memcpy(buf, data, size); - } - } else { - for (i = 0; i < BENCHMARK_ITERATIONS; i++) { - for (j = 0; j < (size/access); j++) { - pcilib_memcpy(buf + j * access, fifo, access); - } - } - } - gettimeofday(&end,NULL); - - time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec); - printf("%8zu bytes - read: %8.2lf MB/s", size, 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.)); - - fflush(0); - - gettimeofday(&start,NULL); - if (mode == ACCESS_BAR) { - for (i = 0; i < BENCHMARK_ITERATIONS; i++) { - pcilib_memcpy(data, buf, size); - } - } else { - for (i = 0; i < BENCHMARK_ITERATIONS; i++) { - for (j = 0; j < (size/access); j++) { - pcilib_memcpy(fifo, buf + j * access, access); - } - } - } - gettimeofday(&end,NULL); - - time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec); - printf(", write: %8.2lf MB/s\n", 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.)); - } - - pcilib_unmap_bar(handle, bar, data); - - printf("\n\nOpen-Transfer-Close time: \n"); - - for (size = 4 ; size < max_size; size *= 8) { - gettimeofday(&start,NULL); - if (mode == ACCESS_BAR) { - for (i = 0; i < BENCHMARK_ITERATIONS; i++) { - pcilib_read(handle, bar, 0, size, buf); - } - } else { - for (i = 0; i < BENCHMARK_ITERATIONS; i++) { - pcilib_read_fifo(handle, bar, addr, access, size / access, buf); - } - } - gettimeofday(&end,NULL); - - time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec); - printf("%8zu bytes - read: %8.2lf MB/s", size, 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.)); - - fflush(0); - - gettimeofday(&start,NULL); - if (mode == ACCESS_BAR) { - for (i = 0; i < BENCHMARK_ITERATIONS; i++) { - pcilib_write(handle, bar, 0, size, buf); - } - } else { - for (i = 0; i < BENCHMARK_ITERATIONS; i++) { - pcilib_write_fifo(handle, bar, addr, access, size / access, buf); - } - } - - gettimeofday(&end,NULL); - - time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec); - printf(", write: %8.2lf MB/s", 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.)); - - if (mode == ACCESS_BAR) { - gettimeofday(&start,NULL); - for (i = 0, errors = 0; i < BENCHMARK_ITERATIONS; i++) { - pcilib_write(handle, bar, 0, size, buf); - pcilib_read(handle, bar, 0, size, check); - if (memcmp(buf, check, size)) ++errors; - } - gettimeofday(&end,NULL); - - time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec); - printf(", write-verify: %8.2lf MB/s", 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.)); - if (errors) printf(", errors: %u of %u", errors, BENCHMARK_ITERATIONS); - } - printf("\n"); - } - - printf("\n\n"); - - free(check); - free(buf); - - return 0; -} - -#define pci2host16(endianess, value) endianess? - -/* -typedef struct { - size_t size; - void *data; - size_t pos; - - int multi_mode; -} DMACallbackContext; - -static int DMACallback(void *arg, pcilib_dma_flags_t flags, size_t bufsize, void *buf) { - DMACallbackContext *ctx = (DMACallbackContext*)arg; - - if ((ctx->pos + bufsize > ctx->size)||(!ctx->data)) { - ctx->size *= 2; - ctx->data = realloc(ctx->data, ctx->size); - if (!ctx->data) { - Error("Allocation of %i bytes of memory have failed", ctx->size); - return 0; - } - } - - memcpy(ctx->data + ctx->pos, buf, bufsize); - ctx->pos += bufsize; - - if (flags & PCILIB_DMA_FLAG_EOP) return 0; - return 1; -} -*/ - - -int ReadData(pcilib_t *handle, ACCESS_MODE mode, FLAGS flags, pcilib_dma_engine_addr_t dma, pcilib_bar_t bar, uintptr_t addr, size_t n, access_t access, int endianess, size_t timeout, FILE *o) { - void *buf; - int i, err; - size_t ret, bytes; - size_t size = n * abs(access); - int block_width, blocks_per_line; - int numbers_per_block, numbers_per_line; - pcilib_dma_engine_t dmaid; - pcilib_dma_flags_t dma_flags = 0; - - int fd; - char stmp[256]; - struct stat st; - const pcilib_board_info_t *board_info; - - numbers_per_block = BLOCK_SIZE / access; - - block_width = numbers_per_block * ((access * 2) + SEPARATOR_WIDTH); - blocks_per_line = (LINE_WIDTH - 10) / (block_width + BLOCK_SEPARATOR_WIDTH); - if ((blocks_per_line > 1)&&(blocks_per_line % 2)) --blocks_per_line; - numbers_per_line = blocks_per_line * numbers_per_block; - - if (size) { - buf = malloc(size); - if (!buf) Error("Allocation of %zu bytes of memory has failed", size); - } else { - buf = NULL; - } - - switch (mode) { - case ACCESS_DMA: - if (timeout == (size_t)-1) timeout = PCILIB_DMA_TIMEOUT; - - dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_FROM_DEVICE, dma); - if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (%lu) is specified", dma); - - if (flags&FLAG_MULTIPACKET) dma_flags |= PCILIB_DMA_FLAG_MULTIPACKET; - if (flags&FLAG_WAIT) dma_flags |= PCILIB_DMA_FLAG_WAIT; - - if (size) { - err = pcilib_read_dma_custom(handle, dmaid, addr, size, dma_flags, timeout, buf, &bytes); - if (err) Error("Error (%i) is reported by DMA engine", err); - } else { - dma_flags |= PCILIB_DMA_FLAG_IGNORE_ERRORS; - - size = 2048; bytes = 0; - do { - size *= 2; - buf = realloc(buf, size); - if (!buf) Error("Allocation of %zu bytes of memory has failed", size); - err = pcilib_read_dma_custom(handle, dmaid, addr, size - bytes, dma_flags, timeout, buf + bytes, &ret); - bytes += ret; - - if ((!err)&&(flags&FLAG_MULTIPACKET)) { - err = PCILIB_ERROR_TOOBIG; - if ((flags&FLAG_WAIT)==0) timeout = 0; - } - } while (err == PCILIB_ERROR_TOOBIG); - } - - if ((err)&&(err != PCILIB_ERROR_TIMEOUT)) { - Error("Error (%i) during DMA read", err); - } - if (bytes <= 0) { - pcilib_warning("No data is returned by DMA engine"); - return 0; - } - size = bytes; - n = bytes / abs(access); - addr = 0; - break; - case ACCESS_FIFO: - pcilib_read_fifo(handle, bar, addr, access, n, buf); - addr = 0; - break; - case ACCESS_CONFIG: - board_info = pcilib_get_board_info(handle); - sprintf(stmp, "/sys/bus/pci/devices/0000:%02x:%02x.%1x/config", board_info->bus, board_info->slot, board_info->func); - fd = open(stmp, O_RDONLY); - - if ((!fd)||(fstat(fd, &st))) Error("Can't open %s", stmp); - - if (st.st_size < addr) - Error("Access beyond the end of PCI configuration space"); - - if (st.st_size < (addr + size)) { - n = (st.st_size - addr) / abs(access); - size = n * abs(access); - if (!n) Error("Access beyond the end of PCI configuration space"); - } - - lseek(fd, addr, SEEK_SET); - ret = read(fd, buf, size); - if (ret == (size_t)-1) Error("Error reading %s", stmp); - - if (ret < size) { - size = ret; - n = ret / abs(access); - } - - close(fd); - break; - default: - pcilib_read(handle, bar, addr, size, buf); - } - - if (endianess) pcilib_swap(buf, buf, abs(access), n); - - if (o) { - printf("Writting output (%zu bytes) to file (append to the end)...\n", n * abs(access)); - fwrite(buf, abs(access), n, o); - } else { - for (i = 0; i < n; i++) { - if (i) { - if (i%numbers_per_line == 0) printf("\n"); - else { - printf("%*s", SEPARATOR_WIDTH, ""); - if (i%numbers_per_block == 0) printf("%*s", BLOCK_SEPARATOR_WIDTH, ""); - } - } - - if (i%numbers_per_line == 0) printf("%8lx: ", addr + i * abs(access)); - - switch (access) { - case 1: printf("%0*hhx", access * 2, ((uint8_t*)buf)[i]); break; - case 2: printf("%0*hx", access * 2, ((uint16_t*)buf)[i]); break; - case 4: printf("%0*x", access * 2, ((uint32_t*)buf)[i]); break; - case 8: printf("%0*lx", access * 2, ((uint64_t*)buf)[i]); break; - } - } - printf("\n\n"); - } - - - free(buf); - return 0; -} - - - - -int ReadRegister(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, const char *reg) { - int i; - int err; - const char *format; - - pcilib_register_bank_t bank_id; - pcilib_register_bank_addr_t bank_addr = 0; - - pcilib_register_value_t value; - - if (reg) { - pcilib_register_t regid = pcilib_find_register(handle, bank, reg); - bank_id = pcilib_find_bank_by_addr(handle, model_info->registers[regid].bank); - format = model_info->banks[bank_id].format; - if (!format) format = "%lu"; - - err = pcilib_read_register_by_id(handle, regid, &value); - // err = pcilib_read_register(handle, bank, reg, &value); - if (err) printf("Error reading register %s\n", reg); - else { - printf("%s = ", reg); - printf(format, value); - printf("\n"); - } - } else { - // Adding DMA registers - pcilib_get_dma_info(handle); - - if (model_info->registers) { - if (bank) { - bank_id = pcilib_find_bank(handle, bank); - bank_addr = model_info->banks[bank_id].addr; - } - - printf("Registers:\n"); - for (i = 0; model_info->registers[i].bits; i++) { - if ((model_info->registers[i].mode & PCILIB_REGISTER_R)&&((!bank)||(model_info->registers[i].bank == bank_addr))&&(model_info->registers[i].type != PCILIB_REGISTER_BITS)) { - bank_id = pcilib_find_bank_by_addr(handle, model_info->registers[i].bank); - format = model_info->banks[bank_id].format; - if (!format) format = "%lu"; - - err = pcilib_read_register_by_id(handle, i, &value); - if (err) printf(" %s = error reading value", model_info->registers[i].name); - else { - printf(" %s = ", model_info->registers[i].name); - printf(format, value); - } - - printf(" ["); - printf(format, model_info->registers[i].defvalue); - printf("]"); - printf("\n"); - } - } - } else { - printf("No registers"); - } - printf("\n"); - } - - return 0; -} - -#define WRITE_REGVAL(buf, n, access, o) {\ - uint##access##_t tbuf[n]; \ - for (i = 0; i < n; i++) { \ - tbuf[i] = (uint##access##_t)buf[i]; \ - } \ - fwrite(tbuf, access/8, n, o); \ -} - -int ReadRegisterRange(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, uintptr_t addr, long addr_shift, size_t n, FILE *o) { - int err; - int i; - - pcilib_register_bank_description_t *banks = model_info->banks; - pcilib_register_bank_t bank_id = pcilib_find_bank(handle, bank); - - if (bank_id == PCILIB_REGISTER_BANK_INVALID) { - if (bank) Error("Invalid register bank is specified (%s)", bank); - else Error("Register bank should be specified"); - } - - int access = banks[bank_id].access / 8; -// int size = n * abs(access); - int block_width, blocks_per_line; - int numbers_per_block, numbers_per_line; - - numbers_per_block = BLOCK_SIZE / access; - - block_width = numbers_per_block * ((access * 2) + SEPARATOR_WIDTH); - blocks_per_line = (LINE_WIDTH - 6) / (block_width + BLOCK_SEPARATOR_WIDTH); - if ((blocks_per_line > 1)&&(blocks_per_line % 2)) --blocks_per_line; - numbers_per_line = blocks_per_line * numbers_per_block; - - - pcilib_register_value_t buf[n]; - err = pcilib_read_register_space(handle, bank, addr, n, buf); - if (err) Error("Error reading register space for bank \"%s\" at address %lx, size %lu", bank?bank:"default", addr, n); - - - if (o) { - printf("Writting output (%zu bytes) to file (append to the end)...\n", n * abs(access)); - switch (access) { - case 1: WRITE_REGVAL(buf, n, 8, o) break; - case 2: WRITE_REGVAL(buf, n, 16, o) break; - case 4: WRITE_REGVAL(buf, n, 32, o) break; - case 8: WRITE_REGVAL(buf, n, 64, o) break; - } - } else { - for (i = 0; i < n; i++) { - if (i) { - if (i%numbers_per_line == 0) printf("\n"); - else { - printf("%*s", SEPARATOR_WIDTH, ""); - if (i%numbers_per_block == 0) printf("%*s", BLOCK_SEPARATOR_WIDTH, ""); - } - } - - if (i%numbers_per_line == 0) printf("%4lx: ", addr + 4 * i - addr_shift); - printf("%0*lx", access * 2, (unsigned long)buf[i]); - } - printf("\n\n"); - } - - return 0; -} - -int WriteData(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma, pcilib_bar_t bar, uintptr_t addr, size_t n, access_t access, int endianess, char ** data, int verify) { - int read_back = 0; - void *buf, *check; - int res = 0, i, err; - int size = n * abs(access); - size_t ret; - pcilib_dma_engine_t dmaid; - - if (mode == ACCESS_CONFIG) - Error("Writting to PCI configuration space is not supported"); - - err = posix_memalign( (void**)&buf, 256, size ); - if (!err) err = posix_memalign( (void**)&check, 256, size ); - if ((err)||(!buf)||(!check)) Error("Allocation of %i bytes of memory have failed", size); - - for (i = 0; i < n; i++) { - switch (access) { - case 1: res = sscanf(data[i], "%hhx", ((uint8_t*)buf)+i); break; - case 2: res = sscanf(data[i], "%hx", ((uint16_t*)buf)+i); break; - case 4: res = sscanf(data[i], "%x", ((uint32_t*)buf)+i); break; - case 8: res = sscanf(data[i], "%lx", ((uint64_t*)buf)+i); break; - default: Error("Unexpected data size (%lu)", access); - } - if ((res != 1)||(!isxnumber(data[i]))) Error("Can't parse data value at poition %i, (%s) is not valid hex number", i, data[i]); - } - - if (endianess) pcilib_swap(buf, buf, abs(access), n); - - switch (mode) { - case ACCESS_DMA: - dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_TO_DEVICE, dma); - if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (%lu) is specified", dma); - err = pcilib_write_dma(handle, dmaid, addr, size, buf, &ret); - if ((err)||(ret != size)) { - if (err == PCILIB_ERROR_TIMEOUT) Error("Timeout writting the data to DMA"); - else if (err) Error("DMA engine returned a error while writing the data"); - else if (!ret) Error("No data is written by DMA engine"); - else Error("Only %lu bytes of %lu is written by DMA engine", ret, size); - } - break; - case ACCESS_FIFO: - pcilib_write_fifo(handle, bar, addr, access, n, buf); - break; - default: - pcilib_write(handle, bar, addr, size, buf); - if (verify) { - pcilib_read(handle, bar, addr, size, check); - read_back = 1; - } - } - - if ((read_back)&&(memcmp(buf, check, size))) { - printf("Write failed: the data written and read differ, the foolowing is read back:\n"); - if (endianess) pcilib_swap(check, check, abs(access), n); - ReadData(handle, mode, 0, dma, bar, addr, n, access, endianess, (size_t)-1, NULL); - exit(-1); - } - - free(check); - free(buf); - - return 0; -} - -int WriteRegisterRange(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, uintptr_t addr, long addr_shift, size_t n, char ** data) { - pcilib_register_value_t *buf, *check; - int res, i, err; - unsigned long value; - int size = n * sizeof(pcilib_register_value_t); - - err = posix_memalign( (void**)&buf, 256, size ); - if (!err) err = posix_memalign( (void**)&check, 256, size ); - if ((err)||(!buf)||(!check)) Error("Allocation of %i bytes of memory have failed", size); - - for (i = 0; i < n; i++) { - res = sscanf(data[i], "%lx", &value); - if ((res != 1)||(!isxnumber(data[i]))) Error("Can't parse data value at poition %i, (%s) is not valid hex number", i, data[i]); - buf[i] = value; - } - - err = pcilib_write_register_space(handle, bank, addr, n, buf); - if (err) Error("Error writting register space for bank \"%s\" at address %lx, size %lu", bank?bank:"default", addr, n); - - err = pcilib_read_register_space(handle, bank, addr, n, check); - if (err) Error("Error reading register space for bank \"%s\" at address %lx, size %lu", bank?bank:"default", addr, n); - - if (memcmp(buf, check, size)) { - printf("Write failed: the data written and read differ, the foolowing is read back:\n"); - ReadRegisterRange(handle, model_info, bank, addr, addr_shift, n, NULL); - exit(-1); - } - - free(check); - free(buf); - - return 0; - -} - -int WriteRegister(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, const char *reg, char ** data) { - int err; - - unsigned long val; - pcilib_register_value_t value; - - const char *format = NULL; - - pcilib_register_t regid = pcilib_find_register(handle, bank, reg); - if (regid == PCILIB_REGISTER_INVALID) Error("Can't find register (%s) from bank (%s)", reg, bank?bank:"autodetected"); - -/* - pcilib_register_bank_t bank_id; - pcilib_register_bank_addr_t bank_addr; - - bank_id = pcilib_find_bank_by_addr(handle, model_info->registers[regid].bank); - if (bank_id == PCILIB_REGISTER_BANK_INVALID) Error("Can't find bank of the register (%s)", reg); - format = model_info->banks[bank_id].format; - if (!format) format = "%lu"; -*/ - - if (isnumber(*data)) { - if (sscanf(*data, "%li", &val) != 1) { - Error("Can't parse data value (%s) is not valid decimal number", *data); - } - - format = "%li"; - } else if (isxnumber(*data)) { - if (sscanf(*data, "%lx", &val) != 1) { - Error("Can't parse data value (%s) is not valid decimal number", *data); - } - - format = "0x%lx"; - } else { - Error("Can't parse data value (%s) is not valid decimal number", *data); - } - - value = val; - - err = pcilib_write_register(handle, bank, reg, value); - if (err) Error("Error writting register %s\n", reg); - - if ((model_info->registers[regid].mode&PCILIB_REGISTER_RW) == PCILIB_REGISTER_RW) { - err = pcilib_read_register(handle, bank, reg, &value); - if (err) Error("Error reading back register %s for verification\n", reg); - - if (val != value) { - Error("Failed to write register %s: %lu is written and %lu is read back", reg, val, value); - } else { - printf("%s = ", reg); - printf(format, value); - printf("\n"); - } - } else { - printf("%s is written\n ", reg); - } - - return 0; -} - -typedef struct { - pcilib_t *handle; - pcilib_event_t event; - pcilib_event_data_type_t data; - - fastwriter_t *writer; - - int verbose; - pcilib_timeout_t timeout; - size_t run_time; - size_t trigger_time; - size_t max_triggers; - pcilib_event_flags_t flags; - FORMAT format; - - volatile int event_pending; /**< Used to detect that we have read previously triggered event */ - volatile int trigger_thread_started; /**< Indicates that trigger thread is ready and we can't procced to start event recording */ - volatile int started; /**< Indicates that recording is started */ - - volatile int run_flag; - volatile int writing_flag; - - struct timeval first_frame; - struct timeval last_frame; - size_t last_num; - - size_t trigger_failed; - size_t trigger_count; - size_t event_count; - size_t incomplete_count; - size_t broken_count; - size_t missing_count; - size_t storage_count; - - struct timeval start_time; - struct timeval stop_time; -} GRABContext; - -int GrabCallback(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *user) { - int err = 0; - void *data; - size_t size; - - GRABContext *ctx = (GRABContext*)user; - pcilib_t *handle = ctx->handle; - - gettimeofday(&ctx->last_frame, NULL); - - if (!ctx->event_count) { - memcpy(&ctx->first_frame, &ctx->last_frame, sizeof(struct timeval)); - } - - ctx->event_pending = 0; - ctx->event_count++; - - if (ctx->last_num) - ctx->missing_count += (info->seqnum - ctx->last_num) - 1; - ctx->last_num = info->seqnum; - - if (info->flags&PCILIB_EVENT_INFO_FLAG_BROKEN) { - ctx->incomplete_count++; - return PCILIB_STREAMING_CONTINUE; - } - - switch (ctx->format) { - case FORMAT_DEFAULT: - data = pcilib_get_data(handle, event_id, PCILIB_EVENT_DATA, &size); - break; - default: - data = pcilib_get_data(handle, event_id, PCILIB_EVENT_RAW_DATA, &size); - } - - if (!data) { - ctx->broken_count++; - return PCILIB_STREAMING_CONTINUE; - } - - if (ctx->format == FORMAT_HEADER) { - uint64_t header[8]; - header[0] = info->type; - header[1] = ctx->data; - header[2] = 0; - header[3] = size; - header[4] = info->seqnum; - header[5] = info->offset; - memcpy(header + 6, &info->timestamp, 16); - - err = fastwriter_push(ctx->writer, 64, header); - } - - if (!err) - err = fastwriter_push(ctx->writer, size, data); - - if (err) { - fastwriter_cancel(ctx->writer); - - if (err != EWOULDBLOCK) - Error("Storage error %i", err); - - ctx->storage_count++; - pcilib_return_data(handle, event_id, ctx->data, data); - return PCILIB_STREAMING_CONTINUE; - } - - err = pcilib_return_data(handle, event_id, ctx->data, data); - if (err) { - ctx->missing_count++; - fastwriter_cancel(ctx->writer); - return PCILIB_STREAMING_CONTINUE; - } - - err = fastwriter_commit(ctx->writer); - if (err) Error("Error commiting data to storage, Error: %i", err); - - return PCILIB_STREAMING_CONTINUE; -} - -int raw_data(pcilib_event_id_t event_id, pcilib_event_info_t *info, pcilib_event_flags_t flags, size_t size, void *data, void *user) { - int err; - - GRABContext *ctx = (GRABContext*)user; -// pcilib_t *handle = ctx->handle; - - - if ((info)&&(info->seqnum != ctx->last_num)) { - gettimeofday(&ctx->last_frame, NULL); - if (!ctx->event_count) { - memcpy(&ctx->first_frame, &ctx->last_frame, sizeof(struct timeval)); - } - - ctx->event_count++; - ctx->missing_count += (info->seqnum - ctx->last_num) - 1; - ctx->last_num = info->seqnum; - } - - err = fastwriter_push_data(ctx->writer, size, data); - if (err) { - if (err == EWOULDBLOCK) Error("Storage is not able to handle the data stream, buffer overrun"); - Error("Storage error %i", err); - } - - return PCILIB_STREAMING_CONTINUE; -} - - -void *Trigger(void *user) { - int err; - struct timeval start; - - GRABContext *ctx = (GRABContext*)user; - size_t trigger_time = ctx->trigger_time; - size_t max_triggers = ctx->max_triggers; - - ctx->trigger_thread_started = 1; - ctx->event_pending = 1; - - while (!ctx->started) ; - - gettimeofday(&start, NULL); - do { - err = pcilib_trigger(ctx->handle, ctx->event, 0, NULL); - if (err) ctx->trigger_failed++; - if ((++ctx->trigger_count == max_triggers)&&(max_triggers)) break; - - if (trigger_time) { - pcilib_add_timeout(&start, trigger_time); - if ((ctx->stop_time.tv_sec)&&(pcilib_timecmp(&start, &ctx->stop_time)>0)) break; - pcilib_sleep_until_deadline(&start); - } else { - while ((ctx->event_pending)&&(ctx->run_flag)) usleep(10); - ctx->event_pending = 1; - } - } while (ctx->run_flag); - - ctx->trigger_thread_started = 0; - - return NULL; -} - -void GrabStats(GRABContext *ctx, struct timeval *end_time) { - int verbose; - pcilib_timeout_t duration, fps_duration; - struct timeval cur; - double fps = 0, good_fps = 0; - size_t total, good, pending = 0; - - verbose = ctx->verbose; - - if (end_time) { - if (verbose++) { - printf("-------------------------------------------------------------------------------\n"); - } - } else { - gettimeofday(&cur, NULL); - end_time = &cur; - } - -// if ((ctx->event_count + ctx->missing_count) == 0) -// return; - - duration = pcilib_timediff(&ctx->start_time, end_time); - fps_duration = pcilib_timediff(&ctx->first_frame, &ctx->last_frame); - - if (ctx->trigger_count) { - total = ctx->trigger_count; - pending = ctx->trigger_count - ctx->event_count - ctx->missing_count - ctx->trigger_failed; - } else { - total = ctx->event_count + ctx->missing_count; - } - - good = ctx->event_count - ctx->broken_count - ctx->incomplete_count - ctx->storage_count; - - if (ctx->event_count > 1) { - fps = (ctx->event_count - 1) / (1.*fps_duration/1000000); - } - - if (good > 1) { - good_fps = (good - 1) / (1.*fps_duration/1000000); - } - - printf("Run: "); - PrintTime(duration); - - if (ctx->trigger_count) { - printf(", Triggers: "); - PrintNumber(ctx->trigger_count); - } - - printf(", Captured: "); - PrintNumber(ctx->event_count); - printf(" FPS %5.0lf", fps); - - if ((ctx->flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY) == 0) { - printf(", Stored: "); - PrintNumber(good); - printf(" FPS %5.0lf", good_fps); - } - - printf("\n"); - - if (verbose > 2) { - if (ctx->trigger_count) { - printf("Trig: "); - PrintNumber(ctx->trigger_count); - printf(" Issued: "); - PrintNumber(ctx->trigger_count - ctx->trigger_failed); - printf(" ("); - PrintPercent(ctx->trigger_count - ctx->trigger_failed, ctx->trigger_count); - printf("%%) Failed: "); - PrintNumber(ctx->trigger_failed); - printf( " ("); - PrintPercent(ctx->trigger_failed, ctx->trigger_count); - printf( "%%); Pending: "); - PrintNumber(pending); - printf( " ("); - PrintPercent(pending, ctx->trigger_count); - printf( "%%)\n"); - } - - if (ctx->flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY) { - printf("Captured: "); - PrintNumber(good); - } else { - printf("Good: "); - PrintNumber(good); - printf(", Dropped: "); - PrintNumber(ctx->storage_count); - printf(", Bad: "); - PrintNumber(ctx->incomplete_count); - printf(", Empty: "); - PrintNumber(ctx->broken_count); - } - printf(", Lost: "); - PrintNumber(ctx->missing_count); - printf("\n"); - } - - if (verbose > 1) { - if (ctx->flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY) { - printf("Captured: "); - PrintPercent(good, total); - } else { - printf("Good: "); - PrintPercent(good, total); - printf("%% Dropped: "); - PrintPercent(ctx->storage_count, total); - printf("%% Bad: "); - PrintPercent(ctx->incomplete_count, total); - printf("%% Empty: "); - PrintPercent(ctx->broken_count, total); - } - - printf("%% Lost: "); - PrintPercent(ctx->missing_count, total); - printf("%%"); - printf("\n"); - } -} - -void StorageStats(GRABContext *ctx) { - int err; - fastwriter_stats_t st; - - pcilib_timeout_t duration; - struct timeval cur; - - gettimeofday(&cur, NULL); - duration = pcilib_timediff(&ctx->start_time, &cur); - - - err = fastwriter_get_stats(ctx->writer, &st); - if (err) return; - - printf("Wrote "); - PrintSize(st.written); - printf(" of "); - PrintSize(st.commited); - printf(" at "); - PrintSize(1000000.*st.written / duration); - printf("/s, %6.2lf%% ", 100.*st.buffer_used / st.buffer_size); - printf(" of "); - PrintSize(st.buffer_size); - printf(" buffer (%6.2lf%% max)\n", 100.*st.buffer_max / st.buffer_size); -} - -void *Monitor(void *user) { - struct timeval deadline; - struct timeval nextinfo; - - GRABContext *ctx = (GRABContext*)user; - int verbose = ctx->verbose; - pcilib_timeout_t timeout = ctx->timeout; - - - if (timeout == PCILIB_TIMEOUT_INFINITE) timeout = 0; - -// while (!ctx->started); - - if (timeout) { - memcpy(&deadline, (struct timeval*)&ctx->last_frame, sizeof(struct timeval)); - pcilib_add_timeout(&deadline, timeout); - } - - if (verbose > 0) { - pcilib_calc_deadline(&nextinfo, STATUS_MESSAGE_INTERVAL*1000000); - } - - while (ctx->run_flag) { - if (StopFlag) { - pcilib_stop(ctx->handle, PCILIB_EVENT_FLAG_STOP_ONLY); - break; - } - - if (timeout) { - if (pcilib_calc_time_to_deadline(&deadline) == 0) { - memcpy(&deadline, (struct timeval*)&ctx->last_frame, sizeof(struct timeval)); - pcilib_add_timeout(&deadline, timeout); - - if (pcilib_calc_time_to_deadline(&deadline) == 0) { - pcilib_stop(ctx->handle, PCILIB_EVENT_FLAG_STOP_ONLY); - break; - } - } - } - - if (verbose > 0) { - if (pcilib_calc_time_to_deadline(&nextinfo) == 0) { - GrabStats(ctx, NULL); - StorageStats(ctx); - pcilib_calc_deadline(&nextinfo, STATUS_MESSAGE_INTERVAL*1000000); - } - } - - usleep(100000); - } - - pcilib_calc_deadline(&nextinfo, STATUS_MESSAGE_INTERVAL*1000000); - while (ctx->writing_flag) { - if (pcilib_calc_time_to_deadline(&nextinfo) == 0) { - if (verbose >= 0) StorageStats(ctx); - pcilib_calc_deadline(&nextinfo, STATUS_MESSAGE_INTERVAL*1000000); - } - - usleep(100000); - } - - return NULL; -} - -int TriggerAndGrab(pcilib_t *handle, GRAB_MODE grab_mode, const char *evname, const char *data_type, size_t num, size_t run_time, size_t trigger_time, pcilib_timeout_t timeout, PARTITION partition, FORMAT format, size_t buffer_size, size_t threads, int verbose, const char *output) { - int err; - GRABContext ctx; -// void *data = NULL; -// size_t size, written; - - pcilib_event_t event; - pcilib_event_t listen_events; - pcilib_event_data_type_t data; - - pthread_t monitor_thread; - pthread_t trigger_thread; - pthread_attr_t attr; - struct sched_param sched; - - struct timeval end_time; - pcilib_event_flags_t flags; - - if (evname) { - event = pcilib_find_event(handle, evname); - if (event == PCILIB_EVENT_INVALID) - Error("Can't find event (%s)", evname); - - listen_events = event; - } else { - listen_events = PCILIB_EVENTS_ALL; - event = PCILIB_EVENT0; - } - - if (data_type) { - data = pcilib_find_event_data_type(handle, event, data_type); - if (data == PCILIB_EVENT_DATA_TYPE_INVALID) - Error("Can't find data type (%s)", data_type); - } else { - data = PCILIB_EVENT_DATA; - } - - memset(&ctx, 0, sizeof(GRABContext)); - - ctx.handle = handle; - ctx.event = event; - ctx.data = data; - ctx.run_time = run_time; - ctx.timeout = timeout; - ctx.format = format; - - if (grab_mode&GRAB_MODE_GRAB) ctx.verbose = verbose; - else ctx.verbose = 0; - - if (grab_mode&GRAB_MODE_GRAB) { - ctx.writer = fastwriter_init(output, 0); - if (!ctx.writer) - Error("Can't initialize fastwritter library"); - - fastwriter_set_buffer_size(ctx.writer, buffer_size); - - err = fastwriter_open(ctx.writer, output, 0); - if (err) - Error("Error opening file (%s), Error: %i\n", output, err); - - ctx.writing_flag = 1; - } - - ctx.run_flag = 1; - - flags = PCILIB_EVENT_FLAGS_DEFAULT; - - if (data == PCILIB_EVENT_RAW_DATA) { - if (format == FORMAT_RAW) { - flags |= PCILIB_EVENT_FLAG_RAW_DATA_ONLY; - } - } else { - flags |= PCILIB_EVENT_FLAG_PREPROCESS; - } - - ctx.flags = flags; - -// printf("Limits: %lu %lu %lu\n", num, run_time, timeout); - pcilib_configure_autostop(handle, num, run_time); - - if (flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY) { - pcilib_configure_rawdata_callback(handle, &raw_data, &ctx); - } - - if (flags&PCILIB_EVENT_FLAG_PREPROCESS) { - pcilib_configure_preprocessing_threads(handle, threads); - } - - if (grab_mode&GRAB_MODE_TRIGGER) { - if (trigger_time) { - if ((timeout)&&(trigger_time * 2 > timeout)) { - timeout = 2 * trigger_time; - ctx.timeout = timeout; - } - } else { - // Otherwise, we will trigger next event after previous one is read - if (((grab_mode&GRAB_MODE_GRAB) == 0)||(flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY)) trigger_time = PCILIB_TRIGGER_TIMEOUT; - } - - ctx.max_triggers = num; - ctx.trigger_count = 0; - ctx.trigger_time = trigger_time; - - // We don't really care if RT priority is imposible - pthread_attr_init(&attr); - if (!pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) { - sched.sched_priority = sched_get_priority_min(SCHED_FIFO); - pthread_attr_setschedparam(&attr, &sched); - } - - // Start triggering thread and wait until it is schedulled - if (pthread_create(&trigger_thread, &attr, Trigger, (void*)&ctx)) - Error("Error spawning trigger thread"); - - while (!ctx.trigger_thread_started) usleep(10); - } - - gettimeofday(&ctx.start_time, NULL); - - if (grab_mode&GRAB_MODE_GRAB) { - err = pcilib_start(handle, listen_events, flags); - if (err) Error("Failed to start event engine, error %i", err); - } - - ctx.started = 1; - - if (run_time) { - ctx.stop_time.tv_usec = ctx.start_time.tv_usec + run_time%1000000; - if (ctx.stop_time.tv_usec > 999999) { - ctx.stop_time.tv_usec -= 1000000; - __sync_synchronize(); - ctx.stop_time.tv_sec = ctx.start_time.tv_sec + 1 + run_time / 1000000; - } else { - __sync_synchronize(); - ctx.stop_time.tv_sec = ctx.start_time.tv_sec + run_time / 1000000; - } - } - - memcpy(&ctx.last_frame, &ctx.start_time, sizeof(struct timeval)); - if (pthread_create(&monitor_thread, NULL, Monitor, (void*)&ctx)) - Error("Error spawning monitoring thread"); - - if (grab_mode&GRAB_MODE_GRAB) { - err = pcilib_stream(handle, &GrabCallback, &ctx); - if (err) Error("Error streaming events, error %i", err); - } - - ctx.run_flag = 0; - - if (grab_mode&GRAB_MODE_TRIGGER) { - while (ctx.trigger_thread_started) usleep(10); - } - - if (grab_mode&GRAB_MODE_GRAB) { - pcilib_stop(handle, PCILIB_EVENT_FLAGS_DEFAULT); - } - - gettimeofday(&end_time, NULL); - - if (grab_mode&GRAB_MODE_TRIGGER) { - pthread_join(trigger_thread, NULL); - } - - - if (grab_mode&GRAB_MODE_GRAB) { - if (verbose >= 0) - printf("Grabbing is finished, flushing results....\n"); - - err = fastwriter_close(ctx.writer); - if (err) Error("Storage problems, error %i", err); - } - - ctx.writing_flag = 0; - - pthread_join(monitor_thread, NULL); - - if ((grab_mode&GRAB_MODE_GRAB)&&(verbose>=0)) { - GrabStats(&ctx, &end_time); - StorageStats(&ctx); - } - - fastwriter_destroy(ctx.writer); - - return 0; -} - -int StartStopDMA(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_dma_engine_addr_t dma, pcilib_dma_direction_t dma_direction, int start) { - int err; - pcilib_dma_engine_t dmaid; - - if (dma == PCILIB_DMA_ENGINE_ADDR_INVALID) { - const pcilib_dma_info_t *dma_info = pcilib_get_dma_info(handle); - - if (start) Error("DMA engine should be specified"); - - for (dmaid = 0; dma_info->engines[dmaid]; dmaid++) { - err = pcilib_start_dma(handle, dmaid, 0); - if (err) Error("Error starting DMA Engine (%s %i)", ((dma_info->engines[dmaid]->direction == PCILIB_DMA_FROM_DEVICE)?"C2S":"S2C"), dma_info->engines[dmaid]->addr); - err = pcilib_stop_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT); - if (err) Error("Error stopping DMA Engine (%s %i)", ((dma_info->engines[dmaid]->direction == PCILIB_DMA_FROM_DEVICE)?"C2S":"S2C"), dma_info->engines[dmaid]->addr); - } - - return 0; - } - - if (dma_direction&PCILIB_DMA_FROM_DEVICE) { - dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_FROM_DEVICE, dma); - if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (C2S %lu) is specified", dma); - - if (start) { - err = pcilib_start_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT); - if (err) Error("Error starting DMA engine (C2S %lu)", dma); - } else { - err = pcilib_start_dma(handle, dmaid, 0); - if (err) Error("Error starting DMA engine (C2S %lu)", dma); - err = pcilib_stop_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT); - if (err) Error("Error stopping DMA engine (C2S %lu)", dma); - } - } - - if (dma_direction&PCILIB_DMA_TO_DEVICE) { - dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_TO_DEVICE, dma); - if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (S2C %lu) is specified", dma); - - if (start) { - err = pcilib_start_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT); - if (err) Error("Error starting DMA engine (S2C %lu)", dma); - } else { - err = pcilib_start_dma(handle, dmaid, 0); - if (err) Error("Error starting DMA engine (S2C %lu)", dma); - err = pcilib_stop_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT); - if (err) Error("Error stopping DMA engine (S2C %lu)", dma); - } - } - - return 0; -} - - -typedef struct { - pcilib_kmem_use_t use; - - int referenced; - int hw_lock; - int reusable; - int persistent; - int open; - - size_t count; - size_t size; -} kmem_use_info_t; - -#define MAX_USES 64 - -pcilib_kmem_use_t ParseUse(const char *use) { - unsigned long utmp; - - if (use) { - if ((!isxnumber(use))||(sscanf(use, "%lx", &utmp) != 1)) Error("Invalid use (%s) is specified", use); - - if (strlen(use) < 5) - return PCILIB_KMEM_USE(PCILIB_KMEM_USE_USER,utmp); - else - return utmp; - } - - Error("Kernel memory use is not specified"); - return 0; -} - -size_t FindUse(size_t *n_uses, kmem_use_info_t *uses, pcilib_kmem_use_t use) { - size_t i, n = *n_uses; - - if (uses[n - 1].use == use) return n - 1; - - for (i = 1; i < (n - 1); i++) { - if (uses[i].use == use) return i; - } - - if (n == MAX_USES) return 0; - - uses[n].use = use; - return (*n_uses)++; -} - - -kmem_use_info_t *GetUse(size_t n_uses, kmem_use_info_t *uses, pcilib_kmem_use_t use) { - size_t i; - for (i = 0; i < n_uses; i++) { - if (uses[i].use == use) { - if (uses[i].count) return uses + i; - else return NULL; - } - } - return NULL; -} - - -int ParseKMEM(pcilib_t *handle, const char *device, size_t *uses_number, kmem_use_info_t *uses) { - DIR *dir; - struct dirent *entry; - const char *pos; - char sysdir[256]; - char fname[256]; - char info[256]; - - size_t useid, n_uses = 1; // Use 0 is for others - - memset(uses, 0, sizeof(uses)); - - pos = strrchr(device, '/'); - if (pos) ++pos; - else pos = device; - - snprintf(sysdir, 255, "/sys/class/fpga/%s", pos); - - dir = opendir(sysdir); - if (!dir) Error("Can't open directory (%s)", sysdir); - - while ((entry = readdir(dir)) != NULL) { - FILE *f; - unsigned long use = 0; - unsigned long size = 0; - unsigned long refs = 0; - unsigned long mode = 0; - unsigned long hwref = 0; - - if (strncmp(entry->d_name, "kbuf", 4)) continue; - if (!isnumber(entry->d_name+4)) continue; - - snprintf(fname, 255, "%s/%s", sysdir, entry->d_name); - f = fopen(fname, "r"); - if (!f) Error("Can't access file (%s)", fname); - - while(!feof(f)) { - fgets(info, 256, f); - if (!strncmp(info, "use:", 4)) use = strtoul(info+4, NULL, 16); - if (!strncmp(info, "size:", 5)) size = strtoul(info+5, NULL, 10); - if (!strncmp(info, "refs:", 5)) refs = strtoul(info+5, NULL, 10); - if (!strncmp(info, "mode:", 5)) mode = strtoul(info+5, NULL, 16); - if (!strncmp(info, "hw ref:", 7)) hwref = strtoul(info+7, NULL, 10); - } - fclose(f); - - useid = FindUse(&n_uses, uses, use); - uses[useid].count++; - uses[useid].size += size; - if (refs) uses[useid].referenced = 1; - if (hwref) uses[useid].hw_lock = 1; - if (mode&KMEM_MODE_REUSABLE) uses[useid].reusable = 1; - if (mode&KMEM_MODE_PERSISTENT) uses[useid].persistent = 1; - if (mode&KMEM_MODE_COUNT) uses[useid].open = 1; - } - closedir(dir); - - *uses_number = n_uses; - - return 0; -} - -int ListKMEM(pcilib_t *handle, const char *device) { - int err; - char stmp[256]; - - size_t i, useid, n_uses; - kmem_use_info_t uses[MAX_USES]; - - err = ParseKMEM(handle, device, &n_uses, uses); - if (err) Error("Failed to parse kernel memory information provided through sysfs"); - - if ((n_uses == 1)&&(uses[0].count == 0)) { - printf("No kernel memory is allocated\n"); - return 0; - } - - printf("Use Type Count Total Size REF Mode \n"); - printf("--------------------------------------------------------------------------------\n"); - for (useid = 0; useid < n_uses; useid++) { - if (useid + 1 == n_uses) { - if (!uses[0].count) continue; - i = 0; - } else i = useid + 1; - - printf("%08x ", uses[i].use); - if (!i) printf("All Others "); - else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_RING) printf("DMA%u %s Ring ", uses[i].use&0x7F, ((uses[i].use&0x80)?"S2C":"C2S")); - else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_PAGES) printf("DMA%u %s Pages ", uses[i].use&0x7F, ((uses[i].use&0x80)?"S2C":"C2S")); - else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_USER) printf("User %04x ", uses[i].use&0xFFFF); - else printf (" "); - printf(" "); - printf("% 6lu", uses[i].count); - printf(" "); - printf("% 10s", GetPrintSize(stmp, uses[i].size)); - printf(" "); - if (uses[i].referenced&&uses[i].hw_lock) printf("HW+SW"); - else if (uses[i].referenced) printf(" SW"); - else if (uses[i].hw_lock) printf("HW "); - else printf(" - "); - printf(" "); - if (uses[i].persistent) printf("Persistent"); - else if (uses[i].open) printf("Open "); - else if (uses[i].reusable) printf("Reusable "); - else printf("Closed "); - printf("\n"); - } - printf("--------------------------------------------------------------------------------\n"); - printf("REF - Software/Hardware Reference, MODE - Reusable/Persistent/Open\n"); - - - return 0; -} - -int DetailKMEM(pcilib_t *handle, const char *device, const char *use, size_t block) { - int err; - size_t i, n; - pcilib_kmem_handle_t *kbuf; - pcilib_kmem_use_t useid = ParseUse(use); - - size_t n_uses; - kmem_use_info_t uses[MAX_USES]; - kmem_use_info_t *use_info; - - if (block == (size_t)-1) { - err = ParseKMEM(handle, device, &n_uses, uses); - if (err) Error("Failed to parse kernel memory information provided through sysfs"); - use_info = GetUse(n_uses, uses, useid); - if (!use_info) Error("No kernel buffers is allocated for the specified use (%lx)", useid); - - i = 0; - n = use_info->count; - } else { - i = block; - n = block + 1; - } - - kbuf = pcilib_alloc_kernel_memory(handle, 0, n, 0, 0, useid, PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_TRY); - if (!kbuf) { - Error("Allocation of kernel buffer (use %lx, count %lu) is failed\n", useid, n); - return 0; - } - - printf("Buffer Address Hardware Address Bus Address\n"); - printf("--------------------------------------------------------------------------------\n"); - for (; i < n; i++) { - void *data = pcilib_kmem_get_block_ua(handle, kbuf, i); - uintptr_t pa = pcilib_kmem_get_block_pa(handle, kbuf, i); - uintptr_t ba = pcilib_kmem_get_block_ba(handle, kbuf, i); - printf("%6lu %16p %16lx %16lx\n", i, data, pa, ba); - } - printf("\n"); - - pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE); - - return 0; -} - - -int ReadKMEM(pcilib_t *handle, const char *device, pcilib_kmem_use_t useid, size_t block, size_t max_size, FILE *o) { - int err; - void *data; - size_t size; - pcilib_kmem_handle_t *kbuf; - - if (block == (size_t)-1) block = 0; - - kbuf = pcilib_alloc_kernel_memory(handle, 0, block + 1, 0, 0, useid, PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_TRY); - if (!kbuf) { - Error("The specified kernel buffer is not allocated\n"); - return 0; - } - - err = pcilib_kmem_sync_block(handle, kbuf, PCILIB_KMEM_SYNC_FROMDEVICE, block); - if (err) { - pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE); - Error("The synchronization of kernel buffer has failed\n"); - return 0; - } - - data = pcilib_kmem_get_block_ua(handle, kbuf, block); - if (data) { - size = pcilib_kmem_get_block_size(handle, kbuf, block); - if ((max_size)&&(size > max_size)) size = max_size; - - fwrite(data, 1, size, o?o:stdout); - } else { - pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE); - Error("The specified block is not existing\n"); - return 0; - } - - pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE); - - return 0; -} - -int AllocKMEM(pcilib_t *handle, const char *device, const char *use, const char *type, size_t size, size_t block_size, size_t alignment) { - pcilib_kmem_type_t ktype = PCILIB_KMEM_TYPE_PAGE; - pcilib_kmem_flags_t flags = KMEM_FLAG_REUSE; - pcilib_kmem_handle_t *kbuf; - pcilib_kmem_use_t useid = ParseUse(use); - - long page_size = sysconf(_SC_PAGESIZE); - - if (type) { - if (!strcmp(type, "consistent")) ktype = PCILIB_KMEM_TYPE_CONSISTENT; - else if (!strcmp(type, "c2s")) ktype = PCILIB_KMEM_TYPE_DMA_C2S_PAGE; - else if (!strcmp(type, "s2c")) ktype = PCILIB_KMEM_TYPE_DMA_S2C_PAGE; - else Error("Invalid memory type (%s) is specified", type); - } - - if ((block_size)&&(ktype != PCILIB_KMEM_TYPE_CONSISTENT)) - Error("Selected memory type does not allow custom size"); - - kbuf = pcilib_alloc_kernel_memory(handle, ktype, size, (block_size?block_size:page_size), (alignment?alignment:page_size), useid, flags|KMEM_FLAG_PERSISTENT); - if (!kbuf) Error("Allocation of kernel memory has failed"); - - pcilib_free_kernel_memory(handle, kbuf, flags); - - return 0; -} - -int FreeKMEM(pcilib_t *handle, const char *device, const char *use, int force) { - int err; - int i; - - pcilib_kmem_use_t useid; - - pcilib_kmem_flags_t flags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT|PCILIB_KMEM_FLAG_EXCLUSIVE; - if (force) flags |= PCILIB_KMEM_FLAG_FORCE; // this will ignore mmap locks as well. - - if (!strcasecmp(use, "dma")) { - for (i = 0; i < PCILIB_MAX_DMA_ENGINES; i++) { - err = pcilib_clean_kernel_memory(handle, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, i), flags); - if (err) Error("Error cleaning DMA%i C2S Ring buffer", i); - err = pcilib_clean_kernel_memory(handle, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, 0x80|i), flags); - if (err) Error("Error cleaning DMA%i S2C Ring buffer", i); - err = pcilib_clean_kernel_memory(handle, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, i), flags); - if (err) Error("Error cleaning DMA%i C2S Page buffers", i); - err = pcilib_clean_kernel_memory(handle, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, 0x80|i), flags); - if (err) Error("Error cleaning DMA%i S2C Page buffers", i); - } - - return 0; - } - - useid = ParseUse(use); - err = pcilib_clean_kernel_memory(handle, useid, flags); - if (err) Error("Error cleaning kernel buffers for use (0x%lx)", useid); - - return 0; -} - -int ListDMA(pcilib_t *handle, const char *device, pcilib_model_description_t *model_info) { - int err; - - DIR *dir; - struct dirent *entry; - const char *pos; - char sysdir[256]; - char fname[256]; - char info[256]; - char stmp[256]; - - pcilib_dma_engine_t dmaid; - pcilib_dma_engine_status_t status; - - pos = strrchr(device, '/'); - if (pos) ++pos; - else pos = device; - - snprintf(sysdir, 255, "/sys/class/fpga/%s", pos); - - dir = opendir(sysdir); - if (!dir) Error("Can't open directory (%s)", sysdir); - - printf("DMA Engine Status Total Size Buffer Ring (1st used - 1st free)\n"); - printf("--------------------------------------------------------------------------------\n"); - while ((entry = readdir(dir)) != NULL) { - FILE *f; - unsigned long use = 0; -// unsigned long size = 0; -// unsigned long refs = 0; - unsigned long mode = 0; -// unsigned long hwref = 0; - - if (strncmp(entry->d_name, "kbuf", 4)) continue; - if (!isnumber(entry->d_name+4)) continue; - - snprintf(fname, 255, "%s/%s", sysdir, entry->d_name); - f = fopen(fname, "r"); - if (!f) Error("Can't access file (%s)", fname); - - while(!feof(f)) { - fgets(info, 256, f); - if (!strncmp(info, "use:", 4)) use = strtoul(info+4, NULL, 16); -// if (!strncmp(info, "size:", 5)) size = strtoul(info+5, NULL, 10); -// if (!strncmp(info, "refs:", 5)) refs = strtoul(info+5, NULL, 10); - if (!strncmp(info, "mode:", 5)) mode = strtoul(info+5, NULL, 16); -// if (!strncmp(info, "hw ref:", 7)) hwref = strtoul(info+7, NULL, 10); - } - fclose(f); - - if ((mode&(KMEM_MODE_REUSABLE|KMEM_MODE_PERSISTENT|KMEM_MODE_COUNT)) == 0) continue; // closed - if ((use >> 16) != PCILIB_KMEM_USE_DMA_RING) continue; - - if (use&0x80) { - dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_TO_DEVICE, use&0x7F); - } else { - dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_FROM_DEVICE, use&0x7F); - } - - if (dmaid == PCILIB_DMA_ENGINE_INVALID) continue; - - - printf("DMA%lu %s ", use&0x7F, (use&0x80)?"S2C":"C2S"); - err = pcilib_start_dma(handle, dmaid, 0); - if (err) { - printf("-- Wrong state, start is failed\n"); - continue; - } - - err = pcilib_get_dma_status(handle, dmaid, &status, 0, NULL); - if (err) { - printf("-- Wrong state, failed to obtain status\n"); - pcilib_stop_dma(handle, dmaid, 0); - continue; - } - - pcilib_stop_dma(handle, dmaid, 0); - - if (status.started) printf("S"); - else printf(" "); - - if (status.ring_head == status.ring_tail) printf(" "); - else printf("D"); - - printf(" "); - printf("% 10s", GetPrintSize(stmp, status.ring_size * status.buffer_size)); - - printf(" "); - printf("%zu - %zu (of %zu)", status.ring_tail, status.ring_head, status.ring_size); - - printf("\n"); - - } - closedir(dir); - - printf("--------------------------------------------------------------------------------\n"); - printf("S - Started, D - Data in buffers\n"); - - return 0; -} - -int ListBuffers(pcilib_t *handle, const char *device, pcilib_model_description_t *model_info, pcilib_dma_engine_addr_t dma, pcilib_dma_direction_t dma_direction) { - int err; - size_t i; - pcilib_dma_engine_t dmaid; - pcilib_dma_engine_status_t status; - pcilib_dma_buffer_status_t *buffer; - char stmp[256]; - - dmaid = pcilib_find_dma_by_addr(handle, dma_direction, dma); - if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("The specified DMA engine is not found"); - - err = pcilib_start_dma(handle, dmaid, 0); - if (err) Error("Error starting the specified DMA engine"); - - err = pcilib_get_dma_status(handle, dmaid, &status, 0, NULL); - if (err) Error("Failed to obtain status of the specified DMA engine"); - - buffer = (pcilib_dma_buffer_status_t*)malloc(status.ring_size*sizeof(pcilib_dma_buffer_status_t)); - if (!buffer) Error("Failed to allocate memory for status buffer"); - - err = pcilib_get_dma_status(handle, dmaid, &status, status.ring_size, buffer); - if (err) Error("Failed to obtain extended status of the specified DMA engine"); - - - printf("Buffer Status Total Size \n"); - printf("--------------------------------------------------------------------------------\n"); - - for (i = 0; i < status.ring_size; i++) { - printf("%8zu ", i); - printf("%c%c %c%c ", buffer[i].used?'U':' ', buffer[i].error?'E':' ', buffer[i].first?'F':' ', buffer[i].last?'L':' '); - printf("% 10s", GetPrintSize(stmp, buffer[i].size)); - printf("\n"); - } - - printf("--------------------------------------------------------------------------------\n"); - printf("U - Used, E - Error, F - First block, L - Last Block\n"); - - free(buffer); - - pcilib_stop_dma(handle, dmaid, 0); - - return 0; -} - -int ReadBuffer(pcilib_t *handle, const char *device, pcilib_model_description_t *model_info, pcilib_dma_engine_addr_t dma, pcilib_dma_direction_t dma_direction, size_t block, FILE *o) { - int err; - pcilib_dma_engine_t dmaid; - pcilib_dma_engine_status_t status; - pcilib_dma_buffer_status_t *buffer; - size_t size; - - dmaid = pcilib_find_dma_by_addr(handle, dma_direction, dma); - if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("The specified DMA engine is not found"); - - err = pcilib_start_dma(handle, dmaid, 0); - if (err) Error("Error starting the specified DMA engine"); - - err = pcilib_get_dma_status(handle, dmaid, &status, 0, NULL); - if (err) Error("Failed to obtain status of the specified DMA engine"); - - buffer = (pcilib_dma_buffer_status_t*)malloc(status.ring_size*sizeof(pcilib_dma_buffer_status_t)); - if (!buffer) Error("Failed to allocate memory for status buffer"); - - err = pcilib_get_dma_status(handle, dmaid, &status, status.ring_size, buffer); - if (err) Error("Failed to obtain extended status of the specified DMA engine"); - - if (block == (size_t)-1) { - // get current - } - - size = buffer[block].size; - - free(buffer); - - pcilib_stop_dma(handle, dmaid, 0); - - return ReadKMEM(handle, device, ((dma&0x7F)|((dma_direction == PCILIB_DMA_TO_DEVICE)?0x80:0x00))|(PCILIB_KMEM_USE_DMA_PAGES<<16), block, size, o); -} - - -int EnableIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_type_t irq_type) { - int err; - - err = pcilib_enable_irq(handle, irq_type, 0); - if (err) { - if ((err != PCILIB_ERROR_NOTSUPPORTED)&&(err != PCILIB_ERROR_NOTAVAILABLE)) - Error("Error enabling IRQs"); - } - - return err; -} - -int DisableIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_type_t irq_type) { - int err; - - err = pcilib_disable_irq(handle, 0); - if (err) { - if ((err != PCILIB_ERROR_NOTSUPPORTED)&&(err != PCILIB_ERROR_NOTAVAILABLE)) - Error("Error disabling IRQs"); - } - - return err; -} - -int AckIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_hw_source_t irq_source) { - pcilib_clear_irq(handle, irq_source); - return 0; -} - -int WaitIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_hw_source_t irq_source, pcilib_timeout_t timeout) { - int err; - size_t count; - - err = pcilib_wait_irq(handle, irq_source, timeout, &count); - if (err) { - if (err == PCILIB_ERROR_TIMEOUT) Error("Timeout waiting for IRQ"); - else Error("Error waiting for IRQ"); - } - - return 0; -} - - -int main(int argc, char **argv) { - int i; - long itmp; - size_t ztmp; - unsigned char c; - - const char *stmp; - const char *num_offset; - - int details = 0; - int verbose = 0; - int quiete = 0; - int force = 0; - int verify = 0; - - pcilib_model_t model = PCILIB_MODEL_DETECT; - pcilib_model_description_t *model_info; - MODE mode = MODE_INVALID; - GRAB_MODE grab_mode = 0; - size_t trigger_time = 0; - size_t run_time = 0; - size_t buffer = 0; - size_t threads = 1; - FORMAT format = FORMAT_DEFAULT; - PARTITION partition = PARTITION_UNKNOWN; - FLAGS flags = 0; - const char *atype = NULL; - const char *type = NULL; - ACCESS_MODE amode = ACCESS_BAR; - const char *fpga_device = DEFAULT_FPGA_DEVICE; - pcilib_bar_t bar = PCILIB_BAR_DETECT; - const char *addr = NULL; - const char *reg = NULL; - const char *bank = NULL; - char **data = NULL; - const char *event = NULL; - const char *data_type = NULL; - const char *dma_channel = NULL; - const char *use = NULL; - size_t block = (size_t)-1; - pcilib_irq_type_t irq_type = PCILIB_IRQ_TYPE_ALL; - pcilib_irq_hw_source_t irq_source = PCILIB_IRQ_SOURCE_DEFAULT; - pcilib_dma_direction_t dma_direction = PCILIB_DMA_BIDIRECTIONAL; - pcilib_kmem_use_t useid = 0; - - pcilib_dma_engine_addr_t dma = PCILIB_DMA_ENGINE_ADDR_INVALID; - long addr_shift = 0; - uintptr_t start = -1; - size_t block_size = 0; - size_t size = 1; - access_t access = 4; -// int skip = 0; - int endianess = 0; - size_t timeout = 0; - size_t alignment = 0; - const char *output = NULL; - FILE *ofile = NULL; - size_t iterations = BENCHMARK_ITERATIONS; - - pcilib_t *handle; - - int size_set = 0; - int timeout_set = 0; -// int run_time_set = 0; - - while ((c = getopt_long(argc, argv, "hqilr::w::g::d:m:t:b:a:s:e:o:", long_options, NULL)) != (unsigned char)-1) { - extern int optind; - switch (c) { - case OPT_HELP: - Usage(argc, argv, NULL); - break; - case OPT_INFO: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_INFO; - break; - case OPT_LIST: - if (mode == MODE_LIST) details++; - else if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_LIST; - break; - case OPT_RESET: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_RESET; - break; - case OPT_BENCHMARK: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_BENCHMARK; - - if (optarg) addr = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) addr = argv[optind++]; - break; - case OPT_READ: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_READ; - if (optarg) addr = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) addr = argv[optind++]; - break; - case OPT_WRITE: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_WRITE; - if (optarg) addr = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) addr = argv[optind++]; - break; - case OPT_GRAB: - if ((mode != MODE_INVALID)&&((mode != MODE_GRAB)||(grab_mode&GRAB_MODE_GRAB))) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_GRAB; - grab_mode |= GRAB_MODE_GRAB; - - stmp = NULL; - if (optarg) stmp = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) stmp = argv[optind++]; - - if (stmp) { - if ((event)&&(strcasecmp(stmp,event))) Usage(argc, argv, "Redefinition of considered event"); - event = stmp; - } - break; - case OPT_TRIGGER: - if ((mode != MODE_INVALID)&&((mode != MODE_GRAB)||(grab_mode&GRAB_MODE_TRIGGER))) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_GRAB; - grab_mode |= GRAB_MODE_TRIGGER; - - stmp = NULL; - if (optarg) stmp = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) stmp = argv[optind++]; - - if (stmp) { - if ((event)&&(strcasecmp(stmp,event))) Usage(argc, argv, "Redefinition of considered event"); - event = stmp; - } - break; - case OPT_LIST_DMA: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_LIST_DMA; - break; - case OPT_LIST_DMA_BUFFERS: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_LIST_DMA_BUFFERS; - dma_channel = optarg; - break; - case OPT_READ_DMA_BUFFER: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_READ_DMA_BUFFER; - - num_offset = strchr(optarg, ':'); - - if (num_offset) { - if (sscanf(num_offset + 1, "%zu", &block) != 1) - Usage(argc, argv, "Invalid buffer is specified (%s)", num_offset + 1); - - *(char*)num_offset = 0; - } else block = (size_t)-1; - - dma_channel = optarg; - break; - case OPT_START_DMA: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_START_DMA; - if (optarg) dma_channel = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) dma_channel = argv[optind++]; - break; - case OPT_STOP_DMA: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_STOP_DMA; - if (optarg) dma_channel = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) dma_channel = argv[optind++]; - break; - case OPT_ENABLE_IRQ: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_ENABLE_IRQ; - if (optarg) num_offset = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++]; - else num_offset = NULL; - - if (num_offset) { - if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1)) - Usage(argc, argv, "Invalid IRQ source is specified (%s)", num_offset); - - irq_type = itmp; - } - break; - case OPT_DISABLE_IRQ: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_DISABLE_IRQ; - if (optarg) num_offset = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++]; - else num_offset = NULL; - - if (num_offset) { - if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1)) - Usage(argc, argv, "Invalid IRQ source is specified (%s)", num_offset); - - irq_type = itmp; - } - break; - case OPT_ACK_IRQ: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_ACK_IRQ; - if (optarg) num_offset = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++]; - else num_offset = NULL; - - if (num_offset) { - if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1)) - Usage(argc, argv, "Invalid IRQ source is specified (%s)", num_offset); - - irq_source = itmp; - } - break; - case OPT_WAIT_IRQ: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - - mode = MODE_WAIT_IRQ; - if (optarg) num_offset = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++]; - else num_offset = NULL; - - if (num_offset) { - if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1)) - Usage(argc, argv, "Invalid IRQ source is specified (%s)", num_offset); - - irq_source = itmp; - } - break; - case OPT_LIST_KMEM: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - mode = MODE_LIST_KMEM; - - if (optarg) use = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) use = argv[optind++]; - else use = NULL; - - if (use) { - num_offset = strchr(use, ':'); - - if (num_offset) { - if (sscanf(num_offset + 1, "%zu", &block) != 1) - Usage(argc, argv, "Invalid block number is specified (%s)", num_offset + 1); - - *(char*)num_offset = 0; - } - } - break; - case OPT_READ_KMEM: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - mode = MODE_READ_KMEM; - - num_offset = strchr(optarg, ':'); - - if (num_offset) { - if (sscanf(num_offset + 1, "%zu", &block) != 1) - Usage(argc, argv, "Invalid block number is specified (%s)", num_offset + 1); - - *(char*)num_offset = 0; - } - - use = optarg; - useid = ParseUse(use); - break; - case OPT_ALLOC_KMEM: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - mode = MODE_ALLOC_KMEM; - - if (optarg) use = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) use = argv[optind++]; - break; - case OPT_FREE_KMEM: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); - mode = MODE_FREE_KMEM; - - if (optarg) use = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) use = argv[optind++]; - break; - case OPT_DEVICE: - fpga_device = optarg; - break; - case OPT_MODEL: - if (!strcasecmp(optarg, "pci")) model = PCILIB_MODEL_PCI; - else if (!strcasecmp(optarg, "ipecamera")) model = PCILIB_MODEL_IPECAMERA; - else if (!strcasecmp(optarg, "kapture")) model = PCILIB_MODEL_KAPTURE; - else Usage(argc, argv, "Invalid memory model (%s) is specified", optarg); - break; - case OPT_BAR: - bank = optarg; -// if ((sscanf(optarg,"%li", &itmp) != 1)||(itmp < 0)||(itmp >= PCILIB_MAX_BANKS)) Usage(argc, argv, "Invalid data bank (%s) is specified", optarg); -// else bar = itmp; - break; - case OPT_ALIGNMENT: - if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &alignment) != 1)) { - Usage(argc, argv, "Invalid alignment is specified (%s)", optarg); - } - break; - case OPT_ACCESS: - if (!strncasecmp(optarg, "fifo", 4)) { - atype = "fifo"; - num_offset = optarg + 4; - amode = ACCESS_FIFO; - } else if (!strncasecmp(optarg, "dma", 3)) { - atype = "dma"; - num_offset = optarg + 3; - amode = ACCESS_DMA; - } else if (!strncasecmp(optarg, "bar", 3)) { - atype = "plain"; - num_offset = optarg + 3; - amode = ACCESS_BAR; - } else if (!strncasecmp(optarg, "config", 6)) { - atype = "config"; - num_offset = optarg + 6; - amode = ACCESS_CONFIG; - } else if (!strncasecmp(optarg, "plain", 5)) { - atype = "plain"; - num_offset = optarg + 5; - amode = ACCESS_BAR; - } else { - num_offset = optarg; - } - - if (*num_offset) { - if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1)) - Usage(argc, argv, "Invalid access type (%s) is specified", optarg); - - switch (itmp) { - case 8: access = 1; break; - case 16: access = 2; break; - case 32: access = 4; break; - case 64: access = 8; break; - default: Usage(argc, argv, "Invalid data width (%s) is specified", num_offset); - } - } - break; - case OPT_SIZE: - if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &size) != 1)) { - if (strcasecmp(optarg, "unlimited")) - Usage(argc, argv, "Invalid size is specified (%s)", optarg); - else - size = 0;//(size_t)-1; - } - - size_set = 1; - break; - case OPT_BLOCK_SIZE: - if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &block_size) != 1)) { - Usage(argc, argv, "Invalid size is specified (%s)", optarg); - } - break; - case OPT_ENDIANESS: - if ((*optarg == 'b')||(*optarg == 'B')) { - if (ntohs(1) == 1) endianess = 0; - else endianess = 1; - } else if ((*optarg == 'l')||(*optarg == 'L')) { - if (ntohs(1) == 1) endianess = 1; - else endianess = 0; - } else Usage(argc, argv, "Invalid endianess is specified (%s)", optarg); - - break; - case OPT_TIMEOUT: - if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &timeout) != 1)) { - if (strcasecmp(optarg, "unlimited")) - Usage(argc, argv, "Invalid timeout is specified (%s)", optarg); - else - timeout = PCILIB_TIMEOUT_INFINITE; - } - timeout_set = 1; - break; - case OPT_OUTPUT: - output = optarg; - break; - case OPT_ITERATIONS: - if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &iterations) != 1)) - Usage(argc, argv, "Invalid number of iterations is specified (%s)", optarg); - break; - case OPT_EVENT: - event = optarg; - break; - case OPT_TYPE: - type = optarg; - break; - case OPT_DATA_TYPE: - data_type = optarg; - break; - case OPT_RUN_TIME: - if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &run_time) != 1)) { - if (strcasecmp(optarg, "unlimited")) - Usage(argc, argv, "Invalid run-time is specified (%s)", optarg); - else - run_time = 0; - } -// run_time_set = 1; - break; - case OPT_TRIGGER_TIME: - if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &trigger_time) != 1)) - Usage(argc, argv, "Invalid trigger-time is specified (%s)", optarg); - break; - case OPT_TRIGGER_RATE: - if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &ztmp) != 1)) - Usage(argc, argv, "Invalid trigger-rate is specified (%s)", optarg); - - trigger_time = (1000000 / ztmp) + ((1000000 % ztmp)?1:0); - break; - case OPT_BUFFER: - if (optarg) num_offset = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++]; - else num_offset = NULL; - - if (num_offset) { - if ((!isnumber(num_offset))||(sscanf(num_offset, "%zu", &buffer) != 1)) - Usage(argc, argv, "Invalid buffer size is specified (%s)", num_offset); - buffer *= 1024 * 1024; - } else { - buffer = get_free_memory(); - if (buffer < 256) Error("Not enough free memory (%lz MB) for buffering", buffer / 1024 / 1024); - - buffer -= 128 + buffer/16; - } - break; - case OPT_THREADS: - if (optarg) num_offset = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++]; - else num_offset = NULL; - - if (num_offset) { - if ((!isnumber(num_offset))||(sscanf(num_offset, "%zu", &threads) != 1)) - Usage(argc, argv, "Invalid threads number is specified (%s)", num_offset); - } else { - threads = 0; - } - break; - case OPT_FORMAT: - if (!strcasecmp(optarg, "raw")) format = FORMAT_RAW; - else if (!strcasecmp(optarg, "add_header")) format = FORMAT_HEADER; -// else if (!strcasecmp(optarg, "ringfs")) format = FORMAT_RINGFS; - else if (strcasecmp(optarg, "default")) Error("Invalid format (%s) is specified", optarg); - break; - case OPT_QUIETE: - quiete = 1; - verbose = -1; - break; - case OPT_VERBOSE: - if (optarg) num_offset = optarg; - else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++]; - else num_offset = NULL; - - if (num_offset) { - if ((!isnumber(num_offset))||(sscanf(num_offset, "%i", &verbose) != 1)) - Usage(argc, argv, "Invalid verbosity level is specified (%s)", num_offset); - } else { - verbose = 1; - } - break; - case OPT_FORCE: - force = 1; - break; - case OPT_VERIFY: - verify = 1; - break; - case OPT_MULTIPACKET: - flags |= FLAG_MULTIPACKET; - break; - case OPT_WAIT: - flags |= FLAG_WAIT; - break; - default: - Usage(argc, argv, "Unknown option (%s) with argument (%s)", optarg?argv[optind-2]:argv[optind-1], optarg?optarg:"(null)"); - } - } - - if (mode == MODE_INVALID) { - if (argc > 1) Usage(argc, argv, "Operation is not specified"); - else Usage(argc, argv, NULL); - } - - pcilib_set_error_handler(&Error, quiete?Silence:NULL); - - handle = pcilib_open(fpga_device, model); - if (handle < 0) Error("Failed to open FPGA device: %s", fpga_device); - - model = pcilib_get_model(handle); - model_info = pcilib_get_model_description(handle); - - switch (mode) { - case MODE_WRITE: - if (((argc - optind) == 1)&&(*argv[optind] == '*')) { - int vallen = strlen(argv[optind]); - if (vallen > 1) { - data = (char**)malloc(size * (vallen + sizeof(char*))); - if (!data) Error("Error allocating memory for data array"); - - for (i = 0; i < size; i++) { - data[i] = ((char*)data) + size * sizeof(char*) + i * vallen; - strcpy(data[i], argv[optind] + 1); - } - } else { - data = (char**)malloc(size * (9 + sizeof(char*))); - if (!data) Error("Error allocating memory for data array"); - - for (i = 0; i < size; i++) { - data[i] = ((char*)data) + size * sizeof(char*) + i * 9; - sprintf(data[i], "%x", i); - } - } - } else if ((argc - optind) == size) data = argv + optind; - else Usage(argc, argv, "The %i data values is specified, but %i required", argc - optind, size); - case MODE_READ: - if (!addr) { - if (model == PCILIB_MODEL_PCI) { - if ((amode != ACCESS_DMA)&&(amode != ACCESS_CONFIG)) - Usage(argc, argv, "The address is not specified"); - } else ++mode; - } - break; - case MODE_START_DMA: - case MODE_STOP_DMA: - case MODE_LIST_DMA_BUFFERS: - case MODE_READ_DMA_BUFFER: - if ((dma_channel)&&(*dma_channel)) { - itmp = strlen(dma_channel) - 1; - if (dma_channel[itmp] == 'r') dma_direction = PCILIB_DMA_FROM_DEVICE; - else if (dma_channel[itmp] == 'w') dma_direction = PCILIB_DMA_TO_DEVICE; - - if (dma_direction != PCILIB_DMA_BIDIRECTIONAL) itmp--; - - if (strncmp(dma_channel, "dma", 3)) num_offset = dma_channel; - else { - num_offset = dma_channel + 3; - itmp -= 3; - } - - if (bank) { - if (strncmp(num_offset, bank, itmp)) Usage(argc, argv, "Conflicting DMA channels are specified in mode parameter (%s) and bank parameter (%s)", dma_channel, bank); - } - - if (!isnumber_n(num_offset, itmp)) - Usage(argc, argv, "Invalid DMA channel (%s) is specified", dma_channel); - - dma = atoi(num_offset); - } - break; - default: - if (argc > optind) Usage(argc, argv, "Invalid non-option parameters are supplied"); - } - - - if (addr) { - if ((!strncmp(addr, "dma", 3))&&((addr[3]==0)||isnumber(addr+3))) { - if ((atype)&&(amode != ACCESS_DMA)) Usage(argc, argv, "Conflicting access modes, the DMA read is requested, but access type is (%s)", type); - if (bank) { - if ((addr[3] != 0)&&(strcmp(addr + 3, bank))) Usage(argc, argv, "Conflicting DMA channels are specified in read parameter (%s) and bank parameter (%s)", addr + 3, bank); - } else { - if (addr[3] == 0) Usage(argc, argv, "The DMA channel is not specified"); - } - dma = atoi(addr + 3); - amode = ACCESS_DMA; - addr = NULL; - } else if ((!strncmp(addr, "bar", 3))&&((addr[3]==0)||isnumber(addr+3))) { - if ((atype)&&(amode != ACCESS_BAR)) Usage(argc, argv, "Conflicting access modes, the plain PCI read is requested, but access type is (%s)", type); - if ((addr[3] != 0)&&(strcmp(addr + 3, bank))) Usage(argc, argv, "Conflicting PCI bars are specified in read parameter (%s) and bank parameter (%s)", addr + 3, bank); - bar = atoi(addr + 3); - amode = ACCESS_BAR; - addr = NULL; - } else if (!strcmp(addr, "config")) { - if ((atype)&&(amode != ACCESS_CONFIG)) Usage(argc, argv, "Conflicting access modes, the read of PCI configurataion space is requested, but access type is (%s)", type); - amode = ACCESS_CONFIG; - addr = NULL; - } else if ((isxnumber(addr))&&(sscanf(addr, "%lx", &start) == 1)) { - // check if the address in the register range - pcilib_register_range_t *ranges = model_info->ranges; - - if (ranges) { - for (i = 0; ranges[i].start != ranges[i].end; i++) - if ((start >= ranges[i].start)&&(start <= ranges[i].end)) break; - - // register access in plain mode - if (ranges[i].start != ranges[i].end) { - pcilib_register_bank_t regbank = pcilib_find_bank_by_addr(handle, ranges[i].bank); - if (regbank == PCILIB_REGISTER_BANK_INVALID) Error("Configuration error: register bank specified in the address range is not found"); - - bank = model_info->banks[regbank].name; - start += ranges[i].addr_shift; - addr_shift = ranges[i].addr_shift; - ++mode; - } - } - } else { - if (pcilib_find_register(handle, bank, addr) == PCILIB_REGISTER_INVALID) { - Usage(argc, argv, "Invalid address (%s) is specified", addr); - } else { - reg = addr; - ++mode; - } - } - } - - if (mode == MODE_GRAB) { - if (output) { - char fsname[128]; - if (!get_file_fs(output, 127, fsname)) { - if (!strcmp(fsname, "ext4")) partition = PARTITION_EXT4; - else if (!strcmp(fsname, "raw")) partition = PARTITION_RAW; - } - } else { - output = "/dev/null"; - partition = PARTITION_NULL; - } - - if (!timeout_set) { - if (run_time) timeout = PCILIB_TIMEOUT_INFINITE; - else timeout = PCILIB_EVENT_TIMEOUT; - } - - if (!size_set) { - if (run_time) size = 0; - } - } - - if (mode != MODE_GRAB) { - if (size == (size_t)-1) - Usage(argc, argv, "Unlimited size is not supported in selected operation mode"); - } - - - if ((bank)&&(amode == ACCESS_DMA)) { - if ((!isnumber(bank))||(sscanf(bank,"%li", &itmp) != 1)||(itmp < 0)) - Usage(argc, argv, "Invalid DMA channel (%s) is specified", bank); - else dma = itmp; - } else if (bank) { - switch (mode) { - case MODE_BENCHMARK: - case MODE_READ: - case MODE_WRITE: - if ((!isnumber(bank))||(sscanf(bank,"%li", &itmp) != 1)||(itmp < 0)||(itmp >= PCILIB_MAX_BANKS)) - Usage(argc, argv, "Invalid data bank (%s) is specified", bank); - else bar = itmp; - break; - default: - if (pcilib_find_bank(handle, bank) == PCILIB_REGISTER_BANK_INVALID) - Usage(argc, argv, "Invalid data bank (%s) is specified", bank); - } - } - - signal(SIGINT, signal_exit_handler); - - if ((mode != MODE_GRAB)&&(output)) { - ofile = fopen(output, "a+"); - if (!ofile) { - Error("Failed to open file \"%s\"", output); - } - } - - switch (mode) { - case MODE_INFO: - Info(handle, model_info); - break; - case MODE_LIST: - List(handle, model_info, bank, details); - break; - case MODE_BENCHMARK: - Benchmark(handle, amode, dma, bar, start, size_set?size:0, access, iterations); - break; - case MODE_READ: - if (amode == ACCESS_DMA) { - ReadData(handle, amode, flags, dma, bar, start, size_set?size:0, access, endianess, timeout_set?timeout:(size_t)-1, ofile); - } else if (amode == ACCESS_CONFIG) { - ReadData(handle, amode, flags, dma, bar, addr?start:0, (addr||size_set)?size:(256/abs(access)), access, endianess, (size_t)-1, ofile); - } else if (addr) { - ReadData(handle, amode, flags, dma, bar, start, size, access, endianess, (size_t)-1, ofile); - } else { - Error("Address to read is not specified"); - } - break; - case MODE_READ_REGISTER: - if ((reg)||(!addr)) ReadRegister(handle, model_info, bank, reg); - else ReadRegisterRange(handle, model_info, bank, start, addr_shift, size, ofile); - break; - case MODE_WRITE: - WriteData(handle, amode, dma, bar, start, size, access, endianess, data, verify); - break; - case MODE_WRITE_REGISTER: - if (reg) WriteRegister(handle, model_info, bank, reg, data); - else WriteRegisterRange(handle, model_info, bank, start, addr_shift, size, data); - break; - case MODE_RESET: - pcilib_reset(handle); - break; - case MODE_GRAB: - TriggerAndGrab(handle, grab_mode, event, data_type, size, run_time, trigger_time, timeout, partition, format, buffer, threads, verbose, output); - break; - case MODE_LIST_DMA: - ListDMA(handle, fpga_device, model_info); - break; - case MODE_LIST_DMA_BUFFERS: - ListBuffers(handle, fpga_device, model_info, dma, dma_direction); - break; - case MODE_READ_DMA_BUFFER: - ReadBuffer(handle, fpga_device, model_info, dma, dma_direction, block, ofile); - break; - case MODE_START_DMA: - StartStopDMA(handle, model_info, dma, dma_direction, 1); - break; - case MODE_STOP_DMA: - StartStopDMA(handle, model_info, dma, dma_direction, 0); - break; - case MODE_ENABLE_IRQ: - EnableIRQ(handle, model_info, irq_type); - break; - case MODE_DISABLE_IRQ: - DisableIRQ(handle, model_info, irq_type); - break; - case MODE_ACK_IRQ: - AckIRQ(handle, model_info, irq_source); - break; - case MODE_WAIT_IRQ: - WaitIRQ(handle, model_info, irq_source, timeout); - break; - case MODE_LIST_KMEM: - if (use) DetailKMEM(handle, fpga_device, use, block); - else ListKMEM(handle, fpga_device); - break; - case MODE_READ_KMEM: - ReadKMEM(handle, fpga_device, useid, block, 0, ofile); - break; - case MODE_ALLOC_KMEM: - AllocKMEM(handle, fpga_device, use, type, size, block_size, alignment); - break; - case MODE_FREE_KMEM: - FreeKMEM(handle, fpga_device, use, force); - break; - case MODE_INVALID: - break; - } - - if (ofile) fclose(ofile); - - pcilib_close(handle); - - if (data != argv + optind) free(data); -} diff --git a/cmosis.c b/cmosis.c new file mode 100644 index 0000000..a8a2251 --- /dev/null +++ b/cmosis.c @@ -0,0 +1,216 @@ +#define _BSD_SOURCE +#define _IPECAMERA_MODEL_C +#include +#include +#include + +#include +#include +#include + +#include "cmosis.h" +#include "private.h" + +#define ADDR_MASK 0x7F00 +#define WRITE_BIT 0x8000 +#define RETRIES 10 + +//ToDo: check bot 1 and 2 bits for READY +#define READ_READY_BIT 0x20000 +#define READ_ERROR_BIT 0x40000 + +#define ipecamera_datacpy(dst, src, bank) pcilib_datacpy(dst, src, 4, 1, bank->raw_endianess) + +//#define IPECAMERA_SIMPLIFIED_READOUT +#define IPECAMERA_MULTIREAD + +//static pcilib_register_value_t ipecamera_bit_mask[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 }; + +int ipecamera_cmosis_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t *value) { + uint32_t val, tmp[4]; + char *wr, *rd; + struct timeval start;//, cur; + int retries = RETRIES; + const pcilib_register_bank_description_t *bank = bank_ctx->bank; + + assert(addr < 128); + + wr = pcilib_resolve_register_address(ctx, bank->bar, bank->write_addr); + rd = pcilib_resolve_register_address(ctx, bank->bar, bank->read_addr); + if ((!rd)||(!wr)) { + pcilib_error("Error resolving addresses of read & write registers"); + return PCILIB_ERROR_INVALID_ADDRESS; + } + + //printf("%i %x %p %p\n", addr, val, wr, rd); + +/* +#ifdef IPECAMERA_SIMPLIFIED_READOUT + ipecamera_datacpy(tmp, rd, bank); +#endif +*/ + +retry: + val = (addr << 8); + + ipecamera_datacpy(wr, &val, bank); + +#ifdef IPECAMERA_SIMPLIFIED_READOUT + usleep(IPECAMERA_REGISTER_TIMEOUT); +// ipecamera_datacpy(tmp, rd, bank); +// usleep(IPECAMERA_REGISTER_TIMEOUT); + ipecamera_datacpy(wr, &val, bank); + usleep(IPECAMERA_REGISTER_TIMEOUT); +// ipecamera_datacpy(tmp, rd, bank); +// usleep(IPECAMERA_REGISTER_TIMEOUT); + ipecamera_datacpy(wr, &val, bank); + usleep(IPECAMERA_REGISTER_TIMEOUT); +#endif /* IPECAMERA_SIMPLIFIED_READOUT */ + + gettimeofday(&start, NULL); + +#ifdef IPECAMERA_MULTIREAD + usleep(IPECAMERA_REGISTER_TIMEOUT); + pcilib_datacpy(tmp, rd, 4, 4, bank->raw_endianess); + val = tmp[0]; +#else /* IPECAMERA_MULTIREAD */ + ipecamera_datacpy(&val, rd, bank); + + while ((val & READ_READY_BIT) == 0) { + gettimeofday(&cur, NULL); + if (((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) > IPECAMERA_REGISTER_TIMEOUT) break; + + ipecamera_datacpy(&val, rd, bank); + } +#endif /* IPECAMERA_MULTIREAD */ + + if ((val & READ_READY_BIT) == 0) { + if (--retries > 0) { + pcilib_warning("Timeout reading register value (CMOSIS %lu, status: %lx), retrying (try %i of %i)...", addr, val, RETRIES - retries, RETRIES); + goto retry; + } + pcilib_error("Timeout reading register value (CMOSIS %lu, status: %lx)", addr, val); + return PCILIB_ERROR_TIMEOUT; + } + + if (val & READ_ERROR_BIT) { +/* if (--retries > 0) { + pcilib_warning("Error reading register (CMOSIS %lu, status: %lx), retrying (try %i of %i)...", addr, val, RETRIES - retries, RETRIES); + goto retry; + }*/ + pcilib_error("Error reading register value (CMOSIS %lu, status: %lx)", addr, val); + return PCILIB_ERROR_FAILED; + } + + if (((val&ADDR_MASK) >> 8) != addr) { + if (--retries > 0) { + pcilib_warning("Address verification failed during register read (CMOSIS %lu, status: %lx), retrying (try %i of %i)...", addr, val, RETRIES - retries, RETRIES); + goto retry; + } + pcilib_error("Address verification failed during register read (CMOSIS %lu, status: %lx)", addr, val); + return PCILIB_ERROR_VERIFY; + } + +// *value = val&ipecamera_bit_mask[bits]; + *value = val&0xFF; + + return 0; +} + +int ipecamera_cmosis_write(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t value) { + uint32_t val, tmp[4]; + char *wr, *rd; + struct timeval start;//, cur; + int retries = RETRIES; + const pcilib_register_bank_description_t *bank = bank_ctx->bank; + + assert(addr < 128); + assert(value < 256); + + wr = pcilib_resolve_register_address(ctx, bank->bar, bank->write_addr); + rd = pcilib_resolve_register_address(ctx, bank->bar, bank->read_addr); + if ((!rd)||(!wr)) { + pcilib_error("Error resolving addresses of read & write registers"); + return PCILIB_ERROR_INVALID_ADDRESS; + } + + //printf("%i %x %p %p\n", addr, val, wr, rd); + +/* +#ifdef IPECAMERA_SIMPLIFIED_READOUT + ipecamera_datacpy(tmp, rd, bank); +#endif +*/ + +retry: + val = WRITE_BIT|(addr << 8)|(value&0xFF); + ipecamera_datacpy(wr, &val, bank); + +#ifdef IPECAMERA_SIMPLIFIED_READOUT + usleep(IPECAMERA_REGISTER_TIMEOUT); +// ipecamera_datacpy(tmp, rd, bank); +// usleep(IPECAMERA_REGISTER_TIMEOUT); + ipecamera_datacpy(wr, &val, bank); + usleep(IPECAMERA_REGISTER_TIMEOUT); +// ipecamera_datacpy(tmp, rd, bank); +// usleep(IPECAMERA_REGISTER_TIMEOUT); + ipecamera_datacpy(wr, &val, bank); + usleep(IPECAMERA_REGISTER_TIMEOUT); +#endif /* IPECAMERA_SIMPLIFIED_READOUT */ + + gettimeofday(&start, NULL); + +#ifdef IPECAMERA_MULTIREAD + usleep(IPECAMERA_REGISTER_TIMEOUT); + pcilib_datacpy(tmp, rd, 4, 4, bank->raw_endianess); + val = tmp[0]; +#else /* IPECAMERA_MULTIREAD */ + ipecamera_datacpy(&val, rd, bank); + while ((val & READ_READY_BIT) == 0) { + gettimeofday(&cur, NULL); + if (((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) > IPECAMERA_REGISTER_TIMEOUT) break; + + ipecamera_datacpy(&val, rd, bank); + } +#endif /* IPECAMERA_MULTIREAD */ + + if ((val & READ_READY_BIT) == 0) { + if (--retries > 0) { + pcilib_warning("Timeout occured during register write (CMOSIS %lu, value: %lu, status: %lx), retrying (try %i of %i)...", addr, value, val, RETRIES - retries, RETRIES); + goto retry; + } + + pcilib_error("Timeout writting register value (CMOSIS %lu, value: %lu, status: %lx)", addr, value, val); + return PCILIB_ERROR_TIMEOUT; + } + + if (val & READ_ERROR_BIT) { +/* if (--retries > 0) { + pcilib_warning("Register write has failed (CMOSIS %lu, value: %lu, status: %lx), retrying (try %i of %i)...", addr, value, val, RETRIES - retries, RETRIES); + goto retry; + }*/ + pcilib_error("Error writting register value (CMOSIS %lu, value: %lu, status: %lx)", addr, value, val); + return PCILIB_ERROR_FAILED; + } + + if (((val&ADDR_MASK) >> 8) != addr) { + if (--retries > 0) { + pcilib_warning("Address verification failed during register write (CMOSIS %lu, value: %lu, status: %lx), retrying (try %i of %i)...", addr, value, val, RETRIES - retries, RETRIES); + goto retry; + } + pcilib_error("Address verification failed during register write (CMOSIS %lu, value: %lu, status: %lx)", addr, value, val); + return PCILIB_ERROR_VERIFY; + } + + if ((val&0xFF/*&ipecamera_bit_mask[bits]*/) != value) { + pcilib_error("Value verification failed during register read (CMOSIS %lu, value: %lu != %lu)", addr, val/*&ipecamera_bit_mask[bits]*/, value); + return PCILIB_ERROR_VERIFY; + } + + //printf("%i\n", val&ipecamera_bit_mask[bits]); + + return 0; +} + + + diff --git a/cmosis.h b/cmosis.h new file mode 100644 index 0000000..0d9c7a1 --- /dev/null +++ b/cmosis.h @@ -0,0 +1,9 @@ +#ifndef _IPECAMERA_CMOSIS_H +#define _IPECAMERA_CMOSIS_H + +#include + +int ipecamera_cmosis_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *value); +int ipecamera_cmosis_write(pcilib_t *ctx, pcilib_register_bank_context_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t value); + +#endif /* _IPECAMERA_CMOSIS_H */ diff --git a/common.mk b/common.mk deleted file mode 100644 index c8d7387..0000000 --- a/common.mk +++ /dev/null @@ -1,61 +0,0 @@ -# Compiler and default flags -CC ?= gcc -CFLAGS ?= -O0 - - -# Defaults for directories -ROOTDIR ?= $(shell pwd) - -INCDIR ?= $(ROOTDIR) -BINDIR ?= $(ROOTDIR) -LIBDIR ?= $(ROOTDIR) -OBJDIR ?= $(ROOTDIR) -DEPENDDIR ?= $(ROOTDIR) - -CXXFLAGS += $(addprefix -I ,$(INCDIR)) -fPIC -CFLAGS += $(addprefix -I ,$(INCDIR)) -fPIC -std=c99 - -# Source files in this directory -SRC = $(wildcard *.cpp) -SRCC = $(wildcard *.c) - -SRC += $(wildcard ipecamera/*.cpp) -SRCC += $(wildcard ipecamera/*.c) - -SRC += $(wildcard dma/*.cpp) -SRCC += $(wildcard dma/*.c) - -# Corresponding object files -OBJ = $(addprefix $(OBJDIR)/,$(SRC:.cpp=.o)) -OBJ += $(addprefix $(OBJDIR)/,$(SRCC:.c=.o)) - -# Corresponding dependency files -DEPEND = $(addprefix $(DEPENDDIR)/,$(SRC:.cpp=.d)) -DEPEND += $(addprefix $(DEPENDDIR)/,$(SRCC:.c=.d)) - -# This makes Verbose easier. Just prefix $(Q) to any command -ifdef VERBOSE - Q ?= -else - Q ?= @ -endif - -############################################################### -# Target definitions - -# Target for automatic dependency generation -depend: $(DEPEND) $(DEPENDC); - -# This rule generates a dependency makefile for each source -$(DEPENDDIR)/%.d: %.c - @echo -e "DEPEND \t$<" - $(Q)$(CC) $(addprefix -I ,$(INCDIR)) -MM -MF $@ \ - -MT $(OBJDIR)/$(<:.c=.o) -MT $@ $< - -# This includes the automatically -# generated dependency files --include $(DEPEND) - -$(OBJDIR)/%.o: %.c - @echo -e "CC \t$<" - $(Q)@$(CC) $(CFLAGS) -c -o $@ $< diff --git a/data.c b/data.c new file mode 100644 index 0000000..adb9c82 --- /dev/null +++ b/data.c @@ -0,0 +1,287 @@ +#define _BSD_SOURCE +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "private.h" +#include "data.h" + +// DS: Currently, on event_id overflow we are assuming the buffer is lost +static int ipecamera_resolve_event_id(ipecamera_t *ctx, pcilib_event_id_t evid) { + pcilib_event_id_t diff; + + if (evid > ctx->event_id) { + diff = (((pcilib_event_id_t)-1) - ctx->event_id) + evid; + if (diff >= ctx->buffer_size) return -1; + } else { + diff = ctx->event_id - evid; + if (diff >= ctx->buffer_size) return -1; + } + + // DS: Request buffer_size to be power of 2 and replace to shifts (just recompute in set_buffer_size) + return (evid - 1) % ctx->buffer_size; +} + +inline static int ipecamera_decode_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) { + int err = 0; + size_t res; + uint16_t *pixels; + + int buf_ptr = ipecamera_resolve_event_id(ctx, event_id); + if (buf_ptr < 0) return PCILIB_ERROR_TIMEOUT; + + if (ctx->frame[buf_ptr].event.image_ready) return 0; + + if (ctx->frame[buf_ptr].event.info.flags&PCILIB_EVENT_INFO_FLAG_BROKEN) { + err = PCILIB_ERROR_INVALID_DATA; + ctx->frame[buf_ptr].event.image_broken = err; + goto ready; + } + + + pixels = ctx->image + buf_ptr * ctx->image_size; + memset(ctx->cmask + ctx->buffer_pos * ctx->dim.height, 0, ctx->dim.height * sizeof(ipecamera_change_mask_t)); +/* + printf("decoding %lx...\n", ctx->raw_size); + FILE *f = fopen("/mnt/frame.xxx", "w"); + fwrite(ctx->buffer + buf_ptr * ctx->padded_size, 1, ctx->raw_size, f); + fclose(f);*/ + res = ufo_decoder_decode_frame(ctx->ipedec, ctx->buffer + buf_ptr * ctx->padded_size, ctx->raw_size, pixels, &ctx->frame[buf_ptr].event.meta); +// puts("done\n"); + if (!res) { +#ifdef IPECAMERA_DEBUG_BROKEN_FRAMES + char name[128]; + sprintf(name, "%s/broken.%4lu", IPECAMERA_DEBUG_BROKEN_FRAMES, ctx->event_id); + FILE *f = fopen(name, "w"); + if (f) { + fwrite(ctx->buffer + buf_ptr * ctx->padded_size, ctx->raw_size, 1, f); + fclose(f); + } +#endif /* IPECAMERA_DEBUG_BROKEN_FRAMES */ + err = PCILIB_ERROR_FAILED; + ctx->frame[buf_ptr].event.image_broken = err; + goto ready; + } + + ctx->frame[buf_ptr].event.image_broken = 0; + +ready: + ctx->frame[buf_ptr].event.image_ready = 1; + + if (ipecamera_resolve_event_id(ctx, event_id) < 0) { + ctx->frame[buf_ptr].event.image_ready = 0; + return PCILIB_ERROR_TIMEOUT; + } + + return err; +} + +static int ipecamera_get_next_buffer_to_process(ipecamera_t *ctx, pcilib_event_id_t *evid) { + int res; + + if (ctx->preproc_id == ctx->event_id) return -1; + + if (ctx->preproc) + pthread_mutex_lock(&ctx->preproc_mutex); + + if (ctx->preproc_id == ctx->event_id) { + if (ctx->preproc) + pthread_mutex_unlock(&ctx->preproc_mutex); + return -1; + } + + if ((ctx->event_id - ctx->preproc_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) ctx->preproc_id = ctx->event_id - (ctx->buffer_size - 1 - IPECAMERA_RESERVE_BUFFERS - 1); + + res = ctx->preproc_id%ctx->buffer_size; + + if (pthread_rwlock_trywrlock(&ctx->frame[res].mutex)) { + pthread_mutex_unlock(&ctx->preproc_mutex); + return -1; + } + + *evid = ++ctx->preproc_id; + + if (ctx->preproc) + pthread_mutex_unlock(&ctx->preproc_mutex); + + return res; +} + + +void *ipecamera_preproc_thread(void *user) { + int buf_ptr; + pcilib_event_id_t evid; + + ipecamera_preprocessor_t *preproc = (ipecamera_preprocessor_t*)user; + ipecamera_t *ctx = preproc->ipecamera; + + while (ctx->run_preprocessors) { + buf_ptr = ipecamera_get_next_buffer_to_process(ctx, &evid); + if (buf_ptr < 0) { + usleep(IPECAMERA_NOFRAME_PREPROC_SLEEP); + continue; + } + + ipecamera_decode_frame(ctx, evid); + + pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex); + } + + return NULL; +} + +static int ipecamera_get_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) { + int err; + int buf_ptr = (event_id - 1) % ctx->buffer_size; + + if (ctx->preproc) { + if (ctx->frame[buf_ptr].event.image_broken) + return ctx->frame[buf_ptr].event.image_broken; + } else { + pthread_rwlock_rdlock(&ctx->frame[buf_ptr].mutex); + + err = ipecamera_decode_frame(ctx, event_id); + + if (err) { + pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex); + return err; + } + + return 0; + } + + + while (!ctx->frame[buf_ptr].event.image_ready) { + usleep(IPECAMERA_NOFRAME_PREPROC_SLEEP); + + buf_ptr = ipecamera_resolve_event_id(ctx, event_id); + if (buf_ptr < 0) return PCILIB_ERROR_OVERWRITTEN; + } + + pthread_rwlock_rdlock(&ctx->frame[buf_ptr].mutex); + + buf_ptr = ipecamera_resolve_event_id(ctx, event_id); + if ((buf_ptr < 0)||(!ctx->frame[buf_ptr].event.image_ready)) { + pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex); + return PCILIB_ERROR_OVERWRITTEN; + } + + return 0; +} + + +/* + We will lock the data for non-raw data to prevent ocasional overwritting. The + raw data will be overwritten by the reader thread anyway and we can't do + anything to prevent it for performance reasons. +*/ +int ipecamera_get(pcilib_context_t *vctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size, void **ret) { + int err; + int buf_ptr; + size_t raw_size; + ipecamera_t *ctx = (ipecamera_t*)vctx; + + void *data = *ret; + + if (!ctx) { + pcilib_error("IPECamera imaging is not initialized"); + return PCILIB_ERROR_NOTINITIALIZED; + } + + buf_ptr = ipecamera_resolve_event_id(ctx, event_id); + if (buf_ptr < 0) return PCILIB_ERROR_OVERWRITTEN; + + switch ((ipecamera_data_type_t)data_type) { + case IPECAMERA_RAW_DATA: + raw_size = ctx->frame[buf_ptr].event.raw_size; + if (data) { + if ((!size)||(*size < raw_size)) return PCILIB_ERROR_TOOBIG; + memcpy(data, ctx->buffer + buf_ptr * ctx->padded_size, raw_size); + if (ipecamera_resolve_event_id(ctx, event_id) < 0) return PCILIB_ERROR_OVERWRITTEN; + *size = raw_size; + return 0; + } + if (size) *size = raw_size; + *ret = ctx->buffer + buf_ptr * ctx->padded_size; + return 0; + case IPECAMERA_IMAGE_DATA: + err = ipecamera_get_frame(ctx, event_id); + if (err) return err; + + if (data) { + if ((!size)||(*size < ctx->image_size * sizeof(ipecamera_pixel_t))) return PCILIB_ERROR_TOOBIG; + memcpy(data, ctx->image + buf_ptr * ctx->image_size, ctx->image_size * sizeof(ipecamera_pixel_t)); + pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex); + *size = ctx->image_size * sizeof(ipecamera_pixel_t); + return 0; + } + + if (size) *size = ctx->image_size * sizeof(ipecamera_pixel_t); + *ret = ctx->image + buf_ptr * ctx->image_size; + return 0; + case IPECAMERA_CHANGE_MASK: + err = ipecamera_get_frame(ctx, event_id); + if (err) return err; + + if (data) { + if ((!size)||(*size < ctx->dim.height * sizeof(ipecamera_change_mask_t))) return PCILIB_ERROR_TOOBIG; + memcpy(data, ctx->image + buf_ptr * ctx->dim.height, ctx->dim.height * sizeof(ipecamera_change_mask_t)); + pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex); + *size = ctx->dim.height * sizeof(ipecamera_change_mask_t); + return 0; + } + + if (size) *size = ctx->dim.height * sizeof(ipecamera_change_mask_t); + *ret = ctx->cmask + buf_ptr * ctx->dim.height; + return 0; + case IPECAMERA_DIMENSIONS: + if (size) *size = sizeof(ipecamera_image_dimensions_t); + ret = (void*)&ctx->dim; + return 0; + case IPECAMERA_IMAGE_REGION: + case IPECAMERA_PACKED_IMAGE: + // Shall we return complete image or only changed parts? + case IPECAMERA_PACKED_LINE: + case IPECAMERA_PACKED_PAYLOAD: + pcilib_error("Support for data type (%li) is not implemented yet", data_type); + return PCILIB_ERROR_NOTSUPPORTED; + default: + pcilib_error("Unknown data type (%li) is requested", data_type); + return PCILIB_ERROR_INVALID_REQUEST; + } +} + + +/* + We will unlock non-raw data and check if the raw data is not overwritten yet +*/ +int ipecamera_return(pcilib_context_t *vctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, void *data) { + ipecamera_t *ctx = (ipecamera_t*)vctx; + + if (!ctx) { + pcilib_error("IPECamera imaging is not initialized"); + return PCILIB_ERROR_NOTINITIALIZED; + + } + + if ((ipecamera_data_type_t)data_type == IPECAMERA_RAW_DATA) { + if (ipecamera_resolve_event_id(ctx, event_id) < 0) return PCILIB_ERROR_OVERWRITTEN; + } else { + int buf_ptr = (event_id - 1) % ctx->buffer_size; + pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex); + } + + return 0; +} diff --git a/data.h b/data.h new file mode 100644 index 0000000..846cb78 --- /dev/null +++ b/data.h @@ -0,0 +1,6 @@ +#ifndef _IPECAMERA_DATA_H +#define _IPECAMERA_DATA_H + +void *ipecamera_preproc_thread(void *user); + +#endif /* _IPECAMERA_DATA_H */ diff --git a/default.c b/default.c deleted file mode 100644 index 0ea4d61..0000000 --- a/default.c +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include -#include - -#include "tools.h" -#include "default.h" -#include "error.h" - -#define default_datacpy(dst, src, access, bank) pcilib_datacpy(dst, src, access, 1, bank->raw_endianess) - -int pcilib_default_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *value) { - char *ptr; - pcilib_register_value_t val = 0; - int access = bank->access / 8; - - ptr = pcilib_resolve_register_address(ctx, bank->bar, bank->read_addr + addr); - default_datacpy(&val, ptr, access, bank); - -// *value = val&BIT_MASK(bits); - *value = val; - - return 0; -} - - -int pcilib_default_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t value) { - char *ptr; - int access = bank->access / 8; - - ptr = pcilib_resolve_register_address(ctx, bank->bar, bank->write_addr + addr); - default_datacpy(ptr, &value, access, bank); - - return 0; -} diff --git a/default.h b/default.h deleted file mode 100644 index 6b2cf93..0000000 --- a/default.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _PCILIB_DEFAULT_H -#define _PCILIB_DEFAULT_H - -#include "pcilib.h" - -int pcilib_default_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *value); -int pcilib_default_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t value); - -#endif /* _PCILIB_DEFAULT_H */ diff --git a/dma.c b/dma.c deleted file mode 100644 index e3bc77c..0000000 --- a/dma.c +++ /dev/null @@ -1,327 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "error.h" -#include "pcilib.h" -#include "pci.h" -#include "dma.h" - -const pcilib_dma_info_t *pcilib_get_dma_info(pcilib_t *ctx) { - if (!ctx->dma_ctx) { - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - if ((ctx->event_ctx)&&(model_info->event_api->init_dma)) { - pcilib_map_register_space(ctx); - ctx->dma_ctx = model_info->event_api->init_dma(ctx->event_ctx); - } else if ((model_info->dma_api)&&(model_info->dma_api->init)) { - pcilib_map_register_space(ctx); - ctx->dma_ctx = model_info->dma_api->init(ctx, PCILIB_DMA_MODIFICATION_DEFAULT, NULL); - } - - if (!ctx->dma_ctx) return NULL; - } - - return &ctx->dma_info; -} - -pcilib_dma_engine_t pcilib_find_dma_by_addr(pcilib_t *ctx, pcilib_dma_direction_t direction, pcilib_dma_engine_addr_t dma) { - pcilib_dma_engine_t i; - - const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx); - if (!info) { - pcilib_error("DMA Engine is not configured in the current model"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - for (i = 0; info->engines[i]; i++) { - if ((info->engines[i]->addr == dma)&&((info->engines[i]->direction&direction)==direction)) break; - } - - if (info->engines[i]) return i; - return PCILIB_DMA_ENGINE_INVALID; -} - -int pcilib_set_dma_engine_description(pcilib_t *ctx, pcilib_dma_engine_t engine, pcilib_dma_engine_description_t *desc) { - ctx->dma_info.engines[engine] = desc; - - return 0; -} - -int pcilib_start_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) { - const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx); - if (!info) { - pcilib_error("DMA is not supported by the device"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (!ctx->model_info.dma_api) { - pcilib_error("DMA Engine is not configured in the current model"); - return PCILIB_ERROR_NOTAVAILABLE; - } - - if (!ctx->model_info.dma_api->start_dma) { - return 0; - } - - return ctx->model_info.dma_api->start_dma(ctx->dma_ctx, dma, flags); -} - -int pcilib_stop_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) { - const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx); - - if (!info) { - pcilib_error("DMA is not supported by the device"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (!ctx->model_info.dma_api) { - pcilib_error("DMA Engine is not configured in the current model"); - return PCILIB_ERROR_NOTAVAILABLE; - } - - if (!ctx->model_info.dma_api->stop_dma) { - return 0; - } - - return ctx->model_info.dma_api->stop_dma(ctx->dma_ctx, dma, flags); -} - -int pcilib_enable_irq(pcilib_t *ctx, pcilib_irq_type_t irq_type, pcilib_dma_flags_t flags) { - const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx); - - if ((!info)||(!ctx->model_info.dma_api)||(!ctx->model_info.dma_api->enable_irq)) return 0; - - return ctx->model_info.dma_api->enable_irq(ctx->dma_ctx, irq_type, flags); -} - -int pcilib_disable_irq(pcilib_t *ctx, pcilib_dma_flags_t flags) { - const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx); - - if ((!info)||(!ctx->model_info.dma_api)||(!ctx->model_info.dma_api->disable_irq)) return 0; - - return ctx->model_info.dma_api->disable_irq(ctx->dma_ctx, flags); -} - -int pcilib_acknowledge_irq(pcilib_t *ctx, pcilib_irq_type_t irq_type, pcilib_irq_source_t irq_source) { - const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx); - - if ((!info)||(!ctx->model_info.dma_api)||(!ctx->model_info.dma_api->acknowledge_irq)) return 0; - - return ctx->model_info.dma_api->acknowledge_irq(ctx->dma_ctx, irq_type, irq_source); -} - -typedef struct { - size_t size; - void *data; - size_t pos; - - pcilib_dma_flags_t flags; -} pcilib_dma_read_callback_context_t; - -static int pcilib_dma_read_callback(void *arg, pcilib_dma_flags_t flags, size_t bufsize, void *buf) { - pcilib_dma_read_callback_context_t *ctx = (pcilib_dma_read_callback_context_t*)arg; - - if (ctx->pos + bufsize > ctx->size) { - if ((ctx->flags&PCILIB_DMA_FLAG_IGNORE_ERRORS) == 0) - pcilib_error("Buffer size (%li) is not large enough for DMA packet, at least %li bytes is required", ctx->size, ctx->pos + bufsize); - return -PCILIB_ERROR_TOOBIG; - } - - memcpy(ctx->data + ctx->pos, buf, bufsize); - ctx->pos += bufsize; - - if (flags & PCILIB_DMA_FLAG_EOP) { - if ((ctx->pos < ctx->size)&&(ctx->flags&PCILIB_DMA_FLAG_MULTIPACKET)) { - if (ctx->flags&PCILIB_DMA_FLAG_WAIT) return PCILIB_STREAMING_WAIT; - else return PCILIB_STREAMING_CONTINUE; - } - return PCILIB_STREAMING_STOP; - } - - return PCILIB_STREAMING_REQ_FRAGMENT; -} - -static int pcilib_dma_skip_callback(void *arg, pcilib_dma_flags_t flags, size_t bufsize, void *buf) { - struct timeval *tv = (struct timeval*)arg; - struct timeval cur; - - if (tv) { - gettimeofday(&cur, NULL); - if ((cur.tv_sec > tv->tv_sec)||((cur.tv_sec == tv->tv_sec)&&(cur.tv_usec > tv->tv_usec))) return PCILIB_STREAMING_STOP; - } - - return PCILIB_STREAMING_REQ_PACKET; -} - -int pcilib_stream_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr) { - const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx); - if (!info) { - pcilib_error("DMA is not supported by the device"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (!ctx->model_info.dma_api) { - pcilib_error("DMA Engine is not configured in the current model"); - return PCILIB_ERROR_NOTAVAILABLE; - } - - if (!ctx->model_info.dma_api->stream) { - pcilib_error("The DMA read is not supported by configured DMA engine"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (!info->engines[dma]) { - pcilib_error("The DMA engine (%i) is not supported by device", dma); - return PCILIB_ERROR_NOTAVAILABLE; - } - - if ((info->engines[dma]->direction&PCILIB_DMA_FROM_DEVICE) == 0) { - pcilib_error("The selected engine (%i) is S2C-only and does not support reading", dma); - return PCILIB_ERROR_NOTSUPPORTED; - } - - return ctx->model_info.dma_api->stream(ctx->dma_ctx, dma, addr, size, flags, timeout, cb, cbattr); -} - -int pcilib_read_dma_custom(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *buf, size_t *read_bytes) { - int err; - - pcilib_dma_read_callback_context_t opts = { - size, buf, 0, flags - }; - - err = pcilib_stream_dma(ctx, dma, addr, size, flags, timeout, pcilib_dma_read_callback, &opts); - if (read_bytes) *read_bytes = opts.pos; - return err; -} - -int pcilib_read_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, void *buf, size_t *read_bytes) { - int err; - - pcilib_dma_read_callback_context_t opts = { - size, buf, 0, 0 - }; - - err = pcilib_stream_dma(ctx, dma, addr, size, PCILIB_DMA_FLAGS_DEFAULT, PCILIB_DMA_TIMEOUT, pcilib_dma_read_callback, &opts); - if (read_bytes) *read_bytes = opts.pos; - return err; -} - - -int pcilib_skip_dma(pcilib_t *ctx, pcilib_dma_engine_t dma) { - int err; - struct timeval tv, cur; - - gettimeofday(&tv, NULL); - tv.tv_usec += PCILIB_DMA_SKIP_TIMEOUT; - tv.tv_sec += tv.tv_usec / 1000000; - tv.tv_usec += tv.tv_usec % 1000000; - - do { - // IMMEDIATE timeout is not working properly, so default is set - err = pcilib_stream_dma(ctx, dma, 0, 0, PCILIB_DMA_FLAGS_DEFAULT, PCILIB_DMA_TIMEOUT, pcilib_dma_skip_callback, &tv); - gettimeofday(&cur, NULL); - } while ((!err)&&((cur.tv_sec < tv.tv_sec)||((cur.tv_sec == tv.tv_sec)&&(cur.tv_usec < tv.tv_usec)))); - - if ((cur.tv_sec > tv.tv_sec)||((cur.tv_sec == tv.tv_sec)&&(cur.tv_usec > tv.tv_usec))) return PCILIB_ERROR_TIMEOUT; - - return 0; -} - - -int pcilib_push_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *buf, size_t *written) { - const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx); - if (!info) { - pcilib_error("DMA is not supported by the device"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (!ctx->model_info.dma_api) { - pcilib_error("DMA Engine is not configured in the current model"); - return PCILIB_ERROR_NOTAVAILABLE; - } - - if (!ctx->model_info.dma_api->push) { - pcilib_error("The DMA write is not supported by configured DMA engine"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (!info->engines[dma]) { - pcilib_error("The DMA engine (%i) is not supported by device", dma); - return PCILIB_ERROR_NOTAVAILABLE; - } - - if ((info->engines[dma]->direction&PCILIB_DMA_TO_DEVICE) == 0) { - pcilib_error("The selected engine (%i) is C2S-only and does not support writes", dma); - return PCILIB_ERROR_NOTSUPPORTED; - } - - return ctx->model_info.dma_api->push(ctx->dma_ctx, dma, addr, size, flags, timeout, buf, written); -} - - -int pcilib_write_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, void *buf, size_t *written_bytes) { - return pcilib_push_dma(ctx, dma, addr, size, PCILIB_DMA_FLAG_EOP|PCILIB_DMA_FLAG_WAIT, PCILIB_DMA_TIMEOUT, buf, written_bytes); -} - -double pcilib_benchmark_dma(pcilib_t *ctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction) { - const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx); - if (!info) { - pcilib_error("DMA is not supported by the device"); - return 0; - } - - if (!ctx->model_info.dma_api) { - pcilib_error("DMA Engine is not configured in the current model"); - return -1; - } - - if (!ctx->model_info.dma_api->benchmark) { - pcilib_error("The DMA benchmark is not supported by configured DMA engine"); - return -1; - } - - if (!info->engines[dma]) { - pcilib_error("The DMA engine (%i) is not supported by device", dma); - return -1; - } - - return ctx->model_info.dma_api->benchmark(ctx->dma_ctx, dma, addr, size, iterations, direction); -} - -int pcilib_get_dma_status(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers) { - const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx); - if (!info) { - pcilib_error("DMA is not supported by the device"); - return 0; - } - - if (!ctx->model_info.dma_api) { - pcilib_error("DMA Engine is not configured in the current model"); - return -1; - } - - if (!ctx->model_info.dma_api->status) { - memset(status, 0, sizeof(pcilib_dma_engine_status_t)); - return -1; - } - - if (!info->engines[dma]) { - pcilib_error("The DMA engine (%i) is not supported by device", dma); - return -1; - } - - return ctx->model_info.dma_api->status(ctx->dma_ctx, dma, status, n_buffers, buffers); -} diff --git a/dma.h b/dma.h deleted file mode 100644 index 30b9a18..0000000 --- a/dma.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _PCILIB_DMA_H -#define _PCILIB_DMA_H - -#define PCILIB_DMA_BUFFER_INVALID ((size_t)-1) -#define PCILIB_DMA_MODIFICATION_DEFAULT 0 /**< first 0x100 are reserved */ - -typedef uint32_t pcilib_dma_modification_t; - -typedef struct { - int started; - size_t ring_size, buffer_size; - size_t ring_head, ring_tail; -} pcilib_dma_engine_status_t; - -typedef struct { - int used; - int error; - int first; - int last; - size_t size; -} pcilib_dma_buffer_status_t; - -struct pcilib_dma_api_description_s { - const char *title; - - pcilib_dma_context_t *(*init)(pcilib_t *ctx, pcilib_dma_modification_t type, void *arg); - void (*free)(pcilib_dma_context_t *ctx); - - int (*status)(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers); - - int (*enable_irq)(pcilib_dma_context_t *ctx, pcilib_irq_type_t irq_type, pcilib_dma_flags_t flags); - int (*disable_irq)(pcilib_dma_context_t *ctx, pcilib_dma_flags_t flags); - int (*acknowledge_irq)(pcilib_dma_context_t *ctx, pcilib_irq_type_t irq_type, pcilib_irq_source_t irq_source); - - int (*start_dma)(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags); - int (*stop_dma)(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags); - - int (*push)(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *buf, size_t *written); - int (*stream)(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr); - - double (*benchmark)(pcilib_dma_context_t *ctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction); -}; - -struct pcilib_dma_context_s { - int ignore_eop; -}; - - -int pcilib_set_dma_engine_description(pcilib_t *ctx, pcilib_dma_engine_t engine, pcilib_dma_engine_description_t *desc); -int pcilib_get_dma_status(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers); - -#endif /* _PCILIB_DMA_H */ diff --git a/dma/CMakeLists.txt b/dma/CMakeLists.txt deleted file mode 100644 index 44bf18c..0000000 --- a/dma/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -include_directories( - ${CMAKE_SOURCE_DIR} -) - - -set(HEADERS ${HEADERS} nwl.h nwl_private.h nwl_engine.h nwl_irq.h nwl_loopback.h nwl_register.h ipe.h ipe_private.h ipe_registers.h) - -add_library(dma STATIC nwl.c nwl_engine.c nwl_irq.c nwl_loopback.c nwl_register.c ipe.c) - diff --git a/dma/ipe.c b/dma/ipe.c deleted file mode 100644 index 61480d4..0000000 --- a/dma/ipe.c +++ /dev/null @@ -1,541 +0,0 @@ -#define _PCILIB_DMA_IPE_C -#define _BSD_SOURCE - -#include -#include -#include -#include -#include -#include - -#include "pci.h" -#include "pcilib.h" -#include "error.h" -#include "tools.h" - -#include "ipe.h" -#include "ipe_private.h" -#include "ipe_registers.h" - - -#define WR(addr, value) { *(uint32_t*)(ctx->base_addr + addr) = value; } -#define RD(addr, value) { value = *(uint32_t*)(ctx->base_addr + addr); } - - -pcilib_dma_context_t *dma_ipe_init(pcilib_t *pcilib, pcilib_dma_modification_t type, void *arg) { - int err = 0; - - pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib); - - ipe_dma_t *ctx = malloc(sizeof(ipe_dma_t)); - - if (ctx) { - memset(ctx, 0, sizeof(ipe_dma_t)); - ctx->pcilib = pcilib; -// ctx->mode64 = 1; - - memset(ctx->engine, 0, 2 * sizeof(pcilib_dma_engine_description_t)); - ctx->engine[0].addr = 0; - ctx->engine[0].type = PCILIB_DMA_TYPE_PACKET; - ctx->engine[0].direction = PCILIB_DMA_FROM_DEVICE; - ctx->engine[0].addr_bits = 32; - pcilib_set_dma_engine_description(pcilib, 0, &ctx->engine[0]); - pcilib_set_dma_engine_description(pcilib, 1, NULL); - - pcilib_register_bank_t dma_bank = pcilib_find_bank_by_addr(pcilib, PCILIB_REGISTER_BANK_DMA); - if (dma_bank == PCILIB_REGISTER_BANK_INVALID) { - free(ctx); - pcilib_error("DMA Register Bank could not be found"); - return NULL; - } - - ctx->dma_bank = model_info->banks + dma_bank; - ctx->base_addr = pcilib_resolve_register_address(pcilib, ctx->dma_bank->bar, ctx->dma_bank->read_addr); - - err = pcilib_add_registers(ctx->pcilib, 0, ipe_dma_registers); - if (err) { - free(ctx); - pcilib_error("Error adding DMA registers"); - return NULL; - } - } - - return (pcilib_dma_context_t*)ctx; -} - -void dma_ipe_free(pcilib_dma_context_t *vctx) { - ipe_dma_t *ctx = (ipe_dma_t*)vctx; - - if (ctx) { - dma_ipe_stop(vctx, PCILIB_DMA_ENGINE_ALL, PCILIB_DMA_FLAGS_DEFAULT); - free(ctx); - } -} - - -int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) { - size_t i; - - ipe_dma_t *ctx = (ipe_dma_t*)vctx; - - int preserve = 0; - pcilib_kmem_flags_t kflags; - pcilib_kmem_reuse_state_t reuse_desc, reuse_pages; - - volatile void *desc_va; - volatile uint32_t *last_written_addr_ptr; - - pcilib_register_value_t value; - - uint32_t address64; - - - if (dma == PCILIB_DMA_ENGINE_INVALID) return 0; - else if (dma > 1) return PCILIB_ERROR_INVALID_BANK; - - if (!ctx->started) ctx->started = 1; - - if (flags&PCILIB_DMA_FLAG_PERSISTENT) ctx->preserve = 1; - - if (ctx->pages) return 0; - - kflags = PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_EXCLUSIVE|PCILIB_KMEM_FLAG_HARDWARE|(ctx->preserve?PCILIB_KMEM_FLAG_PERSISTENT:0); - pcilib_kmem_handle_t *desc = pcilib_alloc_kernel_memory(ctx->pcilib, PCILIB_KMEM_TYPE_CONSISTENT, 1, IPEDMA_DESCRIPTOR_SIZE, IPEDMA_DESCRIPTOR_ALIGNMENT, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, 0x00), kflags); - pcilib_kmem_handle_t *pages = pcilib_alloc_kernel_memory(ctx->pcilib, PCILIB_KMEM_TYPE_DMA_C2S_PAGE, IPEDMA_DMA_PAGES, 0, 0, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, 0x00), kflags); - - if (!desc||!pages) { - if (pages) pcilib_free_kernel_memory(ctx->pcilib, pages, 0); - if (desc) pcilib_free_kernel_memory(ctx->pcilib, desc, 0); - return PCILIB_ERROR_MEMORY; - } - reuse_desc = pcilib_kmem_is_reused(ctx->pcilib, desc); - reuse_pages = pcilib_kmem_is_reused(ctx->pcilib, pages); - - if (reuse_desc == reuse_pages) { - if (reuse_desc & PCILIB_KMEM_REUSE_PARTIAL) pcilib_warning("Inconsistent DMA buffers are found (only part of required buffers is available), reinitializing..."); - else if (reuse_desc & PCILIB_KMEM_REUSE_REUSED) { - if ((reuse_desc & PCILIB_KMEM_REUSE_PERSISTENT) == 0) pcilib_warning("Lost DMA buffers are found (non-persistent mode), reinitializing..."); - else if ((reuse_desc & PCILIB_KMEM_REUSE_HARDWARE) == 0) pcilib_warning("Lost DMA buffers are found (missing HW reference), reinitializing..."); - else { -#ifndef IPEDMA_BUG_DMARD - RD(IPEDMA_REG_PAGE_COUNT, value); - - if (value != IPEDMA_DMA_PAGES) pcilib_warning("Inconsistent DMA buffers are found (Number of allocated buffers (%lu) does not match current request (%lu)), reinitializing...", value + 1, IPEDMA_DMA_PAGES); - else -#endif /* IPEDMA_BUG_DMARD */ - preserve = 1; - } - } - } else pcilib_warning("Inconsistent DMA buffers (modes of ring and page buffers does not match), reinitializing...."); - - desc_va = pcilib_kmem_get_ua(ctx->pcilib, desc); - if (ctx->mode64) last_written_addr_ptr = desc_va + 3 * sizeof(uint32_t); - else last_written_addr_ptr = desc_va + 4 * sizeof(uint32_t); - - if (preserve) { - ctx->reused = 1; - ctx->preserve = 1; - - -// usleep(100000); - - // Detect the current state of DMA engine -#ifdef IPEDMA_BUG_DMARD - FILE *f = fopen("/tmp/pcitool_lastread", "r"); - if (!f) pcilib_error("Can't read current status"); - fread(&value, 1, sizeof(pcilib_register_value_t), f); - fclose(f); -#else /* IPEDMA_BUG_DMARD */ - RD(IPEDMA_REG_LAST_READ, value); - // Numbered from 1 in FPGA - value--; -#endif /* IPEDMA_BUG_DMARD */ - - ctx->last_read = value; - } else { - ctx->reused = 0; - - // Disable DMA - WR(IPEDMA_REG_CONTROL, 0x0); - usleep(100000); - - // Reset DMA engine - WR(IPEDMA_REG_RESET, 0x1); - usleep(100000); - WR(IPEDMA_REG_RESET, 0x0); - usleep(100000); - -#ifndef IPEDMA_BUG_DMARD - // Verify PCIe link status - RD(IPEDMA_REG_RESET, value); - if (value != 0x14031700) pcilib_warning("PCIe is not ready, code is %lx", value); -#endif /* IPEDMA_BUG_DMARD */ - - // Enable 64 bit addressing and configure TLP and PACKET sizes (40 bit mode can be used with big pre-allocated buffers later) - if (ctx->mode64) address64 = 0x8000 | (0<<24); - else address64 = 0; - - WR(IPEDMA_REG_TLP_SIZE, address64 | IPEDMA_TLP_SIZE); - WR(IPEDMA_REG_TLP_COUNT, IPEDMA_PAGE_SIZE / (4 * IPEDMA_TLP_SIZE * IPEDMA_CORES)); - - // Setting progress register threshold - WR(IPEDMA_REG_UPDATE_THRESHOLD, IPEDMA_DMA_PROGRESS_THRESHOLD); - - // Reseting configured DMA pages - WR(IPEDMA_REG_PAGE_COUNT, 0); - - // Setting current read position and configuring progress register - WR(IPEDMA_REG_LAST_READ, IPEDMA_DMA_PAGES); - WR(IPEDMA_REG_UPDATE_ADDR, pcilib_kmem_get_block_ba(ctx->pcilib, desc, 0)); - - // Instructing DMA engine that writting should start from the first DMA page - *last_written_addr_ptr = 0;//htonl(pcilib_kmem_get_block_ba(ctx->pcilib, pages, IPEDMA_DMA_PAGES - 1)); - - - for (i = 0; i < IPEDMA_DMA_PAGES; i++) { - uintptr_t bus_addr_check, bus_addr = pcilib_kmem_get_block_ba(ctx->pcilib, pages, i); - WR(IPEDMA_REG_PAGE_ADDR, bus_addr); - if (bus_addr%4096) printf("Bad address %lu: %lx\n", i, bus_addr); - - RD(IPEDMA_REG_PAGE_ADDR, bus_addr_check); - if (bus_addr_check != bus_addr) { - pcilib_error("Written (%x) and read (%x) bus addresses does not match\n", bus_addr, bus_addr_check); - } - - usleep(1000); - } - - // Enable DMA - WR(IPEDMA_REG_CONTROL, 0x1); - - ctx->last_read = IPEDMA_DMA_PAGES - 1; - -#ifdef IPEDMA_BUG_DMARD - FILE *f = fopen("/tmp/pcitool_lastread", "w"); - if (!f) pcilib_error("Can't write current status"); - value = ctx->last_read; - fwrite(&value, 1, sizeof(pcilib_register_value_t), f); - fclose(f); -#endif /* IPEDMA_BUG_DMARD */ - } - -// ctx->last_read_addr = htonl(pcilib_kmem_get_block_ba(ctx->pcilib, pages, ctx->last_read)); - ctx->last_read_addr = pcilib_kmem_get_block_ba(ctx->pcilib, pages, ctx->last_read); - - - ctx->desc = desc; - ctx->pages = pages; - ctx->page_size = pcilib_kmem_get_block_size(ctx->pcilib, pages, 0);; - ctx->ring_size = IPEDMA_DMA_PAGES; - - return 0; -} - -int dma_ipe_stop(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) { - pcilib_kmem_flags_t kflags; - - ipe_dma_t *ctx = (ipe_dma_t*)vctx; - - if (!ctx->started) return 0; - - if ((dma != PCILIB_DMA_ENGINE_INVALID)&&(dma > 1)) return PCILIB_ERROR_INVALID_BANK; - - // ignoring previous setting if flag specified - if (flags&PCILIB_DMA_FLAG_PERSISTENT) { - ctx->preserve = 0; - } - - if (ctx->preserve) { - kflags = PCILIB_KMEM_FLAG_REUSE; - } else { - kflags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT; - - ctx->started = 0; - - // Disable DMA - WR(IPEDMA_REG_CONTROL, 0); - usleep(100000); - - // Reset DMA engine - WR(IPEDMA_REG_RESET, 0x1); - usleep(100000); - WR(IPEDMA_REG_RESET, 0x0); - usleep(100000); - - // Reseting configured DMA pages - WR(IPEDMA_REG_PAGE_COUNT, 0); - usleep(100000); - } - - // Clean buffers - if (ctx->desc) { - pcilib_free_kernel_memory(ctx->pcilib, ctx->desc, kflags); - ctx->desc = NULL; - } - - if (ctx->pages) { - pcilib_free_kernel_memory(ctx->pcilib, ctx->pages, kflags); - ctx->pages = NULL; - } - - return 0; -} - - -int dma_ipe_get_status(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers) { - size_t i; - ipe_dma_t *ctx = (ipe_dma_t*)vctx; - - void *desc_va = (void*)pcilib_kmem_get_ua(ctx->pcilib, ctx->desc); - uint32_t *last_written_addr_ptr; - uint32_t last_written_addr; - - if (!status) return -1; - - if (ctx->mode64) last_written_addr_ptr = desc_va + 3 * sizeof(uint32_t); - else last_written_addr_ptr = desc_va + 4 * sizeof(uint32_t); - - last_written_addr = *last_written_addr_ptr; - - status->started = ctx->started; - status->ring_size = ctx->ring_size; - status->buffer_size = ctx->page_size; - - // For simplicity, we keep last_read here, and fix in the end - status->ring_tail = ctx->last_read; - - // Find where the ring head is actually are - for (i = 0; i < ctx->ring_size; i++) { - uintptr_t bus_addr = pcilib_kmem_get_block_ba(ctx->pcilib, ctx->pages, i); - - if (bus_addr == last_written_addr) { - status->ring_head = i; - break; - } - } - - if (i == ctx->ring_size) { - if (last_written_addr) { - pcilib_warning("DMA is in unknown state, last_written_addr does not correspond any of available buffers"); - return -1; - } - status->ring_head = 0; - status->ring_tail = 0; - } - - if (n_buffers > ctx->ring_size) n_buffers = ctx->ring_size; - - if (buffers) { - memset(buffers, 0, n_buffers * sizeof(pcilib_dma_buffer_status_t)); - if (status->ring_head >= status->ring_tail) { - for (i = status->ring_tail + 1; (i <= status->ring_head)&&(i < n_buffers); i++) { - buffers[i].used = 1; - buffers[i].size = ctx->page_size; - buffers[i].first = 1; - buffers[i].last = 1; - } - } else { - for (i = 0; (i <= status->ring_head)&&(i < n_buffers); i++) { - buffers[i].used = 1; - buffers[i].size = ctx->page_size; - buffers[i].first = 1; - buffers[i].last = 1; - } - - for (i = status->ring_tail + 1; (i < status->ring_size)&&(i < n_buffers); i++) { - buffers[i].used = 1; - buffers[i].size = ctx->page_size; - buffers[i].first = 1; - buffers[i].last = 1; - } - } - } - - // We actually keep last_read in the ring_tail, so need to increase - if (status->ring_tail != status->ring_head) { - status->ring_tail++; - if (status->ring_tail == status->ring_size) status->ring_tail = 0; - } - - return 0; -} - -int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr) { - int err, ret = PCILIB_STREAMING_REQ_PACKET; - - - pcilib_timeout_t wait = 0; - struct timeval start, cur; - - volatile void *desc_va; - volatile uint32_t *last_written_addr_ptr; - volatile uint32_t *empty_detected_ptr; - - pcilib_dma_flags_t packet_flags = PCILIB_DMA_FLAG_EOP; - -#ifdef IPEDMA_BUG_DMARD - pcilib_register_value_t value; -#endif /* IPEDMA_BUG_DMARD */ - - size_t cur_read; - - ipe_dma_t *ctx = (ipe_dma_t*)vctx; - - err = dma_ipe_start(vctx, dma, PCILIB_DMA_FLAGS_DEFAULT); - if (err) return err; - - desc_va = (void*)pcilib_kmem_get_ua(ctx->pcilib, ctx->desc); - - if (ctx->mode64) last_written_addr_ptr = desc_va + 3 * sizeof(uint32_t); - else last_written_addr_ptr = desc_va + 4 * sizeof(uint32_t); - - empty_detected_ptr = last_written_addr_ptr - 2; - - do { - switch (ret&PCILIB_STREAMING_TIMEOUT_MASK) { - case PCILIB_STREAMING_CONTINUE: - // Hardware indicates that there is no more data pending and we can safely stop if there is no data in the kernel buffers already -#ifdef IPEDMA_SUPPORT_EMPTY_DETECTED - if (*empty_detected_ptr) - wait = 0; - else -#endif /* IPEDMA_SUPPORT_EMPTY_DETECTED */ - wait = IPEDMA_DMA_TIMEOUT; - break; - case PCILIB_STREAMING_WAIT: - wait = (timeout > IPEDMA_DMA_TIMEOUT)?timeout:IPEDMA_DMA_TIMEOUT; - break; -// case PCILIB_STREAMING_CHECK: wait = 0; break; - } - -#ifdef IPEDMA_DEBUG - printf("Waiting for data: %u (last read) 0x%x (last read addr) 0x%x (last_written)\n", ctx->last_read, ctx->last_read_addr, *last_written_addr_ptr); -#endif /* IPEDMA_DEBUG */ - - gettimeofday(&start, NULL); - memcpy(&cur, &start, sizeof(struct timeval)); - while (((*last_written_addr_ptr == 0)||(ctx->last_read_addr == (*last_written_addr_ptr)))&&((wait == PCILIB_TIMEOUT_INFINITE)||(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < wait))) { - usleep(10); -#ifdef IPEDMA_SUPPORT_EMPTY_DETECTED - if ((ret != PCILIB_STREAMING_REQ_PACKET)&&(*empty_detected_ptr)) break; -#endif /* IPEDMA_SUPPORT_EMPTY_DETECTED */ - gettimeofday(&cur, NULL); - } - - // Failing out if we exited on timeout - if ((ctx->last_read_addr == (*last_written_addr_ptr))||(*last_written_addr_ptr == 0)) { -#ifdef IPEDMA_SUPPORT_EMPTY_DETECTED -# ifdef IPEDMA_DEBUG - if ((wait)&&(*last_written_addr_ptr)&&(!*empty_detected_ptr)) - pcilib_warning("The empty_detected flag is not set, but no data arrived within %lu us\n", wait); -# endif /* IPEDMA_DEBUG */ -#endif /* IPEDMA_SUPPORT_EMPTY_DETECTED */ - return (ret&PCILIB_STREAMING_FAIL)?PCILIB_ERROR_TIMEOUT:0; - } - - // Getting next page to read - cur_read = ctx->last_read + 1; - if (cur_read == ctx->ring_size) cur_read = 0; - -#ifdef IPEDMA_DEBUG - printf("Reading: %u (last read) 0x%x (last read addr) 0x%x (last_written)\n", cur_read, ctx->last_read_addr, *last_written_addr_ptr); -#endif /* IPEDMA_DEBUG */ - -#ifdef IPEDMA_DETECT_PACKETS - if ((*empty_detected_ptr)&&(pcilib_kmem_get_block_ba(ctx->pcilib, ctx->pages, cur_read) == (*last_written_addr_ptr))) packet_flags = PCILIB_DMA_FLAG_EOP; - else packet_flags = 0; -#endif /* IPEDMA_DETECT_PACKETS */ - - pcilib_kmem_sync_block(ctx->pcilib, ctx->pages, PCILIB_KMEM_SYNC_FROMDEVICE, cur_read); - void *buf = pcilib_kmem_get_block_ua(ctx->pcilib, ctx->pages, cur_read); - ret = cb(cbattr, packet_flags, ctx->page_size, buf); - if (ret < 0) return -ret; - -// DS: Fixme, it looks like we can avoid calling this for the sake of performance -// pcilib_kmem_sync_block(ctx->pcilib, ctx->pages, PCILIB_KMEM_SYNC_TODEVICE, cur_read); - - // Numbered from 1 - WR(IPEDMA_REG_LAST_READ, cur_read + 1); - - ctx->last_read = cur_read; -// ctx->last_read_addr = htonl(pcilib_kmem_get_block_ba(ctx->pcilib, ctx->pages, cur_read)); - ctx->last_read_addr = pcilib_kmem_get_block_ba(ctx->pcilib, ctx->pages, cur_read); - -#ifdef IPEDMA_BUG_DMARD - FILE *f = fopen("/tmp/pcitool_lastread", "w"); - if (!f) pcilib_error("Can't write current status"); - value = cur_read; - fwrite(&value, 1, sizeof(pcilib_register_value_t), f); - fclose(f); -#endif /* IPEDMA_BUG_DMARD */ - - } while (ret); - - return 0; -} - -double dma_ipe_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction) { - int err = 0; - - ipe_dma_t *ctx = (ipe_dma_t*)vctx; - - int iter; - size_t us = 0; - struct timeval start, cur; - - void *buf; - size_t bytes, rbytes; - - if ((direction == PCILIB_DMA_TO_DEVICE)||(direction == PCILIB_DMA_BIDIRECTIONAL)) return -1.; - - if ((dma != PCILIB_DMA_ENGINE_INVALID)&&(dma > 1)) return -1.; - - err = dma_ipe_start(vctx, 0, PCILIB_DMA_FLAGS_DEFAULT); - if (err) return err; - - WR(IPEDMA_REG_CONTROL, 0x0); - - err = pcilib_skip_dma(ctx->pcilib, 0); - if (err) { - pcilib_error("Can't start benchmark, devices continuously writes unexpected data using DMA engine"); - return -1; - } - - if (size%IPEDMA_PAGE_SIZE) size = (1 + size / IPEDMA_PAGE_SIZE) * IPEDMA_PAGE_SIZE; - - // Allocate memory and prepare data - buf = malloc(size); - if (!buf) return -1; - - for (iter = 0; iter < iterations; iter++) { - gettimeofday(&start, NULL); - - // Starting DMA - WR(IPEDMA_REG_CONTROL, 0x1); - - for (bytes = 0; bytes < size; bytes += rbytes) { - err = pcilib_read_dma(ctx->pcilib, 0, addr, size - bytes, buf + bytes, &rbytes); - if (err) { - pcilib_error("Can't read data from DMA, error %i", err); - return -1; - } - } - - // Stopping DMA - WR(IPEDMA_REG_CONTROL, 0x0); - if (err) break; - - gettimeofday(&cur, NULL); - us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)); - - err = pcilib_skip_dma(ctx->pcilib, 0); - if (err) { - pcilib_error("Can't start iteration, devices continuously writes unexpected data using DMA engine"); - break; - } - } - - free(buf); - - return err?-1:((1. * size * iterations * 1000000) / (1024. * 1024. * us)); -} diff --git a/dma/ipe.h b/dma/ipe.h deleted file mode 100644 index 2c34ff1..0000000 --- a/dma/ipe.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _PCILIB_DMA_IPE_H -#define _PCILIB_DMA_IPE_H - -#include -#include "../pcilib.h" - -//#define PCILIB_NWL_MODIFICATION_IPECAMERA 0x100 - -pcilib_dma_context_t *dma_ipe_init(pcilib_t *ctx, pcilib_dma_modification_t type, void *arg); -void dma_ipe_free(pcilib_dma_context_t *vctx); - -int dma_ipe_get_status(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers); - - -int dma_ipe_start(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags); -int dma_ipe_stop(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags); - -int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr); -double dma_ipe_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction); - - -#ifdef _PCILIB_DMA_IPE_C -pcilib_dma_api_description_t ipe_dma_api = { - "ipe_dma", - dma_ipe_init, - dma_ipe_free, - dma_ipe_get_status, - NULL, - NULL, - NULL, - dma_ipe_start, - dma_ipe_stop, - NULL, - dma_ipe_stream_read, - dma_ipe_benchmark -}; -#else -extern pcilib_dma_api_description_t ipe_dma_api; -#endif - - -#endif /* _PCILIB_DMA_IPE_H */ diff --git a/dma/ipe_private.h b/dma/ipe_private.h deleted file mode 100644 index fd44011..0000000 --- a/dma/ipe_private.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _PCILIB_DMA_IPE_PRIVATE_H -#define _PCILIB_DMA_IPE_PRIVATE_H - -#define IPEDMA_CORES 1 -#define IPEDMA_TLP_SIZE 32 -#define IPEDMA_PAGE_SIZE 4096 -#define IPEDMA_DMA_PAGES 16 /**< number of DMA pages in the ring buffer to allocate */ -#define IPEDMA_DMA_PROGRESS_THRESHOLD 1 /**< how many pages the DMA engine should fill before reporting progress */ -#define IPEDMA_DESCRIPTOR_SIZE 128 -#define IPEDMA_DESCRIPTOR_ALIGNMENT 64 - -//#define IPEDMA_DEBUG -//#define IPEDMA_BUG_DMARD /**< No register read during DMA transfer */ -//#define IPEDMA_DETECT_PACKETS /**< Using empty_deceted flag */ -#define IPEDMA_SUPPORT_EMPTY_DETECTED /**< Avoid waiting for data when empty_detected flag is set in hardware */ -#define IPEDMA_DMA_TIMEOUT 100000 /**< us, overrides PCILIB_DMA_TIMEOUT (actual hardware timeout is 50ms according to Lorenzo) */ - -#define IPEDMA_REG_RESET 0x00 -#define IPEDMA_REG_CONTROL 0x04 -#define IPEDMA_REG_TLP_SIZE 0x0C -#define IPEDMA_REG_TLP_COUNT 0x10 -#define IPEDMA_REG_PAGE_ADDR 0x50 -#define IPEDMA_REG_UPDATE_ADDR 0x54 -#define IPEDMA_REG_LAST_READ 0x58 -#define IPEDMA_REG_PAGE_COUNT 0x5C -#define IPEDMA_REG_UPDATE_THRESHOLD 0x60 - - - -typedef struct ipe_dma_s ipe_dma_t; - -struct ipe_dma_s { - struct pcilib_dma_context_s dmactx; - pcilib_dma_engine_description_t engine[2]; - - pcilib_t *pcilib; - - pcilib_register_bank_description_t *dma_bank; - char *base_addr; - - pcilib_irq_type_t irq_enabled; /**< indicates that IRQs are enabled */ - pcilib_irq_type_t irq_preserve; /**< indicates that IRQs should not be disabled during clean-up */ - int irq_started; /**< indicates that IRQ subsystem is initialized (detecting which types should be preserverd) */ - - int started; /**< indicates that DMA buffers are initialized and reading is allowed */ - int writting; /**< indicates that we are in middle of writting packet */ - int reused; /**< indicates that DMA was found intialized, buffers were reused, and no additional initialization is needed */ - int preserve; /**< indicates that DMA should not be stopped during clean-up */ - int mode64; /**< indicates 64-bit operation mode */ - - pcilib_kmem_handle_t *desc; /**< in-memory status descriptor written by DMA engine upon operation progess */ - pcilib_kmem_handle_t *pages; /**< collection of memory-locked pages for DMA operation */ - - size_t ring_size, page_size; - size_t last_read, last_read_addr, last_written; - -}; - -#endif /* _PCILIB_DMA_IPE_PRIVATE_H */ diff --git a/dma/ipe_registers.h b/dma/ipe_registers.h deleted file mode 100644 index 17fc41a..0000000 --- a/dma/ipe_registers.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _PCILIB_DMA_IPE_REGISTERS_H -#define _PCILIB_DMA_IPE_REGISTERS_H - -#ifdef _PCILIB_DMA_IPE_C -static pcilib_register_description_t ipe_dma_registers[] = { - {0x0000, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dcr", "Device Control Status Register"}, - {0x0000, 0, 1, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "reset_dma", ""}, - {0x0000, 16, 4, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "datapath_width", ""}, - {0x0000, 24, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "fpga_family", ""}, - {0x0004, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "ddmacr", "Device DMA Control Status Register"}, - {0x0004, 0, 1, 0, 0xFFFFFFFF, PCILIB_REGISTER_RW , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_start", "Start writting memory"}, - {0x0004, 5, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_relxed_order", ""}, - {0x0004, 6, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_nosnoop", ""}, - {0x0004, 7, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_int_dis", ""}, - {0x0004, 16, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mrd_start", ""}, - {0x0004, 21, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mrd_relaxed_order", ""}, - {0x0004, 22, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mrd_nosnoop", ""}, - {0x0004, 23, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mrd_int_dis", ""}, - {0x000C, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "mwr_size", "DMA TLP size"}, - {0x000C, 0, 16, 0x20, 0xFFFFFFFF, PCILIB_REGISTER_RW , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_len", "Max TLP size"}, - {0x000C, 16, 3, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_tlp_tc", "TC for TLP packets"}, - {0x000C, 19, 1, 0, 0xFFFFFFFF, PCILIB_REGISTER_RW , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_64b_en", "Enable 64 bit memory addressing"}, - {0x000C, 20, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_phant_func_dis", "Disable MWR phantom function"}, - {0x000C, 24, 8, 0, 0xFFFFFFFF, PCILIB_REGISTER_RW , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_up_addr", "Upper address for 64 bit memory addressing"}, - {0x0010, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "mwr_count", "Write DMA TLP Count"}, - {0x0014, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "mwr_pattern", "DMA generator data pattern"}, - {0x0028, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "mwr_perf", "MWR Performance"}, - {0x003C, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "cfg_lnk_width", "Negotiated and max width of PCIe Link"}, - {0x003C, 0, 6, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "cfg_cap_max_lnk_width", "Max link width"}, - {0x003C, 8, 6, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "cfg_prg_max_lnk_width", "Negotiated link width"}, - {0x0040, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "cfg_payload_size", ""}, - {0x0040, 0, 4, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "cfg_cap_max_payload_size", "Max payload size"}, - {0x0040, 8, 3, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "cfg_prg_max_payload_size", "Prog max payload size"}, - {0x0040, 16, 3, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "cfg_max_rd_req_size", "Max read request size"}, - {0x0050, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "desc_mem_din", "Descriptor memory"}, - {0x0054, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "update_addr", "Address of progress register"}, - {0x0058, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "last_descriptor_read", "Last descriptor read by the host"}, - {0x005C, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "desc_mem_addr", "Number of descriptors configured"}, - {0x0060, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "update_thresh", "Update threshold of progress register"}, - {0, 0, 0, 0, 0x00000000, 0, 0, 0, NULL, NULL} -}; -#endif /* _PCILIB_DMA_IPE_C */ - -#endif /* _PCILIB_DMA_IPE_REGISTERS_H */ diff --git a/dma/nwl.c b/dma/nwl.c deleted file mode 100644 index 52b46ef..0000000 --- a/dma/nwl.c +++ /dev/null @@ -1,139 +0,0 @@ -#define _PCILIB_DMA_NWL_C -#define _BSD_SOURCE - -#include -#include -#include -#include -#include - -#include "pci.h" -#include "pcilib.h" -#include "error.h" -#include "tools.h" -#include "nwl_private.h" - -#include "nwl_defines.h" - -int dma_nwl_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) { - int err; - nwl_dma_t *ctx = (nwl_dma_t*)vctx; - - if (!ctx->started) { - // global initialization, should we do anything? - ctx->started = 1; - } - - if (dma == PCILIB_DMA_ENGINE_INVALID) return 0; - else if (dma > ctx->n_engines) return PCILIB_ERROR_INVALID_BANK; - - if (flags&PCILIB_DMA_FLAG_PERSISTENT) ctx->engines[dma].preserve = 1; - - err = dma_nwl_start_engine(ctx, dma); - - return err; -} - -int dma_nwl_stop(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) { - int err; - int preserving = 0; - - nwl_dma_t *ctx = (nwl_dma_t*)vctx; - - if (!ctx->started) return 0; - - // stop everything - if (dma == PCILIB_DMA_ENGINE_INVALID) { - for (dma = 0; dma < ctx->n_engines; dma++) { - if (flags&PCILIB_DMA_FLAG_PERSISTENT) { - ctx->engines[dma].preserve = 0; - } - - if (ctx->engines[dma].preserve) preserving = 1; - - err = dma_nwl_stop_engine(ctx, dma); - if (err) return err; - } - - // global cleanup, should we do anything? - if (!preserving) { - ctx->started = 0; - } - - return 0; - } - - if (dma > ctx->n_engines) return PCILIB_ERROR_INVALID_BANK; - - // ignorign previous setting if flag specified - if (flags&PCILIB_DMA_FLAG_PERSISTENT) { - ctx->engines[dma].preserve = 0; - } - - return dma_nwl_stop_engine(ctx, dma); -} - - -pcilib_dma_context_t *dma_nwl_init(pcilib_t *pcilib, pcilib_dma_modification_t type, void *arg) { - int i; - int err; - pcilib_dma_engine_t n_engines; - - pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib); - - nwl_dma_t *ctx = malloc(sizeof(nwl_dma_t)); - if (ctx) { - memset(ctx, 0, sizeof(nwl_dma_t)); - ctx->pcilib = pcilib; - ctx->type = type; - - if (type == PCILIB_NWL_MODIFICATION_IPECAMERA) { - ctx->dmactx.ignore_eop = 1; - } - - pcilib_register_bank_t dma_bank = pcilib_find_bank_by_addr(pcilib, PCILIB_REGISTER_BANK_DMA); - if (dma_bank == PCILIB_REGISTER_BANK_INVALID) { - free(ctx); - pcilib_error("DMA Register Bank could not be found"); - return NULL; - } - - ctx->dma_bank = model_info->banks + dma_bank; - ctx->base_addr = pcilib_resolve_register_address(pcilib, ctx->dma_bank->bar, ctx->dma_bank->read_addr); - - for (i = 0, n_engines = 0; i < 2 * PCILIB_MAX_DMA_ENGINES; i++) { - char *addr = ctx->base_addr + DMA_OFFSET + i * DMA_ENGINE_PER_SIZE; - - memset(ctx->engines + n_engines, 0, sizeof(pcilib_nwl_engine_description_t)); - - err = dma_nwl_read_engine_config(ctx, ctx->engines + n_engines, addr); - if (err) continue; - - pcilib_set_dma_engine_description(pcilib, n_engines, (pcilib_dma_engine_description_t*)(ctx->engines + n_engines)); - ++n_engines; - } - pcilib_set_dma_engine_description(pcilib, n_engines, NULL); - - ctx->n_engines = n_engines; - - err = nwl_add_registers(ctx); - if (err) { - free(ctx); - pcilib_error("Failed to add DMA registers"); - return NULL; - } - } - return (pcilib_dma_context_t*)ctx; -} - -void dma_nwl_free(pcilib_dma_context_t *vctx) { - nwl_dma_t *ctx = (nwl_dma_t*)vctx; - - if (ctx) { - if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) dma_nwl_stop_loopback(ctx); - dma_nwl_free_irq(ctx); - dma_nwl_stop(vctx, PCILIB_DMA_ENGINE_ALL, PCILIB_DMA_FLAGS_DEFAULT); - - free(ctx); - } -} diff --git a/dma/nwl.h b/dma/nwl.h deleted file mode 100644 index 21df94c..0000000 --- a/dma/nwl.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _PCILIB_DMA_NWL_H -#define _PCILIB_DMA_NWL_H - -#include -#include "../pcilib.h" - -#define PCILIB_NWL_MODIFICATION_IPECAMERA 0x100 - -pcilib_dma_context_t *dma_nwl_init(pcilib_t *ctx, pcilib_dma_modification_t type, void *arg); -void dma_nwl_free(pcilib_dma_context_t *vctx); - -int dma_nwl_get_status(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers); - -int dma_nwl_enable_irq(pcilib_dma_context_t *vctx, pcilib_irq_type_t type, pcilib_dma_flags_t flags); -int dma_nwl_disable_irq(pcilib_dma_context_t *vctx, pcilib_dma_flags_t flags); -int dma_nwl_acknowledge_irq(pcilib_dma_context_t *ctx, pcilib_irq_type_t irq_type, pcilib_irq_source_t irq_source); - -int dma_nwl_start(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags); -int dma_nwl_stop(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags); - -int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *data, size_t *written); -int dma_nwl_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr); -double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction); - - -#ifdef _PCILIB_DMA_NWL_C -pcilib_dma_api_description_t nwl_dma_api = { - "nwl_dma", - dma_nwl_init, - dma_nwl_free, - dma_nwl_get_status, - dma_nwl_enable_irq, - dma_nwl_disable_irq, - dma_nwl_acknowledge_irq, - dma_nwl_start, - dma_nwl_stop, - dma_nwl_write_fragment, - dma_nwl_stream_read, - dma_nwl_benchmark -}; -#else -extern pcilib_dma_api_description_t nwl_dma_api; -#endif - - -#endif /* _PCILIB_DMA_NWL_H */ diff --git a/dma/nwl_defines.h b/dma/nwl_defines.h deleted file mode 100644 index ce3b686..0000000 --- a/dma/nwl_defines.h +++ /dev/null @@ -1,145 +0,0 @@ -/** @name Buffer Descriptor offsets - * USR fields are defined by higher level IP. For example, checksum offload - * setup for EMAC type devices. The 1st 8 words are utilized by hardware. Any - * words after the 8th are for software use only. - * @{ - */ -#define DMA_BD_BUFL_STATUS_OFFSET 0x00 /**< Buffer length + status */ -#define DMA_BD_USRL_OFFSET 0x04 /**< User logic specific - LSBytes */ -#define DMA_BD_USRH_OFFSET 0x08 /**< User logic specific - MSBytes */ -#define DMA_BD_CARDA_OFFSET 0x0C /**< Card address */ -#define DMA_BD_BUFL_CTRL_OFFSET 0x10 /**< Buffer length + control */ -#define DMA_BD_BUFAL_OFFSET 0x14 /**< Buffer address LSBytes */ -#define DMA_BD_BUFAH_OFFSET 0x18 /**< Buffer address MSBytes */ -#define DMA_BD_NDESC_OFFSET 0x1C /**< Next descriptor pointer */ - -/* Bit masks for some BD fields */ -#define DMA_BD_BUFL_MASK 0x000FFFFF /**< Byte count */ -#define DMA_BD_STATUS_MASK 0xFF000000 /**< Status Flags */ -#define DMA_BD_CTRL_MASK 0xFF000000 /**< Control Flags */ - -/* Bit masks for BD control field */ -#define DMA_BD_INT_ERROR_MASK 0x02000000 /**< Intr on error */ -#define DMA_BD_INT_COMP_MASK 0x01000000 /**< Intr on BD completion */ - -/* Bit masks for BD status field */ -#define DMA_BD_SOP_MASK 0x80000000 /**< Start of packet */ -#define DMA_BD_EOP_MASK 0x40000000 /**< End of packet */ -#define DMA_BD_ERROR_MASK 0x10000000 /**< BD had error */ -#define DMA_BD_USER_HIGH_ZERO_MASK 0x08000000 /**< User High Status zero */ -#define DMA_BD_USER_LOW_ZERO_MASK 0x04000000 /**< User Low Status zero */ -#define DMA_BD_SHORT_MASK 0x02000000 /**< BD not fully used */ -#define DMA_BD_COMP_MASK 0x01000000 /**< BD completed */ - - - -#define DMA_BD_MINIMUM_ALIGNMENT 0x40 /**< Minimum byte alignment */ - -/* Common DMA registers */ -#define REG_DMA_CTRL_STATUS 0x4000 /**< DMA Common Ctrl & Status */ - -/* These engine registers are applicable to both S2C and C2S channels. - * Register field mask and shift definitions are later in this file. - */ - -#define REG_DMA_ENG_CAP 0x00000000 /**< DMA Engine Capabilities */ -#define REG_DMA_ENG_CTRL_STATUS 0x00000004 /**< DMA Engine Control */ -#define REG_DMA_ENG_NEXT_BD 0x00000008 /**< HW Next desc pointer */ -#define REG_SW_NEXT_BD 0x0000000C /**< SW Next desc pointer */ -#define REG_DMA_ENG_LAST_BD 0x00000010 /**< HW Last completed pointer */ -#define REG_DMA_ENG_ACTIVE_TIME 0x00000014 /**< DMA Engine Active Time */ -#define REG_DMA_ENG_WAIT_TIME 0x00000018 /**< DMA Engine Wait Time */ -#define REG_DMA_ENG_COMP_BYTES 0x0000001C /**< DMA Engine Completed Bytes */ - -/* Register masks. The following constants define bit locations of various - * control bits in the registers. For further information on the meaning of - * the various bit masks, refer to the hardware spec. - * - * Masks have been written assuming HW bits 0-31 correspond to SW bits 0-31 - */ - -/** @name Bitmasks of REG_DMA_CTRL_STATUS register. - * @{ - */ -#define DMA_INT_ENABLE 0x00000001 /**< Enable global interrupts */ -#define DMA_INT_DISABLE 0x00000000 /**< Disable interrupts */ -#define DMA_INT_ACTIVE_MASK 0x00000002 /**< Interrupt active? */ -#define DMA_INT_PENDING_MASK 0x00000004 /**< Engine interrupt pending */ -#define DMA_INT_MSI_MODE 0x00000008 /**< MSI or Legacy mode? */ -#define DMA_USER_INT_ENABLE 0x00000010 /**< Enable user interrupts */ -#define DMA_USER_INT_ACTIVE_MASK 0x00000020 /**< Int - user interrupt */ -#define DMA_USER_INT_ACK 0x00000020 /**< Acknowledge */ -#define DMA_MPS_USED 0x00000700 /**< MPS Used */ -#define DMA_MRRS_USED 0x00007000 /**< MRRS Used */ -#define DMA_S2C_ENG_INT_VAL 0x00FF0000 /**< IRQ value of 1st 8 S2Cs */ -#define DMA_C2S_ENG_INT_VAL 0xFF000000 /**< IRQ value of 1st 8 C2Ss */ - -/** @name Bitmasks of REG_DMA_ENG_CAP register. - * @{ - */ -/* DMA engine characteristics */ -#define DMA_ENG_PRESENT_MASK 0x00000001 /**< DMA engine present? */ -#define DMA_ENG_DIRECTION_MASK 0x00000002 /**< DMA engine direction */ -#define DMA_ENG_C2S 0x00000002 /**< DMA engine - C2S */ -#define DMA_ENG_S2C 0x00000000 /**< DMA engine - S2C */ -#define DMA_ENG_TYPE_MASK 0x00000030 /**< DMA engine type */ -#define DMA_ENG_BLOCK 0x00000000 /**< DMA engine - Block type */ -#define DMA_ENG_PACKET 0x00000010 /**< DMA engine - Packet type */ -#define DMA_ENG_NUMBER 0x0000FF00 /**< DMA engine number */ -#define DMA_ENG_BD_MAX_BC 0x3F000000 /**< DMA engine max buffer size */ - - -/* Shift constants for selected masks */ -#define DMA_ENG_NUMBER_SHIFT 8 -#define DMA_ENG_BD_MAX_BC_SHIFT 24 - -/** @name Bitmasks of REG_DMA_ENG_CTRL_STATUS register. - * @{ - */ -/* Interrupt activity and acknowledgement bits */ -#define DMA_ENG_INT_ENABLE 0x00000001 /**< Enable interrupts */ -#define DMA_ENG_INT_DISABLE 0x00000000 /**< Disable interrupts */ -#define DMA_ENG_INT_ACTIVE_MASK 0x00000002 /**< Interrupt active? */ -#define DMA_ENG_INT_ACK 0x00000002 /**< Interrupt ack */ -#define DMA_ENG_INT_BDCOMP 0x00000004 /**< Int - BD completion */ -#define DMA_ENG_INT_BDCOMP_ACK 0x00000004 /**< Acknowledge */ -#define DMA_ENG_INT_ALERR 0x00000008 /**< Int - BD align error */ -#define DMA_ENG_INT_ALERR_ACK 0x00000008 /**< Acknowledge */ -#define DMA_ENG_INT_FETERR 0x00000010 /**< Int - BD fetch error */ -#define DMA_ENG_INT_FETERR_ACK 0x00000010 /**< Acknowledge */ -#define DMA_ENG_INT_ABORTERR 0x00000020 /**< Int - DMA abort error */ -#define DMA_ENG_INT_ABORTERR_ACK 0x00000020 /**< Acknowledge */ -#define DMA_ENG_INT_CHAINEND 0x00000080 /**< Int - BD chain ended */ -#define DMA_ENG_INT_CHAINEND_ACK 0x00000080 /**< Acknowledge */ - -/* DMA engine control */ -#define DMA_ENG_ENABLE_MASK 0x00000100 /**< DMA enabled? */ -#define DMA_ENG_ENABLE 0x00000100 /**< Enable DMA */ -#define DMA_ENG_DISABLE 0x00000000 /**< Disable DMA */ -#define DMA_ENG_STATE_MASK 0x00000C00 /**< Current DMA state? */ -#define DMA_ENG_RUNNING 0x00000400 /**< DMA running */ -#define DMA_ENG_IDLE 0x00000000 /**< DMA idle */ -#define DMA_ENG_WAITING 0x00000800 /**< DMA waiting */ -#define DMA_ENG_STATE_WAITED 0x00001000 /**< DMA waited earlier */ -#define DMA_ENG_WAITED_ACK 0x00001000 /**< Acknowledge */ -#define DMA_ENG_USER_RESET 0x00004000 /**< Reset only user logic */ -#define DMA_ENG_RESET 0x00008000 /**< Reset DMA engine + user */ - -#define DMA_ENG_ALLINT_MASK 0x000000BE /**< To get only int events */ - -#define DMA_ENGINE_PER_SIZE 0x100 /**< Separation between engine regs */ -#define DMA_OFFSET 0 /**< Starting register offset */ - /**< Size of DMA engine reg space */ -#define DMA_SIZE (MAX_DMA_ENGINES * DMA_ENGINE_PER_SIZE) - - -#define TX_CONFIG_ADDRESS 0x9108 /* Reg for controlling TX data */ -#define RX_CONFIG_ADDRESS 0x9100 /* Reg for controlling RX pkt generator */ -#define PKT_SIZE_ADDRESS 0x9104 /* Reg for programming packet size */ -#define STATUS_ADDRESS 0x910C /* Reg for checking TX pkt checker status */ - -/* Test start / stop conditions */ -#define PKTCHKR 0x00000001 /* Enable TX packet checker */ -#define PKTGENR 0x00000001 /* Enable RX packet generator */ -#define CHKR_MISMATCH 0x00000001 /* TX checker reported data mismatch */ -#define LOOPBACK 0x00000002 /* Enable TX data loopback onto RX */ diff --git a/dma/nwl_engine.c b/dma/nwl_engine.c deleted file mode 100644 index f541d0b..0000000 --- a/dma/nwl_engine.c +++ /dev/null @@ -1,318 +0,0 @@ -#define _BSD_SOURCE - -#include -#include -#include -#include -#include - -#include "pci.h" -#include "pcilib.h" -#include "error.h" -#include "tools.h" -#include "nwl_private.h" - -#include "nwl_defines.h" - -#include "nwl_engine_buffers.h" - -int dma_nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, char *base) { - uint32_t val; - - info->base_addr = base; - - nwl_read_register(val, ctx, base, REG_DMA_ENG_CAP); - - if ((val & DMA_ENG_PRESENT_MASK) == 0) return PCILIB_ERROR_NOTAVAILABLE; - - info->desc.addr = (val & DMA_ENG_NUMBER) >> DMA_ENG_NUMBER_SHIFT; - if ((info->desc.addr > PCILIB_MAX_DMA_ENGINES)||(info->desc.addr < 0)) return PCILIB_ERROR_INVALID_DATA; - - switch (val & DMA_ENG_DIRECTION_MASK) { - case DMA_ENG_C2S: - info->desc.direction = PCILIB_DMA_FROM_DEVICE; - break; - default: - info->desc.direction = PCILIB_DMA_TO_DEVICE; - } - - switch (val & DMA_ENG_TYPE_MASK) { - case DMA_ENG_BLOCK: - info->desc.type = PCILIB_DMA_TYPE_BLOCK; - break; - case DMA_ENG_PACKET: - info->desc.type = PCILIB_DMA_TYPE_PACKET; - break; - default: - info->desc.type = PCILIB_DMA_TYPE_UNKNOWN; - } - - info->desc.addr_bits = (val & DMA_ENG_BD_MAX_BC) >> DMA_ENG_BD_MAX_BC_SHIFT; - - info->base_addr = base; - - return 0; -} - -int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) { - int err; - uint32_t val; - uint32_t ring_pa; - struct timeval start, cur; - - pcilib_nwl_engine_description_t *info = ctx->engines + dma; - char *base = ctx->engines[dma].base_addr; - - if (info->started) return 0; - - - // This will only successed if there are no parallel access to DMA engine - err = dma_nwl_allocate_engine_buffers(ctx, info); - if (err) { - info->started = 1; - dma_nwl_stop_engine(ctx, dma); - return err; - } - - if (info->reused) { - info->preserve = 1; - - dma_nwl_acknowledge_irq((pcilib_dma_context_t*)ctx, PCILIB_DMA_IRQ, dma); - -#ifdef NWL_GENERATE_DMA_IRQ - dma_nwl_enable_engine_irq(ctx, dma); -#endif /* NWL_GENERATE_DMA_IRQ */ - } else { - // Disable IRQs - err = dma_nwl_disable_engine_irq(ctx, dma); - if (err) { - info->started = 1; - dma_nwl_stop_engine(ctx, dma); - return err; - } - - // Disable Engine & Reseting - val = DMA_ENG_DISABLE|DMA_ENG_USER_RESET; - nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); - - gettimeofday(&start, NULL); - do { - nwl_read_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); - gettimeofday(&cur, NULL); - } while ((val & (DMA_ENG_STATE_MASK|DMA_ENG_USER_RESET))&&(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < PCILIB_REGISTER_TIMEOUT)); - - if (val & (DMA_ENG_STATE_MASK|DMA_ENG_USER_RESET)) { - pcilib_error("Timeout during reset of DMA engine %i", info->desc.addr); - - info->started = 1; - dma_nwl_stop_engine(ctx, dma); - return PCILIB_ERROR_TIMEOUT; - } - - val = DMA_ENG_RESET; - nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); - - gettimeofday(&start, NULL); - do { - nwl_read_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); - gettimeofday(&cur, NULL); - } while ((val & DMA_ENG_RESET)&&(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < PCILIB_REGISTER_TIMEOUT)); - - if (val & DMA_ENG_RESET) { - pcilib_error("Timeout during reset of DMA engine %i", info->desc.addr); - - info->started = 1; - dma_nwl_stop_engine(ctx, dma); - return PCILIB_ERROR_TIMEOUT; - } - - dma_nwl_acknowledge_irq((pcilib_dma_context_t*)ctx, PCILIB_DMA_IRQ, dma); - - ring_pa = pcilib_kmem_get_pa(ctx->pcilib, info->ring); - nwl_write_register(ring_pa, ctx, info->base_addr, REG_DMA_ENG_NEXT_BD); - nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD); - - __sync_synchronize(); - - nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS); - val |= (DMA_ENG_ENABLE); - nwl_write_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS); - - __sync_synchronize(); - -#ifdef NWL_GENERATE_DMA_IRQ - dma_nwl_enable_engine_irq(ctx, dma); -#endif /* NWL_GENERATE_DMA_IRQ */ - - if (info->desc.direction == PCILIB_DMA_FROM_DEVICE) { - ring_pa += (info->ring_size - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD); - - info->tail = 0; - info->head = (info->ring_size - 1); - } else { - info->tail = 0; - info->head = 0; - } - } - - info->started = 1; - - return 0; -} - - -int dma_nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) { - int err; - uint32_t val; - uint32_t ring_pa; - struct timeval start, cur; - pcilib_kmem_flags_t flags; - - - pcilib_nwl_engine_description_t *info = ctx->engines + dma; - char *base = ctx->engines[dma].base_addr; - - if (!info->started) return 0; - - info->started = 0; - - err = dma_nwl_disable_engine_irq(ctx, dma); - if (err) return err; - - if (!info->preserve) { - // Stopping DMA is not enough reset is required - val = DMA_ENG_DISABLE|DMA_ENG_USER_RESET|DMA_ENG_RESET; - nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); - - gettimeofday(&start, NULL); - do { - nwl_read_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); - gettimeofday(&cur, NULL); - } while ((val & (DMA_ENG_RUNNING))&&(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < PCILIB_REGISTER_TIMEOUT)); - - if (info->ring) { - ring_pa = pcilib_kmem_get_pa(ctx->pcilib, info->ring); - nwl_write_register(ring_pa, ctx, info->base_addr, REG_DMA_ENG_NEXT_BD); - nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD); - } - } - - dma_nwl_acknowledge_irq((pcilib_dma_context_t*)ctx, PCILIB_DMA_IRQ, dma); - - if (info->preserve) { - flags = PCILIB_KMEM_FLAG_REUSE; - } else { - flags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT; - } - - // Clean buffers - if (info->ring) { - pcilib_free_kernel_memory(ctx->pcilib, info->ring, flags); - info->ring = NULL; - } - - if (info->pages) { - pcilib_free_kernel_memory(ctx->pcilib, info->pages, flags); - info->pages = NULL; - } - - return 0; -} - -int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *data, size_t *written) { - int err; - size_t pos; - size_t bufnum; - nwl_dma_t *ctx = (nwl_dma_t*)vctx; - - pcilib_nwl_engine_description_t *info = ctx->engines + dma; - - err = dma_nwl_start(vctx, dma, PCILIB_DMA_FLAGS_DEFAULT); - if (err) return err; - - if (data) { - for (pos = 0; pos < size; pos += info->page_size) { - int block_size = min2(size - pos, info->page_size); - - bufnum = dma_nwl_get_next_buffer(ctx, info, 1, timeout); - if (bufnum == PCILIB_DMA_BUFFER_INVALID) { - if (written) *written = pos; - return PCILIB_ERROR_TIMEOUT; - } - - void *buf = pcilib_kmem_get_block_ua(ctx->pcilib, info->pages, bufnum); - - pcilib_kmem_sync_block(ctx->pcilib, info->pages, PCILIB_KMEM_SYNC_FROMDEVICE, bufnum); - memcpy(buf, data, block_size); - pcilib_kmem_sync_block(ctx->pcilib, info->pages, PCILIB_KMEM_SYNC_TODEVICE, bufnum); - - err = dma_nwl_push_buffer(ctx, info, block_size, (flags&PCILIB_DMA_FLAG_EOP)&&((pos + block_size) == size), timeout); - if (err) { - if (written) *written = pos; - return err; - } - } - } - - if (written) *written = size; - - if (flags&PCILIB_DMA_FLAG_WAIT) { - bufnum = dma_nwl_get_next_buffer(ctx, info, PCILIB_NWL_DMA_PAGES - 1, timeout); - if (bufnum == PCILIB_DMA_BUFFER_INVALID) return PCILIB_ERROR_TIMEOUT; - } - - return 0; -} - -int dma_nwl_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr) { - int err, ret = PCILIB_STREAMING_REQ_PACKET; - pcilib_timeout_t wait = 0; - size_t res = 0; - size_t bufnum; - size_t bufsize; - - nwl_dma_t *ctx = (nwl_dma_t*)vctx; - - int eop; - - pcilib_nwl_engine_description_t *info = ctx->engines + dma; - - err = dma_nwl_start(vctx, dma, PCILIB_DMA_FLAGS_DEFAULT); - if (err) return err; - - do { - switch (ret&PCILIB_STREAMING_TIMEOUT_MASK) { - case PCILIB_STREAMING_CONTINUE: wait = PCILIB_DMA_TIMEOUT; break; - case PCILIB_STREAMING_WAIT: wait = timeout; break; -// case PCILIB_STREAMING_CHECK: wait = 0; break; - } - - bufnum = dma_nwl_wait_buffer(ctx, info, &bufsize, &eop, wait); - if (bufnum == PCILIB_DMA_BUFFER_INVALID) { - return (ret&PCILIB_STREAMING_FAIL)?PCILIB_ERROR_TIMEOUT:0; - } - - // EOP is not respected in IPE Camera - if (ctx->dmactx.ignore_eop) eop = 1; - - pcilib_kmem_sync_block(ctx->pcilib, info->pages, PCILIB_KMEM_SYNC_FROMDEVICE, bufnum); - void *buf = pcilib_kmem_get_block_ua(ctx->pcilib, info->pages, bufnum); - ret = cb(cbattr, (eop?PCILIB_DMA_FLAG_EOP:0), bufsize, buf); - if (ret < 0) return -ret; -// DS: Fixme, it looks like we can avoid calling this for the sake of performance -// pcilib_kmem_sync_block(ctx->pcilib, info->pages, PCILIB_KMEM_SYNC_TODEVICE, bufnum); - dma_nwl_return_buffer(ctx, info); - - res += bufsize; - - } while (ret); - - return 0; -} - -int dma_nwl_wait_completion(nwl_dma_t * ctx, pcilib_dma_engine_t dma, pcilib_timeout_t timeout) { - if (dma_nwl_get_next_buffer(ctx, ctx->engines + dma, PCILIB_NWL_DMA_PAGES - 1, PCILIB_DMA_TIMEOUT) == (PCILIB_NWL_DMA_PAGES - 1)) return 0; - else return PCILIB_ERROR_TIMEOUT; -} - diff --git a/dma/nwl_engine.h b/dma/nwl_engine.h deleted file mode 100644 index f9f3f60..0000000 --- a/dma/nwl_engine.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _PCILIB_DMA_NWL_ENGINE_H -#define _PCILIB_DMA_NWL_ENGINE_H - -int dma_nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, char *base); -int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma); -int dma_nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma); - -int dma_nwl_wait_completion(nwl_dma_t * ctx, pcilib_dma_engine_t dma, pcilib_timeout_t timeout); - - -#endif /* _PCILIB_DMA_NWL_ENGINE_H */ - diff --git a/dma/nwl_engine_buffers.h b/dma/nwl_engine_buffers.h deleted file mode 100644 index c45c3ca..0000000 --- a/dma/nwl_engine_buffers.h +++ /dev/null @@ -1,412 +0,0 @@ -#define NWL_RING_GET(data, offset) *(uint32_t*)(((char*)(data)) + (offset)) -#define NWL_RING_SET(data, offset, val) *(uint32_t*)(((char*)(data)) + (offset)) = (val) -#define NWL_RING_UPDATE(data, offset, mask, val) *(uint32_t*)(((char*)(data)) + (offset)) = ((*(uint32_t*)(((char*)(data)) + (offset)))&(mask))|(val) - -static int dma_nwl_compute_read_s2c_pointers(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, unsigned char *ring, uint32_t ring_pa) { - uint32_t val; - - char *base = info->base_addr; - - nwl_read_register(val, ctx, base, REG_SW_NEXT_BD); - if ((val < ring_pa)||((val - ring_pa) % PCILIB_NWL_DMA_DESCRIPTOR_SIZE)) { - if (val < ring_pa) pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_SW_NEXT_BD register value (%lx) is below start of ring [%lx,%lx])", val, ring_pa, PCILIB_NWL_DMA_DESCRIPTOR_SIZE); - else pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_SW_NEXT_BD register value (%zu / %u) is fractal)", val - ring_pa, PCILIB_NWL_DMA_DESCRIPTOR_SIZE); - return PCILIB_ERROR_INVALID_STATE; - } - - info->head = (val - ring_pa) / PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - if (info->head >= PCILIB_NWL_DMA_PAGES) { - pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_SW_NEXT_BD register value (%zu) out of range)", info->head); - return PCILIB_ERROR_INVALID_STATE; - } - - nwl_read_register(val, ctx, base, REG_DMA_ENG_NEXT_BD); - if ((val < ring_pa)||((val - ring_pa) % PCILIB_NWL_DMA_DESCRIPTOR_SIZE)) { - if (val < ring_pa) pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_DMA_ENG_NEXT_BD register value (%lx) is below start of ring [%lx,%lx])", val, ring_pa, PCILIB_NWL_DMA_DESCRIPTOR_SIZE); - else pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_DMA_ENG_NEXT_BD register value (%zu / %u) is fractal)", val - ring_pa, PCILIB_NWL_DMA_DESCRIPTOR_SIZE); - return PCILIB_ERROR_INVALID_STATE; - } - - info->tail = (val - ring_pa) / PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - if (info->tail >= PCILIB_NWL_DMA_PAGES) { - pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_DMA_ENG_NEXT_BD register value (%zu) out of range)", info->tail); - return PCILIB_ERROR_INVALID_STATE; - } - -#ifdef DEBUG_NWL - printf("S2C: %lu %lu\n", info->tail, info->head); -#endif /* DEBUG_NWL */ - - return 0; -} - -static int dma_nwl_compute_read_c2s_pointers(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, unsigned char *ring, uint32_t ring_pa) { - uint32_t val; - - char *base = info->base_addr; - - nwl_read_register(val, ctx, base, REG_SW_NEXT_BD); - if ((val < ring_pa)||((val - ring_pa) % PCILIB_NWL_DMA_DESCRIPTOR_SIZE)) { - if (val < ring_pa) pcilib_warning("Inconsistent C2S DMA Ring buffer is found (REG_SW_NEXT_BD register value (%lx) is below start of the ring [%lx,%lx])", val, ring_pa, PCILIB_NWL_DMA_DESCRIPTOR_SIZE); - else pcilib_warning("Inconsistent C2S DMA Ring buffer is found (REG_SW_NEXT_BD register value (%zu / %u) is fractal)", val - ring_pa, PCILIB_NWL_DMA_DESCRIPTOR_SIZE); - return PCILIB_ERROR_INVALID_STATE; - } - - info->head = (val - ring_pa) / PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - if (info->head >= PCILIB_NWL_DMA_PAGES) { - pcilib_warning("Inconsistent C2S DMA Ring buffer is found (REG_SW_NEXT_BD register value (%zu) out of range)", info->head); - return PCILIB_ERROR_INVALID_STATE; - } - - info->tail = info->head + 1; - if (info->tail == PCILIB_NWL_DMA_PAGES) info->tail = 0; - -#ifdef DEBUG_NWL - printf("C2S: %lu %lu\n", info->tail, info->head); -#endif /* DEBUG_NWL */ - - return 0; -} - - -static int dma_nwl_allocate_engine_buffers(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info) { - int err = 0; - - int i; - int preserve = 0; - uint16_t sub_use; - uint32_t val; - uint32_t buf_sz; - uint64_t buf_pa; - pcilib_kmem_reuse_state_t reuse_ring, reuse_pages; - pcilib_kmem_flags_t flags; - pcilib_kmem_type_t type; - - char *base = info->base_addr; - - if (info->pages) return 0; - - // Or bidirectional specified by 0x0|addr, or read 0x0|addr and write 0x80|addr - type = (info->desc.direction == PCILIB_DMA_TO_DEVICE)?PCILIB_KMEM_TYPE_DMA_S2C_PAGE:PCILIB_KMEM_TYPE_DMA_C2S_PAGE; - sub_use = info->desc.addr|((info->desc.direction == PCILIB_DMA_TO_DEVICE)?0x80:0x00); - flags = PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_EXCLUSIVE|PCILIB_KMEM_FLAG_HARDWARE|(info->preserve?PCILIB_KMEM_FLAG_PERSISTENT:0); - - pcilib_kmem_handle_t *ring = pcilib_alloc_kernel_memory(ctx->pcilib, PCILIB_KMEM_TYPE_CONSISTENT, 1, PCILIB_NWL_DMA_PAGES * PCILIB_NWL_DMA_DESCRIPTOR_SIZE, PCILIB_NWL_ALIGNMENT, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, sub_use), flags); - pcilib_kmem_handle_t *pages = pcilib_alloc_kernel_memory(ctx->pcilib, type, PCILIB_NWL_DMA_PAGES, 0, 0, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, sub_use), flags); - - if (!ring||!pages) { - if (pages) pcilib_free_kernel_memory(ctx->pcilib, pages, 0); - if (ring) pcilib_free_kernel_memory(ctx->pcilib, ring, 0); - return PCILIB_ERROR_MEMORY; - } - - reuse_ring = pcilib_kmem_is_reused(ctx->pcilib, ring); - reuse_pages = pcilib_kmem_is_reused(ctx->pcilib, pages); - -// I guess idea here was that we not need to check all that stuff during the second iteration -// which is basicaly true (shall we expect any driver-triggered changes or parallel accesses?) -// but still we need to set preserve flag (and that if we enforcing preservation --start-dma). -// Probably having checks anyway is not harming... -// if (!info->preserve) { - if (reuse_ring == reuse_pages) { - if (reuse_ring & PCILIB_KMEM_REUSE_PARTIAL) pcilib_warning("Inconsistent DMA buffers are found (only part of required buffers is available), reinitializing..."); - else if (reuse_ring & PCILIB_KMEM_REUSE_REUSED) { - if ((reuse_ring & PCILIB_KMEM_REUSE_PERSISTENT) == 0) pcilib_warning("Lost DMA buffers are found (non-persistent mode), reinitializing..."); - else if ((reuse_ring & PCILIB_KMEM_REUSE_HARDWARE) == 0) pcilib_warning("Lost DMA buffers are found (missing HW reference), reinitializing..."); - else { - nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS); - - if ((val&DMA_ENG_RUNNING) == 0) pcilib_warning("Lost DMA buffers are found (DMA engine is stopped), reinitializing..."); - else preserve = 1; - } - } - } else pcilib_warning("Inconsistent DMA buffers (modes of ring and page buffers does not match), reinitializing...."); -// } - - - unsigned char *data = (unsigned char*)pcilib_kmem_get_ua(ctx->pcilib, ring); - uint32_t ring_pa = pcilib_kmem_get_pa(ctx->pcilib, ring); - - if (preserve) { - if (info->desc.direction == PCILIB_DMA_FROM_DEVICE) err = dma_nwl_compute_read_c2s_pointers(ctx, info, data, ring_pa); - else err = dma_nwl_compute_read_s2c_pointers(ctx, info, data, ring_pa); - - if (err) preserve = 0; - } - - if (preserve) { - info->reused = 1; - buf_sz = pcilib_kmem_get_block_size(ctx->pcilib, pages, 0); - } else { - info->reused = 0; - - memset(data, 0, PCILIB_NWL_DMA_PAGES * PCILIB_NWL_DMA_DESCRIPTOR_SIZE); - - for (i = 0; i < PCILIB_NWL_DMA_PAGES; i++, data += PCILIB_NWL_DMA_DESCRIPTOR_SIZE) { - buf_pa = pcilib_kmem_get_block_pa(ctx->pcilib, pages, i); - buf_sz = pcilib_kmem_get_block_size(ctx->pcilib, pages, i); - - NWL_RING_SET(data, DMA_BD_NDESC_OFFSET, ring_pa + ((i + 1) % PCILIB_NWL_DMA_PAGES) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE); - NWL_RING_SET(data, DMA_BD_BUFAL_OFFSET, buf_pa&0xFFFFFFFF); - NWL_RING_SET(data, DMA_BD_BUFAH_OFFSET, buf_pa>>32); -#ifdef NWL_GENERATE_DMA_IRQ - NWL_RING_SET(data, DMA_BD_BUFL_CTRL_OFFSET, buf_sz | DMA_BD_INT_ERROR_MASK | DMA_BD_INT_COMP_MASK); -#else /* NWL_GENERATE_DMA_IRQ */ - NWL_RING_SET(data, DMA_BD_BUFL_CTRL_OFFSET, buf_sz); -#endif /* NWL_GENERATE_DMA_IRQ */ - } - - val = ring_pa; - nwl_write_register(val, ctx, base, REG_DMA_ENG_NEXT_BD); - nwl_write_register(val, ctx, base, REG_SW_NEXT_BD); - - info->head = 0; - info->tail = 0; - } - - info->ring = ring; - info->pages = pages; - info->page_size = buf_sz; - info->ring_size = PCILIB_NWL_DMA_PAGES; - - return 0; -} - - -static size_t dma_nwl_clean_buffers(nwl_dma_t * ctx, pcilib_nwl_engine_description_t *info) { - size_t res = 0; - uint32_t status; - - unsigned char *ring = pcilib_kmem_get_ua(ctx->pcilib, info->ring); - ring += info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - -next_buffer: - status = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET)&DMA_BD_STATUS_MASK; -// control = NWL_RING_GET(ring, DMA_BD_BUFL_CTRL_OFFSET)&DMA_BD_CTRL_MASK; - - if (status & DMA_BD_ERROR_MASK) { - pcilib_error("NWL DMA Engine reported error in ring descriptor"); - return (size_t)-1; - } - - if (status & DMA_BD_SHORT_MASK) { - pcilib_error("NWL DMA Engine reported short error"); - return (size_t)-1; - } - - if (status & DMA_BD_COMP_MASK) { - info->tail++; - if (info->tail == info->ring_size) { - ring -= (info->tail - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - info->tail = 0; - } else { - ring += PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - } - - res++; - - if (info->tail != info->head) goto next_buffer; - } - -// printf("====> Cleaned: %i\n", res); - return res; -} - - -static size_t dma_nwl_get_next_buffer(nwl_dma_t * ctx, pcilib_nwl_engine_description_t *info, size_t n_buffers, pcilib_timeout_t timeout) { - struct timeval start, cur; - - size_t res, n = 0; - size_t head; - - for (head = info->head; (((head + 1)%info->ring_size) != info->tail)&&(n < n_buffers); head++, n++); - if (n == n_buffers) return info->head; - - gettimeofday(&start, NULL); - - res = dma_nwl_clean_buffers(ctx, info); - if (res == (size_t)-1) return PCILIB_DMA_BUFFER_INVALID; - else n += res; - - - while (n < n_buffers) { - if (timeout != PCILIB_TIMEOUT_INFINITE) { - gettimeofday(&cur, NULL); - if (((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) > timeout) break; - } - - usleep (10); - - res = dma_nwl_clean_buffers(ctx, info); - if (res == (size_t)-1) return PCILIB_DMA_BUFFER_INVALID; - else if (res > 0) { - gettimeofday(&start, NULL); - n += res; - } - } - - if (n < n_buffers) return PCILIB_DMA_BUFFER_INVALID; - - return info->head; -} - -static int dma_nwl_push_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, size_t size, int eop, pcilib_timeout_t timeout) { - int flags = 0; - - uint32_t val; - unsigned char *ring = pcilib_kmem_get_ua(ctx->pcilib, info->ring); - uint32_t ring_pa = pcilib_kmem_get_pa(ctx->pcilib, info->ring); - - ring += info->head * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - - - if (!info->writting) { - flags |= DMA_BD_SOP_MASK; - info->writting = 1; - } - if (eop) { - flags |= DMA_BD_EOP_MASK; - info->writting = 0; - } - - NWL_RING_SET(ring, DMA_BD_BUFL_CTRL_OFFSET, size|flags); - NWL_RING_SET(ring, DMA_BD_BUFL_STATUS_OFFSET, size); - - info->head++; - if (info->head == info->ring_size) info->head = 0; - - val = ring_pa + info->head * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - nwl_write_register(val, ctx, info->base_addr, REG_SW_NEXT_BD); - - return 0; -} - - -static size_t dma_nwl_wait_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, size_t *size, int *eop, pcilib_timeout_t timeout) { - struct timeval start, cur; - uint32_t status_size, status; - - unsigned char *ring = pcilib_kmem_get_ua(ctx->pcilib, info->ring); - - ring += info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - - gettimeofday(&start, NULL); - - do { - status_size = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET); - status = status_size & DMA_BD_STATUS_MASK; - - if (status & DMA_BD_ERROR_MASK) { - pcilib_error("NWL DMA Engine reported error in ring descriptor"); - return (size_t)-1; - } - - if (status & DMA_BD_COMP_MASK) { - if (status & DMA_BD_EOP_MASK) *eop = 1; - else *eop = 0; - - *size = status_size & DMA_BD_BUFL_MASK; - -/* - if (mrd) { - if ((info->tail + 1) == info->ring_size) ring -= info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - else ring += PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - *mrd = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET)&DMA_BD_COMP_MASK; - } -*/ - - return info->tail; - } - - usleep(10); - gettimeofday(&cur, NULL); - } while ((timeout == PCILIB_TIMEOUT_INFINITE)||(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < timeout)); - - return (size_t)-1; -} - -/* - // This function is not used now, but we may need it in the future -static int dma_nwl_is_overflown(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info) { - uint32_t status; - unsigned char *ring = pcilib_kmem_get_ua(ctx->pcilib, info->ring); - if (info->tail > 0) ring += (info->tail - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - else ring += (info->ring_size - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - - status = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET); - return status&DMA_BD_COMP_MASK?1:0; -} -*/ - -static int dma_nwl_return_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info) { - uint32_t val; - - unsigned char *ring = pcilib_kmem_get_ua(ctx->pcilib, info->ring); - uint32_t ring_pa = pcilib_kmem_get_pa(ctx->pcilib, info->ring); - size_t bufsz = pcilib_kmem_get_block_size(ctx->pcilib, info->pages, info->tail); - - ring += info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - -#ifdef NWL_GENERATE_DMA_IRQ - NWL_RING_SET(ring, DMA_BD_BUFL_CTRL_OFFSET, bufsz | DMA_BD_INT_ERROR_MASK | DMA_BD_INT_COMP_MASK); -#else /* NWL_GENERATE_DMA_IRQ */ - NWL_RING_SET(ring, DMA_BD_BUFL_CTRL_OFFSET, bufsz); -#endif /* NWL_GENERATE_DMA_IRQ */ - - NWL_RING_SET(ring, DMA_BD_BUFL_STATUS_OFFSET, 0); - - val = ring_pa + info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - nwl_write_register(val, ctx, info->base_addr, REG_SW_NEXT_BD); - - info->tail++; - if (info->tail == info->ring_size) info->tail = 0; - - return 0; -} - -int dma_nwl_get_status(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers) { - size_t i; - uint32_t bstatus; - nwl_dma_t *ctx = (nwl_dma_t*)vctx; - pcilib_nwl_engine_description_t *info = ctx->engines + dma; - unsigned char *ring = (unsigned char*)pcilib_kmem_get_ua(ctx->pcilib, info->ring); - - - if (!status) return -1; - - status->started = info->started; - status->ring_size = info->ring_size; - status->buffer_size = info->page_size; - status->ring_tail = info->tail; - - if (info->desc.direction == PCILIB_DMA_FROM_DEVICE) { - size_t pos = 0; - for (i = 0; i < info->ring_size; i++) { - pos = status->ring_tail + i; - if (pos >= info->ring_size) pos -= info->ring_size; - - bstatus = NWL_RING_GET(ring + pos * PCILIB_NWL_DMA_DESCRIPTOR_SIZE, DMA_BD_BUFL_STATUS_OFFSET); - if ((bstatus&(DMA_BD_ERROR_MASK|DMA_BD_COMP_MASK)) == 0) break; - } - status->ring_head = pos; - } else { - status->ring_head = info->head; - } - - - if (buffers) { - for (i = 0; (i < info->ring_size)&&(i < n_buffers); i++) { - bstatus = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET); - - buffers[i].error = bstatus & (DMA_BD_ERROR_MASK/*|DMA_BD_SHORT_MASK*/); - buffers[i].used = bstatus & DMA_BD_COMP_MASK; - buffers[i].size = bstatus & DMA_BD_BUFL_MASK; - buffers[i].first = bstatus & DMA_BD_SOP_MASK; - buffers[i].last = bstatus & DMA_BD_EOP_MASK; - - ring += PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - } - } - - return 0; -} diff --git a/dma/nwl_irq.c b/dma/nwl_irq.c deleted file mode 100644 index e71c76a..0000000 --- a/dma/nwl_irq.c +++ /dev/null @@ -1,119 +0,0 @@ -#include -#include -#include -#include -#include - -#include "pcilib.h" - -#include "pci.h" -#include "error.h" -#include "tools.h" - -#include "nwl_private.h" -#include "nwl_defines.h" - -int dma_nwl_init_irq(nwl_dma_t *ctx, uint32_t val) { - if (val&(DMA_INT_ENABLE|DMA_USER_INT_ENABLE)) { - if (val&DMA_INT_ENABLE) ctx->irq_preserve |= PCILIB_DMA_IRQ; - if (val&DMA_USER_INT_ENABLE) ctx->irq_preserve |= PCILIB_EVENT_IRQ; - } - - ctx->irq_started = 1; - return 0; -} - -int dma_nwl_free_irq(nwl_dma_t *ctx) { - if (ctx->irq_started) { - dma_nwl_disable_irq((pcilib_dma_context_t*)ctx, 0); - if (ctx->irq_preserve) dma_nwl_enable_irq((pcilib_dma_context_t*)ctx, ctx->irq_preserve, 0); - ctx->irq_enabled = 0; - ctx->irq_started = 0; - } - return 0; -} - -int dma_nwl_enable_irq(pcilib_dma_context_t *vctx, pcilib_irq_type_t type, pcilib_dma_flags_t flags) { - uint32_t val; - nwl_dma_t *ctx = (nwl_dma_t*)vctx; - - if (flags&PCILIB_DMA_FLAG_PERSISTENT) ctx->irq_preserve |= type; - - if ((ctx->irq_enabled&type) == type) return 0; - - type |= ctx->irq_enabled; - - nwl_read_register(val, ctx, ctx->base_addr, REG_DMA_CTRL_STATUS); - if (!ctx->irq_started) dma_nwl_init_irq(ctx, val); - - val &= ~(DMA_INT_ENABLE|DMA_USER_INT_ENABLE); - nwl_write_register(val, ctx, ctx->base_addr, REG_DMA_CTRL_STATUS); - - pcilib_clear_irq(ctx->pcilib, NWL_DMA_IRQ_SOURCE); - - if (type & PCILIB_DMA_IRQ) val |= DMA_INT_ENABLE; - if (type & PCILIB_EVENT_IRQ) val |= DMA_USER_INT_ENABLE; - nwl_write_register(val, ctx, ctx->base_addr, REG_DMA_CTRL_STATUS); - - ctx->irq_enabled = type; - - return 0; -} - - -int dma_nwl_disable_irq(pcilib_dma_context_t *vctx, pcilib_dma_flags_t flags) { - uint32_t val; - nwl_dma_t *ctx = (nwl_dma_t*)vctx; - - ctx->irq_enabled = 0; - - nwl_read_register(val, ctx, ctx->base_addr, REG_DMA_CTRL_STATUS); - if (!ctx->irq_started) dma_nwl_init_irq(ctx, val); - val &= ~(DMA_INT_ENABLE|DMA_USER_INT_ENABLE); - nwl_write_register(val, ctx, ctx->base_addr, REG_DMA_CTRL_STATUS); - - if (flags&PCILIB_DMA_FLAG_PERSISTENT) ctx->irq_preserve = 0; - - return 0; -} - - -int dma_nwl_enable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma) { - uint32_t val; - - dma_nwl_enable_irq((pcilib_dma_context_t*)ctx, PCILIB_DMA_IRQ, 0); - - nwl_read_register(val, ctx, ctx->engines[dma].base_addr, REG_DMA_ENG_CTRL_STATUS); - val |= (DMA_ENG_INT_ENABLE); - nwl_write_register(val, ctx, ctx->engines[dma].base_addr, REG_DMA_ENG_CTRL_STATUS); - - return 0; -} - -int dma_nwl_disable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma) { - uint32_t val; - - nwl_read_register(val, ctx, ctx->engines[dma].base_addr, REG_DMA_ENG_CTRL_STATUS); - val &= ~(DMA_ENG_INT_ENABLE); - nwl_write_register(val, ctx, ctx->engines[dma].base_addr, REG_DMA_ENG_CTRL_STATUS); - - return 0; -} - -int dma_nwl_acknowledge_irq(pcilib_dma_context_t *vctx, pcilib_irq_type_t irq_type, pcilib_irq_source_t irq_source) { - uint32_t val; - - nwl_dma_t *ctx = (nwl_dma_t*)vctx; - pcilib_nwl_engine_description_t *info = ctx->engines + irq_source; - - if (irq_type != PCILIB_DMA_IRQ) return PCILIB_ERROR_NOTSUPPORTED; - if (irq_source >= ctx->n_engines) return PCILIB_ERROR_NOTAVAILABLE; - - nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS); - if (val & DMA_ENG_INT_ACTIVE_MASK) { - val |= DMA_ENG_ALLINT_MASK; - nwl_write_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS); - } - - return 0; -} diff --git a/dma/nwl_irq.h b/dma/nwl_irq.h deleted file mode 100644 index 811b632..0000000 --- a/dma/nwl_irq.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _PCILIB_NWL_IRQ_H -#define _PCILIB_NWL_IRQ_H - -int dma_nwl_init_irq(nwl_dma_t *ctx, uint32_t val); -int dma_nwl_free_irq(nwl_dma_t *ctx); - -int dma_nwl_enable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma); -int dma_nwl_disable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma); - -#endif /* _PCILIB_NWL_IRQ_H */ diff --git a/dma/nwl_loopback.c b/dma/nwl_loopback.c deleted file mode 100644 index 381a462..0000000 --- a/dma/nwl_loopback.c +++ /dev/null @@ -1,255 +0,0 @@ -#define _BSD_SOURCE -#include -#include -#include -#include -#include - -#include "pci.h" -#include "pcilib.h" -#include "error.h" -#include "tools.h" -#include "nwl_private.h" - -#include "nwl_defines.h" - -#define NWL_BUG_EXTRA_DATA - - -int dma_nwl_start_loopback(nwl_dma_t *ctx, pcilib_dma_direction_t direction, size_t packet_size) { - uint32_t val; - - ctx->loopback_started = 1; - dma_nwl_stop_loopback(ctx); - - val = packet_size; - nwl_write_register(val, ctx, ctx->base_addr, PKT_SIZE_ADDRESS); - - if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) { - switch (direction) { - case PCILIB_DMA_BIDIRECTIONAL: - val = LOOPBACK; - nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS); - break; - case PCILIB_DMA_TO_DEVICE: - return -1; - case PCILIB_DMA_FROM_DEVICE: - val = PKTGENR; - nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS); - break; - } - } - - ctx->loopback_started = 1; - - return 0; -} - -int dma_nwl_stop_loopback(nwl_dma_t *ctx) { - uint32_t val = 0; - - if (!ctx->loopback_started) return 0; - - /* Stop in any case, otherwise we can have problems in benchmark due to - engine initialized in previous run, and benchmark is only actual usage. - Otherwise, we should detect current loopback status during initialization */ - - if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) { - nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS); - nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS); - } - - ctx->loopback_started = 0; - - return 0; -} - -double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction) { - int iter, i; - int err; - size_t bytes, rbytes; - uint32_t *buf, *cmp; - const char *error = NULL; - size_t packet_size, blocks; - - size_t us = 0; - struct timeval start, cur; - - nwl_dma_t *ctx = (nwl_dma_t*)vctx; - - pcilib_dma_engine_t readid = pcilib_find_dma_by_addr(ctx->pcilib, PCILIB_DMA_FROM_DEVICE, dma); - pcilib_dma_engine_t writeid = pcilib_find_dma_by_addr(ctx->pcilib, PCILIB_DMA_TO_DEVICE, dma); - - if (size%sizeof(uint32_t)) size = 1 + size / sizeof(uint32_t); - else size /= sizeof(uint32_t); - - // Not supported - if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) { - if (direction == PCILIB_DMA_TO_DEVICE) return -1.; - } -// else if ((direction == PCILIB_DMA_FROM_DEVICE)&&(ctx->type != PCILIB_DMA_MODIFICATION_DEFAULT)) return -1.; - - // Stop Generators and drain old data - if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) dma_nwl_stop_loopback(ctx); -// dma_nwl_stop_engine(ctx, readid); // DS: replace with something better - - __sync_synchronize(); - - err = pcilib_skip_dma(ctx->pcilib, readid); - if (err) { - pcilib_error("Can't start benchmark, devices continuously writes unexpected data using DMA engine"); - return -1; - } - -#ifdef NWL_GENERATE_DMA_IRQ - dma_nwl_enable_engine_irq(ctx, readid); - dma_nwl_enable_engine_irq(ctx, writeid); -#endif /* NWL_GENERATE_DMA_IRQ */ - - if (size * sizeof(uint32_t) > NWL_MAX_PACKET_SIZE) { - packet_size = NWL_MAX_PACKET_SIZE; - blocks = (size * sizeof(uint32_t)) / packet_size + (((size*sizeof(uint32_t))%packet_size)?1:0); - } else { - packet_size = size * sizeof(uint32_t); - blocks = 1; - } - - dma_nwl_start_loopback(ctx, direction, packet_size); - - // Allocate memory and prepare data - buf = malloc(blocks * packet_size * sizeof(uint32_t)); - cmp = malloc(blocks * packet_size * sizeof(uint32_t)); - if ((!buf)||(!cmp)) { - if (buf) free(buf); - if (cmp) free(cmp); - return -1; - } - - if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) { - pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e5); - usleep(100000); - pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e1); - - // This way causes more problems with garbage - //pcilib_write_register(ctx->pcilib, NULL, "control", 0x3e1); - } - - // Benchmark - for (iter = 0; iter < iterations; iter++) { - memset(cmp, 0x13 + iter, size * sizeof(uint32_t)); - - if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) { - pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e1); - } - - if ((direction&PCILIB_DMA_TO_DEVICE)||(ctx->type != PCILIB_DMA_MODIFICATION_DEFAULT)) { - memcpy(buf, cmp, size * sizeof(uint32_t)); - - if (direction&PCILIB_DMA_TO_DEVICE) { - gettimeofday(&start, NULL); - } - - err = pcilib_write_dma(ctx->pcilib, writeid, addr, size * sizeof(uint32_t), buf, &bytes); - if ((err)||(bytes != size * sizeof(uint32_t))) { - error = "Write failed"; - break; - } - - if (direction&PCILIB_DMA_TO_DEVICE) { - // wait written - if (direction == PCILIB_DMA_TO_DEVICE) { - dma_nwl_wait_completion(ctx, writeid, PCILIB_DMA_TIMEOUT); - } - gettimeofday(&cur, NULL); - us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)); - } - } - - if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) { - pcilib_write_register(ctx->pcilib, NULL, "control", 0x3e1); - } - - memset(buf, 0, size * sizeof(uint32_t)); - - if (direction&PCILIB_DMA_FROM_DEVICE) { - gettimeofday(&start, NULL); - } - - for (i = 0, bytes = 0; i < blocks; i++) { -#ifdef NWL_BUG_EXTRA_DATA - retry: -#endif - - err = pcilib_read_dma(ctx->pcilib, readid, addr, packet_size * sizeof(uint32_t), buf + (bytes>>2), &rbytes); - if ((err)||(rbytes%sizeof(uint32_t))) { - break; - } -#ifdef NWL_BUG_EXTRA_DATA - else if (rbytes == 8) { - goto retry; - } -#endif - bytes += rbytes; - } - - if (direction&PCILIB_DMA_FROM_DEVICE) { - gettimeofday(&cur, NULL); - us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)); - } -#ifdef NWL_BUG_EXTRA_DATA - if ((err)||((bytes != size * sizeof(uint32_t))&&((bytes - 8) != size * sizeof(uint32_t)))) { -#else - if ((err)||(bytes != size * sizeof(uint32_t))) { -#endif - printf("Expected: %zu bytes, but %zu read, error: %i\n", size * sizeof(uint32_t), bytes, err); - error = "Read failed"; - break; - } - -#ifndef NWL_BUG_EXTRA_DATA - if (direction == PCILIB_DMA_BIDIRECTIONAL) { - if (memcmp(buf, cmp, size * sizeof(uint32_t))) { - for (i = 0; i < size; i++) - if (buf[i] != cmp[i]) break; - - bytes = i; - printf("Expected: *0x%lx, Written at dword %lu:", 0x13 + iter, bytes); - for (; (i < size)&&(i < (bytes + 16)); i++) { - if (((i - bytes)%8)==0) printf("\n"); - printf("% 10lx", buf[i]); - } - printf("\n"); - - error = "Written and read values does not match"; - break; - } - } -#endif - } - - if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) { - pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e1); - } - - if (error) { - pcilib_warning("%s at iteration %i, error: %i, bytes: %zu", error, iter, err, bytes); - } - -#ifdef NWL_GENERATE_DMA_IRQ - dma_nwl_disable_engine_irq(ctx, writeid); - dma_nwl_disable_engine_irq(ctx, readid); -#endif /* NWL_GENERATE_DMA_IRQ */ - - dma_nwl_stop_loopback(ctx); - - __sync_synchronize(); - - if (direction == PCILIB_DMA_FROM_DEVICE) { - pcilib_skip_dma(ctx->pcilib, readid); - } - - free(cmp); - free(buf); - - return /*error?-1:*/(1. * size * sizeof(uint32_t) * iterations * 1000000) / (1024. * 1024. * us); -} diff --git a/dma/nwl_loopback.h b/dma/nwl_loopback.h deleted file mode 100644 index 63c8446..0000000 --- a/dma/nwl_loopback.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _PCILIB_NWL_LOOPBACK_H -#define _PCILIB_NWL_LOOPBACK_H - -int dma_nwl_start_loopback(nwl_dma_t *ctx, pcilib_dma_direction_t direction, size_t packet_size); -int dma_nwl_stop_loopback(nwl_dma_t *ctx); - -#endif /* _PCILIB_NWL_LOOPBACK_H */ diff --git a/dma/nwl_private.h b/dma/nwl_private.h deleted file mode 100644 index 756e6ca..0000000 --- a/dma/nwl_private.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef _PCILIB_DMA_NWL_PRIVATE_H -#define _PCILIB_DMA_NWL_PRIVATE_H - -typedef struct nwl_dma_s nwl_dma_t; -typedef struct pcilib_nwl_engine_description_s pcilib_nwl_engine_description_t; - -#define NWL_DMA_IRQ_SOURCE 0 - -#define NWL_XAUI_ENGINE 0 -#define NWL_XRAWDATA_ENGINE 1 -#define NWL_MAX_PACKET_SIZE 4096 //16384 -//#define NWL_GENERATE_DMA_IRQ - -#define PCILIB_NWL_ALIGNMENT 64 // in bytes -#define PCILIB_NWL_DMA_DESCRIPTOR_SIZE 64 // in bytes -#define PCILIB_NWL_DMA_PAGES 256 // 1024 - -//#define DEBUG_HARDWARE -//#define DEBUG_NWL - -#include "nwl.h" -#include "nwl_irq.h" -#include "nwl_register.h" -#include "nwl_engine.h" -#include "nwl_loopback.h" - -#define nwl_read_register(var, ctx, base, reg) pcilib_datacpy(&var, base + reg, 4, 1, ctx->dma_bank->raw_endianess) -#define nwl_write_register(var, ctx, base, reg) pcilib_datacpy(base + reg, &var, 4, 1, ctx->dma_bank->raw_endianess) - -struct pcilib_nwl_engine_description_s { - pcilib_dma_engine_description_t desc; - char *base_addr; - - size_t ring_size, page_size; - size_t head, tail; - pcilib_kmem_handle_t *ring; - pcilib_kmem_handle_t *pages; - - int started; /**< indicates that DMA buffers are initialized and reading is allowed */ - int writting; /**< indicates that we are in middle of writting packet */ - int reused; /**< indicates that DMA was found intialized, buffers were reused, and no additional initialization is needed */ - int preserve; /**< indicates that DMA should not be stopped during clean-up */ -}; - - -struct nwl_dma_s { - struct pcilib_dma_context_s dmactx; - - pcilib_t *pcilib; - - pcilib_dma_modification_t type; - - pcilib_register_bank_description_t *dma_bank; - char *base_addr; - - pcilib_irq_type_t irq_enabled; /**< indicates that IRQs are enabled */ - pcilib_irq_type_t irq_preserve; /**< indicates that IRQs should not be disabled during clean-up */ - int started; /**< indicates that DMA subsystem is initialized and DMA engine can start */ - int irq_started; /**< indicates that IRQ subsystem is initialized (detecting which types should be preserverd) */ - int loopback_started; /**< indicates that benchmarking subsystem is initialized */ - - pcilib_dma_engine_t n_engines; - pcilib_nwl_engine_description_t engines[PCILIB_MAX_DMA_ENGINES + 1]; -}; - - -#endif /* _PCILIB_DMA_NWL_PRIVATE_H */ diff --git a/dma/nwl_register.c b/dma/nwl_register.c deleted file mode 100644 index 6a3771a..0000000 --- a/dma/nwl_register.c +++ /dev/null @@ -1,77 +0,0 @@ -#define _PCILIB_NWL_REGISTER_C - -#include -#include -#include -#include -#include - -#include "pcilib.h" - -#include "pci.h" -#include "error.h" -#include "tools.h" - -#include "nwl_private.h" -#include "nwl_register.h" - -int nwl_add_registers(nwl_dma_t *ctx) { - int err; - size_t n, i, j; - int length; - const char *names[NWL_MAX_DMA_ENGINE_REGISTERS]; - uintptr_t addr[NWL_MAX_DMA_ENGINE_REGISTERS]; - - // We don't want DMA registers - if (pcilib_find_bank_by_addr(ctx->pcilib, PCILIB_REGISTER_BANK_DMA) == PCILIB_REGISTER_BANK_INVALID) return 0; - - err = pcilib_add_registers(ctx->pcilib, 0, nwl_dma_registers); - if (err) return err; - - if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) { - err = pcilib_add_registers(ctx->pcilib, 0, nwl_xrawdata_registers); - if (err) return err; - } - - - for (n = 0; nwl_dma_engine_registers[n].bits; n++) { - names[n] = nwl_dma_engine_registers[n].name; - addr[n] = nwl_dma_engine_registers[n].addr; - } - - if (ctx->n_engines > 9) length = 2; - else length = 1; - - - for (i = 0; i < ctx->n_engines; i++) { - for (j = 0; nwl_dma_engine_registers[j].bits; j++) { - const char *direction; - nwl_dma_engine_registers[j].name = nwl_dma_engine_register_names[i * NWL_MAX_DMA_ENGINE_REGISTERS + j]; - nwl_dma_engine_registers[j].addr = addr[j] + (ctx->engines[i].base_addr - ctx->base_addr); -// printf("%lx %lx\n", (ctx->engines[i].base_addr - ctx->base_addr), nwl_dma_engine_registers[j].addr); - - switch (ctx->engines[i].desc.direction) { - case PCILIB_DMA_FROM_DEVICE: - direction = "r"; - break; - case PCILIB_DMA_TO_DEVICE: - direction = "w"; - break; - default: - direction = ""; - } - - sprintf((char*)nwl_dma_engine_registers[j].name, names[j], length, ctx->engines[i].desc.addr, direction); - } - - err = pcilib_add_registers(ctx->pcilib, n, nwl_dma_engine_registers); - if (err) return err; - } - - for (n = 0; nwl_dma_engine_registers[n].bits; n++) { - nwl_dma_engine_registers[n].name = names[n]; - nwl_dma_engine_registers[n].addr = addr[n]; - } - - return 0; -} diff --git a/dma/nwl_register.h b/dma/nwl_register.h deleted file mode 100644 index a71942b..0000000 --- a/dma/nwl_register.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef _PCILIB_NWL_REGISTERS_H -#define _PCILIB_NWL_REGISTERS_H - -#ifdef _PCILIB_NWL_REGISTER_C - // DMA -static pcilib_register_description_t nwl_dma_registers[] = { - {0x4000, 0, 32, 0, 0x00000011, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_control_and_status", ""}, - {0x4000, 0, 1, 0, 0x00000011, PCILIB_REGISTER_RW , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_interrupt_enable", ""}, - {0x4000, 1, 1, 0, 0x00000011, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_interrupt_active", ""}, - {0x4000, 2, 1, 0, 0x00000011, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_interrupt_pending", ""}, - {0x4000, 3, 1, 0, 0x00000011, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_interrupt_mode", ""}, - {0x4000, 4, 1, 0, 0x00000011, PCILIB_REGISTER_RW , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_user_interrupt_enable", ""}, - {0x4000, 5, 1, 0, 0x00000011, PCILIB_REGISTER_RW1C, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_user_interrupt_active", ""}, - {0x4000, 16, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_s2c_interrupt_status", ""}, - {0x4000, 24, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_c2s_interrupt_status", ""}, - {0x8000, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_design_version", ""}, - {0x8000, 0, 4, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_subversion_number", ""}, - {0x8000, 4, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_version_number", ""}, - {0x8000, 28, 4, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_targeted_device", ""}, - {0x8200, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_transmit_utilization", ""}, - {0x8200, 0, 2, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_transmit_sample_count", ""}, - {0x8200, 2, 30, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_transmit_dword_count", ""}, - {0x8204, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_receive_utilization", ""}, - {0x8004, 0, 2, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_receive_sample_count", ""}, - {0x8004, 2, 30, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_receive_dword_count", ""}, - {0x8208, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_mwr", ""}, - {0x8008, 0, 2, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_mwr_sample_count", ""}, - {0x8008, 2, 30, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_mwr_dword_count", ""}, - {0x820C, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_cpld", ""}, - {0x820C, 0, 2, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_cpld_sample_count", ""}, - {0x820C, 2, 30, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_cpld_dword_count", ""}, - {0x8210, 0, 12, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_init_fc_cpld", ""}, - {0x8214, 0, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_init_fc_cplh", ""}, - {0x8218, 0, 12, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_init_fc_npd", ""}, - {0x821C, 0, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_init_fc_nph", ""}, - {0x8220, 0, 12, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_init_fc_pd", ""}, - {0x8224, 0, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_init_fc_ph", ""}, - {0, 0, 0, 0, 0x00000000, 0, 0, 0, NULL, NULL} -}; - - // DMA Engine Registers -#define NWL_MAX_DMA_ENGINE_REGISTERS 64 -#define NWL_MAX_REGISTER_NAME 128 -static char nwl_dma_engine_register_names[PCILIB_MAX_DMA_ENGINES * NWL_MAX_DMA_ENGINE_REGISTERS][NWL_MAX_REGISTER_NAME]; -static pcilib_register_description_t nwl_dma_engine_registers[] = { - {0x0000, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_engine_capabilities", ""}, - {0x0000, 0, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_present", ""}, - {0x0000, 1, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_direction", ""}, - {0x0000, 4, 2, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_type", ""}, - {0x0000, 8, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_number", ""}, - {0x0000, 24, 6, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_max_buffer_size", ""}, - {0x0004, 0, 32, 0, 0x0000C100, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_engine_control", ""}, - {0x0004, 0, 1, 0, 0x0000C100, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_interrupt_enable", ""}, - {0x0004, 1, 1, 0, 0x0000C100, PCILIB_REGISTER_RW1C, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_interrupt_active", ""}, - {0x0004, 2, 1, 0, 0x0000C100, PCILIB_REGISTER_RW1C, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_descriptor_complete", ""}, - {0x0004, 3, 1, 0, 0x0000C100, PCILIB_REGISTER_RW1C, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_descriptor_alignment_error", ""}, - {0x0004, 4, 1, 0, 0x0000C100, PCILIB_REGISTER_RW1C, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_descriptor_fetch_error", ""}, - {0x0004, 5, 1, 0, 0x0000C100, PCILIB_REGISTER_RW1C, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_sw_abort_error", ""}, - {0x0004, 8, 1, 0, 0x0000C100, PCILIB_REGISTER_RW , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_enable", ""}, - {0x0004, 10, 1, 0, 0x0000C100, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_running", ""}, - {0x0004, 11, 1, 0, 0x0000C100, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_waiting", ""}, - {0x0004, 14, 1, 0, 0x0000C100, PCILIB_REGISTER_RW , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_reset_request", ""}, - {0x0004, 15, 1, 0, 0x0000C100, PCILIB_REGISTER_W , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_reset", ""}, - {0x0008, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_next_descriptor", ""}, - {0x000C, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_sw_descriptor", ""}, - {0x0010, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_last_descriptor", ""}, - {0x0014, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_active_time", ""}, - {0x0018, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_wait_time", ""}, - {0x001C, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_counter", ""}, - {0x001C, 0, 2, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_sample_count", ""}, - {0x001C, 2, 30, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_dword_count", ""}, - {0, 0, 0, 0, 0x00000000, 0, 0, 0, NULL, NULL} -}; - -/* - // XAUI registers -static pcilib_register_description_t nwl_xaui_registers[] = { - {0, 0, 0, 0, 0, 0, 0, NULL, NULL} -}; -*/ - - // XRAWDATA registers -static pcilib_register_description_t nwl_xrawdata_registers[] = { - {0x9100, 0, 1, 0, 0x00000000, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "xrawdata_enable_generator", ""}, - {0x9104, 0, 16, 0, 0x00000000, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "xrawdata_packet_length", ""}, - {0x9108, 0, 2, 0, 0x00000003, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "xrawdata_control", ""}, - {0x9108, 0, 1, 0, 0x00000003, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "xrawdata_enable_checker", ""}, - {0x9108, 1, 1, 0, 0x00000003, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "xrawdata_enable_loopback", ""}, - {0x910C, 0, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "xrawdata_data_mistmatch", ""}, - {0, 0, 0, 0, 0x00000000, 0, 0, 0, NULL, NULL} -}; - -#endif /* _PCILIB_NWL_REGISTERS_C */ - -int nwl_add_registers(nwl_dma_t *ctx); - -#endif /* _PCILIB_NWL_REGISTERS_H */ diff --git a/driver/Makefile b/driver/Makefile deleted file mode 100644 index e353228..0000000 --- a/driver/Makefile +++ /dev/null @@ -1,49 +0,0 @@ - -obj-m := pciDriver.o -pciDriver-objs := base.o int.o umem.o kmem.o sysfs.o ioctl.o - -KERNELDIR ?= /lib/modules/$(shell uname -r)/build -INSTALLDIR ?= /lib/modules/$(shell uname -r)/extra -PWD := $(shell pwd) - -EXTRA_CFLAGS += -I$(M)/.. - -default: - @KERNEL_GCC_VERSION=`cat /proc/version | head -n1 | cut -d " " -f 7` ;\ - GCC_VERSION=`$(CC) --version | head -n 1 | tr ' ' '\n' | grep -e "[0-9]\+\.[0-9]" | tail -n 1` ;\ - if [ $$KERNEL_GCC_VERSION != $$GCC_VERSION ]; then \ - echo "Kernel is compiled with gcc $$KERNEL_GCC_VERSION, but you are now using $$GCC_VERSION" ;\ - GCC_MAJOR=`echo $$KERNEL_GCC_VERSION | cut -d "." -f 1-2` ;\ - newCC=gcc-$$GCC_MAJOR ;\ - CC=`which $$newCC 2>/dev/null` ;\ - if [ $$? -ne 0 ]; then \ - echo "No compiler of $$GCC_MAJOR series is installed" ;\ - exit 1 ;\ - fi ;\ - GCC_VERSION=`$$CC --version | head -n 1 | tr ' ' '\n' | grep -e "[0-9]\+\.[0-9]" | head -n 1` ;\ - if [ $$KERNEL_GCC_VERSION != $$GCC_VERSION ]; then \ - echo "The $$GCC_VERSION of $$GCC_MAJOR series is installed" ;\ - exit 1 ;\ - fi ;\ - echo "Setting CC to $$newCC" ;\ - else \ - CC=$(CC) ;\ - fi ;\ - $(MAKE) $(CFLAGS) -C $(KERNELDIR) M=$(PWD) CC=$$CC modules - -install: - @mkdir -p $(INSTALLDIR) - @echo "INSTALL $(INSTALLDIR)/pciDriver.ko" - @install -m 755 pciDriver.ko $(INSTALLDIR) - @echo "INSTALL /usr/include/pciDriver/driver/pciDriver.h" - @mkdir -p /usr/include/pciDriver/driver - @install -m 644 pciDriver.h /usr/include/pciDriver/driver - -uninstall: - @echo "UNINSTALL $(INSTALLDIR)/pciDriver.ko" - @rm -f $(INSTALLDIR)/pciDriver.ko - @echo "UNINSTALL /usr/include/pciDriver/driver/pciDriver.h" - @rm -rf /usr/include/pciDriver/driver - -clean: - rm -rf *.o *.ko *.mod.c .*.o.cmd .*.o.tmp .*.ko.cmd .*.o *.symvers modules.order .tmp_versions diff --git a/driver/base.c b/driver/base.c deleted file mode 100644 index 974224d..0000000 --- a/driver/base.c +++ /dev/null @@ -1,676 +0,0 @@ -/** - * - * @file base.c - * @author Guillermo Marcus - * @date 2009-04-05 - * @brief Contains the main code which connects all the different parts and does - * basic driver tasks like initialization. - * - * This is a full rewrite of the pciDriver. - * New default is to support kernel 2.6, using kernel 2.6 APIs. - * - */ - -/* - * Change History: - * - * $Log: not supported by cvs2svn $ - * Revision 1.13 2008-05-30 11:38:15 marcus - * Added patches for kernel 2.6.24 - * - * Revision 1.12 2008-01-24 14:21:36 marcus - * Added a CLEAR_INTERRUPT_QUEUE ioctl. - * Added a sysfs attribute to show the outstanding IRQ queues. - * - * Revision 1.11 2008-01-24 12:53:11 marcus - * Corrected wait_event condition in waiti_ioctl. Improved the loop too. - * - * Revision 1.10 2008-01-14 10:39:39 marcus - * Set some messages as debug instead of normal. - * - * Revision 1.9 2008-01-11 10:18:28 marcus - * Modified interrupt mechanism. Added atomic functions and queues, to address race conditions. Removed unused interrupt code. - * - * Revision 1.8 2007-07-17 13:15:55 marcus - * Removed Tasklets. - * Using newest map for the ABB interrupts. - * - * Revision 1.7 2007-07-06 15:56:04 marcus - * Change default status for OLD_REGISTERS to not defined. - * - * Revision 1.6 2007-07-05 15:29:59 marcus - * Corrected issue with the bar mapping for interrupt handling. - * Added support up to kernel 2.6.20 - * - * Revision 1.5 2007-05-29 07:50:18 marcus - * Split code into 2 files. May get merged in the future again.... - * - * Revision 1.4 2007/03/01 17:47:34 marcus - * Fixed bug when the kernel memory was less than one page, it was not locked properly, recalling an old mapping issue in this case. - * - * Revision 1.3 2007/03/01 17:01:22 marcus - * comment fix (again). - * - * Revision 1.2 2007/03/01 17:00:25 marcus - * Changed some comment in the log. - * - * Revision 1.1 2007/03/01 16:57:43 marcus - * Divided driver file to ease the interrupt hooks for the user of the driver. - * Modified Makefile accordingly. - * - * From pciDriver.c: - * Revision 1.11 2006/12/11 16:15:43 marcus - * Fixed kernel buffer mmapping, and driver crash when application crashes. - * Buffer memory is now marked reserved during allocation, and mmaped with - * remap_xx_range. - * - * Revision 1.10 2006/11/21 09:50:49 marcus - * Added PROGRAPE4 vendor/device IDs. - * - * Revision 1.9 2006/11/17 18:47:36 marcus - * Removed MERGE_SGENTRIES flag, now it is selected at runtime with 'type'. - * Removed noncached in non-prefetchable areas, to allow the use of MTRRs. - * - * Revision 1.8 2006/11/17 16:41:21 marcus - * Added slot number to the PCI info IOctl. - * - * Revision 1.7 2006/11/13 12:30:34 marcus - * Added a IOctl call, to confiure the interrupt response. (testing pending). - * Basic interrupts are now supported, using a Tasklet and Completions. - * - * Revision 1.6 2006/11/08 21:30:02 marcus - * Added changes after compile tests in kernel 2.6.16 - * - * Revision 1.5 2006/10/31 07:57:38 marcus - * Improved the pfn calculation in nopage(), to deal with some possible border - * conditions. It was really no issue, because they are normally page-aligned - * anyway, but to be on the safe side. - * - * Revision 1.4 2006/10/30 19:37:40 marcus - * Solved bug on kernel memory not mapping properly. - * - * Revision 1.3 2006/10/18 11:19:20 marcus - * Added kernel 2.6.8 support based on comments from Joern Adamczewski (GSI). - * - * Revision 1.2 2006/10/18 11:04:15 marcus - * Bus Master is only activated when we detect a specific board. - * - * Revision 1.1 2006/10/10 14:46:51 marcus - * Initial commit of the new pciDriver for kernel 2.6 - * - * Revision 1.9 2006/10/05 11:30:46 marcus - * Prerelease. Added bus and devfn to pciInfo for compatibility. - * - * Revision 1.8 2006/09/25 16:51:07 marcus - * Added PCI config IOctls, and implemented basic mmap functions. - * - * Revision 1.7 2006/09/20 11:12:41 marcus - * Added Merge SG entries - * - * Revision 1.6 2006/09/19 17:22:18 marcus - * backup commit. - * - * Revision 1.5 2006/09/18 17:13:11 marcus - * backup commit. - * - * Revision 1.4 2006/09/15 15:44:41 marcus - * backup commit. - * - * Revision 1.3 2006/08/15 11:40:02 marcus - * backup commit. - * - * Revision 1.2 2006/08/12 18:28:42 marcus - * Sync with the laptop - * - * Revision 1.1 2006/08/11 15:30:46 marcus - * Sync with the laptop - * - */ - -#include - -/* Check macros and kernel version first */ -#ifndef KERNEL_VERSION -#error "No KERNEL_VERSION macro! Stopping." -#endif - -#ifndef LINUX_VERSION_CODE -#error "No LINUX_VERSION_CODE macro! Stopping." -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) -#error "This driver has been tested only for Kernel 2.6.8 or above." -#endif - -/* Required includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Configuration for the driver (what should be compiled in, module name, etc...) */ -#include "config.h" - -/* Compatibility functions/definitions (provides functions which are not available on older kernels) */ -#include "compat.h" - -/* External interface for the driver */ -#include "pciDriver.h" - -/* Internal definitions for all parts (prototypes, data, macros) */ -#include "common.h" - -/* Internal definitions for the base part */ -#include "base.h" - -/* Internal definitions of the IRQ handling part */ -#include "int.h" - -/* Internal definitions for kernel memory */ -#include "kmem.h" - -/* Internal definitions for user space memory */ -#include "umem.h" - -#include "ioctl.h" - -/*************************************************************************/ -/* Module device table associated with this driver */ -MODULE_DEVICE_TABLE(pci, pcidriver_ids); - -/* Module init and exit points */ -module_init(pcidriver_init); -module_exit(pcidriver_exit); - -/* Module info */ -MODULE_AUTHOR("Guillermo Marcus"); -MODULE_DESCRIPTION("Simple PCI Driver"); -MODULE_LICENSE("GPL v2"); - -/* Module class */ -static struct class_compat *pcidriver_class; - -/** - * - * Called when loading the driver - * - */ -static int __init pcidriver_init(void) -{ - int err; - - /* Initialize the device count */ - atomic_set(&pcidriver_deviceCount, 0); - - /* Allocate character device region dynamically */ - if ((err = alloc_chrdev_region(&pcidriver_devt, MINORNR, MAXDEVICES, NODENAME)) != 0) { - mod_info("Couldn't allocate chrdev region. Module not loaded.\n"); - goto init_alloc_fail; - } - mod_info("Major %d allocated to nodename '%s'\n", MAJOR(pcidriver_devt), NODENAME); - - /* Register driver class */ - pcidriver_class = class_create(THIS_MODULE, NODENAME); - - if (IS_ERR(pcidriver_class)) { - mod_info("No sysfs support. Module not loaded.\n"); - goto init_class_fail; - } - - /* Register PCI driver. This function returns the number of devices on some - * systems, therefore check for errors as < 0. */ - if ((err = pci_register_driver(&pcidriver_driver)) < 0) { - mod_info("Couldn't register PCI driver. Module not loaded.\n"); - goto init_pcireg_fail; - } - - mod_info("Module loaded\n"); - - return 0; - -init_pcireg_fail: - class_destroy(pcidriver_class); -init_class_fail: - unregister_chrdev_region(pcidriver_devt, MAXDEVICES); -init_alloc_fail: - return err; -} - -/** - * - * Called when unloading the driver - * - */ -static void pcidriver_exit(void) -{ - pci_unregister_driver(&pcidriver_driver); - unregister_chrdev_region(pcidriver_devt, MAXDEVICES); - - if (pcidriver_class != NULL) - class_destroy(pcidriver_class); - - mod_info("Module unloaded\n"); -} - -/*************************************************************************/ -/* Driver functions */ - -/** - * - * This struct defines the PCI entry points. - * Will be registered at module init. - * - */ -static struct pci_driver pcidriver_driver = { - .name = MODNAME, - .id_table = pcidriver_ids, - .probe = pcidriver_probe, - .remove = pcidriver_remove, -}; - -/** - * - * This function is called when installing the driver for a device - * @param pdev Pointer to the PCI device - * - */ -static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - int err; - int devno; - pcidriver_privdata_t *privdata; - int devid; - - /* At the moment there is no difference between these boards here, other than - * printing a different message in the log. - * - * However, there is some difference in the interrupt handling functions. - */ - if (id->vendor == PCIE_XILINX_VENDOR_ID) { - if (id->device == PCIE_ML605_DEVICE_ID) { - mod_info("Found ML605 board at %s\n", dev_name(&pdev->dev)); - } else if (id->device == PCIE_IPECAMERA_DEVICE_ID) { - mod_info("Found IPE Camera at %s\n", dev_name(&pdev->dev)); - } else if (id->device == PCIE_KAPTURE_DEVICE_ID) { - mod_info("Found KAPTURE board at %s\n", dev_name(&pdev->dev)); - } else { - mod_info("Found unknown Xilinx device (%x) at %s\n", id->device, dev_name(&pdev->dev)); - } - } else { - /* It is something else */ - mod_info( "Found unknown board (%x:%x) at %s\n", id->vendor, id->device, dev_name(&pdev->dev)); - } - - /* Enable the device */ - if ((err = pci_enable_device(pdev)) != 0) { - mod_info("Couldn't enable device\n"); - goto probe_pcien_fail; - } - - /* Bus master & dma */ - if ((id->vendor == PCIE_XILINX_VENDOR_ID)&&(id->device == PCIE_IPECAMERA_DEVICE_ID)) { - pci_set_master(pdev); - - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (err < 0) { - printk(KERN_ERR "pci_set_dma_mask failed\n"); - goto probe_dma_fail; - } - } - - /* Set Memory-Write-Invalidate support */ - if ((err = pci_set_mwi(pdev)) != 0) - mod_info("MWI not supported. Continue without enabling MWI.\n"); - - /* Get / Increment the device id */ - devid = atomic_inc_return(&pcidriver_deviceCount) - 1; - if (devid >= MAXDEVICES) { - mod_info("Maximum number of devices reached! Increase MAXDEVICES.\n"); - err = -ENOMSG; - goto probe_maxdevices_fail; - } - - /* Allocate and initialize the private data for this device */ - if ((privdata = kcalloc(1, sizeof(*privdata), GFP_KERNEL)) == NULL) { - err = -ENOMEM; - goto probe_nomem; - } - - INIT_LIST_HEAD(&(privdata->kmem_list)); - spin_lock_init(&(privdata->kmemlist_lock)); - atomic_set(&privdata->kmem_count, 0); - - INIT_LIST_HEAD(&(privdata->umem_list)); - spin_lock_init(&(privdata->umemlist_lock)); - atomic_set(&privdata->umem_count, 0); - - pci_set_drvdata( pdev, privdata ); - privdata->pdev = pdev; - - /* Device add to sysfs */ - devno = MKDEV(MAJOR(pcidriver_devt), MINOR(pcidriver_devt) + devid); - privdata->devno = devno; - if (pcidriver_class != NULL) { - /* FIXME: some error checking missing here */ - privdata->class_dev = class_device_create(pcidriver_class, NULL, devno, &(pdev->dev), NODENAMEFMT, MINOR(pcidriver_devt) + devid, privdata); - class_set_devdata( privdata->class_dev, privdata ); - mod_info("Device /dev/%s%d added\n",NODENAME,MINOR(pcidriver_devt) + devid); - } - - /* Setup mmaped BARs into kernel space */ - if ((err = pcidriver_probe_irq(privdata)) != 0) - goto probe_irq_probe_fail; - - /* Populate sysfs attributes for the class device */ - /* TODO: correct errorhandling. ewww. must remove the files in reversed order :-( */ - #define sysfs_attr(name) do { \ - if (class_device_create_file(sysfs_attr_def_pointer, &sysfs_attr_def_name(name)) != 0) \ - goto probe_device_create_fail; \ - } while (0) - #ifdef ENABLE_IRQ - sysfs_attr(irq_count); - sysfs_attr(irq_queues); - #endif - - sysfs_attr(mmap_mode); - sysfs_attr(mmap_area); - sysfs_attr(kmem_count); - sysfs_attr(kmem_alloc); - sysfs_attr(kmem_free); - sysfs_attr(kbuffers); - sysfs_attr(umappings); - sysfs_attr(umem_unmap); - #undef sysfs_attr - - /* Register character device */ - cdev_init( &(privdata->cdev), &pcidriver_fops ); - privdata->cdev.owner = THIS_MODULE; - privdata->cdev.ops = &pcidriver_fops; - err = cdev_add( &privdata->cdev, devno, 1 ); - if (err) { - mod_info( "Couldn't add character device.\n" ); - goto probe_cdevadd_fail; - } - - return 0; - -probe_device_create_fail: -probe_cdevadd_fail: -probe_irq_probe_fail: - pcidriver_irq_unmap_bars(privdata); - kfree(privdata); -probe_nomem: - atomic_dec(&pcidriver_deviceCount); -probe_maxdevices_fail: -probe_dma_fail: - pci_disable_device(pdev); -probe_pcien_fail: - return err; -} - -/** - * - * This function is called when disconnecting a device - * - */ -static void __devexit pcidriver_remove(struct pci_dev *pdev) -{ - pcidriver_privdata_t *privdata; - - /* Get private data from the device */ - privdata = pci_get_drvdata(pdev); - - /* Removing sysfs attributes from class device */ - #define sysfs_attr(name) do { \ - class_device_remove_file(sysfs_attr_def_pointer, &sysfs_attr_def_name(name)); \ - } while (0) - #ifdef ENABLE_IRQ - sysfs_attr(irq_count); - sysfs_attr(irq_queues); - #endif - - sysfs_attr(mmap_mode); - sysfs_attr(mmap_area); - sysfs_attr(kmem_count); - sysfs_attr(kmem_alloc); - sysfs_attr(kmem_free); - sysfs_attr(kbuffers); - sysfs_attr(umappings); - sysfs_attr(umem_unmap); - #undef sysfs_attr - - /* Free all allocated kmem buffers before leaving */ - pcidriver_kmem_free_all( privdata ); - -#ifdef ENABLE_IRQ - pcidriver_remove_irq(privdata); -#endif - - /* Removing Character device */ - cdev_del(&(privdata->cdev)); - - /* Removing the device from sysfs */ - class_device_destroy(pcidriver_class, privdata->devno); - - /* Releasing privdata */ - kfree(privdata); - - /* Disabling PCI device */ - pci_disable_device(pdev); - - mod_info("Device at %s removed\n", dev_name(&pdev->dev)); -} - -/*************************************************************************/ -/* File operations */ -/*************************************************************************/ - -/** - * This struct defines the file operation entry points. - * - * @see pcidriver_ioctl - * @see pcidriver_mmap - * @see pcidriver_open - * @see pcidriver_release - * - */ -static struct file_operations pcidriver_fops = { - .owner = THIS_MODULE, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) - .ioctl = pcidriver_ioctl, -#else - .unlocked_ioctl = pcidriver_ioctl, -#endif - .mmap = pcidriver_mmap, - .open = pcidriver_open, - .release = pcidriver_release, -}; - -void pcidriver_module_get(pcidriver_privdata_t *privdata) { - atomic_inc(&(privdata->refs)); -// mod_info("Ref: %i\n", atomic_read(&(privdata->refs))); -} - -void pcidriver_module_put(pcidriver_privdata_t *privdata) { - if (atomic_add_negative(-1, &(privdata->refs))) { - atomic_inc(&(privdata->refs)); - mod_info("Reference counting error..."); - } else { -// mod_info("Unref: %i\n", atomic_read(&(privdata->refs))); - } -} - -/** - * - * Called when an application open()s a /dev/fpga*, attaches the private data - * with the file pointer. - * - */ -int pcidriver_open(struct inode *inode, struct file *filp) -{ - pcidriver_privdata_t *privdata; - - /* Set the private data area for the file */ - privdata = container_of( inode->i_cdev, pcidriver_privdata_t, cdev); - filp->private_data = privdata; - - pcidriver_module_get(privdata); - - return 0; -} - -/** - * - * Called when the application close()s the file descriptor. Does nothing at - * the moment. - * - */ -int pcidriver_release(struct inode *inode, struct file *filp) -{ - pcidriver_privdata_t *privdata; - - /* Get the private data area */ - privdata = filp->private_data; - - pcidriver_module_put(privdata); - - return 0; -} - -/** - * - * This function is the entry point for mmap() and calls either pcidriver_mmap_pci - * or pcidriver_mmap_kmem - * - * @see pcidriver_mmap_pci - * @see pcidriver_mmap_kmem - * - */ -int pcidriver_mmap(struct file *filp, struct vm_area_struct *vma) -{ - pcidriver_privdata_t *privdata; - int ret = 0, bar; - - mod_info_dbg("Entering mmap\n"); - - /* Get the private data area */ - privdata = filp->private_data; - - /* Check the current mmap mode */ - switch (privdata->mmap_mode) { - case PCIDRIVER_MMAP_PCI: - /* Mmap a PCI region */ - switch (privdata->mmap_area) { - case PCIDRIVER_BAR0: bar = 0; break; - case PCIDRIVER_BAR1: bar = 1; break; - case PCIDRIVER_BAR2: bar = 2; break; - case PCIDRIVER_BAR3: bar = 3; break; - case PCIDRIVER_BAR4: bar = 4; break; - case PCIDRIVER_BAR5: bar = 5; break; - default: - mod_info("Attempted to mmap a PCI area with the wrong mmap_area value: %d\n",privdata->mmap_area); - return -EINVAL; /* invalid parameter */ - break; - } - ret = pcidriver_mmap_pci(privdata, vma, bar); - break; - case PCIDRIVER_MMAP_KMEM: - /* mmap a Kernel buffer */ - ret = pcidriver_mmap_kmem(privdata, vma); - break; - default: - mod_info( "Invalid mmap_mode value (%d)\n",privdata->mmap_mode ); - return -EINVAL; /* Invalid parameter (mode) */ - } - - return ret; -} - -/*************************************************************************/ -/* Internal driver functions */ -int pcidriver_mmap_pci(pcidriver_privdata_t *privdata, struct vm_area_struct *vmap, int bar) -{ - int ret = 0; - unsigned long bar_addr; - unsigned long bar_length, vma_size; - unsigned long bar_flags; - - mod_info_dbg("Entering mmap_pci\n"); - - /* Get info of the BAR to be mapped */ - bar_addr = pci_resource_start(privdata->pdev, bar); - bar_length = pci_resource_len(privdata->pdev, bar); - bar_flags = pci_resource_flags(privdata->pdev, bar); - - /* Check sizes */ - vma_size = (vmap->vm_end - vmap->vm_start); - - if ((vma_size != bar_length) && - ((bar_length < PAGE_SIZE) && (vma_size != PAGE_SIZE))) { - mod_info( "mmap size is not correct! bar: %lu - vma: %lu\n", bar_length, vma_size ); - return -EINVAL; - } - - if (bar_flags & IORESOURCE_IO) { - /* Unlikely case, we will mmap a IO region */ - - /* IO regions are never cacheable */ -#ifdef pgprot_noncached - vmap->vm_page_prot = pgprot_noncached(vmap->vm_page_prot); -#endif - - /* Map the BAR */ - ret = io_remap_pfn_range_compat( - vmap, - vmap->vm_start, - bar_addr, - bar_length, - vmap->vm_page_prot); - } else { - /* Normal case, mmap a memory region */ - - /* Ensure this VMA is non-cached, if it is not flaged as prefetchable. - * If it is prefetchable, caching is allowed and will give better performance. - * This should be set properly by the BIOS, but we want to be sure. */ - /* adapted from drivers/char/mem.c, mmap function. */ -#ifdef pgprot_noncached -/* Setting noncached disables MTRR registers, and we want to use them. - * So we take this code out. This can lead to caching problems if and only if - * the System BIOS set something wrong. Check LDDv3, page 425. - */ -// if (!(bar_flags & IORESOURCE_PREFETCH)) -// vmap->vm_page_prot = pgprot_noncached(vmap->vm_page_prot); -#endif - - /* Map the BAR */ - ret = remap_pfn_range_compat( - vmap, - vmap->vm_start, - bar_addr, - bar_length, - vmap->vm_page_prot); - } - - if (ret) { - mod_info("remap_pfn_range failed\n"); - return -EAGAIN; - } - - return 0; /* success */ -} diff --git a/driver/base.h b/driver/base.h deleted file mode 100644 index 9384e2d..0000000 --- a/driver/base.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef _PCIDRIVER_BASE_H -#define _PCIDRIVER_BASE_H - -#include "sysfs.h" - -/** - * - * This file contains prototypes and data structures for internal use of the pciDriver. - * - * - */ - -/* prototypes for file_operations */ -static struct file_operations pcidriver_fops; -int pcidriver_mmap( struct file *filp, struct vm_area_struct *vmap ); -int pcidriver_open(struct inode *inode, struct file *filp ); -int pcidriver_release(struct inode *inode, struct file *filp); - -/* prototypes for device operations */ -static struct pci_driver pcidriver_driver; -static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_device_id *id); -static void __devexit pcidriver_remove(struct pci_dev *pdev); - - - -/* prototypes for module operations */ -static int __init pcidriver_init(void); -static void pcidriver_exit(void); - -/* - * This is the table of PCI devices handled by this driver by default - * If you want to add devices dynamically to this list, do: - * - * echo "vendor device" > /sys/bus/pci/drivers/pciDriver/new_id - * where vendor and device are in hex, without leading '0x'. - * - * The IDs themselves can be found in common.h - * - * For more info, see /Documentation/pci.txt - * - * __devinitdata is applied because the kernel does not need those - * tables any more after boot is finished on systems which don't - * support hotplug. - * - */ - -static const __devinitdata struct pci_device_id pcidriver_ids[] = { - { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_ML605_DEVICE_ID ) }, // PCI-E Xilinx ML605 - { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_IPECAMERA_DEVICE_ID ) }, // PCI-E IPE Camera - { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_KAPTURE_DEVICE_ID ) }, // PCI-E KAPTURE board for HEB - {0,0,0,0}, -}; - -/* prototypes for internal driver functions */ -int pcidriver_pci_read( pcidriver_privdata_t *privdata, pci_cfg_cmd *pci_cmd ); -int pcidriver_pci_write( pcidriver_privdata_t *privdata, pci_cfg_cmd *pci_cmd ); -int pcidriver_pci_info( pcidriver_privdata_t *privdata, pcilib_board_info_t *pci_info ); - -int pcidriver_mmap_pci( pcidriver_privdata_t *privdata, struct vm_area_struct *vmap , int bar ); -int pcidriver_mmap_kmem( pcidriver_privdata_t *privdata, struct vm_area_struct *vmap ); - -/*************************************************************************/ -/* Static data */ -/* Hold the allocated major & minor numbers */ -static dev_t pcidriver_devt; - -/* Number of devices allocated */ -static atomic_t pcidriver_deviceCount; - -/* Sysfs attributes */ -static DEVICE_ATTR(mmap_mode, (S_IRUGO | S_IWUGO), pcidriver_show_mmap_mode, pcidriver_store_mmap_mode); -static DEVICE_ATTR(mmap_area, (S_IRUGO | S_IWUGO), pcidriver_show_mmap_area, pcidriver_store_mmap_area); -static DEVICE_ATTR(kmem_count, S_IRUGO, pcidriver_show_kmem_count, NULL); -static DEVICE_ATTR(kbuffers, S_IRUGO, pcidriver_show_kbuffers, NULL); -static DEVICE_ATTR(kmem_alloc, S_IWUGO, NULL, pcidriver_store_kmem_alloc); -static DEVICE_ATTR(kmem_free, S_IWUGO, NULL, pcidriver_store_kmem_free); -static DEVICE_ATTR(umappings, S_IRUGO, pcidriver_show_umappings, NULL); -static DEVICE_ATTR(umem_unmap, S_IWUGO, NULL, pcidriver_store_umem_unmap); - -#ifdef ENABLE_IRQ -static DEVICE_ATTR(irq_count, S_IRUGO, pcidriver_show_irq_count, NULL); -static DEVICE_ATTR(irq_queues, S_IRUGO, pcidriver_show_irq_queues, NULL); -#endif - -#endif diff --git a/driver/common.h b/driver/common.h deleted file mode 100644 index eba56d7..0000000 --- a/driver/common.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef _PCIDRIVER_COMMON_H -#define _PCIDRIVER_COMMON_H - -#include "pcilib_types.h" - -/*************************************************************************/ -/* Private data types and structures */ - - -/* Define an entry in the kmem list (this list is per device) */ -/* This list keeps references to the allocated kernel buffers */ -typedef struct { - int id; - enum dma_data_direction direction; - - struct list_head list; - dma_addr_t dma_handle; - unsigned long cpua; - unsigned long size; - unsigned long type; - unsigned long align; - - unsigned long use; - unsigned long item; - - spinlock_t lock; - unsigned long mode; - unsigned long refs; - - struct class_device_attribute sysfs_attr; /* initialized when adding the entry */ -} pcidriver_kmem_entry_t; - -/* Define an entry in the umem list (this list is per device) */ -/* This list keeps references to the SG lists for each mapped userspace region */ -typedef struct { - int id; - struct list_head list; - unsigned int nr_pages; /* number of pages for this user memeory area */ - struct page **pages; /* list of pointers to the pages */ - unsigned int nents; /* actual entries in the scatter/gatter list (NOT nents for the map function, but the result) */ - struct scatterlist *sg; /* list of sg entries */ - struct class_device_attribute sysfs_attr; /* initialized when adding the entry */ -} pcidriver_umem_entry_t; - -/* Hold the driver private data */ -typedef struct { - dev_t devno; /* device number (major and minor) */ - struct pci_dev *pdev; /* PCI device */ - struct class_device *class_dev; /* Class device */ - struct cdev cdev; /* char device struct */ - int mmap_mode; /* current mmap mode */ - int mmap_area; /* current PCI mmap area */ - -#ifdef ENABLE_IRQ - int irq_enabled; /* Non-zero if IRQ is enabled */ - int irq_count; /* Just an IRQ counter */ - - wait_queue_head_t irq_queues[ PCIDRIVER_INT_MAXSOURCES ]; - /* One queue per interrupt source */ - atomic_t irq_outstanding[ PCIDRIVER_INT_MAXSOURCES ]; - /* Outstanding interrupts per queue */ - volatile unsigned int *bars_kmapped[6]; /* PCI BARs mmapped in kernel space */ - -#endif - - spinlock_t kmemlist_lock; /* Spinlock to lock kmem list operations */ - struct list_head kmem_list; /* List of 'kmem_list_entry's associated with this device */ - atomic_t kmem_count; /* id for next kmem entry */ - - int kmem_cur_id; /* Currently selected kmem buffer, for mmap */ - - spinlock_t umemlist_lock; /* Spinlock to lock umem list operations */ - struct list_head umem_list; /* List of 'umem_list_entry's associated with this device */ - atomic_t umem_count; /* id for next umem entry */ - - int msi_mode; /* Flag specifying if interrupt have been initialized in MSI mode */ - atomic_t refs; /* Reference counter */ -} pcidriver_privdata_t; - - -void pcidriver_module_get(pcidriver_privdata_t *privdata); -void pcidriver_module_put(pcidriver_privdata_t *privdata); - -/*************************************************************************/ -/* Some nice defines that make code more readable */ -/* This is to print nice info in the log */ - -#ifdef DEBUG - #define mod_info( args... ) \ - do { printk( KERN_INFO "%s - %s : ", MODNAME , __FUNCTION__ );\ - printk( args ); } while(0) - #define mod_info_dbg( args... ) \ - do { printk( KERN_INFO "%s - %s : ", MODNAME , __FUNCTION__ );\ - printk( args ); } while(0) -#else - #define mod_info( args... ) \ - do { printk( KERN_INFO "%s: ", MODNAME );\ - printk( args ); } while(0) - #define mod_info_dbg( args... ) -#endif - -#define mod_crit( args... ) \ - do { printk( KERN_CRIT "%s: ", MODNAME );\ - printk( args ); } while(0) - -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -#endif diff --git a/driver/compat.h b/driver/compat.h deleted file mode 100644 index 25e402a..0000000 --- a/driver/compat.h +++ /dev/null @@ -1,198 +0,0 @@ -/** - * - * @file compat.h - * @author Michael Stapelberg - * @date 2009-04-05 - * @brief Contains compatibility definitions for the different linux kernel versions to avoid - * putting ifdefs all over the driver code. - * - */ -#ifndef _COMPAT_H -#define _COMPAT_H - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) -# define __devinit -# define __devexit -# define __devinitdata -#endif - -/* dev_name is the wrapper one needs to use to access what was formerly called - * bus_id in struct device. However, before 2.6.27, direct access was necessary, - * so we provide our own version. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) -static inline const char *dev_name(struct device *dev) { - return dev->bus_id; -} -#endif - -/* SetPageLocked disappeared in v2.6.27 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) - #define compat_lock_page SetPageLocked - #define compat_unlock_page ClearPageLocked -#else - /* in v2.6.28, __set_page_locked and __clear_page_locked was introduced */ - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) - #define compat_lock_page __set_page_locked - #define compat_unlock_page __clear_page_locked - #else - /* However, in v2.6.27 itself, neither of them is there, so - * we need to use our own function fiddling with bits inside - * the page struct :-\ */ - static inline void compat_lock_page(struct page *page) { - __set_bit(PG_locked, &page->flags); - } - - static inline void compat_unlock_page(struct page *page) { - __clear_bit(PG_locked, &page->flags); - } - #endif -#endif - -/* Before 2.6.13, simple_class was the standard interface. Nowadays, it's just called class */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) - - #define class_compat class_simple - - /* These functions are redirected to their old corresponding functions */ - #define class_create(module, name) class_simple_create(module, name) - #define class_destroy(type) class_simple_destroy(type) - #define class_device_destroy(unused, devno) class_simple_device_remove(devno) - #define class_device_create(type, unused, devno, devpointer, nameformat, minor, unused) \ - class_simple_device_add(type, devno, devpointer, nameformat, minor) - #define class_set_devdata(classdev, privdata) classdev->class_data = privdata - #define DEVICE_ATTR_COMPAT - #define sysfs_attr_def_name(name) class_device_attr_##name - #define sysfs_attr_def_pointer privdata->class_dev - #define SYSFS_GET_FUNCTION(name) ssize_t name(struct class_device *cls, char *buf) - #define SYSFS_SET_FUNCTION(name) ssize_t name(struct class_device *cls, const char *buf, size_t count) - #define SYSFS_GET_PRIVDATA (pcidriver_privdata_t*)cls->class_data - -#else - -/* In 2.6.26, device.h was changed quite significantly. Luckily, it only affected - type/function names, for the most part. */ -//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - #define class_device_attribute device_attribute - #define CLASS_DEVICE_ATTR DEVICE_ATTR - #define class_device device - #define class_data dev -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) - #define class_device_create(type, parent, devno, devpointer, nameformat, minor, privdata) \ - device_create(type, parent, devno, privdata, nameformat, minor) -#else - #define class_device_create(type, parent, devno, devpointer, nameformat, minor, unused) \ - device_create(type, parent, devno, nameformat, minor) -#endif - #define class_device_create_file device_create_file - #define class_device_remove_file device_remove_file - #define class_device_destroy device_destroy - #define DEVICE_ATTR_COMPAT struct device_attribute *attr, - #define class_set_devdata dev_set_drvdata - - #define sysfs_attr_def_name(name) dev_attr_##name - #define sysfs_attr_def_pointer privdata->class_dev - #define SYSFS_GET_FUNCTION(name) ssize_t name(struct device *dev, struct device_attribute *attr, char *buf) - #define SYSFS_SET_FUNCTION(name) ssize_t name(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) - #define SYSFS_GET_PRIVDATA dev_get_drvdata(dev) - -//#endif - -#define class_compat class - -#endif - -/* The arguments of IRQ handlers have been changed in 2.6.19. It's very likely that - int irq will disappear somewhen in the future (current is 2.6.29), too. */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) - #define IRQ_HANDLER_FUNC(name) irqreturn_t name(int irq, void *dev_id) -#else - #define IRQ_HANDLER_FUNC(name) irqreturn_t name(int irq, void *dev_id, struct pt_regs *regs) -#endif - -/* atomic_inc_return appeared in 2.6.9, at least in CERN scientific linux, provide - compatibility wrapper for older kernels */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -static int atomic_inc_return(atomic_t *variable) { - atomic_inc(variable); - return atomic_read(variable); -} -#endif - -/* sg_set_page is available starting at 2.6.24 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - -#define sg_set_page(sg, set_page, set_length, set_offset) do { \ - (sg)->page = set_page; \ - (sg)->length = set_length; \ - (sg)->offset = set_offset; \ -} while (0) - -#endif - -/* Before 2.6.20, disable was not an atomic counter, so this check was needed */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -#define pci_disable_device(pdev) do { \ - if (pdev->is_enabled) \ - pci_disable_device(pdev); \ -} while (0) -#endif - -/* Before 2.6.24, scatter/gather lists did not need to be initialized */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - #define sg_init_table(sg, nr_pages) -#endif - -/* SA_SHIRQ was renamed to IRQF_SHARED in 2.6.24 */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) - #define request_irq(irq, irq_handler, modname, privdata) request_irq(irq, irq_handler, IRQF_SHARED, modname, privdata) -#else - #define request_irq(irq, irq_handler, modname, privdata) request_irq(irq, irq_handler, SA_SHIRQ, modname, privdata) -#endif - -/* In 2.6.13, io_remap_page_range was removed in favor for io_remap_pfn_range which works on - more platforms and allows more memory space */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) -#define io_remap_pfn_range_compat(vmap, vm_start, bar_addr, bar_length, vm_page_prot) \ - io_remap_pfn_range(vmap, vm_start, (bar_addr >> PAGE_SHIFT), bar_length, vm_page_prot) -#else -#define io_remap_pfn_range_compat(vmap, vm_start, bar_addr, bar_length, vm_page_prot) \ - io_remap_page_range(vmap, vm_start, bar_addr, bar_length, vm_page_prot) -#endif - -/* In 2.6.10, remap_pfn_range was introduced, see io_remap_pfn_range_compat */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) -#define remap_pfn_range_compat(vmap, vm_start, bar_addr, bar_length, vm_page_prot) \ - remap_pfn_range(vmap, vm_start, (bar_addr >> PAGE_SHIFT), bar_length, vm_page_prot) - -#define remap_pfn_range_cpua_compat(vmap, vm_start, cpua, size, vm_page_prot) \ - remap_pfn_range(vmap, vm_start, page_to_pfn(virt_to_page((void*)cpua)), size, vm_page_prot) - -#else -#define remap_pfn_range_compat(vmap, vm_start, bar_addr, bar_length, vm_page_prot) \ - remap_page_range(vmap, vm_start, bar_addr, bar_length, vm_page_prot) - -#define remap_pfn_range_cpua_compat(vmap, vm_start, cpua, size, vm_page_prot) \ - remap_page_range(vmap, vm_start, virt_to_phys((void*)cpua), size, vm_page_prot) -#endif - -/** - * Go over the pages of the kmem buffer, and mark them as reserved. - * This is needed, otherwise mmaping the kernel memory to user space - * will fail silently (mmaping /dev/null) when using remap_xx_range. - */ -static inline void set_pages_reserved_compat(unsigned long cpua, unsigned long size) -{ - /* Starting in 2.6.15, the PG_RESERVED bit was removed. - See also http://lwn.net/Articles/161204/ */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) - struct page *page, *last_page; - - page = virt_to_page(cpua); - last_page = virt_to_page(cpua + size - 1); - - for (; page <= last_page; page++) - SetPageReserved(page); -#endif -} - -#endif diff --git a/driver/config.h b/driver/config.h deleted file mode 100644 index c217afd..0000000 --- a/driver/config.h +++ /dev/null @@ -1,23 +0,0 @@ -/*******************************/ -/* Configuration of the driver */ -/*******************************/ - -/* Debug messages */ -//#define DEBUG - -/* Enable/disable IRQ handling */ -#define ENABLE_IRQ - -/* The name of the module */ -#define MODNAME "pciDriver" - -/* Major number is allocated dynamically */ -/* Minor number */ -#define MINORNR 0 - -/* Node name of the char device */ -#define NODENAME "fpga" -#define NODENAMEFMT "fpga%d" - -/* Maximum number of devices*/ -#define MAXDEVICES 4 diff --git a/driver/int.c b/driver/int.c deleted file mode 100644 index 5dbcb7f..0000000 --- a/driver/int.c +++ /dev/null @@ -1,258 +0,0 @@ -/** - * - * @file int.c - * @author Guillermo Marcus - * @date 2009-04-05 - * @brief Contains the interrupt handler. - * - */ - -/* - * Change History: - * - * $Log: not supported by cvs2svn $ - * Revision 1.7 2008-01-11 10:18:28 marcus - * Modified interrupt mechanism. Added atomic functions and queues, to address race conditions. Removed unused interrupt code. - * - * Revision 1.6 2007-11-04 20:58:22 marcus - * Added interrupt generator acknowledge. - * Fixed wrong operator. - * - * Revision 1.5 2007-10-31 15:42:21 marcus - * Added IG ack for testing, may be removed later. - * - * Revision 1.4 2007-07-17 13:15:56 marcus - * Removed Tasklets. - * Using newest map for the ABB interrupts. - * - * Revision 1.3 2007-07-05 15:30:30 marcus - * Added support for both register maps of the ABB. - * - * Revision 1.2 2007-05-29 07:50:18 marcus - * Split code into 2 files. May get merged in the future again.... - * - * Revision 1.1 2007/03/01 16:57:43 marcus - * Divided driver file to ease the interrupt hooks for the user of the driver. - * Modified Makefile accordingly. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" - -#include "compat.h" - -#include "pciDriver.h" - -#include "common.h" - -#include "int.h" - -/* - * The ID between IRQ_SOURCE in irq_outstanding and the actual source is arbitrary. - * Therefore, be careful when communicating with multiple implementations. - */ - -/* IRQ_SOURCES */ -#define ABB_IRQ_CH0 0 -#define ABB_IRQ_CH1 1 -#define ABB_IRQ_IG 2 - -/* See ABB user’s guide, register definitions (3.1) */ -#define ABB_INT_ENABLE (0x0010 >> 2) -#define ABB_INT_STAT (0x0008 >> 2) - -#define ABB_INT_CH1_TIMEOUT (1 << 4) -#define ABB_INT_CH0_TIMEOUT (1 << 5) -#define ABB_INT_IG (1 << 2) -#define ABB_INT_CH0 (1 << 1) /* downstream */ -#define ABB_INT_CH1 (1) /* upstream */ - -#define ABB_CH0_CTRL (108 >> 2) -#define ABB_CH1_CTRL (72 >> 2) -#define ABB_CH_RESET (0x0201000A) -#define ABB_IG_CTRL (0x0080 >> 2) -#define ABB_IG_ACK (0x00F0) - -/** - * - * If IRQ-handling is enabled, this function will be called from pcidriver_probe - * to initialize the IRQ handling (maps the BARs) - * - */ -int pcidriver_probe_irq(pcidriver_privdata_t *privdata) -{ - unsigned char int_pin, int_line; - unsigned long bar_addr, bar_len, bar_flags; - int i; - int err; - - for (i = 0; i < 6; i++) - privdata->bars_kmapped[i] = NULL; - - for (i = 0; i < 6; i++) { - bar_addr = pci_resource_start(privdata->pdev, i); - bar_len = pci_resource_len(privdata->pdev, i); - bar_flags = pci_resource_flags(privdata->pdev, i); - - /* check if it is a valid BAR, skip if not */ - if ((bar_addr == 0) || (bar_len == 0)) - continue; - - /* Skip IO regions (map only mem regions) */ - if (bar_flags & IORESOURCE_IO) - continue; - - /* Check if the region is available */ - if ((err = pci_request_region(privdata->pdev, i, NULL)) != 0) { - mod_info( "Failed to request BAR memory region.\n" ); - return err; - } - - /* Map it into kernel space. */ - /* For x86 this is just a dereference of the pointer, but that is - * not portable. So we need to do the portable way. Thanks Joern! - */ - - /* respect the cacheable-bility of the region */ - if (bar_flags & IORESOURCE_PREFETCH) - privdata->bars_kmapped[i] = ioremap(bar_addr, bar_len); - else - privdata->bars_kmapped[i] = ioremap_nocache(bar_addr, bar_len); - - /* check for error */ - if (privdata->bars_kmapped[i] == NULL) { - mod_info( "Failed to remap BAR%d into kernel space.\n", i ); - return -EIO; - } - } - - /* Initialize the interrupt handler for this device */ - /* Initialize the wait queues */ - for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++) { - init_waitqueue_head(&(privdata->irq_queues[i])); - atomic_set(&(privdata->irq_outstanding[i]), 0); - } - - /* Initialize the irq config */ - if ((err = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_PIN, &int_pin)) != 0) { - /* continue without interrupts */ - int_pin = 0; - mod_info("Error getting the interrupt pin. Disabling interrupts for this device\n"); - } - - /* Disable interrupts and activate them if everything can be set up properly */ - privdata->irq_enabled = 0; - - if (int_pin == 0) - return 0; - - if ((err = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_LINE, &int_line)) != 0) { - mod_info("Error getting the interrupt line. Disabling interrupts for this device\n"); - return 0; - } - - /* Enable interrupts using MSI mode */ - if (!pci_enable_msi(privdata->pdev)) - privdata->msi_mode = 1; - - /* register interrupt handler */ - if ((err = request_irq(privdata->pdev->irq, pcidriver_irq_handler, MODNAME, privdata)) != 0) { - mod_info("Error registering the interrupt handler. Disabling interrupts for this device\n"); - return 0; - } - - privdata->irq_enabled = 1; - mod_info("Registered Interrupt Handler at pin %i, line %i, IRQ %i\n", int_pin, int_line, privdata->pdev->irq ); - - return 0; -} - -/** - * - * Frees/cleans up the data structures, called from pcidriver_remove() - * - */ -void pcidriver_remove_irq(pcidriver_privdata_t *privdata) -{ - /* Release the IRQ handler */ - if (privdata->irq_enabled != 0) - free_irq(privdata->pdev->irq, privdata); - - if (privdata->msi_mode) { - pci_disable_msi(privdata->pdev); - privdata->msi_mode = 0; - } - - pcidriver_irq_unmap_bars(privdata); -} - -/** - * - * Unmaps the BARs and releases them - * - */ -void pcidriver_irq_unmap_bars(pcidriver_privdata_t *privdata) -{ - int i; - - for (i = 0; i < 6; i++) { - if (privdata->bars_kmapped[i] == NULL) - continue; - - iounmap((void*)privdata->bars_kmapped[i]); - pci_release_region(privdata->pdev, i); - } -} - -/** - * - * Acknowledges the receival of an interrupt to the card. - * - * @returns true if the card was acknowledget - * @returns false if the interrupt was not for one of our cards - * - * @see check_acknowlegde_channel - * - */ -static bool pcidriver_irq_acknowledge(pcidriver_privdata_t *privdata) -{ - int channel = 0; -// volatile unsigned int *bar; -// bar = privdata->bars_kmapped[0]; -// mod_info_dbg("interrupt registers. ISR: %x, IER: %x\n", bar[ABB_INT_STAT], bar[ABB_INT_ENABLE]); - - atomic_inc(&(privdata->irq_outstanding[channel])); - wake_up_interruptible(&(privdata->irq_queues[channel])); - - return true; -} - -/** - * - * Handles IRQs. At the moment, this acknowledges the card that this IRQ - * was received and then increases the driver's IRQ counter. - * - * @see pcidriver_irq_acknowledge - * - */ -IRQ_HANDLER_FUNC(pcidriver_irq_handler) -{ - pcidriver_privdata_t *privdata = (pcidriver_privdata_t *)dev_id; - - if (!pcidriver_irq_acknowledge(privdata)) - return IRQ_NONE; - - privdata->irq_count++; - return IRQ_HANDLED; -} diff --git a/driver/int.h b/driver/int.h deleted file mode 100644 index 4a834c7..0000000 --- a/driver/int.h +++ /dev/null @@ -1,9 +0,0 @@ -#if !defined(_PCIDRIVER_INT_H) && defined(ENABLE_IRQ) -#define _PCIDRIVER_INT_H - -int pcidriver_probe_irq(pcidriver_privdata_t *privdata); -void pcidriver_remove_irq(pcidriver_privdata_t *privdata); -void pcidriver_irq_unmap_bars(pcidriver_privdata_t *privdata); -IRQ_HANDLER_FUNC(pcidriver_irq_handler); - -#endif diff --git a/driver/ioctl.c b/driver/ioctl.c deleted file mode 100644 index 2d4af73..0000000 --- a/driver/ioctl.c +++ /dev/null @@ -1,471 +0,0 @@ -/** - * - * @file ioctl.c - * @author Guillermo Marcus - * @date 2009-04-05 - * @brief Contains the functions handling the different ioctl calls. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" /* Configuration for the driver */ -#include "compat.h" /* Compatibility functions/definitions */ -#include "pciDriver.h" /* External interface for the driver */ -#include "common.h" /* Internal definitions for all parts */ -#include "kmem.h" /* Internal definitions for kernel memory */ -#include "umem.h" /* Internal definitions for user space memory */ -#include "ioctl.h" /* Internal definitions for the ioctl part */ - -/** Declares a variable of the given type with the given name and copies it from userspace */ -#define READ_FROM_USER(type, name) \ - type name; \ - if ((ret = copy_from_user(&name, (type*)arg, sizeof(name))) != 0) \ - return -EFAULT; - -/** Writes back the given variable with the given type to userspace */ -#define WRITE_TO_USER(type, name) \ - if ((ret = copy_to_user((type*)arg, &name, sizeof(name))) != 0) \ - return -EFAULT; - -/** - * - * Sets the mmap mode for following mmap() calls. - * - * @param arg Not a pointer, but either PCIDRIVER_MMAP_PCI or PCIDRIVER_MMAP_KMEM - * - */ -static int ioctl_mmap_mode(pcidriver_privdata_t *privdata, unsigned long arg) -{ - if ((arg != PCIDRIVER_MMAP_PCI) && (arg != PCIDRIVER_MMAP_KMEM)) - return -EINVAL; - - /* change the mode */ - privdata->mmap_mode = arg; - - return 0; -} - -/** - * - * Sets the mmap area (BAR) for following mmap() calls. - * - */ -static int ioctl_mmap_area(pcidriver_privdata_t *privdata, unsigned long arg) -{ - /* validate input */ - if ((arg < PCIDRIVER_BAR0) || (arg > PCIDRIVER_BAR5)) - return -EINVAL; - - /* change the PCI area to mmap */ - privdata->mmap_area = arg; - - return 0; -} - -/** - * - * Reads/writes a byte/word/dword of the device's PCI config. - * - * @see pcidriver_pci_read - * @see pcidriver_pci_write - * - */ -static int ioctl_pci_config_read_write(pcidriver_privdata_t *privdata, unsigned int cmd, unsigned long arg) -{ - int ret; - READ_FROM_USER(pci_cfg_cmd, pci_cmd); - - if (cmd == PCIDRIVER_IOC_PCI_CFG_RD) { - switch (pci_cmd.size) { - case PCIDRIVER_PCI_CFG_SZ_BYTE: - ret = pci_read_config_byte( privdata->pdev, pci_cmd.addr, &(pci_cmd.val.byte) ); - break; - case PCIDRIVER_PCI_CFG_SZ_WORD: - ret = pci_read_config_word( privdata->pdev, pci_cmd.addr, &(pci_cmd.val.word) ); - break; - case PCIDRIVER_PCI_CFG_SZ_DWORD: - ret = pci_read_config_dword( privdata->pdev, pci_cmd.addr, &(pci_cmd.val.dword) ); - break; - default: - return -EINVAL; /* Wrong size setting */ - } - } else { - switch (pci_cmd.size) { - case PCIDRIVER_PCI_CFG_SZ_BYTE: - ret = pci_write_config_byte( privdata->pdev, pci_cmd.addr, pci_cmd.val.byte ); - break; - case PCIDRIVER_PCI_CFG_SZ_WORD: - ret = pci_write_config_word( privdata->pdev, pci_cmd.addr, pci_cmd.val.word ); - break; - case PCIDRIVER_PCI_CFG_SZ_DWORD: - ret = pci_write_config_dword( privdata->pdev, pci_cmd.addr, pci_cmd.val.dword ); - break; - default: - return -EINVAL; /* Wrong size setting */ - break; - } - } - - WRITE_TO_USER(pci_cfg_cmd, pci_cmd); - - return 0; -} - -/** - * - * Gets the PCI information for the device. - * - * @see pcidriver_pci_info - * - */ -static int ioctl_pci_info(pcidriver_privdata_t *privdata, unsigned long arg) -{ - int ret; - int bar; - READ_FROM_USER(pcilib_board_info_t, pci_info); - - pci_info.vendor_id = privdata->pdev->vendor; - pci_info.device_id = privdata->pdev->device; - pci_info.bus = privdata->pdev->bus->number; - pci_info.slot = PCI_SLOT(privdata->pdev->devfn); - pci_info.devfn = privdata->pdev->devfn; - pci_info.func = PCI_FUNC(privdata->pdev->devfn); - - if ((ret = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_PIN, &(pci_info.interrupt_pin))) != 0) - return ret; - - if ((ret = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_LINE, &(pci_info.interrupt_line))) != 0) - return ret; - - for (bar = 0; bar < 6; bar++) { - pci_info.bar_start[bar] = pci_resource_start(privdata->pdev, bar); - pci_info.bar_length[bar] = pci_resource_len(privdata->pdev, bar); - pci_info.bar_flags[bar] = pci_resource_flags(privdata->pdev, bar); - } - - WRITE_TO_USER(pcilib_board_info_t, pci_info); - - return 0; -} - -/** - * - * Allocates kernel memory. - * - * @see pcidriver_kmem_alloc - * - */ -static int ioctl_kmem_alloc(pcidriver_privdata_t *privdata, unsigned long arg) -{ - int ret; - READ_FROM_USER(kmem_handle_t, khandle); - - if ((ret = pcidriver_kmem_alloc(privdata, &khandle)) != 0) - return ret; - - WRITE_TO_USER(kmem_handle_t, khandle); - - return 0; -} - -/** - * - * Frees kernel memory. - * - * @see pcidriver_kmem_free - * - */ -static int ioctl_kmem_free(pcidriver_privdata_t *privdata, unsigned long arg) -{ - int ret; - READ_FROM_USER(kmem_handle_t, khandle); - - if ((ret = pcidriver_kmem_free(privdata, &khandle)) != 0) - return ret; - - return 0; -} - -/** - * - * Syncs kernel memory. - * - * @see pcidriver_kmem_sync - * - */ -static int ioctl_kmem_sync(pcidriver_privdata_t *privdata, unsigned long arg) -{ - int ret; - READ_FROM_USER(kmem_sync_t, ksync); - - if ((ret = pcidriver_kmem_sync(privdata, &ksync)) != 0) - return ret; - - WRITE_TO_USER(kmem_sync_t, ksync); - - return 0; -} - -/* - * - * Maps the given scatter/gather list from memory to PCI bus addresses. - * - * @see pcidriver_umem_sgmap - * - */ -static int ioctl_umem_sgmap(pcidriver_privdata_t *privdata, unsigned long arg) -{ - int ret; - READ_FROM_USER(umem_handle_t, uhandle); - - if ((ret = pcidriver_umem_sgmap(privdata, &uhandle)) != 0) - return ret; - - WRITE_TO_USER(umem_handle_t, uhandle); - - return 0; -} - -/** - * - * Unmaps the given scatter/gather list. - * - * @see pcidriver_umem_sgunmap - * - */ -static int ioctl_umem_sgunmap(pcidriver_privdata_t *privdata, unsigned long arg) -{ - int ret; - pcidriver_umem_entry_t *umem_entry; - READ_FROM_USER(umem_handle_t, uhandle); - - /* Find the associated umem_entry for this buffer, - * return -EINVAL if the specified handle id is invalid */ - if ((umem_entry = pcidriver_umem_find_entry_id(privdata, uhandle.handle_id)) == NULL) - return -EINVAL; - - if ((ret = pcidriver_umem_sgunmap(privdata, umem_entry)) != 0) - return ret; - - return 0; -} - -/** - * - * Copies the scatter/gather list from kernelspace to userspace. - * - * @see pcidriver_umem_sgget - * - */ -static int ioctl_umem_sgget(pcidriver_privdata_t *privdata, unsigned long arg) -{ - int ret; - READ_FROM_USER(umem_sglist_t, usglist); - - /* The umem_sglist_t has a pointer to the scatter/gather list itself which - * needs to be copied separately. The number of elements is stored in ->nents. - * As the list can get very big, we need to use vmalloc. */ - if ((usglist.sg = vmalloc(usglist.nents * sizeof(umem_sgentry_t))) == NULL) - return -ENOMEM; - - /* copy array to kernel structure */ - ret = copy_from_user(usglist.sg, ((umem_sglist_t *)arg)->sg, (usglist.nents)*sizeof(umem_sgentry_t)); - if (ret) return -EFAULT; - - if ((ret = pcidriver_umem_sgget(privdata, &usglist)) != 0) - return ret; - - /* write data to user space */ - ret = copy_to_user(((umem_sglist_t *)arg)->sg, usglist.sg, (usglist.nents)*sizeof(umem_sgentry_t)); - if (ret) return -EFAULT; - - /* free array memory */ - vfree(usglist.sg); - - /* restore sg pointer to vma address in user space before copying */ - usglist.sg = ((umem_sglist_t *)arg)->sg; - - WRITE_TO_USER(umem_sglist_t, usglist); - - return 0; -} - -/** - * - * Syncs user memory. - * - * @see pcidriver_umem_sync - * - */ -static int ioctl_umem_sync(pcidriver_privdata_t *privdata, unsigned long arg) -{ - int ret; - READ_FROM_USER(umem_handle_t, uhandle); - - return pcidriver_umem_sync( privdata, &uhandle ); -} - -/** - * - * Waits for an interrupt - * - * @param arg Not a pointer, but the irq source to wait for (unsigned int) - * - */ -static int ioctl_wait_interrupt(pcidriver_privdata_t *privdata, unsigned long arg) -{ -#ifdef ENABLE_IRQ - int ret; - unsigned long timeout; - unsigned int irq_source; - unsigned long temp = 0; - - READ_FROM_USER(interrupt_wait_t, irq_handle); - - irq_source = irq_handle.source; - - if (irq_source >= PCIDRIVER_INT_MAXSOURCES) - return -EFAULT; /* User tried to overrun the IRQ_SOURCES array */ - - timeout = jiffies + (irq_handle.timeout * HZ / 1000000); - - /* Thanks to Joern for the correction and tips! */ - /* done this way to avoid wrong behaviour (endless loop) of the compiler in AMD platforms */ - do { - /* We wait here with an interruptible timeout. This will be interrupted - * by int.c:check_acknowledge_channel() as soon as in interrupt for - * the specified source arrives. */ - wait_event_interruptible_timeout( (privdata->irq_queues[irq_source]), (atomic_read(&(privdata->irq_outstanding[irq_source])) > 0), (10*HZ/1000) ); - - if (atomic_add_negative( -1, &(privdata->irq_outstanding[irq_source])) ) - atomic_inc( &(privdata->irq_outstanding[irq_source]) ); - else - temp = 1; - } while ((!temp)&&(jiffies < timeout)); - - if ((temp)&&(irq_handle.count)) { - while (!atomic_add_negative( -1, &(privdata->irq_outstanding[irq_source]))) temp++; - atomic_inc( &(privdata->irq_outstanding[irq_source]) ); - } - - irq_handle.count = temp; - - WRITE_TO_USER(interrupt_wait_t, irq_handle); - - return 0; -#else - mod_info("Asked to wait for interrupt but interrupts are not enabled in the driver\n"); - return -EFAULT; -#endif -} - -/** - * - * Clears the interrupt wait queue. - * - * @param arg Not a pointer, but the irq source (unsigned int) - * @returns -EFAULT if the user specified an irq source out of range - * - */ -static int ioctl_clear_ioq(pcidriver_privdata_t *privdata, unsigned long arg) -{ -#ifdef ENABLE_IRQ - unsigned int irq_source; - - if (arg >= PCIDRIVER_INT_MAXSOURCES) - return -EFAULT; - - irq_source = arg; - atomic_set(&(privdata->irq_outstanding[irq_source]), 0); - - return 0; -#else - mod_info("Asked to wait for interrupt but interrupts are not enabled in the driver\n"); - return -EFAULT; -#endif -} - -/** - * - * This function handles all ioctl file operations. - * Generally, the data of the ioctl is copied from userspace to kernelspace, a separate - * function is called to handle the ioctl itself, then the data is copied back to userspace. - * - * @returns -EFAULT when an invalid memory pointer is passed - * - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) -int pcidriver_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -#else -long pcidriver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -#endif -{ - pcidriver_privdata_t *privdata = filp->private_data; - - /* Select the appropiate command */ - switch (cmd) { - case PCIDRIVER_IOC_MMAP_MODE: - return ioctl_mmap_mode(privdata, arg); - - case PCIDRIVER_IOC_MMAP_AREA: - return ioctl_mmap_area(privdata, arg); - - case PCIDRIVER_IOC_PCI_CFG_RD: - case PCIDRIVER_IOC_PCI_CFG_WR: - return ioctl_pci_config_read_write(privdata, cmd, arg); - - case PCIDRIVER_IOC_PCI_INFO: - return ioctl_pci_info(privdata, arg); - - case PCIDRIVER_IOC_KMEM_ALLOC: - return ioctl_kmem_alloc(privdata, arg); - - case PCIDRIVER_IOC_KMEM_FREE: - return ioctl_kmem_free(privdata, arg); - - case PCIDRIVER_IOC_KMEM_SYNC: - return ioctl_kmem_sync(privdata, arg); - - case PCIDRIVER_IOC_UMEM_SGMAP: - return ioctl_umem_sgmap(privdata, arg); - - case PCIDRIVER_IOC_UMEM_SGUNMAP: - return ioctl_umem_sgunmap(privdata, arg); - - case PCIDRIVER_IOC_UMEM_SGGET: - return ioctl_umem_sgget(privdata, arg); - - case PCIDRIVER_IOC_UMEM_SYNC: - return ioctl_umem_sync(privdata, arg); - - case PCIDRIVER_IOC_WAITI: - return ioctl_wait_interrupt(privdata, arg); - - case PCIDRIVER_IOC_CLEAR_IOQ: - return ioctl_clear_ioq(privdata, arg); - - default: - return -EINVAL; - } -} diff --git a/driver/ioctl.h b/driver/ioctl.h deleted file mode 100644 index 696fb8b..0000000 --- a/driver/ioctl.h +++ /dev/null @@ -1,5 +0,0 @@ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) -int pcidriver_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -#else -long pcidriver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -#endif diff --git a/driver/kmem.c b/driver/kmem.c deleted file mode 100644 index b323272..0000000 --- a/driver/kmem.c +++ /dev/null @@ -1,657 +0,0 @@ -/** - * - * @file kmem.c - * @brief This file contains all functions dealing with kernel memory. - * @author Guillermo Marcus - * @date 2009-04-05 - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" /* compile-time configuration */ -#include "compat.h" /* compatibility definitions for older linux */ -#include "pciDriver.h" /* external interface for the driver */ -#include "common.h" /* internal definitions for all parts */ -#include "kmem.h" /* prototypes for kernel memory */ -#include "sysfs.h" /* prototypes for sysfs */ - -/* VM_RESERVED is removed in 3.7-rc1 */ -#ifndef VM_RESERVED -# define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP) -#endif - -/** - * - * Allocates new kernel memory including the corresponding management structure, makes - * it available via sysfs if possible. - * - */ -int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle) -{ - int flags; - pcidriver_kmem_entry_t *kmem_entry; - void *retptr; - - if (kmem_handle->flags&KMEM_FLAG_REUSE) { - kmem_entry = pcidriver_kmem_find_entry_use(privdata, kmem_handle->use, kmem_handle->item); - if (kmem_entry) { - unsigned long flags = kmem_handle->flags; - - if (flags&KMEM_FLAG_TRY) { - kmem_handle->type = kmem_entry->type; - kmem_handle->size = kmem_entry->size; - kmem_handle->align = kmem_entry->align; - } else { - if (kmem_handle->type != kmem_entry->type) { - mod_info("Invalid type of reusable kmem_entry, currently: %lu, but requested: %lu\n", kmem_entry->type, kmem_handle->type); - return -EINVAL; - } - - if ((kmem_handle->type&PCILIB_KMEM_TYPE_MASK) == PCILIB_KMEM_TYPE_PAGE) { - kmem_handle->size = kmem_entry->size; - } else if (kmem_handle->size != kmem_entry->size) { - mod_info("Invalid size of reusable kmem_entry, currently: %lu, but requested: %lu\n", kmem_entry->size, kmem_handle->size); - return -EINVAL; - } - - if (kmem_handle->align != kmem_entry->align) { - mod_info("Invalid alignment of reusable kmem_entry, currently: %lu, but requested: %lu\n", kmem_entry->align, kmem_handle->align); - return -EINVAL; - } - - if (((kmem_entry->mode&KMEM_MODE_EXCLUSIVE)?1:0) != ((flags&KMEM_FLAG_EXCLUSIVE)?1:0)) { - mod_info("Invalid mode of reusable kmem_entry\n"); - return -EINVAL; - } - } - - - if ((kmem_entry->mode&KMEM_MODE_COUNT)==KMEM_MODE_COUNT) { - mod_info("Reuse counter of kmem_entry is overflown"); - return -EBUSY; - } - - - kmem_handle->handle_id = kmem_entry->id; - kmem_handle->pa = (unsigned long)(kmem_entry->dma_handle); - - kmem_handle->flags = KMEM_FLAG_REUSED; - if (kmem_entry->refs&KMEM_REF_HW) kmem_handle->flags |= KMEM_FLAG_REUSED_HW; - if (kmem_entry->mode&KMEM_MODE_PERSISTENT) kmem_handle->flags |= KMEM_FLAG_REUSED_PERSISTENT; - - kmem_entry->mode += 1; - if (flags&KMEM_FLAG_HW) { - if ((kmem_entry->refs&KMEM_REF_HW)==0) - pcidriver_module_get(privdata); - - kmem_entry->refs |= KMEM_REF_HW; - } - if (flags&KMEM_FLAG_PERSISTENT) kmem_entry->mode |= KMEM_MODE_PERSISTENT; - - privdata->kmem_cur_id = kmem_entry->id; - - return 0; - } - - if (kmem_handle->flags&KMEM_FLAG_TRY) return -ENOENT; - } - - /* First, allocate zeroed memory for the kmem_entry */ - if ((kmem_entry = kcalloc(1, sizeof(pcidriver_kmem_entry_t), GFP_KERNEL)) == NULL) - goto kmem_alloc_entry_fail; - - /* Initialize the kmem_entry */ - kmem_entry->id = atomic_inc_return(&privdata->kmem_count) - 1; - privdata->kmem_cur_id = kmem_entry->id; - kmem_handle->handle_id = kmem_entry->id; - - kmem_entry->use = kmem_handle->use; - kmem_entry->item = kmem_handle->item; - kmem_entry->type = kmem_handle->type; - kmem_entry->align = kmem_handle->align; - kmem_entry->direction = PCI_DMA_NONE; - - /* Initialize sysfs if possible */ - if (pcidriver_sysfs_initialize_kmem(privdata, kmem_entry->id, &(kmem_entry->sysfs_attr)) != 0) - goto kmem_alloc_mem_fail; - - /* ...and allocate the DMA memory */ - /* note this is a memory pair, referencing the same area: the cpu address (cpua) - * and the PCI bus address (pa). The CPU and PCI addresses may not be the same. - * The CPU sees only CPU addresses, while the device sees only PCI addresses. - * CPU address is used for the mmap (internal to the driver), and - * PCI address is the address passed to the DMA Controller in the device. - */ - switch (kmem_entry->type&PCILIB_KMEM_TYPE_MASK) { - case PCILIB_KMEM_TYPE_CONSISTENT: - retptr = pci_alloc_consistent( privdata->pdev, kmem_handle->size, &(kmem_entry->dma_handle) ); - break; - case PCILIB_KMEM_TYPE_REGION: - retptr = ioremap(kmem_handle->pa, kmem_handle->size); - kmem_entry->dma_handle = kmem_handle->pa; - if (kmem_entry->type == PCILIB_KMEM_TYPE_REGION_S2C) { - kmem_entry->direction = PCI_DMA_TODEVICE; - } else if (kmem_entry->type == PCILIB_KMEM_TYPE_REGION_C2S) { - kmem_entry->direction = PCI_DMA_FROMDEVICE; - } - break; - case PCILIB_KMEM_TYPE_PAGE: - flags = GFP_KERNEL; - - if (kmem_handle->size == 0) - kmem_handle->size = PAGE_SIZE; - else if (kmem_handle->size%PAGE_SIZE) - goto kmem_alloc_mem_fail; - - retptr = (void*)__get_free_pages(flags, get_order(kmem_handle->size)); - kmem_entry->dma_handle = 0; - - if (retptr) { - if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_S2C_PAGE) { - kmem_entry->direction = PCI_DMA_TODEVICE; - kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, kmem_handle->size, PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(privdata->pdev, kmem_entry->dma_handle)) { - free_pages((unsigned long)retptr, get_order(kmem_handle->size)); - goto kmem_alloc_mem_fail; - } - } else if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_C2S_PAGE) { - kmem_entry->direction = PCI_DMA_FROMDEVICE; - kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, kmem_handle->size, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(privdata->pdev, kmem_entry->dma_handle)) { - free_pages((unsigned long)retptr, get_order(kmem_handle->size)); - goto kmem_alloc_mem_fail; - - } - } - } - - break; - default: - goto kmem_alloc_mem_fail; - } - - - if (retptr == NULL) - goto kmem_alloc_mem_fail; - - kmem_entry->size = kmem_handle->size; - kmem_entry->cpua = (unsigned long)retptr; - kmem_handle->pa = (unsigned long)(kmem_entry->dma_handle); - - kmem_entry->mode = 1; - if (kmem_handle->flags&KMEM_FLAG_REUSE) { - kmem_entry->mode |= KMEM_MODE_REUSABLE; - if (kmem_handle->flags&KMEM_FLAG_EXCLUSIVE) kmem_entry->mode |= KMEM_MODE_EXCLUSIVE; - if (kmem_handle->flags&KMEM_FLAG_PERSISTENT) kmem_entry->mode |= KMEM_MODE_PERSISTENT; - } - - kmem_entry->refs = 0; - if (kmem_handle->flags&KMEM_FLAG_HW) { - pcidriver_module_get(privdata); - - kmem_entry->refs |= KMEM_REF_HW; - } - - kmem_handle->flags = 0; - - set_pages_reserved_compat(kmem_entry->cpua, kmem_entry->size); - - /* Add the kmem_entry to the list of the device */ - spin_lock( &(privdata->kmemlist_lock) ); - list_add_tail( &(kmem_entry->list), &(privdata->kmem_list) ); - spin_unlock( &(privdata->kmemlist_lock) ); - - return 0; - -kmem_alloc_mem_fail: - kfree(kmem_entry); -kmem_alloc_entry_fail: - return -ENOMEM; -} - -static int pcidriver_kmem_free_check(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle, pcidriver_kmem_entry_t *kmem_entry) { - if ((kmem_handle->flags & KMEM_FLAG_FORCE) == 0) { - if (kmem_entry->mode&KMEM_MODE_COUNT) - kmem_entry->mode -= 1; - - if (kmem_handle->flags&KMEM_FLAG_HW) { - if (kmem_entry->refs&KMEM_REF_HW) - pcidriver_module_put(privdata); - - kmem_entry->refs &= ~KMEM_REF_HW; - } - - if (kmem_handle->flags&KMEM_FLAG_PERSISTENT) - kmem_entry->mode &= ~KMEM_MODE_PERSISTENT; - - if (kmem_handle->flags&KMEM_FLAG_REUSE) - return 0; - - if (kmem_entry->refs) { - kmem_entry->mode += 1; - mod_info("can't free referenced kmem_entry\n"); - return -EBUSY; - } - - if (kmem_entry->mode & KMEM_MODE_PERSISTENT) { - kmem_entry->mode += 1; - mod_info("can't free persistent kmem_entry\n"); - return -EBUSY; - } - - if (((kmem_entry->mode&KMEM_MODE_EXCLUSIVE)==0)&&(kmem_entry->mode&KMEM_MODE_COUNT)&&((kmem_handle->flags&KMEM_FLAG_EXCLUSIVE)==0)) - return 0; - } else { - if (kmem_entry->refs&KMEM_REF_HW) - pcidriver_module_put(privdata); - - while (!atomic_add_negative(-1, &(privdata->refs))) pcidriver_module_put(privdata); - atomic_inc(&(privdata->refs)); - - } - - return 1; -} - -static int pcidriver_kmem_free_use(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle) -{ - int err; - int failed = 0; - struct list_head *ptr, *next; - pcidriver_kmem_entry_t *kmem_entry; - - /* iterate safely over the entries and delete them */ - list_for_each_safe(ptr, next, &(privdata->kmem_list)) { - kmem_entry = list_entry(ptr, pcidriver_kmem_entry_t, list); - if (kmem_entry->use == kmem_handle->use) { - err = pcidriver_kmem_free_check(privdata, kmem_handle, kmem_entry); - if (err > 0) - pcidriver_kmem_free_entry(privdata, kmem_entry); /* spin lock inside! */ - else - failed = 1; - } - } - - if (failed) { - mod_info("Some kmem_entries for use %lx are still referenced\n", kmem_handle->use); - return -EBUSY; - } - - return 0; -} - -/** - * - * Called via sysfs, frees kernel memory and the corresponding management structure - * - */ -int pcidriver_kmem_free( pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle ) -{ - int err; - pcidriver_kmem_entry_t *kmem_entry; - - if (kmem_handle->flags&KMEM_FLAG_MASS) { - kmem_handle->flags &= ~KMEM_FLAG_MASS; - return pcidriver_kmem_free_use(privdata, kmem_handle); - } - - /* Find the associated kmem_entry for this buffer */ - if ((kmem_entry = pcidriver_kmem_find_entry(privdata, kmem_handle)) == NULL) - return -EINVAL; /* kmem_handle is not valid */ - - err = pcidriver_kmem_free_check(privdata, kmem_handle, kmem_entry); - - if (err > 0) - return pcidriver_kmem_free_entry(privdata, kmem_entry); - - return err; -} - -/** - * - * Called when cleaning up, frees all kernel memory and their corresponding management structure - * - */ -int pcidriver_kmem_free_all(pcidriver_privdata_t *privdata) -{ -// int failed = 0; - struct list_head *ptr, *next; - pcidriver_kmem_entry_t *kmem_entry; - - /* iterate safely over the entries and delete them */ - list_for_each_safe(ptr, next, &(privdata->kmem_list)) { - kmem_entry = list_entry(ptr, pcidriver_kmem_entry_t, list); - /*if (kmem_entry->refs) - failed = 1; - else*/ - pcidriver_kmem_free_entry(privdata, kmem_entry); /* spin lock inside! */ - } -/* - if (failed) { - mod_info("Some kmem_entries are still referenced\n"); - return -EBUSY; - } -*/ - return 0; -} - - -/** - * - * Synchronize memory to/from the device (or in both directions). - * - */ -int pcidriver_kmem_sync_entry( pcidriver_privdata_t *privdata, pcidriver_kmem_entry_t *kmem_entry, int direction) -{ - if (kmem_entry->direction == PCI_DMA_NONE) - return -EINVAL; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) - switch (direction) { - case PCILIB_KMEM_SYNC_TODEVICE: - pci_dma_sync_single_for_device( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); - break; - case PCILIB_KMEM_SYNC_FROMDEVICE: - pci_dma_sync_single_for_cpu( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); - break; - case PCILIB_KMEM_SYNC_BIDIRECTIONAL: - pci_dma_sync_single_for_device( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); - pci_dma_sync_single_for_cpu( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); - break; - default: - return -EINVAL; /* wrong direction parameter */ - } -#else - switch (direction) { - case PCILIB_KMEM_SYNC_TODEVICE: - pci_dma_sync_single( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); - break; - case PCILIB_KMEM_SYNC_FROMDEVICE: - pci_dma_sync_single( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); - break; - case PCILIB_KMEM_SYNC_BIDIRECTIONAL: - pci_dma_sync_single( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); - break; - default: - return -EINVAL; /* wrong direction parameter */ - } -#endif - - return 0; /* success */ -} - -/** - * - * Synchronize memory to/from the device (or in both directions). - * - */ -int pcidriver_kmem_sync( pcidriver_privdata_t *privdata, kmem_sync_t *kmem_sync ) -{ - pcidriver_kmem_entry_t *kmem_entry; - - /* Find the associated kmem_entry for this buffer */ - if ((kmem_entry = pcidriver_kmem_find_entry(privdata, &(kmem_sync->handle))) == NULL) - return -EINVAL; /* kmem_handle is not valid */ - - return pcidriver_kmem_sync_entry(privdata, kmem_entry, kmem_sync->dir); -} - -/** - * - * Free the given kmem_entry and its memory. - * - */ -int pcidriver_kmem_free_entry(pcidriver_privdata_t *privdata, pcidriver_kmem_entry_t *kmem_entry) -{ - pcidriver_sysfs_remove(privdata, &(kmem_entry->sysfs_attr)); - - /* Go over the pages of the kmem buffer, and mark them as not reserved */ -#if 0 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) - /* - * This code is DISABLED. - * Apparently, it is not needed to unreserve them. Doing so here - * hangs the machine. Why? - * - * Uhm.. see links: - * - * http://lwn.net/Articles/161204/ - * http://lists.openfabrics.org/pipermail/general/2007-March/034101.html - * - * I insist, this should be enabled, but doing so hangs the machine. - * Literature supports the point, and there is even a similar problem (see link) - * But this is not the case. It seems right to me. but obviously is not. - * - * Anyway, this goes away in kernel >=2.6.15. - */ - unsigned long start = __pa(kmem_entry->cpua) >> PAGE_SHIFT; - unsigned long end = __pa(kmem_entry->cpua + kmem_entry->size) >> PAGE_SHIFT; - unsigned long i; - for(i=start;itype&PCILIB_KMEM_TYPE_MASK) { - case PCILIB_KMEM_TYPE_CONSISTENT: - pci_free_consistent( privdata->pdev, kmem_entry->size, (void *)(kmem_entry->cpua), kmem_entry->dma_handle ); - break; - case PCILIB_KMEM_TYPE_REGION: - iounmap((void *)(kmem_entry->cpua)); - break; - case PCILIB_KMEM_TYPE_PAGE: - if (kmem_entry->dma_handle) { - if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_S2C_PAGE) { - pci_unmap_single(privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_TODEVICE); - } else if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_C2S_PAGE) { - pci_unmap_single(privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_FROMDEVICE); - } - } - free_pages((unsigned long)kmem_entry->cpua, get_order(kmem_entry->size)); - break; - } - - - /* Remove the kmem list entry */ - spin_lock( &(privdata->kmemlist_lock) ); - list_del( &(kmem_entry->list) ); - spin_unlock( &(privdata->kmemlist_lock) ); - - /* Release kmem_entry memory */ - kfree(kmem_entry); - - return 0; -} - -/** - * - * Find the corresponding kmem_entry for the given kmem_handle. - * - */ -pcidriver_kmem_entry_t *pcidriver_kmem_find_entry(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle) -{ - struct list_head *ptr; - pcidriver_kmem_entry_t *entry, *result = NULL; - - /* should I implement it better using the handle_id? */ - - spin_lock(&(privdata->kmemlist_lock)); - list_for_each(ptr, &(privdata->kmem_list)) { - entry = list_entry(ptr, pcidriver_kmem_entry_t, list); - - if (entry->id == kmem_handle->handle_id) { - result = entry; - break; - } - } - - spin_unlock(&(privdata->kmemlist_lock)); - return result; -} - -/** - * - * find the corresponding kmem_entry for the given id. - * - */ -pcidriver_kmem_entry_t *pcidriver_kmem_find_entry_id(pcidriver_privdata_t *privdata, int id) -{ - struct list_head *ptr; - pcidriver_kmem_entry_t *entry, *result = NULL; - - spin_lock(&(privdata->kmemlist_lock)); - list_for_each(ptr, &(privdata->kmem_list)) { - entry = list_entry(ptr, pcidriver_kmem_entry_t, list); - - if (entry->id == id) { - result = entry; - break; - } - } - - spin_unlock(&(privdata->kmemlist_lock)); - return result; -} - -/** - * - * find the corresponding kmem_entry for the given use and item. - * - */ -pcidriver_kmem_entry_t *pcidriver_kmem_find_entry_use(pcidriver_privdata_t *privdata, unsigned long use, unsigned long item) -{ - struct list_head *ptr; - pcidriver_kmem_entry_t *entry, *result = NULL; - - spin_lock(&(privdata->kmemlist_lock)); - list_for_each(ptr, &(privdata->kmem_list)) { - entry = list_entry(ptr, pcidriver_kmem_entry_t, list); - - if ((entry->use == use)&&(entry->item == item)&&(entry->mode&KMEM_MODE_REUSABLE)) { - result = entry; - break; - } - } - - spin_unlock(&(privdata->kmemlist_lock)); - return result; -} - - -void pcidriver_kmem_mmap_close(struct vm_area_struct *vma) { - unsigned long vma_size; - pcidriver_kmem_entry_t *kmem_entry = (pcidriver_kmem_entry_t*)vma->vm_private_data; - if (kmem_entry) { -/* - if (kmem_entry->id == 0) { - mod_info("refs: %p %p %lx\n", vma, vma->vm_private_data, kmem_entry->refs); - mod_info("kmem_size: %lu vma_size: %lu, s: %lx, e: %lx\n", kmem_entry->size, (vma->vm_end - vma->vm_start), vma->vm_start, vma->vm_end); - } -*/ - - vma_size = (vma->vm_end - vma->vm_start); - - if (kmem_entry->refs&KMEM_REF_COUNT) { - kmem_entry->refs -= vma_size / PAGE_SIZE; - } - } -} - -static struct vm_operations_struct pcidriver_kmem_mmap_ops = { - .close = pcidriver_kmem_mmap_close -}; - -/** - * - * mmap() kernel memory to userspace. - * - */ -int pcidriver_mmap_kmem(pcidriver_privdata_t *privdata, struct vm_area_struct *vma) -{ - unsigned long vma_size; - pcidriver_kmem_entry_t *kmem_entry; - int ret; - - mod_info_dbg("Entering mmap_kmem\n"); - - /* FIXME: Is this really right? Always just the latest one? Can't we identify one? */ - /* Get latest entry on the kmem_list */ - kmem_entry = pcidriver_kmem_find_entry_id(privdata, privdata->kmem_cur_id); - if (!kmem_entry) { - mod_info("Trying to mmap a kernel memory buffer without creating it first!\n"); - return -EFAULT; - } - - mod_info_dbg("Got kmem_entry with id: %d\n", kmem_entry->id); - - /* Check sizes */ - vma_size = (vma->vm_end - vma->vm_start); - - if ((vma_size > kmem_entry->size) && - ((kmem_entry->size < PAGE_SIZE) && (vma_size != PAGE_SIZE))) { - mod_info("kem_entry size(%lu) and vma size do not match(%lu)\n", kmem_entry->size, vma_size); - return -EINVAL; - } - - /* reference counting */ - if ((kmem_entry->mode&KMEM_MODE_EXCLUSIVE)&&(kmem_entry->refs&KMEM_REF_COUNT)) { - mod_info("can't make second mmaping for exclusive kmem_entry\n"); - return -EBUSY; - } - if (((kmem_entry->refs&KMEM_REF_COUNT) + (vma_size / PAGE_SIZE)) > KMEM_REF_COUNT) { - mod_info("maximal amount of references is reached by kmem_entry\n"); - return -EBUSY; - } - - kmem_entry->refs += vma_size / PAGE_SIZE; - - vma->vm_flags |= (VM_RESERVED); - -#ifdef pgprot_noncached - // This is coherent memory, so it must not be cached. - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -#endif - - mod_info_dbg("Mapping address %08lx / PFN %08lx\n", - virt_to_phys((void*)kmem_entry->cpua), - page_to_pfn(virt_to_page((void*)kmem_entry->cpua))); - - if ((kmem_entry->type&PCILIB_KMEM_TYPE_MASK) == PCILIB_KMEM_TYPE_REGION) { - ret = remap_pfn_range_compat( - vma, - vma->vm_start, - kmem_entry->dma_handle, - (vma_size < kmem_entry->size)?vma_size:kmem_entry->size, - vma->vm_page_prot); - } else { - ret = remap_pfn_range_cpua_compat( - vma, - vma->vm_start, - kmem_entry->cpua, - (vma_size < kmem_entry->size)?vma_size:kmem_entry->size, - vma->vm_page_prot ); - } - - if (ret) { - mod_info("kmem remap failed: %d (%lx)\n", ret,kmem_entry->cpua); - kmem_entry->refs -= 1; - return -EAGAIN; - } - - vma->vm_ops = &pcidriver_kmem_mmap_ops; - vma->vm_private_data = (void*)kmem_entry; - - return ret; -} diff --git a/driver/kmem.h b/driver/kmem.h deleted file mode 100644 index 503620e..0000000 --- a/driver/kmem.h +++ /dev/null @@ -1,9 +0,0 @@ -int pcidriver_kmem_alloc( pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle ); -int pcidriver_kmem_free( pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle ); -int pcidriver_kmem_sync_entry( pcidriver_privdata_t *privdata, pcidriver_kmem_entry_t *kmem_entry, int direction ); -int pcidriver_kmem_sync( pcidriver_privdata_t *privdata, kmem_sync_t *kmem_sync ); -int pcidriver_kmem_free_all( pcidriver_privdata_t *privdata ); -pcidriver_kmem_entry_t *pcidriver_kmem_find_entry( pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle ); -pcidriver_kmem_entry_t *pcidriver_kmem_find_entry_id( pcidriver_privdata_t *privdata, int id ); -pcidriver_kmem_entry_t *pcidriver_kmem_find_entry_use(pcidriver_privdata_t *privdata, unsigned long use, unsigned long item); -int pcidriver_kmem_free_entry( pcidriver_privdata_t *privdata, pcidriver_kmem_entry_t *kmem_entry ); diff --git a/driver/pciDriver.h b/driver/pciDriver.h deleted file mode 100644 index 67a80f2..0000000 --- a/driver/pciDriver.h +++ /dev/null @@ -1,217 +0,0 @@ -#ifndef PCIDRIVER_H_ -#define PCIDRIVER_H_ - -/** - * This is a full rewrite of the pciDriver. - * New default is to support kernel 2.6, using kernel 2.6 APIs. - * - * This header defines the interface to the outside world. - * - * $Revision: 1.6 $ - * $Date: 2008-01-24 14:21:36 $ - * - */ - -/* - * Change History: - * - * $Log: not supported by cvs2svn $ - * Revision 1.5 2008-01-11 10:15:14 marcus - * Removed unused interrupt code. - * Added intSource to the wait interrupt call. - * - * Revision 1.4 2006/11/17 18:44:42 marcus - * Type of SG list can now be selected at runtime. Added type to sglist. - * - * Revision 1.3 2006/11/17 16:23:02 marcus - * Added slot number to the PCI info IOctl. - * - * Revision 1.2 2006/11/13 12:29:09 marcus - * Added a IOctl call, to confiure the interrupt response. (testing pending). - * Basic interrupts are now supported. - * - * Revision 1.1 2006/10/10 14:46:52 marcus - * Initial commit of the new pciDriver for kernel 2.6 - * - * Revision 1.7 2006/10/06 15:18:06 marcus - * Updated PCI info and PCI cmd - * - * Revision 1.6 2006/09/25 16:51:07 marcus - * Added PCI config IOctls, and implemented basic mmap functions. - * - * Revision 1.5 2006/09/18 17:13:12 marcus - * backup commit. - * - * Revision 1.4 2006/09/15 15:44:41 marcus - * backup commit. - * - * Revision 1.3 2006/08/15 11:40:02 marcus - * backup commit. - * - * Revision 1.2 2006/08/12 18:28:42 marcus - * Sync with the laptop - * - * Revision 1.1 2006/08/11 15:30:46 marcus - * Sync with the laptop - * - */ - -#include -#include "../pcilib_types.h" - -/* Identifies the PCI-E Xilinx ML605 */ -#define PCIE_XILINX_VENDOR_ID 0x10ee -#define PCIE_ML605_DEVICE_ID 0x6024 - -/* Identifies the PCI-E IPE Camera */ -#define PCIE_IPECAMERA_DEVICE_ID 0x6081 -#define PCIE_KAPTURE_DEVICE_ID 0x6028 -//#define PCIE_IPECAMERA_DEVICE_ID 0x6018 - - -/* Possible values for ioctl commands */ - -/* PCI mmap areas */ -#define PCIDRIVER_BAR0 0 -#define PCIDRIVER_BAR1 1 -#define PCIDRIVER_BAR2 2 -#define PCIDRIVER_BAR3 3 -#define PCIDRIVER_BAR4 4 -#define PCIDRIVER_BAR5 5 - -/* mmap mode of the device */ -#define PCIDRIVER_MMAP_PCI 0 -#define PCIDRIVER_MMAP_KMEM 1 - -/* Direction of a DMA operation */ -#define PCIDRIVER_DMA_BIDIRECTIONAL 0 -#define PCIDRIVER_DMA_TODEVICE PCILIB_KMEM_SYNC_TODEVICE -#define PCIDRIVER_DMA_FROMDEVICE PCILIB_KMEM_SYNC_FROMDEVICE - -/* Possible sizes in a PCI command */ -#define PCIDRIVER_PCI_CFG_SZ_BYTE 1 -#define PCIDRIVER_PCI_CFG_SZ_WORD 2 -#define PCIDRIVER_PCI_CFG_SZ_DWORD 3 - -/* Possible types of SG lists */ -#define PCIDRIVER_SG_NONMERGED 0 -#define PCIDRIVER_SG_MERGED 1 - -/* Maximum number of interrupt sources */ -#define PCIDRIVER_INT_MAXSOURCES 16 - - -#define KMEM_FLAG_REUSE 1 /**< Try to reuse existing buffer with the same use & item */ -#define KMEM_FLAG_EXCLUSIVE 2 /**< Allow only a single application accessing a specified use & item */ -#define KMEM_FLAG_PERSISTENT 4 /**< Sets persistent mode */ -#define KMEM_FLAG_HW 8 /**< The buffer may be accessed by hardware, the hardware access will not occur any more if passed to _free function */ -#define KMEM_FLAG_FORCE 16 /**< Force memory cleanup even if references are present */ -#define KMEM_FLAG_MASS 32 /**< Apply to all buffers of selected use */ -#define KMEM_FLAG_TRY 64 /**< Do not allocate buffers, try to reuse and fail if not possible */ - -#define KMEM_FLAG_REUSED 1 /**< Indicates if buffer with specified use & item was already allocated and reused */ -#define KMEM_FLAG_REUSED_PERSISTENT 4 /**< Indicates that reused buffer was persistent before the call */ -#define KMEM_FLAG_REUSED_HW 8 /**< Indicates that reused buffer had a HW reference before the call */ - - -/* Types */ -typedef struct { - unsigned long type; - unsigned long pa; - unsigned long size; - unsigned long align; - unsigned long use; - unsigned long item; - int flags; - int handle_id; -} kmem_handle_t; - -typedef struct { - unsigned long addr; - unsigned long size; -} umem_sgentry_t; - -typedef struct { - int handle_id; - int type; - int nents; - umem_sgentry_t *sg; -} umem_sglist_t; - -typedef struct { - unsigned long vma; - unsigned long size; - int handle_id; - int dir; -} umem_handle_t; - -typedef struct { - kmem_handle_t handle; - int dir; -} kmem_sync_t; - -typedef struct { - unsigned long count; - unsigned long timeout; // microseconds - unsigned int source; -} interrupt_wait_t; - -typedef struct { - int size; - int addr; - union { - unsigned char byte; - unsigned short word; - unsigned int dword; /* not strict C, but if not can have problems */ - } val; -} pci_cfg_cmd; - -typedef struct { - unsigned short vendor_id; - unsigned short device_id; - unsigned short bus; - unsigned short slot; - unsigned short func; - unsigned short devfn; - unsigned char interrupt_pin; - unsigned char interrupt_line; - unsigned int irq; - unsigned long bar_start[6]; - unsigned long bar_length[6]; - unsigned long bar_flags[6]; -} pcilib_board_info_t; - - -/* ioctl interface */ -/* See documentation for a detailed usage explanation */ - -/* - * one of the problems of ioctl, is that requires a type definition. - * This type is only 8-bits wide, and half-documented in - * /Documentation/ioctl-number.txt. - * previous SHL -> 'S' definition, conflicts with several devices, - * so I changed it to be pci -> 'p', in the range 0xA0-AF - */ -#define PCIDRIVER_IOC_MAGIC 'p' -#define PCIDRIVER_IOC_BASE 0xA0 - -#define PCIDRIVER_IOC_MMAP_MODE _IO( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 0 ) -#define PCIDRIVER_IOC_MMAP_AREA _IO( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 1 ) -#define PCIDRIVER_IOC_KMEM_ALLOC _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 2, kmem_handle_t * ) -#define PCIDRIVER_IOC_KMEM_FREE _IOW ( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 3, kmem_handle_t * ) -#define PCIDRIVER_IOC_KMEM_SYNC _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 4, kmem_sync_t * ) -#define PCIDRIVER_IOC_UMEM_SGMAP _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 5, umem_handle_t * ) -#define PCIDRIVER_IOC_UMEM_SGUNMAP _IOW( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 6, umem_handle_t * ) -#define PCIDRIVER_IOC_UMEM_SGGET _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 7, umem_sglist_t * ) -#define PCIDRIVER_IOC_UMEM_SYNC _IOW( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 8, umem_handle_t * ) -#define PCIDRIVER_IOC_WAITI _IO( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 9 ) - -/* And now, the methods to access the PCI configuration area */ -#define PCIDRIVER_IOC_PCI_CFG_RD _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 10, pci_cfg_cmd * ) -#define PCIDRIVER_IOC_PCI_CFG_WR _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 11, pci_cfg_cmd * ) -#define PCIDRIVER_IOC_PCI_INFO _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 12, pcilib_board_info_t * ) - -/* Clear interrupt queues */ -#define PCIDRIVER_IOC_CLEAR_IOQ _IO( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 13 ) - -#endif diff --git a/driver/sysfs.c b/driver/sysfs.c deleted file mode 100644 index abc1c8a..0000000 --- a/driver/sysfs.c +++ /dev/null @@ -1,308 +0,0 @@ -/** - * - * @file sysfs.c - * @brief This file contains the functions providing the SysFS-interface. - * @author Guillermo Marcus - * @date 2010-03-01 - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "compat.h" -#include "config.h" -#include "pciDriver.h" -#include "common.h" -#include "umem.h" -#include "kmem.h" -#include "sysfs.h" - -static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry); -static SYSFS_GET_FUNCTION(pcidriver_show_umem_entry); - -/** - * - * Initializes the sysfs attributes for an kmem/umem-entry - * - */ -static int _pcidriver_sysfs_initialize(pcidriver_privdata_t *privdata, - int id, - struct class_device_attribute *sysfs_attr, - const char *fmtstring, - SYSFS_GET_FUNCTION((*callback))) -{ - /* sysfs attributes for kmem buffers don’t make sense before 2.6.13, as - we have no mmap support before */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) - char namebuffer[16]; - - /* allocate space for the name of the attribute */ - snprintf(namebuffer, sizeof(namebuffer), fmtstring, id); - - if ((sysfs_attr->attr.name = kstrdup(namebuffer, GFP_KERNEL)) == NULL) - return -ENOMEM; - - sysfs_attr->attr.mode = S_IRUGO; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - // DS: Shall we lock now while accessing driver data structures??? - sysfs_attr->attr.owner = THIS_MODULE; -#endif - sysfs_attr->show = callback; - sysfs_attr->store = NULL; - - /* name and add attribute */ - if (class_device_create_file(privdata->class_dev, sysfs_attr) != 0) - return -ENXIO; /* Device not configured. Not the really best choice, but hm. */ -#endif - - return 0; -} - -int pcidriver_sysfs_initialize_kmem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr) -{ - return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "kbuf%d", pcidriver_show_kmem_entry); -} - -int pcidriver_sysfs_initialize_umem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr) -{ - return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "umem%d", pcidriver_show_umem_entry); -} - -/** - * - * Removes the file from sysfs and frees the allocated (kstrdup()) memory. - * - */ -void pcidriver_sysfs_remove(pcidriver_privdata_t *privdata, struct class_device_attribute *sysfs_attr) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) - class_device_remove_file(privdata->class_dev, sysfs_attr); - kfree(sysfs_attr->attr.name); -#endif -} - -static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) - pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; - - /* As we can be sure that attr.name contains a filename which we - * created (see _pcidriver_sysfs_initialize), we do not need to have - * sanity checks but can directly call simple_strtol() */ - int id = simple_strtol(attr->attr.name + strlen("kbuf"), NULL, 10); - pcidriver_kmem_entry_t *entry = pcidriver_kmem_find_entry_id(privdata, id); - if (entry) { - unsigned long addr = entry->cpua; - unsigned long dma_addr = entry->dma_handle; - - if (entry->size >= 16) { - pcidriver_kmem_sync_entry(privdata, entry, PCILIB_KMEM_SYNC_FROMDEVICE); - return snprintf(buf, PAGE_SIZE, "buffer: %d\naddr: %lx\nhw addr: %llx\nbus addr: %lx\ntype: %lx\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\ndata: %8x %8x %8x %8x\n", id, addr, virt_to_phys((void*)addr), dma_addr, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode, *(u32*)(entry->cpua), *(u32*)(entry->cpua + 4), *(u32*)(entry->cpua + 8), *(u32*)(entry->cpua + 12)); - } else - return snprintf(buf, PAGE_SIZE, "buffer: %d\naddr: %lx\nhw addr: %llx\nbus addr: %lx\ntype: %lx\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\n", id, addr, virt_to_phys((void*)addr), dma_addr, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode); - } else - return snprintf(buf, PAGE_SIZE, "I am in the kmem_entry show function for buffer %d\n", id); -#else - return 0; -#endif -} - -static SYSFS_GET_FUNCTION(pcidriver_show_umem_entry) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) -#if 0 - pcidriver_privdata_t *privdata = (pcidriver_privdata_t *)cls->class_data; - - return snprintf(buf, PAGE_SIZE, "I am in the umem_entry show function, class_device_kobj_name: %s\n", cls->kobj.name); -#endif - return 0; -#else - return 0; -#endif -} - -#ifdef ENABLE_IRQ -SYSFS_GET_FUNCTION(pcidriver_show_irq_count) -{ - pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; - - return snprintf(buf, PAGE_SIZE, "%d\n", privdata->irq_count); -} - -SYSFS_GET_FUNCTION(pcidriver_show_irq_queues) -{ - pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; - int i, offset; - - /* output will be truncated to PAGE_SIZE */ - offset = snprintf(buf, PAGE_SIZE, "Queue\tOutstanding IRQs\n"); - for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++) - offset += snprintf(buf+offset, PAGE_SIZE-offset, "%d\t%d\n", i, atomic_read(&(privdata->irq_outstanding[i])) ); - - return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1); -} -#endif - -SYSFS_GET_FUNCTION(pcidriver_show_mmap_mode) -{ - pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; - - return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_mode); -} - -SYSFS_SET_FUNCTION(pcidriver_store_mmap_mode) -{ - pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; - int mode = -1; - - /* Set the mmap-mode if it is either PCIDRIVER_MMAP_PCI or PCIDRIVER_MMAP_KMEM */ - if (sscanf(buf, "%d", &mode) == 1 && - (mode == PCIDRIVER_MMAP_PCI || mode == PCIDRIVER_MMAP_KMEM)) - privdata->mmap_mode = mode; - - return strlen(buf); -} - -SYSFS_GET_FUNCTION(pcidriver_show_mmap_area) -{ - pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; - - return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_area); -} - -SYSFS_SET_FUNCTION(pcidriver_store_mmap_area) -{ - pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; - int temp = -1; - - sscanf(buf, "%d", &temp); - - if ((temp >= PCIDRIVER_BAR0) && (temp <= PCIDRIVER_BAR5)) - privdata->mmap_area = temp; - - return strlen(buf); -} - -SYSFS_GET_FUNCTION(pcidriver_show_kmem_count) -{ - pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; - - return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&(privdata->kmem_count))); -} - -SYSFS_SET_FUNCTION(pcidriver_store_kmem_alloc) -{ - pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; - kmem_handle_t kmem_handle; - - /* FIXME: guillermo: is validation of parsing an unsigned int enough? */ - if (sscanf(buf, "%lu", &kmem_handle.size) == 1) - pcidriver_kmem_alloc(privdata, &kmem_handle); - - return strlen(buf); -} - -SYSFS_SET_FUNCTION(pcidriver_store_kmem_free) -{ - pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; - unsigned int id; - pcidriver_kmem_entry_t *kmem_entry; - - /* Parse the ID of the kernel memory to be freed, check bounds */ - if (sscanf(buf, "%u", &id) != 1 || - (id >= atomic_read(&(privdata->kmem_count)))) - goto err; - - if ((kmem_entry = pcidriver_kmem_find_entry_id(privdata,id)) == NULL) - goto err; - - pcidriver_kmem_free_entry(privdata, kmem_entry ); -err: - return strlen(buf); -} - -SYSFS_GET_FUNCTION(pcidriver_show_kbuffers) -{ - pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; - int offset = 0; - struct list_head *ptr; - pcidriver_kmem_entry_t *entry; - - /* print the header */ - offset += snprintf(buf, PAGE_SIZE, "kbuf#\tcpu addr\tsize\n"); - - spin_lock(&(privdata->kmemlist_lock)); - list_for_each(ptr, &(privdata->kmem_list)) { - entry = list_entry(ptr, pcidriver_kmem_entry_t, list); - - /* print entry info */ - if (offset > PAGE_SIZE) { - spin_unlock( &(privdata->kmemlist_lock) ); - return PAGE_SIZE; - } - - offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%08lx\t%lu\n", entry->id, (unsigned long)(entry->dma_handle), entry->size ); - } - - spin_unlock(&(privdata->kmemlist_lock)); - - /* output will be truncated to PAGE_SIZE */ - return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1); -} - -SYSFS_GET_FUNCTION(pcidriver_show_umappings) -{ - int offset = 0; - pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; - struct list_head *ptr; - pcidriver_umem_entry_t *entry; - - /* print the header */ - offset += snprintf(buf, PAGE_SIZE, "umap#\tn_pages\tsg_ents\n"); - - spin_lock( &(privdata->umemlist_lock) ); - list_for_each( ptr, &(privdata->umem_list) ) { - entry = list_entry(ptr, pcidriver_umem_entry_t, list ); - - /* print entry info */ - if (offset > PAGE_SIZE) { - spin_unlock( &(privdata->umemlist_lock) ); - return PAGE_SIZE; - } - - offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%lu\t%lu\n", entry->id, - (unsigned long)(entry->nr_pages), (unsigned long)(entry->nents)); - } - - spin_unlock( &(privdata->umemlist_lock) ); - - /* output will be truncated to PAGE_SIZE */ - return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1); -} - -SYSFS_SET_FUNCTION(pcidriver_store_umem_unmap) -{ - pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; - pcidriver_umem_entry_t *umem_entry; - unsigned int id; - - if (sscanf(buf, "%u", &id) != 1 || - (id >= atomic_read(&(privdata->umem_count)))) - goto err; - - if ((umem_entry = pcidriver_umem_find_entry_id(privdata, id)) == NULL) - goto err; - - pcidriver_umem_sgunmap(privdata, umem_entry); -err: - return strlen(buf); -} diff --git a/driver/sysfs.h b/driver/sysfs.h deleted file mode 100644 index 4c413f0..0000000 --- a/driver/sysfs.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _PCIDRIVER_SYSFS_H -#define _PCIDRIVER_SYSFS_H -int pcidriver_sysfs_initialize_kmem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr); -int pcidriver_sysfs_initialize_umem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr); -void pcidriver_sysfs_remove(pcidriver_privdata_t *privdata, struct class_device_attribute *sysfs_attr); - -#ifdef ENABLE_IRQ -SYSFS_GET_FUNCTION(pcidriver_show_irq_count); -SYSFS_GET_FUNCTION(pcidriver_show_irq_queues); -#endif - -/* prototypes for sysfs operations */ -SYSFS_GET_FUNCTION(pcidriver_show_mmap_mode); -SYSFS_SET_FUNCTION(pcidriver_store_mmap_mode); -SYSFS_GET_FUNCTION(pcidriver_show_mmap_area); -SYSFS_SET_FUNCTION(pcidriver_store_mmap_area); -SYSFS_GET_FUNCTION(pcidriver_show_kmem_count); -SYSFS_GET_FUNCTION(pcidriver_show_kbuffers); -SYSFS_SET_FUNCTION(pcidriver_store_kmem_alloc); -SYSFS_SET_FUNCTION(pcidriver_store_kmem_free); -SYSFS_GET_FUNCTION(pcidriver_show_umappings); -SYSFS_SET_FUNCTION(pcidriver_store_umem_unmap); -#endif diff --git a/driver/umem.c b/driver/umem.c deleted file mode 100644 index 7a8dcc1..0000000 --- a/driver/umem.c +++ /dev/null @@ -1,438 +0,0 @@ -/** - * - * @file umem.c - * @brief This file contains the functions handling user space memory. - * @author Guillermo Marcus - * @date 2009-04-05 - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" /* compile-time configuration */ -#include "compat.h" /* compatibility definitions for older linux */ -#include "pciDriver.h" /* external interface for the driver */ -#include "common.h" /* internal definitions for all parts */ -#include "umem.h" /* prototypes for kernel memory */ -#include "sysfs.h" /* prototypes for sysfs */ - -/** - * - * Reserve a new scatter/gather list and map it from memory to PCI bus addresses. - * - */ -int pcidriver_umem_sgmap(pcidriver_privdata_t *privdata, umem_handle_t *umem_handle) -{ - int i, res, nr_pages; - struct page **pages; - struct scatterlist *sg = NULL; - pcidriver_umem_entry_t *umem_entry; - unsigned int nents; - unsigned long count,offset,length; - - /* - * We do some checks first. Then, the following is necessary to create a - * Scatter/Gather list from a user memory area: - * - Determine the number of pages - * - Get the pages for the memory area - * - Lock them. - * - Create a scatter/gather list of the pages - * - Map the list from memory to PCI bus addresses - * - * Then, we: - * - Create an entry on the umem list of the device, to cache the mapping. - * - Create a sysfs attribute that gives easy access to the SG list - */ - - /* zero-size?? */ - if (umem_handle->size == 0) - return -EINVAL; - - /* Direction is better ignoring during mapping. */ - /* We assume bidirectional buffers always, except when sync'ing */ - - /* calculate the number of pages */ - nr_pages = ((umem_handle->vma & ~PAGE_MASK) + umem_handle->size + ~PAGE_MASK) >> PAGE_SHIFT; - - mod_info_dbg("nr_pages computed: %u\n", nr_pages); - - /* Allocate space for the page information */ - /* This can be very big, so we use vmalloc */ - if ((pages = vmalloc(nr_pages * sizeof(*pages))) == NULL) - return -ENOMEM; - - mod_info_dbg("allocated space for the pages.\n"); - - /* Allocate space for the scatterlist */ - /* We do not know how many entries will be, but the maximum is nr_pages. */ - /* This can be very big, so we use vmalloc */ - if ((sg = vmalloc(nr_pages * sizeof(*sg))) == NULL) - goto umem_sgmap_pages; - - sg_init_table(sg, nr_pages); - - mod_info_dbg("allocated space for the SG list.\n"); - - /* Get the page information */ - down_read(¤t->mm->mmap_sem); - res = get_user_pages( - current, - current->mm, - umem_handle->vma, - nr_pages, - 1, - 0, /* do not force, FIXME: shall I? */ - pages, - NULL ); - up_read(¤t->mm->mmap_sem); - - /* Error, not all pages mapped */ - if (res < (int)nr_pages) { - mod_info("Could not map all user pages (%d of %d)\n", res, nr_pages); - /* If only some pages could be mapped, we release those. If a real - * error occured, we set nr_pages to 0 */ - nr_pages = (res > 0 ? res : 0); - goto umem_sgmap_unmap; - } - - mod_info_dbg("Got the pages (%d).\n", res); - - /* Lock the pages, then populate the SG list with the pages */ - /* page0 is different */ - if ( !PageReserved(pages[0]) ) - compat_lock_page(pages[0]); - - offset = (umem_handle->vma & ~PAGE_MASK); - length = (umem_handle->size > (PAGE_SIZE-offset) ? (PAGE_SIZE-offset) : umem_handle->size); - - sg_set_page(&sg[0], pages[0], length, offset); - - count = umem_handle->size - length; - for(i=1;i PAGE_SIZE) ? PAGE_SIZE : count), 0); - count -= sg[i].length; - } - - /* Use the page list to populate the SG list */ - /* SG entries may be merged, res is the number of used entries */ - /* We have originally nr_pages entries in the sg list */ - if ((nents = pci_map_sg(privdata->pdev, sg, nr_pages, PCI_DMA_BIDIRECTIONAL)) == 0) - goto umem_sgmap_unmap; - - mod_info_dbg("Mapped SG list (%d entries).\n", nents); - - /* Add an entry to the umem_list of the device, and update the handle with the id */ - /* Allocate space for the new umem entry */ - if ((umem_entry = kmalloc(sizeof(*umem_entry), GFP_KERNEL)) == NULL) - goto umem_sgmap_entry; - - /* Fill entry to be added to the umem list */ - umem_entry->id = atomic_inc_return(&privdata->umem_count) - 1; - umem_entry->nr_pages = nr_pages; /* Will be needed when unmapping */ - umem_entry->pages = pages; - umem_entry->nents = nents; - umem_entry->sg = sg; - - if (pcidriver_sysfs_initialize_umem(privdata, umem_entry->id, &(umem_entry->sysfs_attr)) != 0) - goto umem_sgmap_name_fail; - - /* Add entry to the umem list */ - spin_lock( &(privdata->umemlist_lock) ); - list_add_tail( &(umem_entry->list), &(privdata->umem_list) ); - spin_unlock( &(privdata->umemlist_lock) ); - - /* Update the Handle with the Handle ID of the entry */ - umem_handle->handle_id = umem_entry->id; - - return 0; - -umem_sgmap_name_fail: - kfree(umem_entry); -umem_sgmap_entry: - pci_unmap_sg( privdata->pdev, sg, nr_pages, PCI_DMA_BIDIRECTIONAL ); -umem_sgmap_unmap: - /* release pages */ - if (nr_pages > 0) { - for(i=0;isysfs_attr)); - - /* Unmap user memory */ - pci_unmap_sg( privdata->pdev, umem_entry->sg, umem_entry->nr_pages, PCI_DMA_BIDIRECTIONAL ); - - /* Release the pages */ - if (umem_entry->nr_pages > 0) { - for(i=0;i<(umem_entry->nr_pages);i++) { - /* Mark pages as Dirty and unlock it */ - if ( !PageReserved( umem_entry->pages[i] )) { - SetPageDirty( umem_entry->pages[i] ); - compat_unlock_page(umem_entry->pages[i]); - } - /* and release it from the cache */ - page_cache_release( umem_entry->pages[i] ); - } - } - - /* Remove the umem list entry */ - spin_lock( &(privdata->umemlist_lock) ); - list_del( &(umem_entry->list) ); - spin_unlock( &(privdata->umemlist_lock) ); - - /* Release SG list and page list memory */ - /* These two are in the vm area of the kernel */ - vfree(umem_entry->pages); - vfree(umem_entry->sg); - - /* Release umem_entry memory */ - kfree(umem_entry); - - return 0; -} - -/** - * - * Unmap all scatter/gather lists. - * - */ -int pcidriver_umem_sgunmap_all(pcidriver_privdata_t *privdata) -{ - struct list_head *ptr, *next; - pcidriver_umem_entry_t *umem_entry; - - /* iterate safely over the entries and delete them */ - list_for_each_safe( ptr, next, &(privdata->umem_list) ) { - umem_entry = list_entry(ptr, pcidriver_umem_entry_t, list ); - pcidriver_umem_sgunmap( privdata, umem_entry ); /* spin lock inside! */ - } - - return 0; -} - -/** - * - * Copies the scatter/gather list from kernelspace to userspace. - * - */ -int pcidriver_umem_sgget(pcidriver_privdata_t *privdata, umem_sglist_t *umem_sglist) -{ - int i; - pcidriver_umem_entry_t *umem_entry; - struct scatterlist *sg; - int idx = 0; - dma_addr_t cur_addr; - unsigned int cur_size; - - /* Find the associated umem_entry for this buffer */ - umem_entry = pcidriver_umem_find_entry_id( privdata, umem_sglist->handle_id ); - if (umem_entry == NULL) - return -EINVAL; /* umem_handle is not valid */ - - /* Check if passed SG list is enough */ - if (umem_sglist->nents < umem_entry->nents) - return -EINVAL; /* sg has not enough entries */ - - /* Copy the SG list to the user format */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) - if (umem_sglist->type == PCIDRIVER_SG_MERGED) { - for_each_sg(umem_entry->sg, sg, umem_entry->nents, i ) { - if (i==0) { - umem_sglist->sg[0].addr = sg_dma_address( sg ); - umem_sglist->sg[0].size = sg_dma_len( sg ); - idx = 0; - } - else { - cur_addr = sg_dma_address( sg ); - cur_size = sg_dma_len( sg ); - - /* Check if entry fits after current entry */ - if (cur_addr == (umem_sglist->sg[idx].addr + umem_sglist->sg[idx].size)) { - umem_sglist->sg[idx].size += cur_size; - continue; - } - - /* Skip if the entry is zero-length (yes, it can happen.... at the end of the list) */ - if (cur_size == 0) - continue; - - /* None of the above, add new entry */ - idx++; - umem_sglist->sg[idx].addr = cur_addr; - umem_sglist->sg[idx].size = cur_size; - } - } - /* Set the used size of the SG list */ - umem_sglist->nents = idx+1; - } else { - for_each_sg(umem_entry->sg, sg, umem_entry->nents, i ) { - mod_info("entry: %d\n",i); - umem_sglist->sg[i].addr = sg_dma_address( sg ); - umem_sglist->sg[i].size = sg_dma_len( sg ); - } - - /* Set the used size of the SG list */ - /* Check if the last one is zero-length */ - if ( umem_sglist->sg[ umem_entry->nents - 1].size == 0) - umem_sglist->nents = umem_entry->nents -1; - else - umem_sglist->nents = umem_entry->nents; - } -#else - if (umem_sglist->type == PCIDRIVER_SG_MERGED) { - /* Merge entries that are contiguous into a single entry */ - /* Non-optimal but fast for most cases */ - /* First one always true */ - sg=umem_entry->sg; - umem_sglist->sg[0].addr = sg_dma_address( sg ); - umem_sglist->sg[0].size = sg_dma_len( sg ); - sg++; - idx = 0; - - /* Iterate over the SG entries */ - for(i=1; i< umem_entry->nents; i++, sg++ ) { - cur_addr = sg_dma_address( sg ); - cur_size = sg_dma_len( sg ); - - /* Check if entry fits after current entry */ - if (cur_addr == (umem_sglist->sg[idx].addr + umem_sglist->sg[idx].size)) { - umem_sglist->sg[idx].size += cur_size; - continue; - } - - /* Skip if the entry is zero-length (yes, it can happen.... at the end of the list) */ - if (cur_size == 0) - continue; - - /* None of the above, add new entry */ - idx++; - umem_sglist->sg[idx].addr = cur_addr; - umem_sglist->sg[idx].size = cur_size; - } - /* Set the used size of the SG list */ - umem_sglist->nents = idx+1; - } else { - /* Assume pci_map_sg made a good job (ehem..) and just copy it. - * actually, now I assume it just gives them plainly to me. */ - for(i=0, sg=umem_entry->sg ; i< umem_entry->nents; i++, sg++ ) { - umem_sglist->sg[i].addr = sg_dma_address( sg ); - umem_sglist->sg[i].size = sg_dma_len( sg ); - } - /* Set the used size of the SG list */ - /* Check if the last one is zero-length */ - if ( umem_sglist->sg[ umem_entry->nents - 1].size == 0) - umem_sglist->nents = umem_entry->nents -1; - else - umem_sglist->nents = umem_entry->nents; - } -#endif - - return 0; -} - -/** - * - * Sync user space memory from/to device - * - */ -int pcidriver_umem_sync( pcidriver_privdata_t *privdata, umem_handle_t *umem_handle ) -{ - pcidriver_umem_entry_t *umem_entry; - - /* Find the associated umem_entry for this buffer */ - umem_entry = pcidriver_umem_find_entry_id( privdata, umem_handle->handle_id ); - if (umem_entry == NULL) - return -EINVAL; /* umem_handle is not valid */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) - switch (umem_handle->dir) { - case PCIDRIVER_DMA_TODEVICE: - pci_dma_sync_sg_for_device( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_TODEVICE ); - break; - case PCIDRIVER_DMA_FROMDEVICE: - pci_dma_sync_sg_for_cpu( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_FROMDEVICE ); - break; - case PCIDRIVER_DMA_BIDIRECTIONAL: - pci_dma_sync_sg_for_device( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_BIDIRECTIONAL ); - pci_dma_sync_sg_for_cpu( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_BIDIRECTIONAL ); - break; - default: - return -EINVAL; /* wrong direction parameter */ - } -#else - switch (umem_handle->dir) { - case PCIDRIVER_DMA_TODEVICE: - pci_dma_sync_sg( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_TODEVICE ); - break; - case PCIDRIVER_DMA_FROMDEVICE: - pci_dma_sync_sg( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_FROMDEVICE ); - break; - case PCIDRIVER_DMA_BIDIRECTIONAL: - pci_dma_sync_sg( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_BIDIRECTIONAL ); - break; - default: - return -EINVAL; /* wrong direction parameter */ - } -#endif - - return 0; -} - -/* - * - * Get the pcidriver_umem_entry_t structure for the given id. - * - * @param id ID of the umem entry to search for - * - */ -pcidriver_umem_entry_t *pcidriver_umem_find_entry_id(pcidriver_privdata_t *privdata, int id) -{ - struct list_head *ptr; - pcidriver_umem_entry_t *entry; - - spin_lock(&(privdata->umemlist_lock)); - list_for_each(ptr, &(privdata->umem_list)) { - entry = list_entry(ptr, pcidriver_umem_entry_t, list ); - - if (entry->id == id) { - spin_unlock( &(privdata->umemlist_lock) ); - return entry; - } - } - - spin_unlock(&(privdata->umemlist_lock)); - return NULL; -} diff --git a/driver/umem.h b/driver/umem.h deleted file mode 100644 index d16c466..0000000 --- a/driver/umem.h +++ /dev/null @@ -1,5 +0,0 @@ -int pcidriver_umem_sgmap( pcidriver_privdata_t *privdata, umem_handle_t *umem_handle ); -int pcidriver_umem_sgunmap( pcidriver_privdata_t *privdata, pcidriver_umem_entry_t *umem_entry ); -int pcidriver_umem_sgget( pcidriver_privdata_t *privdata, umem_sglist_t *umem_sglist ); -int pcidriver_umem_sync( pcidriver_privdata_t *privdata, umem_handle_t *umem_handle ); -pcidriver_umem_entry_t *pcidriver_umem_find_entry_id( pcidriver_privdata_t *privdata, int id ); diff --git a/error.c b/error.c deleted file mode 100644 index b4f6e2e..0000000 --- a/error.c +++ /dev/null @@ -1,27 +0,0 @@ -#define _PCILIB_ERROR_C - -#include -#include - -#include "error.h" - -static void pcilib_print_error(const char *msg, ...) { - va_list va; - - va_start(va, msg); - vprintf(msg, va); - va_end(va); - printf("\n"); -} - -void (*pcilib_error)(const char *msg, ...) = pcilib_print_error; -void (*pcilib_warning)(const char *msg, ...) = pcilib_print_error; - -int pcilib_set_error_handler(void (*err)(const char *msg, ...), void (*warn)(const char *msg, ...)) { - if (err) pcilib_error = err; - else pcilib_error = pcilib_print_error; - if (warn) pcilib_warning = warn; - else pcilib_warning = pcilib_print_error; - - return 0; -} diff --git a/error.h b/error.h deleted file mode 100644 index 20d1c09..0000000 --- a/error.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _PCILIB_ERROR_H -#define _PCILIB_ERROR_H - -#include - -enum { - PCILIB_ERROR_SUCCESS = 0, - PCILIB_ERROR_MEMORY = ENOMEM, - PCILIB_ERROR_INVALID_REQUEST = EBADR, - PCILIB_ERROR_INVALID_ADDRESS = EFAULT, - PCILIB_ERROR_INVALID_BANK = ENOENT, - PCILIB_ERROR_INVALID_DATA = EILSEQ, - PCILIB_ERROR_INVALID_STATE = EBADFD, - PCILIB_ERROR_INVALID_ARGUMENT = EINVAL, - PCILIB_ERROR_TIMEOUT = ETIME, - PCILIB_ERROR_FAILED = EBADE, - PCILIB_ERROR_VERIFY = EREMOTEIO, - PCILIB_ERROR_NOTSUPPORTED = ENOTSUP, - PCILIB_ERROR_NOTFOUND = ESRCH, - PCILIB_ERROR_OUTOFRANGE = ERANGE, - PCILIB_ERROR_NOTAVAILABLE = ENAVAIL, - PCILIB_ERROR_NOTINITIALIZED = EBADFD, - PCILIB_ERROR_TOOBIG = EFBIG, - PCILIB_ERROR_OVERWRITTEN = ESTALE, - PCILIB_ERROR_BUSY = EBUSY -} pcilib_errot_t; - - -#ifndef _PCILIB_ERROR_C -extern void (*pcilib_error)(const char *msg, ...); -extern void (*pcilib_warning)(const char *msg, ...); -#endif /* _PCILIB_ERROR_C */ - -#endif /* _PCILIB_ERROR_H */ diff --git a/event.c b/event.c deleted file mode 100644 index d9d3ff3..0000000 --- a/event.c +++ /dev/null @@ -1,450 +0,0 @@ -#define _POSIX_C_SOURCE 199309L -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pci.h" - -#include "tools.h" -#include "error.h" - -#ifndef __timespec_defined -struct timespec { - time_t tv_sec; - long tv_nsec; -}; -#endif /* __timespec_defined */ - - -pcilib_event_t pcilib_find_event(pcilib_t *ctx, const char *event) { - int i; - - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - pcilib_event_description_t *events = model_info->events; - - for (i = 0; events[i].name; i++) { - if (!strcasecmp(events[i].name, event)) return events[i].evid; - } - - return (pcilib_event_t)-1; -} - -pcilib_event_data_type_t pcilib_find_event_data_type(pcilib_t *ctx, pcilib_event_t event, const char *data_type) { - int i; - - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - pcilib_event_data_type_description_t *data_types = model_info->data_types; - - for (i = 0; data_types[i].name; i++) { - if ((data_types[i].evid&event)&&(!strcasecmp(data_types[i].name, data_type))) return data_types[i].data_type; - } - - return (pcilib_event_data_type_t)-1; -} - -int pcilib_init_event_engine(pcilib_t *ctx) { - pcilib_event_api_description_t *api; - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - api = model_info->event_api; - -// api = pcilib_model[model].event_api; - if ((api)&&(api->init)) { - ctx->event_ctx = api->init(ctx); - if (ctx->event_ctx) { - ctx->event_ctx->pcilib = ctx; - } - } - - return 0; -} - -int pcilib_reset(pcilib_t *ctx) { - pcilib_event_api_description_t *api; - - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - api = model_info->event_api; - if (!api) { - pcilib_error("Event API is not supported by the selected model"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (api->reset) - return api->reset(ctx->event_ctx); - - return 0; -} - -int pcilib_configure_rawdata_callback(pcilib_t *ctx, pcilib_event_rawdata_callback_t callback, void *user) { - pcilib_event_api_description_t *api; - - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - api = model_info->event_api; - if (!api) { - pcilib_error("Event API is not supported by the selected model"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - ctx->event_ctx->params.rawdata.callback = callback; - ctx->event_ctx->params.rawdata.user = user; - - return 0; -} - -int pcilib_configure_autostop(pcilib_t *ctx, size_t max_events, pcilib_timeout_t duration) { - pcilib_event_api_description_t *api; - - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - api = model_info->event_api; - if (!api) { - pcilib_error("Event API is not supported by the selected model"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - ctx->event_ctx->params.autostop.max_events = max_events; - ctx->event_ctx->params.autostop.duration = duration; - - return 0; -} - -int pcilib_configure_autotrigger(pcilib_t *ctx, pcilib_timeout_t interval, pcilib_event_t event, size_t trigger_size, void *trigger_data) { - /* To support hardware without autotriggering, we need to provide in event.c a code - to generate multiple triggers in a thread (available in cli). The function should - be re-enabled afterwards: just set parameters and let implementation decide if it - can make triggering in hardware or will use our emulation */ - - return PCILIB_ERROR_NOTSUPPORTED; -} - -int pcilib_configure_preprocessing_threads(pcilib_t *ctx, size_t max_threads) { - pcilib_event_api_description_t *api; - - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - api = model_info->event_api; - if (!api) { - pcilib_error("Event API is not supported by the selected model"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - ctx->event_ctx->params.parallel.max_threads = max_threads; - - return 0; -} - -int pcilib_start(pcilib_t *ctx, pcilib_event_t event_mask, pcilib_event_flags_t flags) { - pcilib_event_api_description_t *api; - - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - api = model_info->event_api; - if (!api) { - pcilib_error("Event API is not supported by the selected model"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (api->start) - return api->start(ctx->event_ctx, event_mask, flags); - - return 0; -} - -int pcilib_stop(pcilib_t *ctx, pcilib_event_flags_t flags) { - pcilib_event_api_description_t *api; - - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - api = model_info->event_api; - if (!api) { - pcilib_error("Event API is not supported by the selected model"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (api->stop) - return api->stop(ctx->event_ctx, flags); - - return 0; -} - -int pcilib_stream(pcilib_t *ctx, pcilib_event_callback_t callback, void *user) { - pcilib_event_api_description_t *api; - - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - api = model_info->event_api; - if (!api) { - pcilib_error("Event API is not supported by the selected model"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (api->stream) - return api->stream(ctx->event_ctx, callback, user); - - if (api->next_event) { - pcilib_error("Streaming using next_event API is not implemented yet"); - } - - pcilib_error("Event enumeration is not suppored by API"); - return PCILIB_ERROR_NOTSUPPORTED; -} -/* -typedef struct { - pcilib_event_id_t event_id; - pcilib_event_info_t *info; -} pcilib_return_event_callback_context_t; - -static int pcilib_return_event_callback(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *user) { - pcilib_return_event_callback_context_t *ctx = (pcilib_return_event_callback_context_t*)user; - ctx->event_id = event_id; - ctx->info = info; -} -*/ - -int pcilib_get_next_event(pcilib_t *ctx, pcilib_timeout_t timeout, pcilib_event_id_t *evid, size_t info_size, pcilib_event_info_t *info) { - pcilib_event_api_description_t *api; -// pcilib_return_event_callback_context_t user; - - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - api = model_info->event_api; - if (!api) { - pcilib_error("Event API is not supported by the selected model"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (api->next_event) - return api->next_event(ctx->event_ctx, timeout, evid, info_size, info); - -/* - if (api->stream) { - err = api->stream(ctx->event_ctx, 1, timeout, pcilib_return_event_callback, &user); - if (err) return err; - - if (evid) *evid = user->event_id; - if (info) *info = user->info; - - return 0; - } -*/ - - pcilib_error("Event enumeration is not suppored by API"); - return PCILIB_ERROR_NOTSUPPORTED; -} - -int pcilib_trigger(pcilib_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) { - pcilib_event_api_description_t *api; - - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - api = model_info->event_api; - if (!api) { - pcilib_error("Event API is not supported by the selected model"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (api->trigger) - return api->trigger(ctx->event_ctx, event, trigger_size, trigger_data); - - pcilib_error("Self triggering is not supported by the selected model"); - return PCILIB_ERROR_NOTSUPPORTED; -} - - -void *pcilib_get_data_with_argument(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size) { - int err; - void *res = NULL; - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - pcilib_event_api_description_t *api = model_info->event_api; - if (!api) { - if (size) *size = (size_t)PCILIB_ERROR_NOTSUPPORTED; - pcilib_error("Event API is not supported by the selected model"); - return NULL; - } - - if (api->get_data) { - err = api->get_data(ctx->event_ctx, event_id, data_type, arg_size, arg, size, &res); - if (err) { - if (size) *size = (size_t)err; - return NULL; - } - return res; - } - - if (size) *size = (size_t)PCILIB_ERROR_NOTSUPPORTED; - return NULL; -} - -int pcilib_copy_data_with_argument(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t size, void *buf, size_t *retsize) { - int err; - void *res = buf; - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - pcilib_event_api_description_t *api = model_info->event_api; - if (!api) { - pcilib_error("Event API is not supported by the selected model"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (api->get_data) { - err = api->get_data(ctx->event_ctx, event_id, data_type, arg_size, arg, &size, &res); - if (err) return err; - - if (buf != res) memcpy(buf, res, size); - - if (retsize) *retsize = size; - return 0; - } - - return PCILIB_ERROR_NOTSUPPORTED; -} - - -void *pcilib_get_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size) { - int err; - void *res = NULL; - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - pcilib_event_api_description_t *api = model_info->event_api; - if (!api) { - pcilib_error("Event API is not supported by the selected model"); - if (size) *size = (size_t)PCILIB_ERROR_NOTSUPPORTED; - return NULL; - } - - if (api->get_data) { - err = api->get_data(ctx->event_ctx, event_id, data_type, 0, NULL, size, &res); - if (err) { - if (size) *size = (size_t)err; - return NULL; - } - return res; - } - - if (size) *size = (size_t)PCILIB_ERROR_NOTSUPPORTED; - return NULL; -} - -int pcilib_copy_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t size, void *buf, size_t *ret_size) { - int err; - void *res = buf; - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - pcilib_event_api_description_t *api = model_info->event_api; - if (!api) { - pcilib_error("Event API is not supported by the selected model"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (api->get_data) { - err = api->get_data(ctx->event_ctx, event_id, data_type, 0, NULL, &size, &res); - if (err) return err; - - if (buf != res) memcpy(buf, res, size); - - if (ret_size) *ret_size = size; - return 0; - } - - return PCILIB_ERROR_NOTSUPPORTED; -} - -int pcilib_return_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, void *data) { - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - pcilib_event_api_description_t *api = model_info->event_api; - if (!api) { - pcilib_error("Event API is not supported by the selected model"); - return PCILIB_ERROR_NOTSUPPORTED; - } - - if (api->return_data) - return api->return_data(ctx->event_ctx, event_id, data_type, data); - - return 0; -} - - -typedef struct { - pcilib_t *ctx; - - size_t *size; - void **data; -} pcilib_grab_callback_user_data_t; - - -static int pcilib_grab_callback(pcilib_event_t event, pcilib_event_id_t event_id, void *vuser) { - int err; - void *data; - size_t size; - int allocated = 0; - - pcilib_grab_callback_user_data_t *user = (pcilib_grab_callback_user_data_t*)vuser; - - data = pcilib_get_data(user->ctx, event_id, PCILIB_EVENT_DATA, &size); - if (!data) { - pcilib_error("Error getting event data"); - return -(int)size; - } - - if (*(user->data)) { - if ((user->size)&&(*(user->size) < size)) { - pcilib_error("The supplied buffer does not have enough space to hold the event data. Buffer size is %z, but %z is required", user->size, size); - return -PCILIB_ERROR_MEMORY; - } - - *(user->size) = size; - } else { - *(user->data) = malloc(size); - if (!*(user->data)) { - pcilib_error("Memory allocation (%i bytes) for event data is failed"); - return -PCILIB_ERROR_MEMORY; - } - if (*(user->size)) *(user->size) = size; - allocated = 1; - } - - memcpy(*(user->data), data, size); - - err = pcilib_return_data(user->ctx, event_id, PCILIB_EVENT_DATA, data); - if (err) { - if (allocated) { - free(*(user->data)); - *(user->data) = NULL; - } - pcilib_error("The event data had been overwritten before it was returned, data corruption may occur"); - return -err; - } - - return PCILIB_STREAMING_CONTINUE; -} - -int pcilib_grab(pcilib_t *ctx, pcilib_event_t event_mask, size_t *size, void **data, pcilib_timeout_t timeout) { - int err; - pcilib_event_id_t eid; - - pcilib_grab_callback_user_data_t user = {ctx, size, data}; - - err = pcilib_start(ctx, event_mask, PCILIB_EVENT_FLAGS_DEFAULT); - if (!err) err = pcilib_trigger(ctx, event_mask, 0, NULL); - if (!err) { - err = pcilib_get_next_event(ctx, timeout, &eid, 0, NULL); - if (!err) pcilib_grab_callback(event_mask, eid, &user); - } - pcilib_stop(ctx, PCILIB_EVENT_FLAGS_DEFAULT); - return err; -} diff --git a/event.h b/event.h deleted file mode 100644 index 0675b94..0000000 --- a/event.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef _PCILIB_EVENT_H -#define _PCILIB_EVENT_H - -#include "pcilib.h" - - -/* - * get_data: This call is used by get_data and copy_data functions of public - * interface. When copy_data is the caller, the data parameter will be passed. - * Therefore, depending on data the parameter, the function should behave - * diferently. If get get_data function is used (buf == NULL), the caller is - * expected to call return_data afterwards. Otherwise, if buf != NULL and - * copy_data is used, the return call will not be executed. - * Still, the get_data function is not obliged to return the data in the - * passed buf, but a reference to the staticaly allocated memory may be - * returned instead. The copy can be managed by the envelope function. - */ - -struct pcilib_event_api_description_s { - const char *title; - - pcilib_context_t *(*init)(pcilib_t *ctx); - void (*free)(pcilib_context_t *ctx); - - pcilib_dma_context_t *(*init_dma)(pcilib_context_t *ctx); - - int (*reset)(pcilib_context_t *ctx); - - int (*start)(pcilib_context_t *ctx, pcilib_event_t event_mask, pcilib_event_flags_t flags); - int (*stop)(pcilib_context_t *ctx, pcilib_event_flags_t flags); - int (*trigger)(pcilib_context_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data); - - int (*stream)(pcilib_context_t *ctx, pcilib_event_callback_t callback, void *user); - int (*next_event)(pcilib_context_t *ctx, pcilib_timeout_t timeout, pcilib_event_id_t *evid, size_t info_size, pcilib_event_info_t *info); - - int (*get_data)(pcilib_context_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size, void **data); - int (*return_data)(pcilib_context_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, void *data); -}; - - -typedef struct { - size_t max_events; - pcilib_timeout_t duration; -} pcilib_autostop_parameters_t; - -typedef struct { - pcilib_event_rawdata_callback_t callback; - void *user; -} pcilib_rawdata_parameters_t; - -typedef struct { - size_t max_threads; -} pcilib_parallel_parameters_t; - -typedef struct { - pcilib_autostop_parameters_t autostop; - pcilib_rawdata_parameters_t rawdata; - pcilib_parallel_parameters_t parallel; -} pcilib_event_parameters_t; - -struct pcilib_event_context_s { - pcilib_event_parameters_t params; - pcilib_t *pcilib; -}; - - -int pcilib_init_event_engine(pcilib_t *ctx); - -#endif /* _PCILIB_EVENT_H */ diff --git a/events.c b/events.c new file mode 100644 index 0000000..f942f0d --- /dev/null +++ b/events.c @@ -0,0 +1,160 @@ +#define _BSD_SOURCE +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "ipecamera.h" +#include "private.h" +#include "events.h" + +int ipecamera_stream(pcilib_context_t *vctx, pcilib_event_callback_t callback, void *user) { + int run_flag = 1; + int res, err = 0; + int do_stop = 0; + + ipecamera_event_info_t info; + ipecamera_t *ctx = (ipecamera_t*)vctx; + + if (!ctx) { + pcilib_error("IPECamera imaging is not initialized"); + return PCILIB_ERROR_NOTINITIALIZED; + } + + ctx->streaming = 1; + ctx->run_streamer = 1; + + if (!ctx->started) { + err = ipecamera_start(vctx, PCILIB_EVENTS_ALL, PCILIB_EVENT_FLAGS_DEFAULT); + if (err) { + ctx->streaming = 0; + return err; + } + + do_stop = 1; + } + + if (ctx->parse_data) { + // This loop iterates while the generation + while ((run_flag)&&((ctx->run_streamer)||(ctx->reported_id != ctx->event_id))) { +#ifdef IPECAMERA_ANNOUNCE_READY + while (((!ctx->preproc)&&(ctx->reported_id != ctx->event_id))||((ctx->preproc)&&(ctx->reported_id != ctx->preproc_id))) { +#else /* IPECAMERA_ANNOUNCE_READY */ + while (ctx->reported_id != ctx->event_id) { +#endif /* IPECAMERA_ANNOUNCE_READY */ + if ((ctx->event_id - ctx->reported_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) ctx->reported_id = ctx->event_id - (ctx->buffer_size - 1 - IPECAMERA_RESERVE_BUFFERS); + else ++ctx->reported_id; + + memcpy(&info, ctx->frame + ((ctx->reported_id-1)%ctx->buffer_size), sizeof(ipecamera_event_info_t)); + + if ((ctx->event_id - ctx->reported_id) < ctx->buffer_size) { + res = callback(ctx->reported_id, (pcilib_event_info_t*)&info, user); + if (res <= 0) { + if (res < 0) err = -res; + run_flag = 0; + break; + } + } + } + usleep(IPECAMERA_NOFRAME_SLEEP); + } + } else { + while ((run_flag)&&(ctx->run_streamer)) { + usleep(IPECAMERA_NOFRAME_SLEEP); + } + } + + ctx->streaming = 0; + + if (do_stop) { + ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); + } + + + return err; +} + +int ipecamera_next_event(pcilib_context_t *vctx, pcilib_timeout_t timeout, pcilib_event_id_t *evid, size_t info_size, pcilib_event_info_t *info) { + struct timeval tv; + ipecamera_t *ctx = (ipecamera_t*)vctx; + + if (!ctx) { + pcilib_error("IPECamera imaging is not initialized"); + return PCILIB_ERROR_NOTINITIALIZED; + } + + if (!ctx->started) { + pcilib_error("IPECamera is not in grabbing mode"); + return PCILIB_ERROR_INVALID_REQUEST; + } + + if (!ctx->parse_data) { + pcilib_error("RAWData only mode is requested"); + return PCILIB_ERROR_INVALID_REQUEST; + } + +#ifdef IPECAMERA_ANNOUNCE_READY + if (((!ctx->preproc)&&(ctx->reported_id == ctx->event_id))||((ctx->preproc)&&(ctx->reported_id == ctx->preproc_id))) { +#else /* IPECAMERA_ANNOUNCE_READY */ + if (ctx->reported_id == ctx->event_id) { +#endif /* IPECAMERA_ANNOUNCE_READY */ + + if (timeout) { + if (timeout == PCILIB_TIMEOUT_INFINITE) { +#ifdef IPECAMERA_ANNOUNCE_READY + while ((ctx->started)&&(((!ctx->preproc)&&(ctx->reported_id == ctx->event_id))||((ctx->preproc)&&(ctx->reported_id == ctx->preproc_id)))) { +#else /* IPECAMERA_ANNOUNCE_READY */ + while ((ctx->started)&&(ctx->reported_id == ctx->event_id)) { +#endif /* IPECAMERA_ANNOUNCE_READY */ + usleep(IPECAMERA_NOFRAME_SLEEP); + } + } else { + pcilib_calc_deadline(&tv, timeout); + +#ifdef IPECAMERA_ANNOUNCE_READY + while ((ctx->started)&&(pcilib_calc_time_to_deadline(&tv) > 0)&&(((!ctx->preproc)&&(ctx->reported_id == ctx->event_id))||((ctx->preproc)&&(ctx->reported_id == ctx->preproc_id)))) { +#else /* IPECAMERA_ANNOUNCE_READY */ + while ((ctx->started)&&(pcilib_calc_time_to_deadline(&tv) > 0)&&(ctx->reported_id == ctx->event_id)) { +#endif /* IPECAMERA_ANNOUNCE_READY */ + usleep(IPECAMERA_NOFRAME_SLEEP); + } + } + } + + if (ctx->reported_id == ctx->event_id) { + return PCILIB_ERROR_TIMEOUT; + } + + } + +retry: + if ((ctx->event_id - ctx->reported_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) ctx->reported_id = ctx->event_id - (ctx->buffer_size - 1 - IPECAMERA_RESERVE_BUFFERS); + else ++ctx->reported_id; + + if (evid) *evid = ctx->reported_id; + + if (info) { + if (info_size >= sizeof(ipecamera_event_info_t)) + memcpy(info, ctx->frame + ((ctx->reported_id-1)%ctx->buffer_size), sizeof(ipecamera_event_info_t)); + else if (info_size >= sizeof(pcilib_event_info_t)) + memcpy(info, ctx->frame + ((ctx->reported_id-1)%ctx->buffer_size), sizeof(pcilib_event_info_t)); + else + return PCILIB_ERROR_INVALID_ARGUMENT; + } + + if ((ctx->event_id - ctx->reported_id) >= ctx->buffer_size) goto retry; + + return 0; +} + diff --git a/events.h b/events.h new file mode 100644 index 0000000..5268c81 --- /dev/null +++ b/events.h @@ -0,0 +1,5 @@ +#ifndef _IPECAMERA_EVENTS_H +#define _IPECAMERA_EVENTS_H + + +#endif /* _IPECAMERA_EVENTS_H */ diff --git a/ipecamera.h b/ipecamera.h new file mode 100644 index 0000000..42994ba --- /dev/null +++ b/ipecamera.h @@ -0,0 +1,39 @@ +#ifndef _IPECAMERA_H +#define _IPECAMERA_H + +#include + +typedef struct ipecamera_s ipecamera_t; + +typedef struct { + unsigned int bpp; /*<< Bits per pixel (8, 16, or 32) as returned by IPECAMERA_IMAGE_DATA */ + unsigned int real_bpp; /*<< Bits per pixel as returned by camera and IPECAMERA_PACKED_IMAGE */ + unsigned int width, height; +} ipecamera_image_dimensions_t; + +typedef enum { + IPECAMERA_IMAGE_DATA = 0, + IPECAMERA_RAW_DATA = 1, + IPECAMERA_DIMENSIONS = 0x8000, + IPECAMERA_IMAGE_REGION = 0x8010, + IPECAMERA_PACKED_IMAGE = 0x8020, + IPECAMERA_PACKED_LINE = 0x8021, + IPECAMERA_PACKED_PAYLOAD = 0x8022, + IPECAMERA_CHANGE_MASK = 0x8030 +} ipecamera_data_type_t; + +typedef uint16_t ipecamera_change_mask_t; +typedef uint16_t ipecamera_pixel_t; + +typedef struct { + pcilib_event_info_t info; + UfoDecoderMeta meta; /**< Frame metadata declared in ufodecode.h */ + int image_ready; /**< Indicates if image data is parsed */ + int image_broken; /**< Unlike the info.flags this is bound to the reconstructed image (i.e. is not updated on rawdata overwrite) */ + size_t raw_size; /**< Indicates the actual size of raw data */ +} ipecamera_event_info_t; + +int ipecamera_set_buffer_size(ipecamera_t *ctx, int size); + + +#endif /* _IPECAMERA_H */ diff --git a/ipecamera/CMakeLists.txt b/ipecamera/CMakeLists.txt deleted file mode 100644 index 5b536f2..0000000 --- a/ipecamera/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -include_directories( - ${CMAKE_SOURCE_DIR} - ${UFODECODE_INCLUDE_DIRS} -) - -set(HEADERS ${HEADERS} ipecamera.h model.h reader.h events.h data.h public.h private.h) - -add_library(ipecamera STATIC ipecamera.c model.c reader.c events.c data.c) - -install(FILES ipecamera.h - DESTINATION include -) diff --git a/ipecamera/data.c b/ipecamera/data.c deleted file mode 100644 index 2bcccd5..0000000 --- a/ipecamera/data.c +++ /dev/null @@ -1,287 +0,0 @@ -#define _BSD_SOURCE -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "../tools.h" -#include "../error.h" - -#include "pcilib.h" -#include "private.h" -#include "data.h" - -// DS: Currently, on event_id overflow we are assuming the buffer is lost -static int ipecamera_resolve_event_id(ipecamera_t *ctx, pcilib_event_id_t evid) { - pcilib_event_id_t diff; - - if (evid > ctx->event_id) { - diff = (((pcilib_event_id_t)-1) - ctx->event_id) + evid; - if (diff >= ctx->buffer_size) return -1; - } else { - diff = ctx->event_id - evid; - if (diff >= ctx->buffer_size) return -1; - } - - // DS: Request buffer_size to be power of 2 and replace to shifts (just recompute in set_buffer_size) - return (evid - 1) % ctx->buffer_size; -} - -inline static int ipecamera_decode_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) { - int err = 0; - size_t res; - uint16_t *pixels; - - int buf_ptr = ipecamera_resolve_event_id(ctx, event_id); - if (buf_ptr < 0) return PCILIB_ERROR_TIMEOUT; - - if (ctx->frame[buf_ptr].event.image_ready) return 0; - - if (ctx->frame[buf_ptr].event.info.flags&PCILIB_EVENT_INFO_FLAG_BROKEN) { - err = PCILIB_ERROR_INVALID_DATA; - ctx->frame[buf_ptr].event.image_broken = err; - goto ready; - } - - - pixels = ctx->image + buf_ptr * ctx->image_size; - memset(ctx->cmask + ctx->buffer_pos * ctx->dim.height, 0, ctx->dim.height * sizeof(ipecamera_change_mask_t)); -/* - printf("decoding %lx...\n", ctx->raw_size); - FILE *f = fopen("/mnt/frame.xxx", "w"); - fwrite(ctx->buffer + buf_ptr * ctx->padded_size, 1, ctx->raw_size, f); - fclose(f);*/ - res = ufo_decoder_decode_frame(ctx->ipedec, ctx->buffer + buf_ptr * ctx->padded_size, ctx->raw_size, pixels, &ctx->frame[buf_ptr].event.meta); -// puts("done\n"); - if (!res) { -#ifdef IPECAMERA_DEBUG_BROKEN_FRAMES - char name[128]; - sprintf(name, "%s/broken.%4lu", IPECAMERA_DEBUG_BROKEN_FRAMES, ctx->event_id); - FILE *f = fopen(name, "w"); - if (f) { - fwrite(ctx->buffer + buf_ptr * ctx->padded_size, ctx->raw_size, 1, f); - fclose(f); - } -#endif /* IPECAMERA_DEBUG_BROKEN_FRAMES */ - err = PCILIB_ERROR_FAILED; - ctx->frame[buf_ptr].event.image_broken = err; - goto ready; - } - - ctx->frame[buf_ptr].event.image_broken = 0; - -ready: - ctx->frame[buf_ptr].event.image_ready = 1; - - if (ipecamera_resolve_event_id(ctx, event_id) < 0) { - ctx->frame[buf_ptr].event.image_ready = 0; - return PCILIB_ERROR_TIMEOUT; - } - - return err; -} - -static int ipecamera_get_next_buffer_to_process(ipecamera_t *ctx, pcilib_event_id_t *evid) { - int res; - - if (ctx->preproc_id == ctx->event_id) return -1; - - if (ctx->preproc) - pthread_mutex_lock(&ctx->preproc_mutex); - - if (ctx->preproc_id == ctx->event_id) { - if (ctx->preproc) - pthread_mutex_unlock(&ctx->preproc_mutex); - return -1; - } - - if ((ctx->event_id - ctx->preproc_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) ctx->preproc_id = ctx->event_id - (ctx->buffer_size - 1 - IPECAMERA_RESERVE_BUFFERS - 1); - - res = ctx->preproc_id%ctx->buffer_size; - - if (pthread_rwlock_trywrlock(&ctx->frame[res].mutex)) { - pthread_mutex_unlock(&ctx->preproc_mutex); - return -1; - } - - *evid = ++ctx->preproc_id; - - if (ctx->preproc) - pthread_mutex_unlock(&ctx->preproc_mutex); - - return res; -} - - -void *ipecamera_preproc_thread(void *user) { - int buf_ptr; - pcilib_event_id_t evid; - - ipecamera_preprocessor_t *preproc = (ipecamera_preprocessor_t*)user; - ipecamera_t *ctx = preproc->ipecamera; - - while (ctx->run_preprocessors) { - buf_ptr = ipecamera_get_next_buffer_to_process(ctx, &evid); - if (buf_ptr < 0) { - usleep(IPECAMERA_NOFRAME_PREPROC_SLEEP); - continue; - } - - ipecamera_decode_frame(ctx, evid); - - pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex); - } - - return NULL; -} - -static int ipecamera_get_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) { - int err; - int buf_ptr = (event_id - 1) % ctx->buffer_size; - - if (ctx->preproc) { - if (ctx->frame[buf_ptr].event.image_broken) - return ctx->frame[buf_ptr].event.image_broken; - } else { - pthread_rwlock_rdlock(&ctx->frame[buf_ptr].mutex); - - err = ipecamera_decode_frame(ctx, event_id); - - if (err) { - pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex); - return err; - } - - return 0; - } - - - while (!ctx->frame[buf_ptr].event.image_ready) { - usleep(IPECAMERA_NOFRAME_PREPROC_SLEEP); - - buf_ptr = ipecamera_resolve_event_id(ctx, event_id); - if (buf_ptr < 0) return PCILIB_ERROR_OVERWRITTEN; - } - - pthread_rwlock_rdlock(&ctx->frame[buf_ptr].mutex); - - buf_ptr = ipecamera_resolve_event_id(ctx, event_id); - if ((buf_ptr < 0)||(!ctx->frame[buf_ptr].event.image_ready)) { - pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex); - return PCILIB_ERROR_OVERWRITTEN; - } - - return 0; -} - - -/* - We will lock the data for non-raw data to prevent ocasional overwritting. The - raw data will be overwritten by the reader thread anyway and we can't do - anything to prevent it for performance reasons. -*/ -int ipecamera_get(pcilib_context_t *vctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size, void **ret) { - int err; - int buf_ptr; - size_t raw_size; - ipecamera_t *ctx = (ipecamera_t*)vctx; - - void *data = *ret; - - if (!ctx) { - pcilib_error("IPECamera imaging is not initialized"); - return PCILIB_ERROR_NOTINITIALIZED; - } - - buf_ptr = ipecamera_resolve_event_id(ctx, event_id); - if (buf_ptr < 0) return PCILIB_ERROR_OVERWRITTEN; - - switch ((ipecamera_data_type_t)data_type) { - case IPECAMERA_RAW_DATA: - raw_size = ctx->frame[buf_ptr].event.raw_size; - if (data) { - if ((!size)||(*size < raw_size)) return PCILIB_ERROR_TOOBIG; - memcpy(data, ctx->buffer + buf_ptr * ctx->padded_size, raw_size); - if (ipecamera_resolve_event_id(ctx, event_id) < 0) return PCILIB_ERROR_OVERWRITTEN; - *size = raw_size; - return 0; - } - if (size) *size = raw_size; - *ret = ctx->buffer + buf_ptr * ctx->padded_size; - return 0; - case IPECAMERA_IMAGE_DATA: - err = ipecamera_get_frame(ctx, event_id); - if (err) return err; - - if (data) { - if ((!size)||(*size < ctx->image_size * sizeof(ipecamera_pixel_t))) return PCILIB_ERROR_TOOBIG; - memcpy(data, ctx->image + buf_ptr * ctx->image_size, ctx->image_size * sizeof(ipecamera_pixel_t)); - pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex); - *size = ctx->image_size * sizeof(ipecamera_pixel_t); - return 0; - } - - if (size) *size = ctx->image_size * sizeof(ipecamera_pixel_t); - *ret = ctx->image + buf_ptr * ctx->image_size; - return 0; - case IPECAMERA_CHANGE_MASK: - err = ipecamera_get_frame(ctx, event_id); - if (err) return err; - - if (data) { - if ((!size)||(*size < ctx->dim.height * sizeof(ipecamera_change_mask_t))) return PCILIB_ERROR_TOOBIG; - memcpy(data, ctx->image + buf_ptr * ctx->dim.height, ctx->dim.height * sizeof(ipecamera_change_mask_t)); - pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex); - *size = ctx->dim.height * sizeof(ipecamera_change_mask_t); - return 0; - } - - if (size) *size = ctx->dim.height * sizeof(ipecamera_change_mask_t); - *ret = ctx->cmask + buf_ptr * ctx->dim.height; - return 0; - case IPECAMERA_DIMENSIONS: - if (size) *size = sizeof(ipecamera_image_dimensions_t); - ret = (void*)&ctx->dim; - return 0; - case IPECAMERA_IMAGE_REGION: - case IPECAMERA_PACKED_IMAGE: - // Shall we return complete image or only changed parts? - case IPECAMERA_PACKED_LINE: - case IPECAMERA_PACKED_PAYLOAD: - pcilib_error("Support for data type (%li) is not implemented yet", data_type); - return PCILIB_ERROR_NOTSUPPORTED; - default: - pcilib_error("Unknown data type (%li) is requested", data_type); - return PCILIB_ERROR_INVALID_REQUEST; - } -} - - -/* - We will unlock non-raw data and check if the raw data is not overwritten yet -*/ -int ipecamera_return(pcilib_context_t *vctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, void *data) { - ipecamera_t *ctx = (ipecamera_t*)vctx; - - if (!ctx) { - pcilib_error("IPECamera imaging is not initialized"); - return PCILIB_ERROR_NOTINITIALIZED; - - } - - if ((ipecamera_data_type_t)data_type == IPECAMERA_RAW_DATA) { - if (ipecamera_resolve_event_id(ctx, event_id) < 0) return PCILIB_ERROR_OVERWRITTEN; - } else { - int buf_ptr = (event_id - 1) % ctx->buffer_size; - pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex); - } - - return 0; -} diff --git a/ipecamera/data.h b/ipecamera/data.h deleted file mode 100644 index 846cb78..0000000 --- a/ipecamera/data.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _IPECAMERA_DATA_H -#define _IPECAMERA_DATA_H - -void *ipecamera_preproc_thread(void *user); - -#endif /* _IPECAMERA_DATA_H */ diff --git a/ipecamera/events.c b/ipecamera/events.c deleted file mode 100644 index ef85403..0000000 --- a/ipecamera/events.c +++ /dev/null @@ -1,160 +0,0 @@ -#define _BSD_SOURCE -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "../tools.h" -#include "../error.h" - -#include "pcilib.h" -#include "public.h" -#include "private.h" -#include "events.h" - -int ipecamera_stream(pcilib_context_t *vctx, pcilib_event_callback_t callback, void *user) { - int run_flag = 1; - int res, err = 0; - int do_stop = 0; - - ipecamera_event_info_t info; - ipecamera_t *ctx = (ipecamera_t*)vctx; - - if (!ctx) { - pcilib_error("IPECamera imaging is not initialized"); - return PCILIB_ERROR_NOTINITIALIZED; - } - - ctx->streaming = 1; - ctx->run_streamer = 1; - - if (!ctx->started) { - err = ipecamera_start(vctx, PCILIB_EVENTS_ALL, PCILIB_EVENT_FLAGS_DEFAULT); - if (err) { - ctx->streaming = 0; - return err; - } - - do_stop = 1; - } - - if (ctx->parse_data) { - // This loop iterates while the generation - while ((run_flag)&&((ctx->run_streamer)||(ctx->reported_id != ctx->event_id))) { -#ifdef IPECAMERA_ANNOUNCE_READY - while (((!ctx->preproc)&&(ctx->reported_id != ctx->event_id))||((ctx->preproc)&&(ctx->reported_id != ctx->preproc_id))) { -#else /* IPECAMERA_ANNOUNCE_READY */ - while (ctx->reported_id != ctx->event_id) { -#endif /* IPECAMERA_ANNOUNCE_READY */ - if ((ctx->event_id - ctx->reported_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) ctx->reported_id = ctx->event_id - (ctx->buffer_size - 1 - IPECAMERA_RESERVE_BUFFERS); - else ++ctx->reported_id; - - memcpy(&info, ctx->frame + ((ctx->reported_id-1)%ctx->buffer_size), sizeof(ipecamera_event_info_t)); - - if ((ctx->event_id - ctx->reported_id) < ctx->buffer_size) { - res = callback(ctx->reported_id, (pcilib_event_info_t*)&info, user); - if (res <= 0) { - if (res < 0) err = -res; - run_flag = 0; - break; - } - } - } - usleep(IPECAMERA_NOFRAME_SLEEP); - } - } else { - while ((run_flag)&&(ctx->run_streamer)) { - usleep(IPECAMERA_NOFRAME_SLEEP); - } - } - - ctx->streaming = 0; - - if (do_stop) { - ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - } - - - return err; -} - -int ipecamera_next_event(pcilib_context_t *vctx, pcilib_timeout_t timeout, pcilib_event_id_t *evid, size_t info_size, pcilib_event_info_t *info) { - struct timeval tv; - ipecamera_t *ctx = (ipecamera_t*)vctx; - - if (!ctx) { - pcilib_error("IPECamera imaging is not initialized"); - return PCILIB_ERROR_NOTINITIALIZED; - } - - if (!ctx->started) { - pcilib_error("IPECamera is not in grabbing mode"); - return PCILIB_ERROR_INVALID_REQUEST; - } - - if (!ctx->parse_data) { - pcilib_error("RAWData only mode is requested"); - return PCILIB_ERROR_INVALID_REQUEST; - } - -#ifdef IPECAMERA_ANNOUNCE_READY - if (((!ctx->preproc)&&(ctx->reported_id == ctx->event_id))||((ctx->preproc)&&(ctx->reported_id == ctx->preproc_id))) { -#else /* IPECAMERA_ANNOUNCE_READY */ - if (ctx->reported_id == ctx->event_id) { -#endif /* IPECAMERA_ANNOUNCE_READY */ - - if (timeout) { - if (timeout == PCILIB_TIMEOUT_INFINITE) { -#ifdef IPECAMERA_ANNOUNCE_READY - while ((ctx->started)&&(((!ctx->preproc)&&(ctx->reported_id == ctx->event_id))||((ctx->preproc)&&(ctx->reported_id == ctx->preproc_id)))) { -#else /* IPECAMERA_ANNOUNCE_READY */ - while ((ctx->started)&&(ctx->reported_id == ctx->event_id)) { -#endif /* IPECAMERA_ANNOUNCE_READY */ - usleep(IPECAMERA_NOFRAME_SLEEP); - } - } else { - pcilib_calc_deadline(&tv, timeout); - -#ifdef IPECAMERA_ANNOUNCE_READY - while ((ctx->started)&&(pcilib_calc_time_to_deadline(&tv) > 0)&&(((!ctx->preproc)&&(ctx->reported_id == ctx->event_id))||((ctx->preproc)&&(ctx->reported_id == ctx->preproc_id)))) { -#else /* IPECAMERA_ANNOUNCE_READY */ - while ((ctx->started)&&(pcilib_calc_time_to_deadline(&tv) > 0)&&(ctx->reported_id == ctx->event_id)) { -#endif /* IPECAMERA_ANNOUNCE_READY */ - usleep(IPECAMERA_NOFRAME_SLEEP); - } - } - } - - if (ctx->reported_id == ctx->event_id) { - return PCILIB_ERROR_TIMEOUT; - } - - } - -retry: - if ((ctx->event_id - ctx->reported_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) ctx->reported_id = ctx->event_id - (ctx->buffer_size - 1 - IPECAMERA_RESERVE_BUFFERS); - else ++ctx->reported_id; - - if (evid) *evid = ctx->reported_id; - - if (info) { - if (info_size >= sizeof(ipecamera_event_info_t)) - memcpy(info, ctx->frame + ((ctx->reported_id-1)%ctx->buffer_size), sizeof(ipecamera_event_info_t)); - else if (info_size >= sizeof(pcilib_event_info_t)) - memcpy(info, ctx->frame + ((ctx->reported_id-1)%ctx->buffer_size), sizeof(pcilib_event_info_t)); - else - return PCILIB_ERROR_INVALID_ARGUMENT; - } - - if ((ctx->event_id - ctx->reported_id) >= ctx->buffer_size) goto retry; - - return 0; -} - diff --git a/ipecamera/events.h b/ipecamera/events.h deleted file mode 100644 index 5268c81..0000000 --- a/ipecamera/events.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _IPECAMERA_EVENTS_H -#define _IPECAMERA_EVENTS_H - - -#endif /* _IPECAMERA_EVENTS_H */ diff --git a/ipecamera/ipecamera.c b/ipecamera/ipecamera.c deleted file mode 100644 index 892c59e..0000000 --- a/ipecamera/ipecamera.c +++ /dev/null @@ -1,695 +0,0 @@ -#define _IPECAMERA_IMAGE_C -#define _BSD_SOURCE -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "../tools.h" -#include "../error.h" -#include "../event.h" - -#include "pcilib.h" -#include "private.h" -#include "model.h" -#include "reader.h" -#include "events.h" -#include "data.h" - - -#include "dma/nwl.h" - -#define FIND_REG(var, bank, name) \ - ctx->var = pcilib_find_register(pcilib, bank, name); \ - if (ctx->var == PCILIB_REGISTER_INVALID) { \ - err = PCILIB_ERROR_NOTFOUND; \ - pcilib_error("Unable to find a %s register", name); \ - } - - -#define GET_REG(reg, var) \ - if (!err) { \ - err = pcilib_read_register_by_id(pcilib, ctx->reg, &var); \ - if (err) { \ - pcilib_error("Error reading %s register", ipecamera_registers[ctx->reg].name); \ - } \ - } - -#define SET_REG(reg, val) \ - if (!err) { \ - err = pcilib_write_register_by_id(pcilib, ctx->reg, val); \ - if (err) { \ - pcilib_error("Error writting %s register", ipecamera_registers[ctx->reg].name); \ - } \ - } - -#define CHECK_REG(reg, check) \ - if (!err) { \ - err = pcilib_read_register_by_id(pcilib, ctx->reg, &value); \ - if (err) { \ - pcilib_error("Error reading %s register", ipecamera_registers[ctx->reg].name); \ - } \ - if (value != check) { \ - pcilib_error("Unexpected value (0x%lx) of register %s", value, ipecamera_registers[ctx->reg].name); \ - err = PCILIB_ERROR_INVALID_DATA; \ - } \ - } - -#define IPECAMERA_GET_EXPECTED_STATUS(ctx) ((ctx->firmware == 4)?IPECAMERA_EXPECTED_STATUS_4:IPECAMERA_EXPECTED_STATUS) -#define CHECK_STATUS_REG() CHECK_REG(status_reg, IPECAMERA_GET_EXPECTED_STATUS(ctx)) - -#define CHECK_VALUE(value, val) \ - if ((!err)&&(value != val)) { \ - pcilib_error("Unexpected value (0x%x) in data stream (0x%x is expected)", value, val); \ - err = PCILIB_ERROR_INVALID_DATA; \ - } - -#define CHECK_FLAG(flag, check, ...) \ - if ((!err)&&(!(check))) { \ - pcilib_error("Unexpected value (0x%x) of " flag, __VA_ARGS__); \ - err = PCILIB_ERROR_INVALID_DATA; \ - } - - -pcilib_context_t *ipecamera_init(pcilib_t *pcilib) { - int err = 0; - - ipecamera_t *ctx = malloc(sizeof(ipecamera_t)); - - if (ctx) { - pcilib_register_value_t value; - - memset(ctx, 0, sizeof(ipecamera_t)); - - ctx->buffer_size = IPECAMERA_DEFAULT_BUFFER_SIZE; - ctx->dim.bpp = sizeof(ipecamera_pixel_t) * 8; - - // We need DMA engine initialized to resolve DMA registers -// FIND_REG(packet_len_reg, "fpga", "xrawdata_packet_length"); - - FIND_REG(status_reg, "fpga", "status"); - FIND_REG(control_reg, "fpga", "control"); - - FIND_REG(status2_reg, "fpga", "status2"); - FIND_REG(status3_reg, "fpga", "status3"); - - FIND_REG(n_lines_reg, "cmosis", "cmosis_number_lines"); - FIND_REG(line_reg, "cmosis", "cmosis_start1"); - FIND_REG(exposure_reg, "cmosis", "cmosis_exp_time"); - FIND_REG(flip_reg, "cmosis", "cmosis_image_flipping"); - - FIND_REG(firmware_version_reg, "fpga", "firmware_version"); - FIND_REG(adc_resolution_reg, "fpga", "adc_resolution"); - FIND_REG(output_mode_reg, "fpga", "output_mode"); - - FIND_REG(max_frames_reg, "fpga", "ddr_max_frames"); - FIND_REG(num_frames_reg, "fpga", "ddr_num_frames"); - - - GET_REG(firmware_version_reg, value); - switch (value) { - case 4: - case 5: - ctx->firmware = value; - break; - default: -// pcilib_error("Unsupported version of firmware (%lu)", value); - ctx->firmware = 0; - } - -#ifdef IPECAMERA_BUG_POSTPONED_READ - GET_REG(max_frames_reg, value); - if ((value + IPECAMERA_RESERVE_BUFFERS + 3) > ctx->buffer_size) { - ctx->buffer_size = (value + 1) + IPECAMERA_RESERVE_BUFFERS + 2; - } -#endif /* IPECAMERA_BUG_POSTPONED_READ */ - - - ctx->rdma = PCILIB_DMA_ENGINE_INVALID; - ctx->wdma = PCILIB_DMA_ENGINE_INVALID; - - if (err) { - free(ctx); - return NULL; - } - } - - return (pcilib_context_t*)ctx; -} - -void ipecamera_free(pcilib_context_t *vctx) { - if (vctx) { - ipecamera_t *ctx = (ipecamera_t*)vctx; - ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - free(ctx); - } -} - -pcilib_dma_context_t *ipecamera_init_dma(pcilib_context_t *vctx) { -#ifdef IPECAMERA_DMA_R3 - ipecamera_t *ctx = (ipecamera_t*)vctx; -#endif - - pcilib_model_description_t *model_info = pcilib_get_model_description(vctx->pcilib); - if ((!model_info->dma_api)||(!model_info->dma_api->init)) { - pcilib_error("The DMA engine is not configured in model"); - return NULL; - } - - -#ifdef IPECAMERA_DMA_R3 - if (ctx->firmware) { - return model_info->dma_api->init(vctx->pcilib, PCILIB_NWL_MODIFICATION_IPECAMERA, NULL); - } else { - return model_info->dma_api->init(vctx->pcilib, PCILIB_DMA_MODIFICATION_DEFAULT, NULL); - } -#else - return model_info->dma_api->init(vctx->pcilib, PCILIB_DMA_MODIFICATION_DEFAULT, NULL); -#endif -} - - -int ipecamera_set_buffer_size(ipecamera_t *ctx, int size) { - if (ctx->started) { - pcilib_error("Can't change buffer size while grabbing"); - return PCILIB_ERROR_INVALID_REQUEST; - } - - if (size < 2) { - pcilib_error("The buffer size is too small"); - return PCILIB_ERROR_INVALID_REQUEST; - } - - if (((size^(size-1)) < size) < size) { - pcilib_error("The buffer size is not power of 2"); - } - - ctx->buffer_size = size; - - return 0; -} - -int ipecamera_reset(pcilib_context_t *vctx) { - int err = 0; - ipecamera_t *ctx = (ipecamera_t*)vctx; - pcilib_t *pcilib = vctx->pcilib; - - pcilib_register_t control, status; - pcilib_register_value_t value; - - if (!ctx) { - pcilib_error("IPECamera imaging is not initialized"); - return PCILIB_ERROR_NOTINITIALIZED; - } - - if (!ctx->firmware) { - pcilib_warning("Unsupported version of firmware (%lu)", ctx->firmware); - return 0; - } - - pcilib = vctx->pcilib; - control = ctx->control_reg; - status = ctx->status_reg; - - // Set Reset bit to CMOSIS - err = pcilib_write_register_by_id(pcilib, control, 0x1e4); - if (err) { - pcilib_error("Error setting FPGA reset bit"); - return err; - } - usleep(IPECAMERA_SLEEP_TIME); - - // Remove Reset bit to CMOSIS - err = pcilib_write_register_by_id(pcilib, control, 0x1e1); - if (err) { - pcilib_error("Error reseting FPGA reset bit"); - return err; - } - usleep(IPECAMERA_SLEEP_TIME); - - // Special settings for CMOSIS v.2 - value = 01; err = pcilib_write_register_space(pcilib, "cmosis", 115, 1, &value); - if (err) { - pcilib_error("Error setting CMOSIS configuration"); - return err; - } - usleep(IPECAMERA_SLEEP_TIME); - - value = 07; err = pcilib_write_register_space(pcilib, "cmosis", 82, 1, &value); - if (err) { - pcilib_error("Error setting CMOSIS configuration"); - return err; - } - usleep(IPECAMERA_SLEEP_TIME); - - // Set default parameters - err = pcilib_write_register_by_id(pcilib, control, IPECAMERA_IDLE); - if (err) { - pcilib_error("Error bringing FPGA in default mode"); - return err; - } - - usleep(10000); - - err = pcilib_read_register_by_id(pcilib, status, &value); - if (err) { - pcilib_error("Error reading status register"); - return err; - } - - if (value != IPECAMERA_GET_EXPECTED_STATUS(ctx)) { - pcilib_error("Unexpected value (%lx) of status register, expected %lx", value, IPECAMERA_GET_EXPECTED_STATUS(ctx)); - return PCILIB_ERROR_VERIFY; - } - - return 0; -} - - -int ipecamera_start(pcilib_context_t *vctx, pcilib_event_t event_mask, pcilib_event_flags_t flags) { - int i; - int err = 0; - ipecamera_t *ctx = (ipecamera_t*)vctx; - pcilib_t *pcilib = vctx->pcilib; - pcilib_register_value_t value; - - pthread_attr_t attr; - struct sched_param sched; - - if (!ctx) { - pcilib_error("IPECamera imaging is not initialized"); - return PCILIB_ERROR_NOTINITIALIZED; - } - - if (!ctx->firmware) { - pcilib_error("Unsupported version of firmware (%lu)", ctx->firmware); - return PCILIB_ERROR_INVALID_REQUEST; - } - - if (ctx->started) { - pcilib_error("IPECamera grabbing is already started"); - return PCILIB_ERROR_INVALID_REQUEST; - } - - // Allow readout and clean the FRAME_REQUEST mode if set for some reason - usleep(IPECAMERA_SLEEP_TIME); - if (value&0x1000) ctx->fr_mode = 1; - else { - ctx->fr_mode = 0; - -// CHECK_STATUS_REG(); -// if (err) return err; - } - - ctx->event_id = 0; - ctx->preproc_id = 0; - ctx->reported_id = 0; - ctx->buffer_pos = 0; - ctx->parse_data = (flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY)?0:1; - ctx->cur_size = 0; - - ctx->dim.width = IPECAMERA_WIDTH; - ctx->dim.height = IPECAMERA_MAX_LINES; -// GET_REG(n_lines_reg, ctx->dim.height); - - GET_REG(output_mode_reg, value); - switch (value) { - case IPECAMERA_MODE_16_CHAN_IO: - ctx->cmosis_outputs = 16; - break; - case IPECAMERA_MODE_4_CHAN_IO: - ctx->cmosis_outputs = 4; - break; - default: - pcilib_error("IPECamera reporting invalid output_mode 0x%lx", value); - return PCILIB_ERROR_INVALID_STATE; - } - - ipecamera_compute_buffer_size(ctx, ctx->dim.height); - - ctx->raw_size = ctx->cur_raw_size; - ctx->full_size = ctx->cur_full_size; - ctx->padded_size = ctx->cur_padded_size; - - ctx->image_size = ctx->dim.width * ctx->dim.height; - - - GET_REG(max_frames_reg, value); - ctx->max_frames = value; - - ctx->buffer = malloc(ctx->padded_size * ctx->buffer_size); - if (!ctx->buffer) { - ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - pcilib_error("Unable to allocate ring buffer (%lu bytes)", ctx->padded_size * ctx->buffer_size); - return PCILIB_ERROR_MEMORY; - } - - ctx->image = (ipecamera_pixel_t*)malloc(ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t)); - if (!ctx->image) { - ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - pcilib_error("Unable to allocate image buffer (%lu bytes)", ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t)); - return PCILIB_ERROR_MEMORY; - } - - ctx->cmask = malloc(ctx->dim.height * ctx->buffer_size * sizeof(ipecamera_change_mask_t)); - if (!ctx->cmask) { - ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - pcilib_error("Unable to allocate change-mask buffer"); - return PCILIB_ERROR_MEMORY; - } - - ctx->frame = (ipecamera_frame_t*)malloc(ctx->buffer_size * sizeof(ipecamera_frame_t)); - if (!ctx->frame) { - ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - pcilib_error("Unable to allocate frame-info buffer"); - return PCILIB_ERROR_MEMORY; - } - - memset(ctx->frame, 0, ctx->buffer_size * sizeof(ipecamera_frame_t)); - - for (i = 0; i < ctx->buffer_size; i++) { - err = pthread_rwlock_init(&ctx->frame[i].mutex, NULL); - if (err) break; - } - - ctx->frame_mutex_destroy = i; - - if (err) { - ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - pcilib_error("Initialization of rwlock mutexes for frame synchronization has failed"); - return PCILIB_ERROR_FAILED; - } - - ctx->ipedec = ufo_decoder_new(ctx->dim.height, ctx->dim.width, NULL, 0); - if (!ctx->ipedec) { - ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - pcilib_error("Unable to initialize IPECamera decoder library"); - return PCILIB_ERROR_FAILED; - } - - if (!err) { - ctx->rdma = pcilib_find_dma_by_addr(vctx->pcilib, PCILIB_DMA_FROM_DEVICE, IPECAMERA_DMA_ADDRESS); - if (ctx->rdma == PCILIB_DMA_ENGINE_INVALID) { - err = PCILIB_ERROR_NOTFOUND; - pcilib_error("The C2S channel of IPECamera DMA Engine (%u) is not found", IPECAMERA_DMA_ADDRESS); - } else { - err = pcilib_start_dma(vctx->pcilib, ctx->rdma, PCILIB_DMA_FLAGS_DEFAULT); - if (err) { - ctx->rdma = PCILIB_DMA_ENGINE_INVALID; - pcilib_error("Failed to initialize C2S channel of IPECamera DMA Engine (%u)", IPECAMERA_DMA_ADDRESS); - } - } - } - -/* - if (!err) { - ctx->wdma = pcilib_find_dma_by_addr(vctx->pcilib, PCILIB_DMA_TO_DEVICE, IPECAMERA_DMA_ADDRESS); - if (ctx->wdma == PCILIB_DMA_ENGINE_INVALID) { - err = PCILIB_ERROR_NOTFOUND; - pcilib_error("The S2C channel of IPECamera DMA Engine (%u) is not found", IPECAMERA_DMA_ADDRESS); - } else { - err = pcilib_start_dma(vctx->pcilib, ctx->wdma, PCILIB_DMA_FLAGS_DEFAULT); - if (err) { - ctx->wdma = PCILIB_DMA_ENGINE_INVALID; - pcilib_error("Failed to initialize S2C channel of IPECamera DMA Engine (%u)", IPECAMERA_DMA_ADDRESS); - } - } - } -*/ - -/* - SET_REG(packet_len_reg, IPECAMERA_DMA_PACKET_LENGTH); -*/ - - if (err) { - ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - return err; - } - - // Clean DMA -#ifndef IPECAMERA_BUG_POSTPONED_READ - err = pcilib_skip_dma(vctx->pcilib, ctx->rdma); - if (err) { - ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - pcilib_error("Can't start grabbing, device continuously writes unexpected data using DMA engine"); - return err; - } -#endif /* ! IPECAMERA_BUG_POSTPONED_READ */ - - if (vctx->params.autostop.duration) { - gettimeofday(&ctx->autostop.timestamp, NULL); - ctx->autostop.timestamp.tv_usec += vctx->params.autostop.duration % 1000000; - if (ctx->autostop.timestamp.tv_usec > 999999) { - ctx->autostop.timestamp.tv_sec += 1 + vctx->params.autostop.duration / 1000000; - ctx->autostop.timestamp.tv_usec -= 1000000; - } else { - ctx->autostop.timestamp.tv_sec += vctx->params.autostop.duration / 1000000; - } - } - - if (vctx->params.autostop.max_events) { - ctx->autostop.evid = vctx->params.autostop.max_events; - } - - if ((ctx->parse_data)&&(flags&PCILIB_EVENT_FLAG_PREPROCESS)) { - ctx->n_preproc = pcilib_get_cpu_count(); - - // it would be greate to detect hyperthreading cores and ban them - switch (ctx->n_preproc) { - case 1: break; - case 2 ... 3: ctx->n_preproc -= 1; break; - default: ctx->n_preproc -= 2; break; - } - - if ((vctx->params.parallel.max_threads)&&(vctx->params.parallel.max_threads < ctx->n_preproc)) - ctx->n_preproc = vctx->params.parallel.max_threads; - - ctx->preproc = (ipecamera_preprocessor_t*)malloc(ctx->n_preproc * sizeof(ipecamera_preprocessor_t)); - if (!ctx->preproc) { - ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - pcilib_error("Unable to allocate memory for preprocessor contexts"); - return PCILIB_ERROR_MEMORY; - } - - memset(ctx->preproc, 0, ctx->n_preproc * sizeof(ipecamera_preprocessor_t)); - - err = pthread_mutex_init(&ctx->preproc_mutex, NULL); - if (err) { - ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - pcilib_error("Failed to initialize event mutex"); - return PCILIB_ERROR_FAILED; - } - ctx->preproc_mutex_destroy = 1; - - - ctx->run_preprocessors = 1; - for (i = 0; i < ctx->n_preproc; i++) { - ctx->preproc[i].i = i; - ctx->preproc[i].ipecamera = ctx; - err = pthread_create(&ctx->preproc[i].thread, NULL, ipecamera_preproc_thread, ctx->preproc + i); - if (err) { - err = PCILIB_ERROR_FAILED; - break; - } else { - ctx->preproc[i].started = 1; - } - } - - if (err) { - ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - pcilib_error("Failed to schedule some of the preprocessor threads"); - return err; - } - } else { - ctx->n_preproc = 0; - } - - ctx->started = 1; - ctx->run_reader = 1; - - pthread_attr_init(&attr); - - if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) { - pcilib_warning("Can't schedule a real-time thread, you may consider running as root"); - } else { - sched.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1; // Let 1 priority for something really critcial - pthread_attr_setschedparam(&attr, &sched); - } - - if (pthread_create(&ctx->rthread, &attr, &ipecamera_reader_thread, (void*)ctx)) { - ctx->started = 0; - ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - err = PCILIB_ERROR_FAILED; - } - - pthread_attr_destroy(&attr); - - return err; -} - - -int ipecamera_stop(pcilib_context_t *vctx, pcilib_event_flags_t flags) { - int i; - int err; - void *retcode; - ipecamera_t *ctx = (ipecamera_t*)vctx; - - if (!ctx) { - pcilib_error("IPECamera imaging is not initialized"); - return PCILIB_ERROR_NOTINITIALIZED; - } - - if (flags&PCILIB_EVENT_FLAG_STOP_ONLY) { - ctx->run_reader = 0; - return 0; - } - - if (ctx->started) { - ctx->run_reader = 0; - err = pthread_join(ctx->rthread, &retcode); - if (err) pcilib_error("Error joining the reader thread"); - } - - if (ctx->preproc) { - ctx->run_preprocessors = 0; - - for (i = 0; i < ctx->n_preproc; i++) { - if (ctx->preproc[i].started) { - pthread_join(ctx->preproc[i].thread, &retcode); - ctx->preproc[i].started = 0; - } - } - - if (ctx->preproc_mutex_destroy) { - pthread_mutex_destroy(&ctx->preproc_mutex); - ctx->preproc_mutex_destroy = 0; - } - - free(ctx->preproc); - ctx->preproc = NULL; - } - - if (ctx->frame_mutex_destroy) { - for (i = 0; i < ctx->frame_mutex_destroy; i++) { - pthread_rwlock_destroy(&ctx->frame[i].mutex); - } - ctx->frame_mutex_destroy = 0; - } - - - if (ctx->wdma != PCILIB_DMA_ENGINE_INVALID) { - pcilib_stop_dma(vctx->pcilib, ctx->wdma, PCILIB_DMA_FLAGS_DEFAULT); - ctx->wdma = PCILIB_DMA_ENGINE_INVALID; - } - - if (ctx->rdma != PCILIB_DMA_ENGINE_INVALID) { - pcilib_stop_dma(vctx->pcilib, ctx->rdma, PCILIB_DMA_FLAGS_DEFAULT); - ctx->rdma = PCILIB_DMA_ENGINE_INVALID; - } - - while (ctx->streaming) { - usleep(IPECAMERA_NOFRAME_SLEEP); - } - - if (ctx->ipedec) { - ufo_decoder_free(ctx->ipedec); - ctx->ipedec = NULL; - } - - if (ctx->frame) { - free(ctx->frame); - ctx->frame = NULL; - } - - if (ctx->cmask) { - free(ctx->cmask); - ctx->cmask = NULL; - } - - if (ctx->image) { - free(ctx->image); - ctx->image = NULL; - } - - if (ctx->buffer) { - free(ctx->buffer); - ctx->buffer = NULL; - } - - - memset(&ctx->autostop, 0, sizeof(ipecamera_autostop_t)); - - ctx->event_id = 0; - ctx->reported_id = 0; - ctx->buffer_pos = 0; - ctx->started = 0; - - return 0; -} - - -int ipecamera_trigger(pcilib_context_t *vctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) { - int err = 0; - pcilib_register_value_t value; - - ipecamera_t *ctx = (ipecamera_t*)vctx; - pcilib_t *pcilib = vctx->pcilib; - - if (!ctx) { - pcilib_error("IPECamera imaging is not initialized"); - return PCILIB_ERROR_NOTINITIALIZED; - } - - if (!ctx->firmware) { - pcilib_error("Unsupported version of firmware (%lu)", ctx->firmware); - return PCILIB_ERROR_INVALID_REQUEST; - } - - pcilib_sleep_until_deadline(&ctx->next_trigger); -/* - GET_REG(num_frames_reg, value); - if (value == ctx->max_frames) { - return PCILIB_ERROR_BUSY; - } -*/ - - GET_REG(status2_reg, value); - if (value&0x40000000) { -// printf("%x\n", value); -// GET_REG(status3_reg, value); -// printf("3: %x\n", value); -// GET_REG(status_reg, value); -// printf("1: %x\n", value); - -#ifdef IPECAMERA_TRIGGER_WAIT_IDLE - if (IPECAMERA_TRIGGER_WAIT_IDLE) { - struct timeval deadline; - pcilib_calc_deadline(&deadline, IPECAMERA_TRIGGER_WAIT_IDLE); - do { - usleep(IPECAMERA_READ_STATUS_DELAY); - GET_REG(status2_reg, value); - } while ((value&0x40000000)&&(pcilib_calc_time_to_deadline(&deadline) > 0)); - } - if (value&0x40000000) -#endif /* IPECAMERA_TRIGGER_WAIT_IDLE */ - return PCILIB_ERROR_BUSY; - } - - GET_REG(control_reg, value); - SET_REG(control_reg, value|IPECAMERA_FRAME_REQUEST); - usleep(IPECAMERA_WAIT_FRAME_RCVD_TIME); - //CHECK_REG(status_reg, IPECAMERA_EXPECTED_STATUS); - SET_REG(control_reg, value); - - // We need to compute it differently, on top of that add exposure time and the time FPGA takes to read frame from CMOSIS - pcilib_calc_deadline(&ctx->next_trigger, IPECAMERA_NEXT_FRAME_DELAY); - - return 0; -} diff --git a/ipecamera/ipecamera.h b/ipecamera/ipecamera.h deleted file mode 100644 index 673eea1..0000000 --- a/ipecamera/ipecamera.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _IPECAMERA_H -#define _IPECAMERA_H - -#include - -typedef struct ipecamera_s ipecamera_t; - -typedef struct { - unsigned int bpp; /*<< Bits per pixel (8, 16, or 32) as returned by IPECAMERA_IMAGE_DATA */ - unsigned int real_bpp; /*<< Bits per pixel as returned by camera and IPECAMERA_PACKED_IMAGE */ - unsigned int width, height; -} ipecamera_image_dimensions_t; - -typedef enum { - IPECAMERA_IMAGE_DATA = 0, - IPECAMERA_RAW_DATA = 1, - IPECAMERA_DIMENSIONS = 0x8000, - IPECAMERA_IMAGE_REGION = 0x8010, - IPECAMERA_PACKED_IMAGE = 0x8020, - IPECAMERA_PACKED_LINE = 0x8021, - IPECAMERA_PACKED_PAYLOAD = 0x8022, - IPECAMERA_CHANGE_MASK = 0x8030 -} ipecamera_data_type_t; - -typedef uint16_t ipecamera_change_mask_t; -typedef uint16_t ipecamera_pixel_t; - -typedef struct { - pcilib_event_info_t info; - UfoDecoderMeta meta; /**< Frame metadata declared in ufodecode.h */ - int image_ready; /**< Indicates if image data is parsed */ - int image_broken; /**< Unlike the info.flags this is bound to the reconstructed image (i.e. is not updated on rawdata overwrite) */ - size_t raw_size; /**< Indicates the actual size of raw data */ -} ipecamera_event_info_t; - -int ipecamera_set_buffer_size(ipecamera_t *ctx, int size); - -#endif /* _IPECAMERA_H */ diff --git a/ipecamera/model.c b/ipecamera/model.c deleted file mode 100644 index e60561b..0000000 --- a/ipecamera/model.c +++ /dev/null @@ -1,211 +0,0 @@ -#define _BSD_SOURCE -#define _IPECAMERA_MODEL_C -#include -#include -#include - -#include "../tools.h" -#include "../error.h" -#include "model.h" - -#define ADDR_MASK 0x7F00 -#define WRITE_BIT 0x8000 -#define RETRIES 10 - -//ToDo: check bot 1 and 2 bits for READY -#define READ_READY_BIT 0x20000 -#define READ_ERROR_BIT 0x40000 - -#define ipecamera_datacpy(dst, src, bank) pcilib_datacpy(dst, src, 4, 1, bank->raw_endianess) - -//#define IPECAMERA_SIMPLIFIED_READOUT -#define IPECAMERA_MULTIREAD - -//static pcilib_register_value_t ipecamera_bit_mask[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 }; - -int ipecamera_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *value) { - uint32_t val, tmp[4]; - char *wr, *rd; - struct timeval start;//, cur; - int retries = RETRIES; - - assert(addr < 128); - - wr = pcilib_resolve_register_address(ctx, bank->bar, bank->write_addr); - rd = pcilib_resolve_register_address(ctx, bank->bar, bank->read_addr); - if ((!rd)||(!wr)) { - pcilib_error("Error resolving addresses of read & write registers"); - return PCILIB_ERROR_INVALID_ADDRESS; - } - - //printf("%i %x %p %p\n", addr, val, wr, rd); - -/* -#ifdef IPECAMERA_SIMPLIFIED_READOUT - ipecamera_datacpy(tmp, rd, bank); -#endif -*/ - -retry: - val = (addr << 8); - - ipecamera_datacpy(wr, &val, bank); - -#ifdef IPECAMERA_SIMPLIFIED_READOUT - usleep(PCILIB_REGISTER_TIMEOUT); -// ipecamera_datacpy(tmp, rd, bank); -// usleep(PCILIB_REGISTER_TIMEOUT); - ipecamera_datacpy(wr, &val, bank); - usleep(PCILIB_REGISTER_TIMEOUT); -// ipecamera_datacpy(tmp, rd, bank); -// usleep(PCILIB_REGISTER_TIMEOUT); - ipecamera_datacpy(wr, &val, bank); - usleep(PCILIB_REGISTER_TIMEOUT); -#endif /* IPECAMERA_SIMPLIFIED_READOUT */ - - gettimeofday(&start, NULL); - -#ifdef IPECAMERA_MULTIREAD - usleep(PCILIB_REGISTER_TIMEOUT); - pcilib_datacpy(tmp, rd, 4, 4, bank->raw_endianess); - val = tmp[0]; -#else /* IPECAMERA_MULTIREAD */ - ipecamera_datacpy(&val, rd, bank); - - while ((val & READ_READY_BIT) == 0) { - gettimeofday(&cur, NULL); - if (((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) > PCILIB_REGISTER_TIMEOUT) break; - - ipecamera_datacpy(&val, rd, bank); - } -#endif /* IPECAMERA_MULTIREAD */ - - if ((val & READ_READY_BIT) == 0) { - if (--retries > 0) { - pcilib_warning("Timeout reading register value (CMOSIS %lu, status: %lx), retrying (try %i of %i)...", addr, val, RETRIES - retries, RETRIES); - goto retry; - } - pcilib_error("Timeout reading register value (CMOSIS %lu, status: %lx)", addr, val); - return PCILIB_ERROR_TIMEOUT; - } - - if (val & READ_ERROR_BIT) { -/* if (--retries > 0) { - pcilib_warning("Error reading register (CMOSIS %lu, status: %lx), retrying (try %i of %i)...", addr, val, RETRIES - retries, RETRIES); - goto retry; - }*/ - pcilib_error("Error reading register value (CMOSIS %lu, status: %lx)", addr, val); - return PCILIB_ERROR_FAILED; - } - - if (((val&ADDR_MASK) >> 8) != addr) { - if (--retries > 0) { - pcilib_warning("Address verification failed during register read (CMOSIS %lu, status: %lx), retrying (try %i of %i)...", addr, val, RETRIES - retries, RETRIES); - goto retry; - } - pcilib_error("Address verification failed during register read (CMOSIS %lu, status: %lx)", addr, val); - return PCILIB_ERROR_VERIFY; - } - -// *value = val&ipecamera_bit_mask[bits]; - *value = val&0xFF; - - return 0; -} - -int ipecamera_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t value) { - uint32_t val, tmp[4]; - char *wr, *rd; - struct timeval start;//, cur; - int retries = RETRIES; - - assert(addr < 128); - assert(value < 256); - - wr = pcilib_resolve_register_address(ctx, bank->bar, bank->write_addr); - rd = pcilib_resolve_register_address(ctx, bank->bar, bank->read_addr); - if ((!rd)||(!wr)) { - pcilib_error("Error resolving addresses of read & write registers"); - return PCILIB_ERROR_INVALID_ADDRESS; - } - - //printf("%i %x %p %p\n", addr, val, wr, rd); - -/* -#ifdef IPECAMERA_SIMPLIFIED_READOUT - ipecamera_datacpy(tmp, rd, bank); -#endif -*/ - -retry: - val = WRITE_BIT|(addr << 8)|(value&0xFF); - ipecamera_datacpy(wr, &val, bank); - -#ifdef IPECAMERA_SIMPLIFIED_READOUT - usleep(PCILIB_REGISTER_TIMEOUT); -// ipecamera_datacpy(tmp, rd, bank); -// usleep(PCILIB_REGISTER_TIMEOUT); - ipecamera_datacpy(wr, &val, bank); - usleep(PCILIB_REGISTER_TIMEOUT); -// ipecamera_datacpy(tmp, rd, bank); -// usleep(PCILIB_REGISTER_TIMEOUT); - ipecamera_datacpy(wr, &val, bank); - usleep(PCILIB_REGISTER_TIMEOUT); -#endif /* IPECAMERA_SIMPLIFIED_READOUT */ - - gettimeofday(&start, NULL); - -#ifdef IPECAMERA_MULTIREAD - usleep(PCILIB_REGISTER_TIMEOUT); - pcilib_datacpy(tmp, rd, 4, 4, bank->raw_endianess); - val = tmp[0]; -#else /* IPECAMERA_MULTIREAD */ - ipecamera_datacpy(&val, rd, bank); - while ((val & READ_READY_BIT) == 0) { - gettimeofday(&cur, NULL); - if (((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) > PCILIB_REGISTER_TIMEOUT) break; - - ipecamera_datacpy(&val, rd, bank); - } -#endif /* IPECAMERA_MULTIREAD */ - - if ((val & READ_READY_BIT) == 0) { - if (--retries > 0) { - pcilib_warning("Timeout occured during register write (CMOSIS %lu, value: %lu, status: %lx), retrying (try %i of %i)...", addr, value, val, RETRIES - retries, RETRIES); - goto retry; - } - - pcilib_error("Timeout writting register value (CMOSIS %lu, value: %lu, status: %lx)", addr, value, val); - return PCILIB_ERROR_TIMEOUT; - } - - if (val & READ_ERROR_BIT) { -/* if (--retries > 0) { - pcilib_warning("Register write has failed (CMOSIS %lu, value: %lu, status: %lx), retrying (try %i of %i)...", addr, value, val, RETRIES - retries, RETRIES); - goto retry; - }*/ - pcilib_error("Error writting register value (CMOSIS %lu, value: %lu, status: %lx)", addr, value, val); - return PCILIB_ERROR_FAILED; - } - - if (((val&ADDR_MASK) >> 8) != addr) { - if (--retries > 0) { - pcilib_warning("Address verification failed during register write (CMOSIS %lu, value: %lu, status: %lx), retrying (try %i of %i)...", addr, value, val, RETRIES - retries, RETRIES); - goto retry; - } - pcilib_error("Address verification failed during register write (CMOSIS %lu, value: %lu, status: %lx)", addr, value, val); - return PCILIB_ERROR_VERIFY; - } - - if ((val&0xFF/*&ipecamera_bit_mask[bits]*/) != value) { - pcilib_error("Value verification failed during register read (CMOSIS %lu, value: %lu != %lu)", addr, val/*&ipecamera_bit_mask[bits]*/, value); - return PCILIB_ERROR_VERIFY; - } - - //printf("%i\n", val&ipecamera_bit_mask[bits]); - - return 0; -} - - - diff --git a/ipecamera/model.h b/ipecamera/model.h deleted file mode 100644 index 60226f0..0000000 --- a/ipecamera/model.h +++ /dev/null @@ -1,180 +0,0 @@ -#ifndef _IPECAMERA_MODEL_H -#define _IPECAMERA_MODEL_H - -#include - -#include "../pcilib.h" -#include "public.h" - -//#define IPECAMERA_DEBUG - -#define IPECAMERA_DMA_R3 -#define IPECAMERA_DMA_ADDRESS 0 -#define IPECAMERA_DMA_PACKET_LENGTH 4096 - -//#define IPECAMERA_REGISTER_SPACE 0xfeaffc00 -#define IPECAMERA_REGISTER_SPACE 0x9000 -#define IPECAMERA_REGISTER_WRITE (IPECAMERA_REGISTER_SPACE + 0) -#define IPECAMERA_REGISTER_READ (IPECAMERA_REGISTER_WRITE + 16) - -#ifdef _IPECAMERA_MODEL_C -pcilib_register_bank_description_t ipecamera_register_banks[] = { - { PCILIB_REGISTER_BANK0, PCILIB_BAR0, 128, IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ , IPECAMERA_REGISTER_WRITE, PCILIB_LITTLE_ENDIAN, 8 , PCILIB_LITTLE_ENDIAN, "%lu" , "cmosis", "CMOSIS CMV2000 Registers" }, - { PCILIB_REGISTER_BANK1, PCILIB_BAR0, 0x0200, PCILIB_DEFAULT_PROTOCOL , IPECAMERA_REGISTER_SPACE, IPECAMERA_REGISTER_SPACE, PCILIB_LITTLE_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "0x%lx", "fpga", "IPECamera Registers" }, -// { PCILIB_REGISTER_BANK_DMA, PCILIB_BAR0, 0xA000, PCILIB_DEFAULT_PROTOCOL , 0, 0, PCILIB_LITTLE_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "0x%lx", "dma", "DMA Registers"}, - { PCILIB_REGISTER_BANK_DMA, PCILIB_BAR0, 0x0200, PCILIB_DEFAULT_PROTOCOL , 0, 0, PCILIB_LITTLE_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "0x%lx", "dma", "DMA Registers"}, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } -}; - -pcilib_register_description_t ipecamera_registers[] = { -{1, 0, 16, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines", ""}, -{3, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start1", ""}, -{5, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start2", ""}, -{7, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start3", ""}, -{9, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start4", ""}, -{11, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start5", ""}, -{13, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start6", ""}, -{15, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start7", ""}, -{17, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start8", ""}, -{19, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines1", ""}, -{21, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines2", ""}, -{23, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines3", ""}, -{25, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines4", ""}, -{27, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines5", ""}, -{29, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines6", ""}, -{31, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines7", ""}, -{33, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines8", ""}, -{35, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_sub_s", ""}, -{37, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_sub_a", ""}, -{39, 0, 1, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_color", ""}, -{40, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_image_flipping", ""}, -{41, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_flags", ""}, -{42, 0, 24, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_time", ""}, -{45, 0, 24, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_step", ""}, -{48, 0, 24, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_kp1", ""}, -{51, 0, 24, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_kp2", ""}, -{54, 0, 2, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_nr_slopes", ""}, -{55, 0, 8, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_seq", ""}, -{56, 0, 24, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_time2", ""}, -{59, 0, 24, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_step2", ""}, -{68, 0, 2, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_nr_slopes2", ""}, -{69, 0, 8, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_seq2", ""}, -{70, 0, 16, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_frames", ""}, -{72, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_output_mode", ""}, -{78, 0, 12, 85, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_training_pattern", ""}, -{80, 0, 18, 0x3FFFF,0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_channel_en", ""}, -{82, 0, 3, 7, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_special_82", ""}, -{89, 0, 8, 96, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_vlow2", ""}, -{90, 0, 8, 96, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_vlow3", ""}, -{100, 0, 14, 16260, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_offset", ""}, -{102, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_pga", ""}, -{103, 0, 8, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_adc_gain", ""}, -{111, 0, 1, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_bit_mode", ""}, -{112, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_adc_resolution", ""}, -{115, 0, 1, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_special_115", ""}, -/*{126, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "temp", ""},*/ -{0x00, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "spi_conf_input", ""}, -{0x10, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "spi_conf_output", ""}, -{0x20, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "spi_clk_speed", ""}, -{0x30, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "firmware_info", ""}, -{0x30, 0, 8, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "firmware_version", ""}, -{0x30, 8, 1, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "firmware_bitmode", ""}, -{0x30, 12, 2, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "adc_resolution", ""}, -{0x30, 16, 2, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "output_mode", ""}, -{0x40, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "control", ""}, -{0x50, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "status", ""}, -{0x54, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "status2", ""}, -{0x58, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "status3", ""}, -{0x5c, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "fr_status", ""}, -{0x70, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "start_address", ""}, -{0x74, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "end_address", ""}, -{0x78, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "rd_address", ""}, -{0xa0, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "fr_param1", ""}, -{0xa0, 0, 10, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "fr_skip_lines", ""}, -{0xa0, 10, 11, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "fr_num_lines", ""}, -{0xa0, 21, 11, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "fr_start_address", ""}, -{0xb0, 0, 32, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "fr_param2", ""}, -{0xb0, 0, 11, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "fr_threshold_start_line", ""}, -{0xb0, 16, 10, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "fr_area_lines", ""}, -{0xc0, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "skiped_lines", ""}, -{0xd0, 0, 32, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "fr_thresholds", ""}, -{0xd0, 0, 10, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "fr_pixel_thr", ""}, -{0xd0, 10, 11, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "fr_num_pixel_thr", ""}, -{0xd0, 21, 11, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "fr_num_lines_thr", ""}, -{0x100, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "rawdata_pkt_addr", ""}, -{0x110, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "temperature_info", ""}, -{0x110, 0, 16, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "sensor_temperature", ""}, -{0x110, 16, 3, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "sensor_temperature_alarms", ""}, -{0x110, 19, 10, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "fpga_temperature", ""}, -{0x110, 29, 3, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "fpga_temperature_alarms", ""}, -{0x120, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "num_lines", ""}, -{0x130, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "start_line", ""}, -{0x140, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "exp_time", ""}, -{0x150, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "motor", ""}, -{0x150, 0, 5, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "motor_phi", ""}, -{0x150, 5, 5, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "motor_z", ""}, -{0x150, 10, 5, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "motor_y", ""}, -{0x150, 15, 5, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "motor_x", ""}, -{0x150, 20, 8, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "adc_gain", ""}, -{0x160, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "write_status", ""}, -{0x170, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "num_triggers", ""}, -{0x180, 0, 32, 0x280, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "trigger_period", ""}, -{0x190, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "temperature_sample_period", ""}, -{0x1a0, 0, 32, 0x64, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "ddr_max_frames", ""}, -{0x1b0, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "ddr_num_frames", ""}, -{0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL} -}; - -pcilib_register_range_t ipecamera_register_ranges[] = { -// {0xF000, 0xF000 + 128, PCILIB_REGISTER_BANK0, 0}, -// {0x9000, 0x9FFF, PCILIB_REGISTER_BANK1, -0x9000}, - {0, 0, 0, 0} -}; - -pcilib_event_description_t ipecamera_events[] = { - {PCILIB_EVENT0, "new_frame", ""}, - {0, NULL, NULL} -}; - -pcilib_event_data_type_description_t ipecamera_data_types[] = { - {IPECAMERA_IMAGE_DATA, PCILIB_EVENT0, "image", "16 bit pixel data" }, - {IPECAMERA_RAW_DATA, PCILIB_EVENT0, "raw", "raw data from camera" }, - {IPECAMERA_CHANGE_MASK, PCILIB_EVENT0, "cmask", "change mask" }, - {0, 0, NULL, NULL} -}; - -#else -extern pcilib_register_description_t ipecamera_registers[]; -extern pcilib_register_bank_description_t ipecamera_register_banks[]; -extern pcilib_register_range_t ipecamera_register_ranges[]; -extern pcilib_event_description_t ipecamera_events[]; -extern pcilib_event_data_type_description_t ipecamera_data_types[]; -#endif - -#ifdef _IPECAMERA_IMAGE_C -pcilib_event_api_description_t ipecamera_image_api = { - "ipecamera", - - ipecamera_init, - ipecamera_free, - - ipecamera_init_dma, - - ipecamera_reset, - ipecamera_start, - ipecamera_stop, - ipecamera_trigger, - - ipecamera_stream, - ipecamera_next_event, - ipecamera_get, - ipecamera_return -}; -#else -extern pcilib_event_api_description_t ipecamera_image_api; -#endif - -int ipecamera_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *value); -int ipecamera_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t value); - -#endif /* _IPECAMERA_MODEL_H */ diff --git a/ipecamera/private.h b/ipecamera/private.h deleted file mode 100644 index cf2d689..0000000 --- a/ipecamera/private.h +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef _IPECAMERA_PRIVATE_H -#define _IPECAMERA_PRIVATE_H - -#include "ipecamera.h" - -#define IPECAMERA_BUG_EXTRA_DATA -#define IPECAMERA_BUG_MULTIFRAME_PACKETS //**< this is by design, start of packet comes directly after the end of last one in streaming mode */ -//#define IPECAMERA_BUG_INCOMPLETE_PACKETS -#define IPECAMERA_BUG_POSTPONED_READ -#define IPECAMERA_DEBUG_BROKEN_FRAMES "/mnt/frames" -//#define IPECAMERA_DEBUG_RAW_PACKETS "/mnt/frames" - -//#define IPECAMERA_ANNOUNCE_READY //**< announce new event only after the reconstruction is done */ - -#define IPECAMERA_DEFAULT_BUFFER_SIZE 64 //**< should be power of 2 */ -#define IPECAMERA_RESERVE_BUFFERS 2 //**< Return Frame is Lost error, if requested frame will be overwritten after specified number of frames -#define IPECAMERA_SLEEP_TIME 250000 //**< Michele thinks 250 should be enough, but reset failing in this case */ -#define IPECAMERA_NEXT_FRAME_DELAY 1000 //**< Michele requires 30000 to sync between End Of Readout and next Frame Req */ -#define IPECAMERA_WAIT_FRAME_RCVD_TIME 0 //**< by Uros ,wait 6 ms */ -#define IPECAMERA_TRIGGER_WAIT_IDLE 200000 //**< In trigger call allow specified timeout for camera to get out of busy state. Set 0 to fail immideatly */ -#define IPECAMERA_READ_STATUS_DELAY 1000 //**< According to Uros, 1ms delay needed before consequitive reads from status registers */ - -#define IPECAMERA_NOFRAME_SLEEP 100 -#define IPECAMERA_NOFRAME_PREPROC_SLEEP 100 - -//#define IPECAMERA_MAX_LINES 1088 -#define IPECAMERA_MAX_LINES 2048 -#define IPECAMERA_EXPECTED_STATUS_4 0x08409FFFF -#define IPECAMERA_EXPECTED_STATUS 0x08449FFFF - -#define IPECAMERA_END_OF_SEQUENCE 0x1F001001 - -#define IPECAMERA_MAX_CHANNELS 16 -#define IPECAMERA_PIXELS_PER_CHANNEL 128 -#define IPECAMERA_WIDTH (IPECAMERA_MAX_CHANNELS * IPECAMERA_PIXELS_PER_CHANNEL) - -#define IPECAMERA_FRAME_REQUEST 0x80000209 // 0x1E9 -#define IPECAMERA_IDLE 0x80000201 // 0x1E1 -#define IPECAMERA_START_INTERNAL_STIMULI 0x1F1 - -#define IPECAMERA_MODE_16_CHAN_IO 0 -#define IPECAMERA_MODE_4_CHAN_IO 2 - -#define IPECAMERA_MODE_12_BIT_ADC 2 -#define IPECAMERA_MODE_11_BIT_ADC 1 -#define IPECAMERA_MODE_10_BIT_ADC 0 - -typedef uint32_t ipecamera_payload_t; - -typedef struct { - pcilib_event_id_t evid; - struct timeval timestamp; -} ipecamera_autostop_t; - -typedef struct { - size_t i; - pthread_t thread; - ipecamera_t *ipecamera; - - int started; /**< flag indicating that join & cleanup is required */ -} ipecamera_preprocessor_t; - - -typedef struct { - ipecamera_event_info_t event; /**< this structure is overwritten by the reader thread, we need a copy */ - pthread_rwlock_t mutex; /**< this mutex protects reconstructed buffers only, the raw data, event_info, etc. will be overwritten by reader thread anyway */ -} ipecamera_frame_t; - -struct ipecamera_s { - pcilib_context_t event; - UfoDecoder *ipedec; - - char *data; - ipecamera_pixel_t *image; - size_t size; - - pcilib_event_callback_t cb; - void *cb_user; - - volatile pcilib_event_id_t event_id; - volatile pcilib_event_id_t preproc_id; - pcilib_event_id_t reported_id; - - pcilib_dma_engine_t rdma, wdma; - - pcilib_register_t packet_len_reg; - pcilib_register_t control_reg, status_reg; - pcilib_register_t status2_reg, status3_reg; - pcilib_register_t n_lines_reg; - uint16_t line_reg; - pcilib_register_t exposure_reg; - pcilib_register_t flip_reg; - - pcilib_register_t firmware_version_reg; - pcilib_register_t adc_resolution_reg; - pcilib_register_t output_mode_reg; - - pcilib_register_t max_frames_reg; - pcilib_register_t num_frames_reg; - - int started; /**< Camera is in grabbing mode (start function is called) */ - int streaming; /**< Camera is in streaming mode (we are within stream call) */ - int parse_data; /**< Indicates if some processing of the data is required, otherwise only rawdata_callback will be called */ - - volatile int run_reader; /**< Instructs the reader thread to stop processing */ - volatile int run_streamer; /**< Indicates request to stop streaming events and can be set by reader_thread upon exit or by user request */ - volatile int run_preprocessors; /**< Instructs preprocessors to exit */ - - ipecamera_autostop_t autostop; - - struct timeval autostop_time; - struct timeval next_trigger; /**< The minimal delay between trigger signals is mandatory, this indicates time when next trigger is possible */ - - size_t buffer_size; /**< How many images to store */ - size_t buffer_pos; /**< Current image offset in the buffer, due to synchronization reasons should not be used outside of reader_thread */ - size_t cur_size; /**< Already written part of data in bytes */ - size_t raw_size; /**< Size of raw data in bytes */ - size_t full_size; /**< Size of raw data including the padding */ - size_t padded_size; /**< Size of buffer for raw data, including the padding for performance */ - size_t cur_raw_size; /**< Size of raw data in bytes */ - size_t cur_full_size; /**< Size of raw data including the padding */ - size_t cur_padded_size; /**< Size of buffer for raw data, including the padding for performance */ - - size_t image_size; /**< Size of a single image in bytes */ - - size_t max_frames; /**< Maximal number of frames what may be buffered in camera DDR memory */ - int firmware; /**< Firmware version */ - int fr_mode; /**< Fast Reject mode */ - int cmosis_outputs; /**< Number of active cmosis outputs: 4 or 16 */ - int width, height; - - -// void *raw_buffer; - void *buffer; - ipecamera_change_mask_t *cmask; - ipecamera_frame_t *frame; - - - ipecamera_image_dimensions_t dim; - - pthread_t rthread; - - size_t n_preproc; - ipecamera_preprocessor_t *preproc; - pthread_mutex_t preproc_mutex; - - int preproc_mutex_destroy; - int frame_mutex_destroy; -}; - -#endif /* _IPECAMERA_PRIVATE_H */ diff --git a/ipecamera/public.h b/ipecamera/public.h deleted file mode 100644 index 5f494c2..0000000 --- a/ipecamera/public.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _IPECAMERA_PUBLIC_H -#define _IPECAMERA_PUBLIC_H - -#include - -#include "ipecamera.h" -#include "../pcilib.h" - - -pcilib_context_t *ipecamera_init(pcilib_t *pcilib); -void ipecamera_free(pcilib_context_t *ctx); - -pcilib_dma_context_t *ipecamera_init_dma(pcilib_context_t *ctx); - -int ipecamera_reset(pcilib_context_t *ctx); -int ipecamera_start(pcilib_context_t *ctx, pcilib_event_t event_mask, pcilib_event_flags_t flags); -int ipecamera_stop(pcilib_context_t *ctx, pcilib_event_flags_t flags); -int ipecamera_trigger(pcilib_context_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data); -int ipecamera_stream(pcilib_context_t *vctx, pcilib_event_callback_t callback, void *user); -int ipecamera_next_event(pcilib_context_t *vctx, pcilib_timeout_t timeout, pcilib_event_id_t *evid, size_t info_size, pcilib_event_info_t *info); - -int ipecamera_get(pcilib_context_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size, void **buf); -int ipecamera_return(pcilib_context_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, void *data); - -#endif /* _IPECAMERA_PUBLIC_H */ diff --git a/ipecamera/reader.c b/ipecamera/reader.c deleted file mode 100644 index cad5da8..0000000 --- a/ipecamera/reader.c +++ /dev/null @@ -1,273 +0,0 @@ -#define _BSD_SOURCE -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "../tools.h" -#include "../error.h" - -#include "pcilib.h" -#include "model.h" -#include "private.h" -#include "reader.h" - - -int ipecamera_compute_buffer_size(ipecamera_t *ctx, size_t lines) { - const size_t header_size = 8 * sizeof(ipecamera_payload_t); - const size_t footer_size = 8 * sizeof(ipecamera_payload_t); - - size_t line_size, raw_size, padded_blocks; - - switch (ctx->firmware) { - case 4: - line_size = IPECAMERA_MAX_CHANNELS * (2 + IPECAMERA_PIXELS_PER_CHANNEL / 3) * sizeof(ipecamera_payload_t); - raw_size = header_size + lines * line_size + footer_size; - break; - default: - line_size = (1 + IPECAMERA_PIXELS_PER_CHANNEL) * 32; - raw_size = lines * line_size; - raw_size *= 16 / ctx->cmosis_outputs; - raw_size += header_size + footer_size; - } - - padded_blocks = raw_size / IPECAMERA_DMA_PACKET_LENGTH + ((raw_size % IPECAMERA_DMA_PACKET_LENGTH)?1:0); - - ctx->cur_raw_size = raw_size; - ctx->cur_full_size = padded_blocks * IPECAMERA_DMA_PACKET_LENGTH; - -#ifdef IPECAMERA_BUG_EXTRA_DATA - ctx->cur_full_size += 8; - padded_blocks ++; -#endif /* IPECAMERA_BUG_EXTRA_DATA */ - - ctx->cur_padded_size = padded_blocks * IPECAMERA_DMA_PACKET_LENGTH; -// printf("%lu %lu %lu\n", ctx->cur_raw_size, ctx->cur_full_size, ctx->cur_padded_size); - - return 0; -} - -static inline int ipecamera_new_frame(ipecamera_t *ctx) { - ctx->frame[ctx->buffer_pos].event.raw_size = ctx->cur_size; - - if (ctx->cur_size < ctx->cur_raw_size) { - ctx->frame[ctx->buffer_pos].event.info.flags |= PCILIB_EVENT_INFO_FLAG_BROKEN; - } - - ctx->buffer_pos = (++ctx->event_id) % ctx->buffer_size; - ctx->cur_size = 0; - - ctx->frame[ctx->buffer_pos].event.info.type = PCILIB_EVENT0; - ctx->frame[ctx->buffer_pos].event.info.flags = 0; - ctx->frame[ctx->buffer_pos].event.image_ready = 0; - - if ((ctx->event_id == ctx->autostop.evid)&&(ctx->event_id)) { - ctx->run_reader = 0; - return 1; - } - - if (pcilib_check_deadline(&ctx->autostop.timestamp, PCILIB_DMA_TIMEOUT)) { - ctx->run_reader = 0; - return 1; - } - - return 0; -} - -static uint32_t frame_magic[5] = { 0x51111111, 0x52222222, 0x53333333, 0x54444444, 0x55555555 }; - -static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t bufsize, void *buf) { - int res; - int eof = 0; - -#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS - size_t real_size; - size_t extra_data = 0; -#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */ - - ipecamera_t *ctx = (ipecamera_t*)user; - -#if defined(IPECAMERA_BUG_INCOMPLETE_PACKETS)||defined(IPECAMERA_BUG_MULTIFRAME_PACKETS) - static pcilib_event_id_t invalid_frame_id = (pcilib_event_id_t)-1; -#endif - -#ifdef IPECAMERA_DEBUG_RAW_PACKETS - char fname[128]; - { - static unsigned long packet_id = 0; - sprintf(fname,"%s/frame%4lu", IPECAMERA_DEBUG_RAW_PACKETS, ctx->event_id); - mkdir(fname, 0755); - sprintf(fname,"%s/frame%4lu/frame%9lu", IPECAMERA_DEBUG_RAW_PACKETS, ctx->event_id, packet_id); - FILE *f = fopen(fname, "w"); - if (f) { - fwrite(buf, 1, bufsize, f); - fclose(f); - } - sprintf(fname,"%s/frame%4lu/frame%9lu.invalid", IPECAMERA_DEBUG_RAW_PACKETS, ctx->event_id, packet_id++); - } -#endif /* IPECAMERA_DEBUG_RAW_PACKETS */ - - if (!ctx->cur_size) { -#if defined(IPECAMERA_BUG_INCOMPLETE_PACKETS)||defined(IPECAMERA_BUG_MULTIFRAME_PACKETS) - size_t startpos; - for (startpos = 0; (startpos + sizeof(frame_magic)) < bufsize; startpos += sizeof(uint32_t)) { - if (!memcmp(buf + startpos, frame_magic, sizeof(frame_magic))) break; - } - - if ((startpos + sizeof(frame_magic)) >= bufsize) { -#ifdef IPECAMERA_DEBUG_RAW_PACKETS - FILE *f = fopen(fname, "w"); - if (f) fclose(f); -#endif /* IPECAMERA_DEBUG_RAW_PACKETS */ - - if (invalid_frame_id != ctx->event_id) { -// pcilib_warning("No frame magic in DMA packet of %u bytes, current event %lu (got %lu)", bufsize, ctx->event_id, invalid_frame_id); - invalid_frame_id = ctx->event_id; - } - - return PCILIB_STREAMING_CONTINUE; - } - - if (startpos) { - // pass padding to rawdata callback - if (ctx->event.params.rawdata.callback) { - res = ctx->event.params.rawdata.callback(0, NULL, PCILIB_EVENT_FLAG_RAW_DATA_ONLY, startpos, buf, ctx->event.params.rawdata.user); - if (res <= 0) { - if (res < 0) return res; - ctx->run_reader = 0; - } - } - - - buf += startpos; - bufsize -= startpos; - } -#endif /* IPECAMERA_BUG_INCOMPLETE_PACKETS */ - - if ((bufsize >= 8)&&(!memcmp(buf, frame_magic, sizeof(frame_magic)))) { - size_t n_lines = ((uint32_t*)buf)[5] & 0x7FF; - ipecamera_compute_buffer_size(ctx, n_lines); - - ctx->frame[ctx->buffer_pos].event.info.seqnum = ((uint32_t*)buf)[6] & 0x1FFFFFF; - ctx->frame[ctx->buffer_pos].event.info.offset = (((uint32_t*)buf)[7] & 0xFFFFFF) * 80; - -// ctx->frame[ctx->buffer_pos].event.info.seqnum = ctx->event_id + 1; - - gettimeofday(&ctx->frame[ctx->buffer_pos].event.info.timestamp, NULL); - } else { -// pcilib_warning("Frame magic is not found, ignoring broken data..."); - return PCILIB_STREAMING_CONTINUE; - } - } - -#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS - // for rawdata_callback with complete padding - real_size = bufsize; - - if (ctx->cur_size + bufsize > ctx->cur_raw_size) { - size_t need; - - for (need = ctx->cur_raw_size - ctx->cur_size; (need + sizeof(frame_magic)) < bufsize; need += sizeof(uint32_t)) { - if (!memcmp(buf + need, frame_magic, sizeof(frame_magic))) break; - } - - if ((need + sizeof(frame_magic)) < bufsize) { - extra_data = bufsize - need; - //bufsize = need; - eof = 1; - } - -// printf("%lu %lu %lu - %u\n", ctx->event_id, ctx->cur_size, ctx->cur_raw_size, eof); - - // just rip of padding - bufsize = ctx->cur_raw_size - ctx->cur_size; - -#ifdef IPECAMERA_DEBUG_RAW_PACKETS - sprintf(fname + strlen(fname) - 8, ".partial"); - FILE *f = fopen(fname, "w"); - if (f) { - fwrite(buf, 1, bufsize, f); - fclose(f); - } -#endif /* IPECAMERA_DEBUG_RAW_PACKETS */ - } -#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */ - - if (ctx->parse_data) { - if (ctx->cur_size + bufsize > ctx->full_size) { - pcilib_error("Unexpected event data, we are expecting at maximum (%zu) bytes, but (%zu) already read", ctx->full_size, ctx->cur_size + bufsize); - return -PCILIB_ERROR_TOOBIG; - } - - memcpy(ctx->buffer + ctx->buffer_pos * ctx->padded_size + ctx->cur_size, buf, bufsize); - } - - ctx->cur_size += bufsize; -// printf("%i: %i %i\n", ctx->buffer_pos, ctx->cur_size, bufsize); - - if (ctx->cur_size >= ctx->full_size) { - eof = 1; - } - - if (ctx->event.params.rawdata.callback) { - res = ctx->event.params.rawdata.callback(ctx->event_id, (pcilib_event_info_t*)(ctx->frame + ctx->buffer_pos), (eof?PCILIB_EVENT_FLAG_EOF:PCILIB_EVENT_FLAGS_DEFAULT), bufsize, buf, ctx->event.params.rawdata.user); - if (res <= 0) { - if (res < 0) return res; - ctx->run_reader = 0; - } - } - - if (eof) { - if ((ipecamera_new_frame(ctx))||(!ctx->run_reader)) { - return PCILIB_STREAMING_STOP; - } - -#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS - if (extra_data) { - return ipecamera_data_callback(user, flags, extra_data, buf + (real_size - extra_data)); - } -#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */ - } - - return PCILIB_STREAMING_REQ_FRAGMENT; -} - -void *ipecamera_reader_thread(void *user) { - int err; - ipecamera_t *ctx = (ipecamera_t*)user; - - while (ctx->run_reader) { - err = pcilib_stream_dma(ctx->event.pcilib, ctx->rdma, 0, 0, PCILIB_DMA_FLAG_MULTIPACKET, 10 * PCILIB_DMA_TIMEOUT, &ipecamera_data_callback, user); - if (err) { - if (err == PCILIB_ERROR_TIMEOUT) { - if (ctx->cur_size >= ctx->cur_raw_size) ipecamera_new_frame(ctx); -#ifdef IPECAMERA_BUG_INCOMPLETE_PACKETS - else if (ctx->cur_size > 0) ipecamera_new_frame(ctx); -#endif /* IPECAMERA_BUG_INCOMPLETE_PACKETS */ - if (pcilib_check_deadline(&ctx->autostop.timestamp, 10 * PCILIB_DMA_TIMEOUT)) { - ctx->run_reader = 0; - break; - } - usleep(IPECAMERA_NOFRAME_SLEEP); - } else pcilib_error("DMA error while reading IPECamera frames, error: %i", err); - } //else printf("no error\n"); - - //usleep(1000); - } - - ctx->run_streamer = 0; - -// if (ctx->cur_size) -// pcilib_error("partialy read frame after stop signal, %zu bytes in the buffer", ctx->cur_size); - - return NULL; -} diff --git a/ipecamera/reader.h b/ipecamera/reader.h deleted file mode 100644 index 5d631c0..0000000 --- a/ipecamera/reader.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _IPECAMERA_READER_H -#define _IPECAMERA_READER_H - -int ipecamera_compute_buffer_size(ipecamera_t *ctx, size_t lines); - -void *ipecamera_reader_thread(void *user); - -#endif /* _IPECAMERA_READER_H */ diff --git a/irq.c b/irq.c deleted file mode 100644 index 3d387bb..0000000 --- a/irq.c +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pci.h" - -#include "tools.h" -#include "error.h" - -int pcilib_wait_irq(pcilib_t *ctx, pcilib_irq_hw_source_t source, pcilib_timeout_t timeout, size_t *count) { - int err; - - interrupt_wait_t arg = { 0 }; - - arg.source = source; - arg.timeout = timeout; - - if (count) arg.count = 1; - - err = ioctl(ctx->handle, PCIDRIVER_IOC_WAITI, &arg); - if (err) { - pcilib_error("PCIDRIVER_IOC_WAITI ioctl have failed"); - return PCILIB_ERROR_FAILED; - } - - if (!arg.count) return PCILIB_ERROR_TIMEOUT; - - if (count) *count = arg.count; - - return 0; -} - -int pcilib_clear_irq(pcilib_t *ctx, pcilib_irq_hw_source_t source) { - int err; - - err = ioctl(ctx->handle, PCIDRIVER_IOC_CLEAR_IOQ, source); - if (err) { - pcilib_error("PCIDRIVER_IOC_CLEAR_IOQ ioctl have failed"); - return PCILIB_ERROR_FAILED; - } - - return 0; -} - - diff --git a/irq.h b/irq.h deleted file mode 100644 index 441e0e5..0000000 --- a/irq.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _PCILIB_IRQ_H -#define _PCILIB_IRQ_H - - -#endif /* _PCILIB_IRQ_H */ diff --git a/kapture/CMakeLists.txt b/kapture/CMakeLists.txt deleted file mode 100644 index af74edd..0000000 --- a/kapture/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -include_directories( - ${CMAKE_SOURCE_DIR} - ${UFODECODE_INCLUDE_DIRS} -) - -set(HEADERS ${HEADERS} model.h) - -add_library(kapture STATIC kapture.c) - diff --git a/kapture/kapture.c b/kapture/kapture.c deleted file mode 100644 index 4384592..0000000 --- a/kapture/kapture.c +++ /dev/null @@ -1,62 +0,0 @@ -#define _KAPTURE_C -#include -#include -#include -#include -#include -#include -#include - -#include "../tools.h" -#include "../error.h" -#include "../event.h" - -#include "pcilib.h" -#include "model.h" -#include "kapture.h" -#include "private.h" - - -pcilib_context_t *kapture_init(pcilib_t *vctx) { - kapture_t *ctx = malloc(sizeof(kapture_t)); - - if (ctx) { - memset(ctx, 0, sizeof(kapture_t)); - } - - return ctx; -} - -void kapture_free(pcilib_context_t *vctx) { - if (vctx) { - kapture_t *ctx = (kapture_t*)vctx; - kapture_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); - free(ctx); - } -} - -int kapture_reset(pcilib_context_t *ctx) { -} - -int kapture_start(pcilib_context_t *ctx, pcilib_event_t event_mask, pcilib_event_flags_t flags) { -} - -int kapture_stop(pcilib_context_t *ctx, pcilib_event_flags_t flags) { -} - -int kapture_trigger(pcilib_context_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) { -} - -int kapture_stream(pcilib_context_t *ctx, pcilib_event_callback_t callback, void *user) { -} - -int kapture_next_event(pcilib_context_t *ctx, pcilib_timeout_t timeout, pcilib_event_id_t *evid, size_t info_size, pcilib_event_info_t *info) { -} - -int kapture_get(pcilib_context_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size, void **data) { -} - -int kapture_return(pcilib_context_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, void *data) { -} - - diff --git a/kapture/kapture.h b/kapture/kapture.h deleted file mode 100644 index 3944b8c..0000000 --- a/kapture/kapture.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _KAPTURE_H -#define _KAPTURE_H - -typedef struct kapture_s kapture_t; - -#endif /* _KAPTURE_H */ diff --git a/kapture/model.h b/kapture/model.h deleted file mode 100644 index b45969a..0000000 --- a/kapture/model.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef _KAPTURE_MODEL_H -#define _KAPTURE_MODEL_H - -#include - -#include "../pcilib.h" - - -#define KAPTURE_REGISTER_SPACE 0x9000 - -#ifdef _KAPTURE_C -pcilib_register_bank_description_t kapture_register_banks[] = { -// { PCILIB_REGISTER_BANK0, PCILIB_BAR0, 0x0200, PCILIB_DEFAULT_PROTOCOL , KAPTURE_REGISTER_SPACE, KAPTURE_REGISTER_SPACE, PCILIB_LITTLE_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "0x%lx", "fpga", "KAPTURE Registers" }, - { PCILIB_REGISTER_BANK_DMA, PCILIB_BAR0, 0x0200, PCILIB_DEFAULT_PROTOCOL , 0, 0, PCILIB_LITTLE_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "0x%lx", "dma", "DMA Registers"}, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } -}; - -pcilib_register_description_t kapture_registers[] = { -{0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL} -}; - -pcilib_register_range_t kapture_register_ranges[] = { - {0, 0, 0, 0} -}; - -pcilib_event_description_t kapture_events[] = { - {PCILIB_EVENT0, "event", ""}, - {0, NULL, NULL} -}; - -pcilib_event_data_type_description_t kapture_data_types[] = { - {PCILIB_EVENT_RAW_DATA, PCILIB_EVENT0, "raw", "raw data from kapture" }, - {0, 0, NULL, NULL} -}; - -#else -extern pcilib_register_description_t kapture_registers[]; -extern pcilib_register_bank_description_t kapture_register_banks[]; -extern pcilib_register_range_t kapture_register_ranges[]; -extern pcilib_event_description_t kapture_events[]; -extern pcilib_event_data_type_description_t kapture_data_types[]; -#endif - - -pcilib_context_t *kapture_init(pcilib_t *pcilib); -void kapture_free(pcilib_context_t *ctx); - -int kapture_reset(pcilib_context_t *ctx); -int kapture_start(pcilib_context_t *ctx, pcilib_event_t event_mask, pcilib_event_flags_t flags); -int kapture_stop(pcilib_context_t *ctx, pcilib_event_flags_t flags); -int kapture_trigger(pcilib_context_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data); -int kapture_stream(pcilib_context_t *vctx, pcilib_event_callback_t callback, void *user); -int kapture_next_event(pcilib_context_t *vctx, pcilib_timeout_t timeout, pcilib_event_id_t *evid, size_t info_size, pcilib_event_info_t *info); -int kapture_get(pcilib_context_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size, void **buf); -int kapture_return(pcilib_context_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, void *data); - -#ifdef _KAPTURE_C -pcilib_event_api_description_t kapture_api = { - "kapture", - - kapture_init, - kapture_free, - - NULL, - - kapture_reset, - kapture_start, - kapture_stop, - kapture_trigger, - - kapture_stream, - kapture_next_event, - kapture_get, - kapture_return -}; -#else -extern pcilib_event_api_description_t kapture_api; -#endif - - -#endif /* _KAPTURE_MODEL_H */ diff --git a/kapture/private.h b/kapture/private.h deleted file mode 100644 index bf084c3..0000000 --- a/kapture/private.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _KAPTURE_PRIVATE_H -#define _KAPTURE_PRIVATE_H - -struct kapture_s { - pcilib_context_t event; - -}; - - -#endif /* _KAPTURE_PRIVATE_H */ diff --git a/kernel.h b/kernel.h deleted file mode 100644 index 161d2aa..0000000 --- a/kernel.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Extract from kernel headers - * iomap.h - */ - -/* - * IO resources have these defined flags. - */ -#define IORESOURCE_BITS 0x000000ff /* Bus-specific bits */ - -#define IORESOURCE_TYPE_BITS 0x00000f00 /* Resource type */ -#define IORESOURCE_IO 0x00000100 -#define IORESOURCE_MEM 0x00000200 -#define IORESOURCE_IRQ 0x00000400 -#define IORESOURCE_DMA 0x00000800 - -#define IORESOURCE_PREFETCH 0x00001000 /* No side effects */ -#define IORESOURCE_READONLY 0x00002000 -#define IORESOURCE_CACHEABLE 0x00004000 -#define IORESOURCE_RANGELENGTH 0x00008000 -#define IORESOURCE_SHADOWABLE 0x00010000 - -#define IORESOURCE_SIZEALIGN 0x00020000 /* size indicates alignment */ -#define IORESOURCE_STARTALIGN 0x00040000 /* start field is alignment */ - -#define IORESOURCE_MEM_64 0x00100000 - -#define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ -#define IORESOURCE_DISABLED 0x10000000 -#define IORESOURCE_UNSET 0x20000000 -#define IORESOURCE_AUTO 0x40000000 -#define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */ - -/* PnP IRQ specific bits (IORESOURCE_BITS) */ -#define IORESOURCE_IRQ_HIGHEDGE (1<<0) -#define IORESOURCE_IRQ_LOWEDGE (1<<1) -#define IORESOURCE_IRQ_HIGHLEVEL (1<<2) -#define IORESOURCE_IRQ_LOWLEVEL (1<<3) -#define IORESOURCE_IRQ_SHAREABLE (1<<4) -#define IORESOURCE_IRQ_OPTIONAL (1<<5) - -/* PnP DMA specific bits (IORESOURCE_BITS) */ -#define IORESOURCE_DMA_TYPE_MASK (3<<0) -#define IORESOURCE_DMA_8BIT (0<<0) -#define IORESOURCE_DMA_8AND16BIT (1<<0) -#define IORESOURCE_DMA_16BIT (2<<0) - -#define IORESOURCE_DMA_MASTER (1<<2) -#define IORESOURCE_DMA_BYTE (1<<3) -#define IORESOURCE_DMA_WORD (1<<4) - -#define IORESOURCE_DMA_SPEED_MASK (3<<6) -#define IORESOURCE_DMA_COMPATIBLE (0<<6) -#define IORESOURCE_DMA_TYPEA (1<<6) -#define IORESOURCE_DMA_TYPEB (2<<6) -#define IORESOURCE_DMA_TYPEF (3<<6) - -/* PnP memory I/O specific bits (IORESOURCE_BITS) */ -#define IORESOURCE_MEM_WRITEABLE (1<<0) /* dup: IORESOURCE_READONLY */ -#define IORESOURCE_MEM_CACHEABLE (1<<1) /* dup: IORESOURCE_CACHEABLE */ -#define IORESOURCE_MEM_RANGELENGTH (1<<2) /* dup: IORESOURCE_RANGELENGTH */ -#define IORESOURCE_MEM_TYPE_MASK (3<<3) -#define IORESOURCE_MEM_8BIT (0<<3) -#define IORESOURCE_MEM_16BIT (1<<3) -#define IORESOURCE_MEM_8AND16BIT (2<<3) -#define IORESOURCE_MEM_32BIT (3<<3) -#define IORESOURCE_MEM_SHADOWABLE (1<<5) /* dup: IORESOURCE_SHADOWABLE */ -#define IORESOURCE_MEM_EXPANSIONROM (1<<6) - -/* PnP I/O specific bits (IORESOURCE_BITS) */ -#define IORESOURCE_IO_16BIT_ADDR (1<<0) -#define IORESOURCE_IO_FIXED (1<<1) - -/* PCI ROM control bits (IORESOURCE_BITS) */ -#define IORESOURCE_ROM_ENABLE (1<<0) /* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */ -#define IORESOURCE_ROM_SHADOW (1<<1) /* ROM is copy at C000:0 */ -#define IORESOURCE_ROM_COPY (1<<2) /* ROM is alloc'd copy, resource field overlaid */ -#define IORESOURCE_ROM_BIOS_COPY (1<<3) /* ROM is BIOS copy, resource field overlaid */ - -/* PCI control bits. Shares IORESOURCE_BITS with above PCI ROM. */ -#define IORESOURCE_PCI_FIXED (1<<4) /* Do not move resource */ diff --git a/kmem.c b/kmem.c deleted file mode 100644 index 64f593a..0000000 --- a/kmem.c +++ /dev/null @@ -1,310 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pcilib.h" -#include "pci.h" -#include "kmem.h" -#include "error.h" - -int pcilib_clean_kernel_memory(pcilib_t *ctx, pcilib_kmem_use_t use, pcilib_kmem_flags_t flags) { - kmem_handle_t kh = {0}; - kh.use = use; - kh.flags = flags|KMEM_FLAG_MASS; - - return ioctl(ctx->handle, PCIDRIVER_IOC_KMEM_FREE, &kh); -} - - -static int pcilib_free_kernel_buffer(pcilib_t *ctx, pcilib_kmem_list_t *kbuf, size_t i, pcilib_kmem_flags_t flags) { - kmem_handle_t kh = {0}; - - if (kbuf->buf.blocks[i].ua) munmap(kbuf->buf.blocks[i].ua, kbuf->buf.blocks[i].size + kbuf->buf.blocks[i].alignment_offset); - kh.handle_id = kbuf->buf.blocks[i].handle_id; - kh.pa = kbuf->buf.blocks[i].pa; - kh.flags = flags; - - return ioctl(ctx->handle, PCIDRIVER_IOC_KMEM_FREE, &kh); -} - -static void pcilib_cancel_kernel_memory(pcilib_t *ctx, pcilib_kmem_list_t *kbuf, pcilib_kmem_flags_t flags, int last_flags) { - int ret; - - if (!kbuf->buf.n_blocks) return; - - // consistency error during processing of last block, special treatment could be needed - if (last_flags) { - pcilib_kmem_flags_t failed_flags = flags; - - if (last_flags&KMEM_FLAG_REUSED_PERSISTENT) flags&=~PCILIB_KMEM_FLAG_PERSISTENT; - if (last_flags&KMEM_FLAG_REUSED_HW) flags&=~PCILIB_KMEM_FLAG_HARDWARE; - - if (failed_flags != flags) { - ret = pcilib_free_kernel_buffer(ctx, kbuf, --kbuf->buf.n_blocks, failed_flags); - if (ret) pcilib_error("PCIDRIVER_IOC_KMEM_FREE ioctl have failed"); - } - } - - pcilib_free_kernel_memory(ctx, kbuf, flags); -} - -pcilib_kmem_handle_t *pcilib_alloc_kernel_memory(pcilib_t *ctx, pcilib_kmem_type_t type, size_t nmemb, size_t size, size_t alignment, pcilib_kmem_use_t use, pcilib_kmem_flags_t flags) { - int err = 0; - const char *error = NULL; - - int ret; - int i; - void *addr; - - pcilib_tristate_t reused = PCILIB_TRISTATE_NO; - int persistent = -1; - int hardware = -1; - - kmem_handle_t kh = {0}; - - pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)malloc(sizeof(pcilib_kmem_list_t) + nmemb * sizeof(pcilib_kmem_addr_t)); - if (!kbuf) { - pcilib_error("Memory allocation has failed"); - return NULL; - } - - memset(kbuf, 0, sizeof(pcilib_kmem_list_t) + nmemb * sizeof(pcilib_kmem_addr_t)); - - ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_MODE, PCIDRIVER_MMAP_KMEM ); - if (ret) { - pcilib_error("PCIDRIVER_IOC_MMAP_MODE ioctl have failed"); - return NULL; - } - - kh.type = type; - kh.size = size; - kh.align = alignment; - kh.use = use; - - if ((type&PCILIB_KMEM_TYPE_MASK) == PCILIB_KMEM_TYPE_REGION) { - kh.align = 0; - } else if ((type&PCILIB_KMEM_TYPE_MASK) != PCILIB_KMEM_TYPE_PAGE) { - kh.size += alignment; - } - - for ( i = 0; i < nmemb; i++) { - kh.item = i; - kh.flags = flags; - - if ((type&PCILIB_KMEM_TYPE_MASK) == PCILIB_KMEM_TYPE_REGION) { - kh.pa = alignment + i * size; - } - - ret = ioctl(ctx->handle, PCIDRIVER_IOC_KMEM_ALLOC, &kh); - if (ret) { - kbuf->buf.n_blocks = i; - error = "PCIDRIVER_IOC_KMEM_ALLOC ioctl have failed"; - break; - } - - kbuf->buf.blocks[i].handle_id = kh.handle_id; - kbuf->buf.blocks[i].pa = kh.pa; - kbuf->buf.blocks[i].size = kh.size; - - if (!i) reused = (kh.flags&KMEM_FLAG_REUSED)?PCILIB_TRISTATE_YES:PCILIB_TRISTATE_NO; - - if (kh.flags&KMEM_FLAG_REUSED) { - if (!i) reused = PCILIB_TRISTATE_YES; - else if (!reused) reused = PCILIB_TRISTATE_PARTIAL; - - if (persistent) { - if (persistent < 0) { - /*if (((flags&PCILIB_KMEM_FLAG_PERSISTENT) == 0)&&(kh.flags&KMEM_FLAG_REUSED_PERSISTENT)) err = PCILIB_ERROR_INVALID_STATE; - else*/ persistent = (kh.flags&KMEM_FLAG_REUSED_PERSISTENT)?1:0; - } else if ((kh.flags&KMEM_FLAG_REUSED_PERSISTENT) == 0) err = PCILIB_ERROR_INVALID_STATE; - } else if (kh.flags&KMEM_FLAG_REUSED_PERSISTENT) err = PCILIB_ERROR_INVALID_STATE; - - if (hardware) { - if (hardware < 0) { - /*if (((flags&PCILIB_KMEM_FLAG_HARDWARE) == 0)&&(kh.flags&KMEM_FLAG_REUSED_HW)) err = PCILIB_ERROR_INVALID_STATE; - else*/ hardware = (kh.flags&KMEM_FLAG_REUSED_HW)?1:0; - } else if ((kh.flags&KMEM_FLAG_REUSED_HW) == 0) err = PCILIB_ERROR_INVALID_STATE; - } else if (kh.flags&KMEM_FLAG_REUSED_HW) err = PCILIB_ERROR_INVALID_STATE; - - } else { - if (!i) reused = PCILIB_TRISTATE_NO; - else if (reused) reused = PCILIB_TRISTATE_PARTIAL; - - if ((persistent > 0)&&((flags&PCILIB_KMEM_FLAG_PERSISTENT) == 0)) err = PCILIB_ERROR_INVALID_STATE; - if ((hardware > 0)&&((flags&PCILIB_KMEM_FLAG_HARDWARE) == 0)) err = PCILIB_ERROR_INVALID_STATE; - } - - if (err) { - kbuf->buf.n_blocks = i + 1; - break; - } - - if ((kh.align)&&((kh.type&PCILIB_KMEM_TYPE_MASK) != PCILIB_KMEM_TYPE_PAGE)) { - if (kh.pa % kh.align) kbuf->buf.blocks[i].alignment_offset = kh.align - kh.pa % kh.align; - kbuf->buf.blocks[i].size -= kh.align; - } - - addr = mmap( 0, kbuf->buf.blocks[i].size + kbuf->buf.blocks[i].alignment_offset, PROT_WRITE | PROT_READ, MAP_SHARED, ctx->handle, 0 ); - if ((!addr)||(addr == MAP_FAILED)) { - kbuf->buf.n_blocks = i + 1; - error = "Failed to mmap allocated kernel memory"; - break; - } - - kbuf->buf.blocks[i].ua = addr; -// if (use == PCILIB_KMEM_USE_DMA_PAGES) { -// memset(addr, 10, kbuf->buf.blocks[i].size + kbuf->buf.blocks[i].alignment_offset); -// } - - kbuf->buf.blocks[i].mmap_offset = kh.pa & ctx->page_mask; - } - - //This is possible in the case of error (nothing is allocated yet) or if buffers are not reused - if (persistent < 0) persistent = 0; - if (hardware < 0) hardware = 0; - - if (err||error) { - pcilib_kmem_flags_t free_flags = 0; - - // for the sake of simplicity always clean partialy reused buffers - if ((persistent == PCILIB_TRISTATE_PARTIAL)||((persistent <= 0)&&(flags&PCILIB_KMEM_FLAG_PERSISTENT))) { - free_flags |= PCILIB_KMEM_FLAG_PERSISTENT; - } - - if ((hardware <= 0)&&(flags&PCILIB_KMEM_FLAG_HARDWARE)) { - free_flags |= PCILIB_KMEM_FLAG_HARDWARE; - } - - // do not clean if we have reused peresistent buffers - // we don't care about -1, because it will be the value only if no buffers actually allocated - if ((!persistent)||(reused != PCILIB_TRISTATE_YES)) { - pcilib_cancel_kernel_memory(ctx, kbuf, free_flags, err?kh.flags:0); - } - - if (!error) error = "Reused buffers are inconsistent"; - pcilib_error(error); - - return NULL; - } - - if (nmemb == 1) { - memcpy(&kbuf->buf.addr, &kbuf->buf.blocks[0], sizeof(pcilib_kmem_addr_t)); - } - - kbuf->buf.reused = reused|(persistent?PCILIB_KMEM_REUSE_PERSISTENT:0)|(hardware?PCILIB_KMEM_REUSE_HARDWARE:0); - kbuf->buf.n_blocks = nmemb; - - kbuf->prev = NULL; - kbuf->next = ctx->kmem_list; - if (ctx->kmem_list) ctx->kmem_list->prev = kbuf; - ctx->kmem_list = kbuf; - - return (pcilib_kmem_handle_t*)kbuf; -} - -void pcilib_free_kernel_memory(pcilib_t *ctx, pcilib_kmem_handle_t *k, pcilib_kmem_flags_t flags) { - int ret, err = 0; - int i; - pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - - // if linked in to the list - if (kbuf->next) kbuf->next->prev = kbuf->prev; - if (kbuf->prev) kbuf->prev->next = kbuf->next; - else if (ctx->kmem_list == kbuf) ctx->kmem_list = kbuf->next; - - for (i = 0; i < kbuf->buf.n_blocks; i++) { - ret = pcilib_free_kernel_buffer(ctx, kbuf, i, flags); - if ((ret)&&(!err)) err = ret; - } - - free(kbuf); - - if (err) { - pcilib_error("PCIDRIVER_IOC_KMEM_FREE ioctl have failed"); - } -} - -/* -int pcilib_kmem_sync(pcilib_t *ctx, pcilib_kmem_handle_t *k, pcilib_kmem_sync_direction_t dir) { - int i; - int ret; - pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - - for (i = 0; i < kbuf->buf.n_blocks; i++) { - ret = pcilib_kmem_sync_block(ctx, k, dir, i); - if (ret) { - pcilib_error("PCIDRIVER_IOC_KMEM_SYNC ioctl have failed"); - return PCILIB_ERROR_FAILED; - } - } - - return 0; -} -*/ - -int pcilib_kmem_sync_block(pcilib_t *ctx, pcilib_kmem_handle_t *k, pcilib_kmem_sync_direction_t dir, size_t block) { - int ret; - kmem_sync_t ks; - pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - - ks.dir = dir; - ks.handle.handle_id = kbuf->buf.blocks[block].handle_id; - ks.handle.pa = kbuf->buf.blocks[block].pa; - ret = ioctl(ctx->handle, PCIDRIVER_IOC_KMEM_SYNC, &ks); - if (ret) { - pcilib_error("PCIDRIVER_IOC_KMEM_SYNC ioctl have failed"); - return PCILIB_ERROR_FAILED; - } - - return 0; -} - -void *pcilib_kmem_get_ua(pcilib_t *ctx, pcilib_kmem_handle_t *k) { - pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - return kbuf->buf.addr.ua + kbuf->buf.addr.alignment_offset + kbuf->buf.addr.mmap_offset; -} - -uintptr_t pcilib_kmem_get_pa(pcilib_t *ctx, pcilib_kmem_handle_t *k) { - pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - return kbuf->buf.addr.pa + kbuf->buf.addr.alignment_offset; -} - -uintptr_t pcilib_kmem_get_ba(pcilib_t *ctx, pcilib_kmem_handle_t *k) { - pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - return kbuf->buf.addr.pa + kbuf->buf.addr.alignment_offset; -} - -void *pcilib_kmem_get_block_ua(pcilib_t *ctx, pcilib_kmem_handle_t *k, size_t block) { - pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - return kbuf->buf.blocks[block].ua + kbuf->buf.blocks[block].alignment_offset + kbuf->buf.blocks[block].mmap_offset; -} - -uintptr_t pcilib_kmem_get_block_pa(pcilib_t *ctx, pcilib_kmem_handle_t *k, size_t block) { - pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - return kbuf->buf.blocks[block].pa + kbuf->buf.blocks[block].alignment_offset; -} - -uintptr_t pcilib_kmem_get_block_ba(pcilib_t *ctx, pcilib_kmem_handle_t *k, size_t block) { - pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - return kbuf->buf.blocks[block].pa + kbuf->buf.blocks[block].alignment_offset; -} - -size_t pcilib_kmem_get_block_size(pcilib_t *ctx, pcilib_kmem_handle_t *k, size_t block) { - pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - return kbuf->buf.blocks[block].size; -} - -pcilib_kmem_reuse_state_t pcilib_kmem_is_reused(pcilib_t *ctx, pcilib_kmem_handle_t *k) { - pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - return kbuf->buf.reused; -} diff --git a/kmem.h b/kmem.h deleted file mode 100644 index a11518a..0000000 --- a/kmem.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef _PCILIB_KMEM_H -#define _PCILIB_KMEM_H - -#include "pcilib.h" - -typedef struct pcilib_kmem_list_s pcilib_kmem_list_t; - -#include "tools.h" - -typedef enum { - PCILIB_KMEM_FLAG_REUSE = KMEM_FLAG_REUSE, - PCILIB_KMEM_FLAG_EXCLUSIVE = KMEM_FLAG_EXCLUSIVE, - PCILIB_KMEM_FLAG_PERSISTENT = KMEM_FLAG_PERSISTENT, - PCILIB_KMEM_FLAG_HARDWARE = KMEM_FLAG_HW, - PCILIB_KMEM_FLAG_FORCE = KMEM_FLAG_FORCE, - PCILIB_KMEM_FLAG_TRY = KMEM_FLAG_TRY -} pcilib_kmem_flags_t; - - -typedef enum { - PCILIB_KMEM_REUSE_ALLOCATED = PCILIB_TRISTATE_NO, - PCILIB_KMEM_REUSE_REUSED = PCILIB_TRISTATE_YES, - PCILIB_KMEM_REUSE_PARTIAL = PCILIB_TRISTATE_PARTIAL, - PCILIB_KMEM_REUSE_PERSISTENT = 0x100, - PCILIB_KMEM_REUSE_HARDWARE = 0x200 -} pcilib_kmem_reuse_state_t; - - -typedef struct { - int handle_id; - pcilib_kmem_reuse_state_t reused; - - uintptr_t pa; -// uintptr_t va; - void *ua; - size_t size; - - size_t alignment_offset; - size_t mmap_offset; -} pcilib_kmem_addr_t; - -/** - * single allocation - we set only addr, n_blocks = 0 - * multiple allocation - addr is not set, blocks are set, n_blocks > 0 - * sgmap allocation - addr contains ua, but pa's are set in blocks, n_blocks > 0 - */ -typedef struct { - pcilib_kmem_addr_t addr; - - pcilib_kmem_reuse_state_t reused; - - size_t n_blocks; - pcilib_kmem_addr_t blocks[]; -} pcilib_kmem_buffer_t; - -typedef void pcilib_kmem_handle_t; - - -struct pcilib_kmem_list_s { - pcilib_kmem_list_t *next, *prev; - - pcilib_kmem_buffer_t buf; // variable size, should be last item in struct -}; - -pcilib_kmem_handle_t *pcilib_alloc_kernel_memory(pcilib_t *ctx, pcilib_kmem_type_t type, size_t nmemb, size_t size, size_t alignment, pcilib_kmem_use_t use, pcilib_kmem_flags_t flags); -void pcilib_free_kernel_memory(pcilib_t *ctx, pcilib_kmem_handle_t *k, pcilib_kmem_flags_t flags); -//int pcilib_kmem_sync(pcilib_t *ctx, pcilib_kmem_handle_t *k, pcilib_kmem_sync_direction_t dir); -int pcilib_kmem_sync_block(pcilib_t *ctx, pcilib_kmem_handle_t *k, pcilib_kmem_sync_direction_t dir, size_t block); -void *pcilib_kmem_get_ua(pcilib_t *ctx, pcilib_kmem_handle_t *k); -uintptr_t pcilib_kmem_get_pa(pcilib_t *ctx, pcilib_kmem_handle_t *k); -uintptr_t pcilib_kmem_get_ba(pcilib_t *ctx, pcilib_kmem_handle_t *k); -void *pcilib_kmem_get_block_ua(pcilib_t *ctx, pcilib_kmem_handle_t *k, size_t block); -uintptr_t pcilib_kmem_get_block_pa(pcilib_t *ctx, pcilib_kmem_handle_t *k, size_t block); -uintptr_t pcilib_kmem_get_block_ba(pcilib_t *ctx, pcilib_kmem_handle_t *k, size_t block); -size_t pcilib_kmem_get_block_size(pcilib_t *ctx, pcilib_kmem_handle_t *k, size_t block); -pcilib_kmem_reuse_state_t pcilib_kmem_is_reused(pcilib_t *ctx, pcilib_kmem_handle_t *k); - -int pcilib_clean_kernel_memory(pcilib_t *ctx, pcilib_kmem_use_t use, pcilib_kmem_flags_t flags); - -#endif /* _PCILIB_KMEM_H */ diff --git a/misc/50-pcidriver.rules b/misc/50-pcidriver.rules deleted file mode 100644 index 1283c3b..0000000 --- a/misc/50-pcidriver.rules +++ /dev/null @@ -1 +0,0 @@ -KERNEL=="fpga*", NAME="%k", GROUP="users", MODE="0660" diff --git a/model.c b/model.c new file mode 100644 index 0000000..539f774 --- /dev/null +++ b/model.c @@ -0,0 +1,195 @@ +#include + +#include +#include + +#include "base.h" +#include "cmosis.h" +#include "model.h" + +enum ipecamera_protocol_s { + IPECAMERA_PROTOCOL_CMOSIS = PCILIB_REGISTER_PROTOCOL0, +}; + + +static const pcilib_register_protocol_api_description_t ipecamera_cmosis_protocol_api = + { NULL, NULL, ipecamera_cmosis_read, ipecamera_cmosis_write }; + +/* +static const pcilib_dma_description_t ipecamera_dma = + { &ipe_dma_api, ipe_dma_banks, ipe_dma_registers, ipe_dma_engines, NULL, NULL, "ipedma", "DMA engine developed by M. Caselle" }; +*/ + +static const pcilib_register_protocol_description_t ipecamera_protocols[] = { +// {IPECAMERA_PROTOCOL_FPGA, &pcilib_default_protocol_api, "ipecamera", NULL, "cmosis", "Protocol to access FPGA registers"}, + {IPECAMERA_PROTOCOL_CMOSIS, &ipecamera_cmosis_protocol_api, NULL, NULL, "cmosis", "Protocol to access CMOSIS registers"}, + { 0 } +}; + +static const pcilib_register_bank_description_t ipecamera_banks[] = { + { PCILIB_REGISTER_BANK0, IPECAMERA_PROTOCOL_CMOSIS, PCILIB_BAR0, IPECAMERA_CMOSIS_REGISTER_READ , IPECAMERA_CMOSIS_REGISTER_WRITE, 8, 128, PCILIB_LITTLE_ENDIAN, PCILIB_LITTLE_ENDIAN, "%lu" , "cmosis", "CMOSIS CMV2000 Registers" }, + { PCILIB_REGISTER_BANK1, PCILIB_REGISTER_PROTOCOL_DEFAULT, PCILIB_BAR0, IPECAMERA_REGISTER_SPACE, IPECAMERA_REGISTER_SPACE, 32, 0x0200, PCILIB_LITTLE_ENDIAN, PCILIB_LITTLE_ENDIAN, "0x%lx", "fpga", "IPECamera Registers" }, +// { PCILIB_REGISTER_BANK_DMA, PCILIB_REGISTER_PROTOCOL_DEFAULT, PCILIB_BAR0, 0, 0, 32, 0x0200, PCILIB_LITTLE_ENDIAN, PCILIB_LITTLE_ENDIAN, "0x%lx", "dma", "DMA Registers"}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static const pcilib_register_description_t ipecamera_registers[] = { +{1, 0, 16, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines", ""}, +{3, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start1", ""}, +{5, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start2", ""}, +{7, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start3", ""}, +{9, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start4", ""}, +{11, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start5", ""}, +{13, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start6", ""}, +{15, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start7", ""}, +{17, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_start8", ""}, +{19, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines1", ""}, +{21, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines2", ""}, +{23, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines3", ""}, +{25, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines4", ""}, +{27, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines5", ""}, +{29, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines6", ""}, +{31, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines7", ""}, +{33, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_lines8", ""}, +{35, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_sub_s", ""}, +{37, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_sub_a", ""}, +{39, 0, 1, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_color", ""}, +{40, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_image_flipping", ""}, +{41, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_flags", ""}, +{42, 0, 24, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_time", ""}, +{45, 0, 24, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_step", ""}, +{48, 0, 24, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_kp1", ""}, +{51, 0, 24, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_kp2", ""}, +{54, 0, 2, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_nr_slopes", ""}, +{55, 0, 8, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_seq", ""}, +{56, 0, 24, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_time2", ""}, +{59, 0, 24, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_step2", ""}, +{68, 0, 2, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_nr_slopes2", ""}, +{69, 0, 8, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_exp_seq2", ""}, +{70, 0, 16, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_number_frames", ""}, +{72, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_output_mode", ""}, +{78, 0, 12, 85, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_training_pattern", ""}, +{80, 0, 18, 0x3FFFF,0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_channel_en", ""}, +{82, 0, 3, 7, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_special_82", ""}, +{89, 0, 8, 96, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_vlow2", ""}, +{90, 0, 8, 96, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_vlow3", ""}, +{100, 0, 14, 16260, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_offset", ""}, +{102, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_pga", ""}, +{103, 0, 8, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_adc_gain", ""}, +{111, 0, 1, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_bit_mode", ""}, +{112, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_adc_resolution", ""}, +{115, 0, 1, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "cmosis_special_115", ""}, +{0x00, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "spi_conf_input", ""}, +{0x10, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "spi_conf_output", ""}, +{0x20, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "spi_clk_speed", ""}, +{0x30, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "firmware_info", ""}, +{0x30, 0, 8, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "firmware_version", ""}, +{0x30, 8, 1, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "firmware_bitmode", ""}, +{0x30, 12, 2, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "adc_resolution", ""}, +{0x30, 16, 2, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "output_mode", ""}, +{0x40, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "control", ""}, +{0x50, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "status", ""}, +{0x54, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "status2", ""}, +{0x58, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "status3", ""}, +{0x5c, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "fr_status", ""}, +{0x70, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "start_address", ""}, +{0x74, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "end_address", ""}, +{0x78, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "rd_address", ""}, +{0xa0, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "fr_param1", ""}, +{0xa0, 0, 10, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "fr_skip_lines", ""}, +{0xa0, 10, 11, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "fr_num_lines", ""}, +{0xa0, 21, 11, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "fr_start_address", ""}, +{0xb0, 0, 32, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "fr_param2", ""}, +{0xb0, 0, 11, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "fr_threshold_start_line", ""}, +{0xb0, 16, 10, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "fr_area_lines", ""}, +{0xc0, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "skiped_lines", ""}, +{0xd0, 0, 32, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "fr_thresholds", ""}, +{0xd0, 0, 10, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "fr_pixel_thr", ""}, +{0xd0, 10, 11, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "fr_num_pixel_thr", ""}, +{0xd0, 21, 11, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "fr_num_lines_thr", ""}, +{0x100, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "rawdata_pkt_addr", ""}, +{0x110, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "temperature_info", ""}, +{0x110, 0, 16, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "sensor_temperature", ""}, +{0x110, 16, 3, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "sensor_temperature_alarms", ""}, +{0x110, 19, 10, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "fpga_temperature", ""}, +{0x110, 29, 3, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "fpga_temperature_alarms", ""}, +{0x120, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "num_lines", ""}, +{0x130, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "start_line", ""}, +{0x140, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "exp_time", ""}, +{0x150, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "motor", ""}, +{0x150, 0, 5, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "motor_phi", ""}, +{0x150, 5, 5, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "motor_z", ""}, +{0x150, 10, 5, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "motor_y", ""}, +{0x150, 15, 5, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "motor_x", ""}, +{0x150, 20, 8, 0, PCILIB_REGISTER_ALL_BITS, PCILIB_REGISTER_R, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK1, "adc_gain", ""}, +{0x160, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "write_status", ""}, +{0x170, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "num_triggers", ""}, +{0x180, 0, 32, 0x280, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "trigger_period", ""}, +{0x190, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "temperature_sample_period", ""}, +{0x1a0, 0, 32, 0x64, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "ddr_max_frames", ""}, +{0x1b0, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "ddr_num_frames", ""}, +{0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL} +}; + +static const pcilib_register_range_t ipecamera_ranges[] = { +// {0xF000, 0xF000 + 128, PCILIB_REGISTER_BANK0, 0}, +// {0x9000, 0x9FFF, PCILIB_REGISTER_BANK1, -0x9000}, + {0, 0, 0, 0} +}; + +static const pcilib_event_description_t ipecamera_events[] = { + {PCILIB_EVENT0, "new_frame", ""}, + {0, NULL, NULL} +}; + +static const pcilib_event_data_type_description_t ipecamera_data_types[] = { + {IPECAMERA_IMAGE_DATA, PCILIB_EVENT0, "image", "16 bit pixel data" }, + {IPECAMERA_RAW_DATA, PCILIB_EVENT0, "raw", "raw data from camera" }, + {IPECAMERA_CHANGE_MASK, PCILIB_EVENT0, "cmask", "change mask" }, + {0, 0, NULL, NULL} +}; + +pcilib_event_api_description_t ipecamera_image_api = { + ipecamera_init, + ipecamera_free, + + ipecamera_init_dma, + + ipecamera_reset, + ipecamera_start, + ipecamera_stop, + ipecamera_trigger, + + ipecamera_stream, + ipecamera_next_event, + ipecamera_get, + ipecamera_return +}; + + +static const pcilib_model_description_t ipecamera_models[] = {{ + PCILIB_EVENT_INTERFACE_VERSION, + &ipecamera_image_api, + &pcilib_ipedma, + ipecamera_registers, + ipecamera_banks, + ipecamera_protocols, + ipecamera_ranges, + ipecamera_events, + ipecamera_data_types, + "ipecamera", + "IPE Camera" +}, { 0 }}; + + +const pcilib_model_description_t *pcilib_get_event_model(pcilib_t *pcilib, unsigned short vendor_id, unsigned short device_id, const char *model) { + // Enumeration call + if ((!vendor_id)&&(!device_id)&&(!model)) { + return ipecamera_models; + } + + if ((vendor_id != 0x10ee)&&((!model)||(strcasecmp(model, "ipecamera")))) + return NULL; + + return &ipecamera_models[0]; +} diff --git a/model.h b/model.h new file mode 100644 index 0000000..3984bdc --- /dev/null +++ b/model.h @@ -0,0 +1,18 @@ +#ifndef _IPECAMERA_MODEL_H +#define _IPECAMERA_MODEL_H + +#include +#include + +//#define IPECAMERA_DEBUG + +#define IPECAMERA_DMA_ADDRESS 0 /**< Address of DMA engine to use for communication */ +#define IPECAMERA_DMA_PACKET_LENGTH 4096 /**< IPECamera always use buffers of fixed size adding padding in the end. + This is used to compute expected amount of data for each frame */ +#define IPECAMERA_REGISTER_SPACE 0x9000 +#define IPECAMERA_CMOSIS_REGISTER_WRITE (IPECAMERA_REGISTER_SPACE + 0) +#define IPECAMERA_CMOSIS_REGISTER_READ (IPECAMERA_REGISTER_SPACE + 16) + +const pcilib_model_description_t *pcilib_get_event_model(pcilib_t *pcilib, unsigned short vendor_id, unsigned short device_id, const char *model); + +#endif /* _IPECAMERA_MODEL_H */ diff --git a/pci.c b/pci.c deleted file mode 100644 index ca858de..0000000 --- a/pci.c +++ /dev/null @@ -1,473 +0,0 @@ -#define _PCILIB_PCI_C -//#define PCILIB_FILE_IO -#define _POSIX_C_SOURCE 199309L - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pcilib.h" -#include "pci.h" -#include "kernel.h" -#include "tools.h" -#include "error.h" - -#include "ipecamera/model.h" -#include "kapture/model.h" - - -pcilib_t *pcilib_open(const char *device, pcilib_model_t model) { - pcilib_t *ctx = malloc(sizeof(pcilib_t)); - - if (ctx) { - memset(ctx, 0, sizeof(pcilib_t)); - - ctx->handle = open(device, O_RDWR); - if (ctx->handle < 0) { - pcilib_error("Error opening device (%s)", device); - free(ctx); - return NULL; - } - - ctx->page_mask = (uintptr_t)-1; - ctx->model = model; - - if (!model) model = pcilib_get_model(ctx); - - memcpy(&ctx->model_info, pcilib_model + model, sizeof(pcilib_model_description_t)); - - pcilib_init_event_engine(ctx); - } - - return ctx; -} - -pcilib_model_description_t *pcilib_get_model_description(pcilib_t *ctx) { - return &ctx->model_info; -} - -const pcilib_board_info_t *pcilib_get_board_info(pcilib_t *ctx) { - int ret; - - if (ctx->page_mask == (uintptr_t)-1) { - ret = ioctl( ctx->handle, PCIDRIVER_IOC_PCI_INFO, &ctx->board_info ); - if (ret) { - pcilib_error("PCIDRIVER_IOC_PCI_INFO ioctl have failed"); - return NULL; - } - - ctx->page_mask = pcilib_get_page_mask(); - } - - return &ctx->board_info; -} - - - -pcilib_context_t *pcilib_get_implementation_context(pcilib_t *ctx) { - return ctx->event_ctx; -} - -pcilib_model_t pcilib_get_model(pcilib_t *ctx) { - if (ctx->model == PCILIB_MODEL_DETECT) { -// unsigned short vendor_id; -// unsigned short device_id; - - //return PCILIB_MODEL_PCI; - - const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx); - if (!board_info) return PCILIB_MODEL_PCI; - - if ((board_info->vendor_id == PCIE_XILINX_VENDOR_ID)&&(board_info->device_id == PCIE_IPECAMERA_DEVICE_ID)) - ctx->model = PCILIB_MODEL_IPECAMERA; - else if ((board_info->vendor_id == PCIE_XILINX_VENDOR_ID)&&(board_info->device_id == PCIE_KAPTURE_DEVICE_ID)) - ctx->model = PCILIB_MODEL_IPECAMERA; - else - ctx->model = PCILIB_MODEL_PCI; - } - - return ctx->model; -} - -static pcilib_bar_t pcilib_detect_bar(pcilib_t *ctx, uintptr_t addr, size_t size) { - int n = 0; - pcilib_bar_t i; - - const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx); - if (!board_info) return PCILIB_BAR_INVALID; - - for (i = 0; i < PCILIB_MAX_BANKS; i++) { - if (board_info->bar_length[i] > 0) { - if ((addr >= board_info->bar_start[i])&&((board_info->bar_start[i] + board_info->bar_length[i]) >= (addr + size))) return i; - - if (n) n = -1; - else n = i + 1; - } - } - - if (n > 0) return n - 1; - - return PCILIB_BAR_INVALID; -} - -int pcilib_detect_address(pcilib_t *ctx, pcilib_bar_t *bar, uintptr_t *addr, size_t size) { - const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx); - if (!board_info) return PCILIB_ERROR_NOTFOUND; - - if (*bar == PCILIB_BAR_DETECT) { - *bar = pcilib_detect_bar(ctx, *addr, size); - if (*bar == PCILIB_BAR_INVALID) { - pcilib_error("The requested data block at address 0x%x with size %zu does not belongs to any available memory bank", *addr, size); - return PCILIB_ERROR_NOTFOUND; - } - if (*addr < board_info->bar_start[*bar]) - *addr += board_info->bar_start[*bar]; - } else { - if ((*addr < board_info->bar_start[*bar])||((board_info->bar_start[*bar] + board_info->bar_length[*bar]) < (((uintptr_t)*addr) + size))) { - if ((board_info->bar_length[*bar]) >= (((uintptr_t)*addr) + size)) { - *addr += board_info->bar_start[*bar]; - } else { - pcilib_error("The requested data block at address 0x%x with size %zu does not belong the specified memory bank (Bar %i: starting at 0x%x with size 0x%x)", *addr, size, *bar, board_info->bar_start[*bar], board_info->bar_length[*bar]); - return PCILIB_ERROR_NOTFOUND; - } - } - } - - *addr -= board_info->bar_start[*bar]; - *addr += board_info->bar_start[*bar] & ctx->page_mask; - - return 0; -} - -void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar) { - void *res; - int ret; - - const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx); - if (!board_info) return NULL; - - if (ctx->bar_space[bar]) return ctx->bar_space[bar]; - - ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_MODE, PCIDRIVER_MMAP_PCI ); - if (ret) { - pcilib_error("PCIDRIVER_IOC_MMAP_MODE ioctl have failed", bar); - return NULL; - } - - ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_AREA, PCIDRIVER_BAR0 + bar ); - if (ret) { - pcilib_error("PCIDRIVER_IOC_MMAP_AREA ioctl have failed for bank %i", bar); - return NULL; - } - -#ifdef PCILIB_FILE_IO - file_io_handle = open("/root/data", O_RDWR); - res = mmap( 0, board_info->bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, ctx->file_io_handle, 0 ); -#else - res = mmap( 0, board_info->bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, ctx->handle, 0 ); -#endif - if ((!res)||(res == MAP_FAILED)) { - pcilib_error("Failed to mmap data bank %i", bar); - return NULL; - } - - - return res; -} - -void pcilib_unmap_bar(pcilib_t *ctx, pcilib_bar_t bar, void *data) { - const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx); - if (!board_info) return; - - if (ctx->bar_space[bar]) return; - - munmap(data, board_info->bar_length[bar]); -#ifdef PCILIB_FILE_IO - close(ctx->file_io_handle); -#endif -} - -int pcilib_map_register_space(pcilib_t *ctx) { - int err; - pcilib_register_bank_t i; - - if (!ctx->reg_bar_mapped) { - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - pcilib_register_bank_description_t *banks = model_info->banks; - - for (i = 0; ((banks)&&(banks[i].access)); i++) { -// uint32_t buf[2]; - void *reg_space; - pcilib_bar_t bar = banks[i].bar; - - if (bar == PCILIB_BAR_DETECT) { - uintptr_t addr = banks[0].read_addr; - - err = pcilib_detect_address(ctx, &bar, &addr, 1); - if (err) return err; - - if (!ctx->bar_space[bar]) { - reg_space = pcilib_map_bar(ctx, bar); -// pcilib_memcpy(&buf, reg_space, 8); - - if (reg_space) { - ctx->bar_space[bar] = reg_space; - } else { - return PCILIB_ERROR_FAILED; - } - } - } else if (!ctx->bar_space[bar]) { - reg_space = pcilib_map_bar(ctx, bar); - if (reg_space) { - ctx->bar_space[bar] = reg_space; - } else { - return PCILIB_ERROR_FAILED; - } -// pcilib_memcpy(&buf, reg_space, 8); - - } - if (!i) ctx->reg_bar = bar; - } - - ctx->reg_bar_mapped = 1; - } - - return 0; -} - -int pcilib_map_data_space(pcilib_t *ctx, uintptr_t addr) { - int err; - pcilib_bar_t i; - - if (!ctx->data_bar_mapped) { - const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx); - if (!board_info) return PCILIB_ERROR_FAILED; - - err = pcilib_map_register_space(ctx); - if (err) { - pcilib_error("Error mapping register space"); - return err; - } - - int data_bar = -1; - - for (i = 0; i < PCILIB_MAX_BANKS; i++) { - if ((ctx->bar_space[i])||(!board_info->bar_length[i])) continue; - - if (addr) { - if (board_info->bar_start[i] == addr) { - data_bar = i; - break; - } - } else { - if (data_bar >= 0) { - data_bar = -1; - break; - } - - data_bar = i; - } - } - - - if (data_bar < 0) { - if (addr) pcilib_error("Unable to find the specified data space (%lx)", addr); - else pcilib_error("Unable to find the data space"); - return PCILIB_ERROR_NOTFOUND; - } - - ctx->data_bar = data_bar; - - if (!ctx->bar_space[data_bar]) { - char *data_space = pcilib_map_bar(ctx, data_bar); - if (data_space) ctx->bar_space[data_bar] = data_space; - else { - pcilib_error("Unable to map the data space"); - return PCILIB_ERROR_FAILED; - } - } - - ctx->data_bar_mapped = 0; - } - - return 0; -} - -/* -static void pcilib_unmap_register_space(pcilib_t *ctx) { - if (ctx->reg_space) { - pcilib_unmap_bar(ctx, ctx->reg_bar, ctx->reg_space); - ctx->reg_space = NULL; - } -} - -static void pcilib_unmap_data_space(pcilib_t *ctx) { - if (ctx->data_space) { - pcilib_unmap_bar(ctx, ctx->data_bar, ctx->data_space); - ctx->data_space = NULL; - } -} -*/ - -char *pcilib_resolve_register_address(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr) { - if (bar == PCILIB_BAR_DETECT) { - // First checking the default register bar - size_t offset = addr - ctx->board_info.bar_start[ctx->reg_bar]; - if ((addr > ctx->board_info.bar_start[ctx->reg_bar])&&(offset < ctx->board_info.bar_length[ctx->reg_bar])) { - if (!ctx->bar_space[ctx->reg_bar]) { - pcilib_error("The register bar is not mapped"); - return NULL; - } - - return ctx->bar_space[ctx->reg_bar] + offset + (ctx->board_info.bar_start[ctx->reg_bar] & ctx->page_mask); - } - - // Otherwise trying to detect - bar = pcilib_detect_bar(ctx, addr, 1); - if (bar != PCILIB_BAR_INVALID) { - size_t offset = addr - ctx->board_info.bar_start[bar]; - if ((offset < ctx->board_info.bar_length[bar])&&(ctx->bar_space[bar])) { - if (!ctx->bar_space[bar]) { - pcilib_error("The requested bar (%i) is not mapped", bar); - return NULL; - } - return ctx->bar_space[bar] + offset + (ctx->board_info.bar_start[bar] & ctx->page_mask); - } - } - } else { - if (!ctx->bar_space[bar]) { - pcilib_error("The requested bar (%i) is not mapped", bar); - return NULL; - } - - if (addr < ctx->board_info.bar_length[bar]) { - return ctx->bar_space[bar] + addr + (ctx->board_info.bar_start[bar] & ctx->page_mask); - } - - if ((addr >= ctx->board_info.bar_start[bar])&&(addr < (ctx->board_info.bar_start[bar] + ctx->board_info.bar_length[ctx->reg_bar]))) { - return ctx->bar_space[bar] + (addr - ctx->board_info.bar_start[bar]) + (ctx->board_info.bar_start[bar] & ctx->page_mask); - } - } - - return NULL; -} - -char *pcilib_resolve_data_space(pcilib_t *ctx, uintptr_t addr, size_t *size) { - int err; - - err = pcilib_map_data_space(ctx, addr); - if (err) { - pcilib_error("Failed to map the specified address space (%lx)", addr); - return NULL; - } - - if (size) *size = ctx->board_info.bar_length[ctx->data_bar]; - - return ctx->bar_space[ctx->data_bar] + (ctx->board_info.bar_start[ctx->data_bar] & ctx->page_mask); -} - - -void pcilib_close(pcilib_t *ctx) { - pcilib_bar_t i; - - if (ctx) { - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - pcilib_event_api_description_t *eapi = model_info->event_api; - pcilib_dma_api_description_t *dapi = model_info->dma_api; - - if ((eapi)&&(eapi->free)) eapi->free(ctx->event_ctx); - if ((dapi)&&(dapi->free)) dapi->free(ctx->dma_ctx); - - if (ctx->model_info.registers != model_info->registers) { - free(ctx->model_info.registers); - ctx->model_info.registers = pcilib_model[ctx->model].registers; - } - - if (ctx->kmem_list) { - pcilib_warning("Not all kernel buffers are properly cleaned"); - - while (ctx->kmem_list) { - pcilib_free_kernel_memory(ctx, ctx->kmem_list, 0); - } - } - - for (i = 0; i < PCILIB_MAX_BANKS; i++) { - if (ctx->bar_space[i]) { - char *ptr = ctx->bar_space[i]; - ctx->bar_space[i] = NULL; - pcilib_unmap_bar(ctx, i, ptr); - } - } - close(ctx->handle); - - free(ctx); - } -} - -int pcilib_read(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf) { - void *data; - - pcilib_detect_address(ctx, &bar, &addr, size); - data = pcilib_map_bar(ctx, bar); - - pcilib_memcpy(buf, data + addr, size); - - pcilib_unmap_bar(ctx, bar, data); - - return 0; -} - -int pcilib_write(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf) { - void *data; - - pcilib_detect_address(ctx, &bar, &addr, size); - data = pcilib_map_bar(ctx, bar); - - pcilib_memcpy(data + addr, buf, size); - - pcilib_unmap_bar(ctx, bar, data); - - return 0; -} - - -int pcilib_read_fifo(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, uint8_t fifo_size, size_t n, void *buf) { - int i; - void *data; - - pcilib_detect_address(ctx, &bar, &addr, fifo_size); - data = pcilib_map_bar(ctx, bar); - - for (i = 0; i < n; i++) { - pcilib_memcpy(buf + i * fifo_size, data + addr, fifo_size); - } - - pcilib_unmap_bar(ctx, bar, data); - - return 0; -} - -int pcilib_write_fifo(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, uint8_t fifo_size, size_t n, void *buf) { - int i; - void *data; - - pcilib_detect_address(ctx, &bar, &addr, fifo_size); - data = pcilib_map_bar(ctx, bar); - - for (i = 0; i < n; i++) { - pcilib_memcpy(data + addr, buf + i * fifo_size, fifo_size); - } - - pcilib_unmap_bar(ctx, bar, data); - - return 0; -} diff --git a/pci.h b/pci.h deleted file mode 100644 index 8f8359c..0000000 --- a/pci.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef _PCITOOL_PCI_H -#define _PCITOOL_PCI_H - -#define PCILIB_DEFAULT_CPU_COUNT 2 -#define PCILIB_EVENT_TIMEOUT 1000000 /**< us */ -#define PCILIB_TRIGGER_TIMEOUT 100000 /**< us */ -#define PCILIB_DMA_TIMEOUT 10000 /**< us */ -#define PCILIB_DMA_SKIP_TIMEOUT 1000000 /**< us */ -#define PCILIB_REGISTER_TIMEOUT 10000 /**< us */ - -#include "driver/pciDriver.h" -#include "pcilib_types.h" - -#include "pcilib.h" -#include "register.h" -#include "kmem.h" -#include "irq.h" -#include "dma.h" -#include "event.h" - -struct pcilib_s { - int handle; - - uintptr_t page_mask; - pcilib_board_info_t board_info; - pcilib_dma_info_t dma_info; - pcilib_model_t model; - - char *bar_space[PCILIB_MAX_BANKS]; - - int reg_bar_mapped; - pcilib_bar_t reg_bar; -// char *reg_space; - - int data_bar_mapped; - pcilib_bar_t data_bar; -// char *data_space; -// size_t data_size; - - pcilib_kmem_list_t *kmem_list; - - size_t num_reg, alloc_reg; - pcilib_model_description_t model_info; - - pcilib_dma_context_t *dma_ctx; - pcilib_context_t *event_ctx; - -#ifdef PCILIB_FILE_IO - int file_io_handle; -#endif /* PCILIB_FILE_IO */ -}; - -#ifdef _PCILIB_PCI_C -# include "ipecamera/model.h" -# include "kapture/model.h" -# include "dma/nwl.h" -# include "dma/ipe.h" -# include "default.h" - -pcilib_model_description_t pcilib_model[4] = { - { 4, PCILIB_HOST_ENDIAN, NULL, NULL, NULL, NULL, NULL, NULL }, - { 4, PCILIB_HOST_ENDIAN, NULL, NULL, NULL, NULL, NULL, NULL }, - { 4, PCILIB_LITTLE_ENDIAN, ipecamera_registers, ipecamera_register_banks, ipecamera_register_ranges, ipecamera_events, ipecamera_data_types, &ipe_dma_api, &ipecamera_image_api }, - { 4, PCILIB_LITTLE_ENDIAN, kapture_registers, kapture_register_banks, kapture_register_ranges, kapture_events, kapture_data_types, &ipe_dma_api, &kapture_api }, -}; - -pcilib_protocol_description_t pcilib_protocol[3] = { - { pcilib_default_read, pcilib_default_write }, - { ipecamera_read, ipecamera_write }, - { NULL, NULL } -}; -#else -extern pcilib_model_description_t pcilib_model[]; -extern pcilib_protocol_description_t pcilib_protocol[]; -#endif /* _PCILIB_PCI_C */ - -const pcilib_board_info_t *pcilib_get_board_info(pcilib_t *ctx); -const pcilib_dma_info_t *pcilib_get_dma_info(pcilib_t *ctx); - -int pcilib_map_register_space(pcilib_t *ctx); -int pcilib_map_data_space(pcilib_t *ctx, uintptr_t addr); -int pcilib_detect_address(pcilib_t *ctx, pcilib_bar_t *bar, uintptr_t *addr, size_t size); - - -#endif /* _PCITOOL_PCI_H */ diff --git a/pcilib.h b/pcilib.h deleted file mode 100644 index 12d5252..0000000 --- a/pcilib.h +++ /dev/null @@ -1,380 +0,0 @@ -#ifndef _PCITOOL_PCILIB_H -#define _PCITOOL_PCILIB_H - -#define PCILIB_MAX_BANKS 6 -#define PCILIB_MAX_DMA_ENGINES 32 - -#include -#include - -#define pcilib_memcpy pcilib_memcpy32 -#define pcilib_datacpy pcilib_datacpy32 - -typedef struct pcilib_s pcilib_t; -typedef struct pcilib_event_context_s pcilib_context_t; -typedef struct pcilib_dma_context_s pcilib_dma_context_t; - - -typedef struct pcilib_dma_api_description_s pcilib_dma_api_description_t; -typedef struct pcilib_event_api_description_s pcilib_event_api_description_t; -typedef struct pcilib_protocol_description_s pcilib_protocol_description_t; -typedef unsigned int pcilib_irq_hw_source_t; -typedef uint32_t pcilib_irq_source_t; - -typedef uint8_t pcilib_bar_t; /**< Type holding the PCI Bar number */ -typedef uint8_t pcilib_register_t; /**< Type holding the register ID within the Bank */ -typedef uint32_t pcilib_register_addr_t; /**< Type holding the register ID within the Bank */ -typedef uint8_t pcilib_register_bank_t; /**< Type holding the register bank number */ -typedef uint8_t pcilib_register_bank_addr_t; /**< Type holding the register bank number */ -typedef uint8_t pcilib_register_size_t; /**< Type holding the size in bits of the register */ -typedef uint32_t pcilib_register_value_t; /**< Type holding the register value */ -typedef uint8_t pcilib_dma_engine_addr_t; -typedef uint8_t pcilib_dma_engine_t; -typedef uint64_t pcilib_event_id_t; -typedef uint32_t pcilib_event_t; -typedef uint64_t pcilib_timeout_t; /**< In microseconds */ - -typedef enum { - PCILIB_HOST_ENDIAN = 0, - PCILIB_LITTLE_ENDIAN, - PCILIB_BIG_ENDIAN -} pcilib_endianess_t; - -typedef enum { - PCILIB_MODEL_DETECT, - PCILIB_MODEL_PCI, - PCILIB_MODEL_IPECAMERA, - PCILIB_MODEL_KAPTURE -} pcilib_model_t; - -typedef enum { - PCILIB_REGISTER_R = 1, - PCILIB_REGISTER_W = 2, - PCILIB_REGISTER_RW = 3, - PCILIB_REGISTER_W1C = 4, /**< writting 1 resets the flag */ - PCILIB_REGISTER_RW1C = 5 -} pcilib_register_mode_t; - -typedef enum { - PCILIB_DEFAULT_PROTOCOL, - IPECAMERA_REGISTER_PROTOCOL -} pcilib_register_protocol_t; - -typedef enum { - PCILIB_EVENT_DATA = 0, /**< default data format */ - PCILIB_EVENT_RAW_DATA = 1 /**< raw data */ -} pcilib_event_data_type_t; - -typedef enum { - PCILIB_DMA_FLAGS_DEFAULT = 0, - PCILIB_DMA_FLAG_EOP = 1, /**< last buffer of the packet */ - PCILIB_DMA_FLAG_WAIT = 2, /**< wait completion of write operation / wait for data during read operation */ - PCILIB_DMA_FLAG_MULTIPACKET = 4, /**< read multiple packets */ - PCILIB_DMA_FLAG_PERSISTENT = 8, /**< do not stop DMA engine on application termination / permanently close DMA engine on dma_stop */ - PCILIB_DMA_FLAG_IGNORE_ERRORS = 16 /**< do not crash on errors, but return appropriate error codes */ -} pcilib_dma_flags_t; - -typedef enum { - PCILIB_STREAMING_STOP = 0, /**< stop streaming */ - PCILIB_STREAMING_CONTINUE = 1, /**< wait the default DMA timeout for a new data */ - PCILIB_STREAMING_WAIT = 2, /**< wait the specified timeout for a new data */ - PCILIB_STREAMING_CHECK = 3, /**< do not wait for the data, bail out imideatly if no data ready */ - PCILIB_STREAMING_FAIL = 4, /**< fail if data is not available on timeout */ - PCILIB_STREAMING_REQ_FRAGMENT = 5, /**< only fragment of a packet is read, wait for next fragment and fail if no data during DMA timeout */ - PCILIB_STREAMING_REQ_PACKET = 6, /**< wait for next packet and fail if no data during the specified timeout */ - PCILIB_STREAMING_TIMEOUT_MASK = 3 /**< mask specifying all timeout modes */ -} pcilib_streaming_action_t; - - -typedef enum { - PCILIB_EVENT_FLAGS_DEFAULT = 0, - PCILIB_EVENT_FLAG_RAW_DATA_ONLY = 1, /**< Do not parse data, just read raw and pass it to rawdata callback. If passed to rawdata callback, idicates the data is not identified as event (most probably just padding) */ - PCILIB_EVENT_FLAG_STOP_ONLY = 1, /**< Do not cleanup, just stop acquiring new frames, the cleanup should be requested afterwards */ - PCILIB_EVENT_FLAG_EOF = 2, /**< Indicates that it is the last part of the frame (not required) */ - PCILIB_EVENT_FLAG_PREPROCESS = 4 /**< Enables preprocessing of the raw data (decoding frames, etc.) */ -} pcilib_event_flags_t; - -typedef enum { - PCILIB_EVENT_INFO_FLAG_BROKEN = 1 /**< Indicates broken frames (if this flag is fales, the frame still can be broken) */ -} pcilib_event_info_flags_t; - -typedef enum { - PCILIB_REGISTER_STANDARD = 0, - PCILIB_REGISTER_FIFO, - PCILIB_REGISTER_BITS -} pcilib_register_type_t; - -#define PCILIB_BAR_DETECT ((pcilib_bar_t)-1) -#define PCILIB_BAR_INVALID ((pcilib_bar_t)-1) -#define PCILIB_BAR0 0 -#define PCILIB_BAR1 1 -#define PCILIB_DMA_ENGINE_INVALID ((pcilib_dma_engine_t)-1) -#define PCILIB_DMA_ENGINE_ALL ((pcilib_dma_engine_t)-1) -#define PCILIB_DMA_FLAGS_DEFAULT ((pcilib_dma_flags_t)0) -#define PCILIB_DMA_ENGINE_ADDR_INVALID ((pcilib_dma_engine_addr_t)-1) -#define PCILIB_REGISTER_INVALID ((pcilib_register_t)-1) -#define PCILIB_ADDRESS_INVALID ((uintptr_t)-1) -#define PCILIB_REGISTER_BANK_INVALID ((pcilib_register_bank_t)-1) -#define PCILIB_REGISTER_BANK0 0 -#define PCILIB_REGISTER_BANK1 1 -#define PCILIB_REGISTER_BANK2 2 -#define PCILIB_REGISTER_BANK3 3 -#define PCILIB_REGISTER_BANK_DMA 128 -#define PCILIB_EVENT0 1 -#define PCILIB_EVENT1 2 -#define PCILIB_EVENT2 4 -#define PCILIB_EVENT3 8 -#define PCILIB_EVENTS_ALL ((pcilib_event_t)-1) -#define PCILIB_EVENT_INVALID ((pcilib_event_t)-1) -#define PCILIB_EVENT_DATA_TYPE_INVALID ((pcilib_event_data_type_t)-1) -#define PCILIB_TIMEOUT_INFINITE ((pcilib_timeout_t)-1) -#define PCILIB_TIMEOUT_IMMEDIATE 0 -#define PCILIB_IRQ_TYPE_ALL 0 -#define PCILIB_IRQ_SOURCE_DEFAULT 0 -#define PCILIB_REGISTER_NO_BITS 0 -#define PCILIB_REGISTER_ALL_BITS ((pcilib_register_value_t)-1) - -typedef struct { - pcilib_event_t type; - uint64_t seqnum; /**< we will add seqnum_overflow if required */ - uint64_t offset; /**< nanoseconds */ - struct timeval timestamp; /**< most accurate timestamp */ - pcilib_event_info_flags_t flags; /**< flags */ -} pcilib_event_info_t; - -/**< - * Callback function called when new data is read by DMA streaming function - * @ctx - DMA Engine context - * @flags - DMA Flags - * @bufsize - size of data in bytes - * @buf - data - * @returns - * <0 - error, stop streaming (the value is negative error code) - * 0 - stop streaming (PCILIB_STREAMING_STOP) - * 1 - wait DMA timeout and return gracefuly if no data (PCILIB_STREAMING_CONTINUE) - * 2 - wait the specified timeout and return gracefuly if no data (PCILIB_STREAMING_WAIT) - * 3 - check if more data is available without waiting, return gracefuly if not (PCILIB_STREAMING_CHECK) - * 5 - wait DMA timeout and fail if no data (PCILIB_STREAMING_REQ_FRAGMENT) - * 6 - wait the specified timeout and fail if no data (PCILIB_STREAMING_REQ_PACKET) - */ -typedef int (*pcilib_dma_callback_t)(void *ctx, pcilib_dma_flags_t flags, size_t bufsize, void *buf); -typedef int (*pcilib_event_callback_t)(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *user); -typedef int (*pcilib_event_rawdata_callback_t)(pcilib_event_id_t event_id, pcilib_event_info_t *info, pcilib_event_flags_t flags, size_t size, void *data, void *user); - -typedef struct { - pcilib_register_bank_addr_t addr; - - pcilib_bar_t bar; // optional - size_t size; - - pcilib_register_protocol_t protocol; - - uintptr_t read_addr; // or offset if bar specified - uintptr_t write_addr; // or offset if bar specified - uint8_t raw_endianess; - - uint8_t access; - uint8_t endianess; - - const char *format; - const char *name; - const char *description; -} pcilib_register_bank_description_t; - -typedef struct { - pcilib_register_addr_t addr; - pcilib_register_size_t offset; - pcilib_register_size_t bits; - pcilib_register_value_t defvalue; - pcilib_register_value_t rwmask; /**< 1 - read before write bits, 0 - zero should be written to preserve value - Used to define how external bits of PCILIB_REGISTER_BITS registers are treated. - Currently it is a bit confusing, we may find a better way in the next release */ - pcilib_register_mode_t mode; - pcilib_register_type_t type; - - pcilib_register_bank_t bank; - - const char *name; - const char *description; -} pcilib_register_description_t; - -/** - * Default mappings - */ -typedef struct { - uintptr_t start; - uintptr_t end; - pcilib_register_bank_addr_t bank; - long addr_shift; -} pcilib_register_range_t; - -typedef struct { - pcilib_event_t evid; - const char *name; - const char *description; -} pcilib_event_description_t; - -typedef struct { - pcilib_event_data_type_t data_type; - pcilib_event_t evid; - const char *name; - const char *description; -} pcilib_event_data_type_description_t; - -typedef enum { - PCILIB_DMA_IRQ = 1, - PCILIB_EVENT_IRQ = 2 -} pcilib_irq_type_t; - -typedef enum { - PCILIB_DMA_TO_DEVICE = 1, - PCILIB_DMA_FROM_DEVICE = 2, - PCILIB_DMA_BIDIRECTIONAL = 3 -} pcilib_dma_direction_t; - -typedef enum { - PCILIB_DMA_TYPE_BLOCK, - PCILIB_DMA_TYPE_PACKET, - PCILIB_DMA_TYPE_UNKNOWN -} pcilib_dma_engine_type_t; - -typedef struct { - pcilib_dma_engine_addr_t addr; - pcilib_dma_engine_type_t type; - pcilib_dma_direction_t direction; - size_t addr_bits; -} pcilib_dma_engine_description_t; - -typedef struct { - pcilib_dma_engine_description_t *engines[PCILIB_MAX_DMA_ENGINES + 1]; -} pcilib_dma_info_t; - -typedef struct { - uint8_t access; - uint8_t endianess; - - pcilib_register_description_t *registers; - pcilib_register_bank_description_t *banks; - pcilib_register_range_t *ranges; - pcilib_event_description_t *events; - pcilib_event_data_type_description_t *data_types; - - pcilib_dma_api_description_t *dma_api; - pcilib_event_api_description_t *event_api; -} pcilib_model_description_t; - -int pcilib_set_error_handler(void (*err)(const char *msg, ...), void (*warn)(const char *msg, ...)); - -pcilib_model_t pcilib_get_model(pcilib_t *ctx); -pcilib_model_description_t *pcilib_get_model_description(pcilib_t *ctx); -pcilib_context_t *pcilib_get_implementation_context(pcilib_t *ctx); - -pcilib_t *pcilib_open(const char *device, pcilib_model_t model); -void pcilib_close(pcilib_t *ctx); - -int pcilib_start_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags); -int pcilib_stop_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags); - - // Interrupt API is preliminary and can be significantly changed in future -int pcilib_enable_irq(pcilib_t *ctx, pcilib_irq_type_t irq_type, pcilib_dma_flags_t flags); -int pcilib_acknowledge_irq(pcilib_t *ctx, pcilib_irq_type_t irq_type, pcilib_irq_source_t irq_source); -int pcilib_disable_irq(pcilib_t *ctx, pcilib_dma_flags_t flags); - -int pcilib_wait_irq(pcilib_t *ctx, pcilib_irq_hw_source_t source, pcilib_timeout_t timeout, size_t *count); -int pcilib_clear_irq(pcilib_t *ctx, pcilib_irq_hw_source_t source); - -void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar); -void pcilib_unmap_bar(pcilib_t *ctx, pcilib_bar_t bar, void *data); -char *pcilib_resolve_register_address(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr); // addr is offset if bar is specified -char *pcilib_resolve_data_space(pcilib_t *ctx, uintptr_t addr, size_t *size); - -pcilib_register_bank_t pcilib_find_bank_by_addr(pcilib_t *ctx, pcilib_register_bank_addr_t bank); -pcilib_register_bank_t pcilib_find_bank_by_name(pcilib_t *ctx, const char *bankname); -pcilib_register_bank_t pcilib_find_bank(pcilib_t *ctx, const char *bank); -pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const char *reg); -pcilib_event_t pcilib_find_event(pcilib_t *ctx, const char *event); -pcilib_event_data_type_t pcilib_find_event_data_type(pcilib_t *ctx, pcilib_event_t event, const char *data_type); -pcilib_dma_engine_t pcilib_find_dma_by_addr(pcilib_t *ctx, pcilib_dma_direction_t direction, pcilib_dma_engine_addr_t dma); - -int pcilib_read(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf); -int pcilib_write(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf); -int pcilib_write_fifo(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, uint8_t fifo_size, size_t n, void *buf); -int pcilib_read_fifo(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, uint8_t fifo_size, size_t n, void *buf); - -int pcilib_skip_dma(pcilib_t *ctx, pcilib_dma_engine_t dma); -int pcilib_stream_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr); -int pcilib_push_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *buf, size_t *written_bytes); -int pcilib_read_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, void *buf, size_t *read_bytes); -int pcilib_read_dma_custom(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *buf, size_t *read_bytes); -int pcilib_write_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, void *buf, size_t *written_bytes); -double pcilib_benchmark_dma(pcilib_t *ctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction); - -int pcilib_read_register_space(pcilib_t *ctx, const char *bank, pcilib_register_addr_t addr, size_t n, pcilib_register_value_t *buf); -int pcilib_write_register_space(pcilib_t *ctx, const char *bank, pcilib_register_addr_t addr, size_t n, pcilib_register_value_t *buf); -int pcilib_read_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_register_value_t *value); -int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_register_value_t value); -int pcilib_read_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t *value); -int pcilib_write_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t value); - -int pcilib_reset(pcilib_t *ctx); -int pcilib_trigger(pcilib_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data); - -/* - * The recording of new events will be stopped after reaching max_events records - * or when the specified amount of time is elapsed. However, the @pcilib_stop - * function should be called still. - * NOTE: This options may not be respected if the PCILIB_EVENT_FLAG_RAW_DATA_ONLY - * is specified. - */ -int pcilib_configure_autostop(pcilib_t *ctx, size_t max_events, pcilib_timeout_t duration); - -/* - * Request auto-triggering while grabbing - */ -int pcilib_configure_autotrigger(pcilib_t *ctx, pcilib_timeout_t interval, pcilib_event_t event, size_t trigger_size, void *trigger_data); -/* - * Request streaming the rawdata from the event engine. It is fastest way to acuqire data. - * No memory copies will be performed and DMA buffers will be directly passed to the user - * callback. However, to prevent data loss, no processing should be done on the data. The - * user callback is only expected to copy data into the appropriate place and return control - * to the event engine. - * The performance can be boosted further by disabling any data processing within the event - * engine. Just pass PCILIB_EVENT_FLAG_RAW_DATA_ONLY flag to the @pcilib_start function. - */ -int pcilib_configure_rawdata_callback(pcilib_t *ctx, pcilib_event_rawdata_callback_t callback, void *user); - -/* - * Configures maximal number of preprocessing threads. Actual amount of threads - * may be bigger. For instance, additionaly a real-time reader thread will be - * executed for most of hardware - */ -int pcilib_configure_preprocessing_threads(pcilib_t *ctx, size_t max_threads); - - -int pcilib_start(pcilib_t *ctx, pcilib_event_t event_mask, pcilib_event_flags_t flags); -int pcilib_stop(pcilib_t *ctx, pcilib_event_flags_t flags); - -int pcilib_stream(pcilib_t *ctx, pcilib_event_callback_t callback, void *user); -int pcilib_get_next_event(pcilib_t *ctx, pcilib_timeout_t timeout, pcilib_event_id_t *evid, size_t info_size, pcilib_event_info_t *info); - -int pcilib_copy_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t size, void *buf, size_t *retsize); -int pcilib_copy_data_with_argument(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t size, void *buf, size_t *retsize); -void *pcilib_get_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size_or_err); -void *pcilib_get_data_with_argument(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size_or_err); - -/* - * This function is provided to find potentially corrupted data. If the data is overwritten by - * the time return_data is called it will return error. - */ -int pcilib_return_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, void *data); - - - -/* - * @param data - will be allocated and shuld be freed if NULL, otherwise used and size should contain correct size. - * In case of failure the content of data is undefined. - * @param timeout - will be autotriggered if NULL - */ -int pcilib_grab(pcilib_t *ctx, pcilib_event_t event_mask, size_t *size, void **data, pcilib_timeout_t timeout); - -#endif /* _PCITOOL_PCILIB_H */ diff --git a/pcilib_types.h b/pcilib_types.h deleted file mode 100644 index 52c0879..0000000 --- a/pcilib_types.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _PCILIB_TYPES_H -#define _PCILIB_TYPES_H - -#define KMEM_REF_HW 0x80000000 /**< Special reference to indicate hardware access */ -#define KMEM_REF_COUNT 0x0FFFFFFF /**< Mask of reference counter (mmap/munmap), couting in mmaped memory pages */ - -#define KMEM_MODE_REUSABLE 0x80000000 /**< Indicates reusable buffer */ -#define KMEM_MODE_EXCLUSIVE 0x40000000 /**< Only a single process is allowed to mmap the buffer */ -#define KMEM_MODE_PERSISTENT 0x20000000 /**< Persistent mode instructs kmem_free to preserve buffer in memory */ -#define KMEM_MODE_COUNT 0x0FFFFFFF /**< Mask of reuse counter (alloc/free) */ - -#define PCILIB_KMEM_TYPE_MASK 0xFFFF0000 - -typedef enum { - PCILIB_KMEM_TYPE_CONSISTENT = 0x00000, - PCILIB_KMEM_TYPE_PAGE = 0x10000, - PCILIB_KMEM_TYPE_DMA_S2C_PAGE = 0x10001, - PCILIB_KMEM_TYPE_DMA_C2S_PAGE = 0x10002, - PCILIB_KMEM_TYPE_REGION = 0x20000, - PCILIB_KMEM_TYPE_REGION_S2C = 0x20001, - PCILIB_KMEM_TYPE_REGION_C2S = 0x20002 -} pcilib_kmem_type_t; - -typedef enum { - PCILIB_KMEM_USE_STANDARD = 0, - PCILIB_KMEM_USE_DMA_RING = 1, - PCILIB_KMEM_USE_DMA_PAGES = 2, - PCILIB_KMEM_USE_USER = 0x10 -} pcilib_kmem_use_t; - -typedef enum { - PCILIB_KMEM_SYNC_BIDIRECTIONAL = 0, - PCILIB_KMEM_SYNC_TODEVICE = 1, - PCILIB_KMEM_SYNC_FROMDEVICE = 2 -} pcilib_kmem_sync_direction_t; - - -#define PCILIB_KMEM_USE(type, subtype) (((type) << 16)|(subtype)) - - -//pcilib_alloc_kmem_buffer(pcilib_t *ctx, size_t size, size_t alignment) - - -#endif /* _PCILIB_TYPES_H */ diff --git a/pcitool/CMakeLists.txt b/pcitool/CMakeLists.txt deleted file mode 100644 index 6dc7942..0000000 --- a/pcitool/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -include_directories( - ${CMAKE_SOURCE_DIR} -) - -set(HEADERS ${HEADERS} sysinfo.h formaters.h) - -add_library(pcitool STATIC sysinfo.c formaters.c) - diff --git a/pcitool/formaters.c b/pcitool/formaters.c deleted file mode 100644 index 91b8c77..0000000 --- a/pcitool/formaters.c +++ /dev/null @@ -1,47 +0,0 @@ -#include - -void PrintTime(size_t duration) { - if (duration > 999999999999) printf("%4.1lf""d", 1.*duration/86400000000); - else if (duration > 99999999999) printf("%4.1lf""h", 1.*duration/3600000000); - else if (duration > 9999999999) printf("%4.2lf""h", 1.*duration/3600000000); - else if (duration > 999999999) printf("%4.1lf""m", 1.*duration/60000000); - else if (duration > 99999999) printf("%4.2lf""m", 1.*duration/60000000); - else if (duration > 9999999) printf("%4.1lf""s", 1.*duration/1000000); - else if (duration > 999999) printf("%4.2lf""s", 1.*duration/1000000); - else if (duration > 999) printf("%3lu""ms", duration/1000); - else printf("%3lu""us", duration); -} - -void PrintNumber(size_t num) { - if (num > 999999999999999999) printf("%3lue", num/1000000000000000000); - else if (num > 999999999999999) printf("%3lup", num/1000000000000000); - else if (num > 999999999999) printf("%3lut", num/1000000000000); - else if (num > 999999999) printf("%3lug", num/1000000000); - else if (num > 999999) printf("%3lum", num/1000000); - else if (num > 9999) printf("%3luk", num/1000); - else printf("%4lu", num); -} - -void PrintSize(size_t num) { - if (num >= 112589990684263) printf("%4.1lf PB", 1.*num/1125899906842624); - else if (num >= 109951162778) printf("%4.1lf TB", 1.*num/1099511627776); - else if (num >= 107374183) printf("%4.1lf GB", 1.*num/1073741824); - else if (num >= 1048576) printf("%4lu MB", num/1048576); - else if (num >= 1024) printf("%4lu KB", num/1024); - else printf("%5lu B", num); -} - -void PrintPercent(size_t num, size_t total) { - if (num >= total) printf(" 100"); - else printf("%4.1lf", 100.*num/total); - -} - -char *GetPrintSize(char *str, size_t size) { - if (size >= 1073741824) sprintf(str, "%.1lf GB", 1.*size / 1073741824); - else if (size >= 1048576) sprintf(str, "%.1lf MB", 1.*size / 1048576); - else if (size >= 1024) sprintf(str, "%lu KB", size / 1024); - else sprintf(str, "%lu B ", size); - - return str; -} diff --git a/pcitool/formaters.h b/pcitool/formaters.h deleted file mode 100644 index c854da5..0000000 --- a/pcitool/formaters.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _PCITOOL_FORMATERS_H -#define _PCITOOL_FORMATERS_H - -void PrintTime(size_t duration); -void PrintNumber(size_t num); -void PrintSize(size_t num); -void PrintPercent(size_t num, size_t total); -char *GetPrintSize(char *str, size_t size); - - -#endif /* _PCITOOL_FORMATERS_H */ - diff --git a/pcitool/sysinfo.c b/pcitool/sysinfo.c deleted file mode 100644 index d6f57fe..0000000 --- a/pcitool/sysinfo.c +++ /dev/null @@ -1,172 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#define MEMINFO_FILE "/proc/meminfo" -#define MTAB_FILE "/etc/mtab" - -#define BAD_OPEN_MESSAGE \ -"Error: /proc must be mounted\n" \ -" To mount /proc at boot you need an /etc/fstab line like:\n" \ -" /proc /proc proc defaults\n" \ -" In the meantime, run \"mount /proc /proc -t proc\"\n" - -/* This macro opens filename only if necessary and seeks to 0 so - * that successive calls to the functions are more efficient. - * It also reads the current contents of the file into the global buf. - */ -#define FILE_TO_BUF(filename) do{ \ - static int fd, local_n; \ - if ((fd = open(filename, O_RDONLY)) == -1) { \ - fputs(BAD_OPEN_MESSAGE, stderr); \ - fflush(NULL); \ - _exit(102); \ - } \ - lseek(fd, 0L, SEEK_SET); \ - if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) { \ - perror(filename); \ - fflush(NULL); \ - _exit(103); \ - } \ - buf[local_n] = '\0'; \ - close(fd); \ -}while(0) - - -typedef struct mem_table_struct { - const char *name; /* memory type name */ - unsigned long *slot; /* slot in return struct */ -} mem_table_struct; - -static int compare_mem_table_structs(const void *a, const void *b){ - return strcmp(((const mem_table_struct*)a)->name,((const mem_table_struct*)b)->name); -} - -size_t get_free_memory(void){ - char buf[4096]; - unsigned long kb_main_buffers, kb_main_cached, kb_main_free; - char namebuf[16]; /* big enough to hold any row name */ - mem_table_struct findme = { namebuf, NULL}; - mem_table_struct *found; - char *head; - char *tail; - - const mem_table_struct mem_table[] = { - {"Buffers", &kb_main_buffers}, // important - {"Cached", &kb_main_cached}, // important - {"MemFree", &kb_main_free}, // important - }; - const int mem_table_count = sizeof(mem_table)/sizeof(mem_table_struct); - - FILE_TO_BUF(MEMINFO_FILE); - - head = buf; - for(;;){ - tail = strchr(head, ':'); - if(!tail) break; - *tail = '\0'; - if(strlen(head) >= sizeof(namebuf)){ - head = tail+1; - goto nextline; - } - strcpy(namebuf,head); - found = bsearch(&findme, mem_table, mem_table_count, - sizeof(mem_table_struct), compare_mem_table_structs - ); - head = tail+1; - if(!found) goto nextline; - *(found->slot) = strtoul(head,&tail,10); -nextline: - tail = strchr(head, '\n'); - if(!tail) break; - head = tail+1; - } - - return (kb_main_buffers + kb_main_cached + kb_main_free) * 1024; -} - - -int get_file_fs(const char *fname, size_t size, char *fs) { - int err = 0; - char buf[4096]; - char *fn; - - char *head; - char *tail; - - size_t len, max = 0; - struct stat st; - - if ((!fname)||(!fs)||(size < 3)) return -1; - - if (*fname == '/') { - fn = (char*)fname; - } else { - if (!getcwd(buf, 4095)) return -1; - fn = malloc(strlen(fname) + strlen(buf) + 2); - if (!fn) return -1; - sprintf(fn, "%s/%s", buf, fname); - } - - if (!stat(fn, &st)) { - if (S_ISBLK(st.st_mode)) { - strcpy(fs, "raw"); - goto clean; - } - } - - FILE_TO_BUF(MTAB_FILE); - - head = buf; - for(;;){ - head = strchr(head, ' '); - if(!head) break; - - head += 1; - tail = strchr(head, ' '); - if(!tail) break; - - *tail = '\0'; - - len = strlen(head); - if((len <= max)||(strncmp(head, fn, len))) { - head = tail+1; - goto nextline; - } - - head = tail + 1; - tail = strchr(head, ' '); - if(!tail) break; - - *tail = '\0'; - - if (!strncasecmp(head,"root",4)) { - head = tail+1; - goto nextline; - } - - max = len; - - if (strlen(head) >= size) err = -1; - else { - err = 0; - strcpy(fs, head); - } - - head = tail+1; -nextline: - tail = strchr(head, '\n'); - if(!tail) break; - head = tail+1; - } - -clean: - if (fn != fname) free(fn); - - return err; -} diff --git a/pcitool/sysinfo.h b/pcitool/sysinfo.h deleted file mode 100644 index d5636a7..0000000 --- a/pcitool/sysinfo.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _PCITOOL_SYSINFO_H -#define _PCITOOL_SYSINFO_H - -size_t get_free_memory(); -int get_file_fs(const char *fname, size_t size, char *fs); - -#endif /* _PCITOOL_SYSINFO_H */ diff --git a/private.h b/private.h new file mode 100644 index 0000000..a0611f3 --- /dev/null +++ b/private.h @@ -0,0 +1,155 @@ +#ifndef _IPECAMERA_PRIVATE_H +#define _IPECAMERA_PRIVATE_H + +#include +#include +#include "ipecamera.h" + +//#define IPECAMERA_BUG_EXTRA_DATA +#define IPECAMERA_BUG_MULTIFRAME_PACKETS //**< this is by design, start of packet comes directly after the end of last one in streaming mode */ +//#define IPECAMERA_BUG_INCOMPLETE_PACKETS +#define IPECAMERA_BUG_POSTPONED_READ +#define IPECAMERA_DEBUG_BROKEN_FRAMES "/mnt/frames" +//#define IPECAMERA_DEBUG_RAW_PACKETS "/mnt/frames" + +//#define IPECAMERA_ANNOUNCE_READY //**< announce new event only after the reconstruction is done */ + +#define IPECAMERA_REGISTER_TIMEOUT 10000 //**< us */ +#define IPECAMERA_DMA_TIMEOUT 50000 //**< us */ + +#define IPECAMERA_DEFAULT_BUFFER_SIZE 64 //**< should be power of 2 */ +#define IPECAMERA_RESERVE_BUFFERS 2 //**< Return Frame is Lost error, if requested frame will be overwritten after specified number of frames +#define IPECAMERA_SLEEP_TIME 250000 //**< Michele thinks 250 should be enough, but reset failing in this case */ +#define IPECAMERA_NEXT_FRAME_DELAY 1000 //**< Michele requires 30000 to sync between End Of Readout and next Frame Req */ +#define IPECAMERA_WAIT_FRAME_RCVD_TIME 0 //**< by Uros ,wait 6 ms */ +#define IPECAMERA_TRIGGER_WAIT_IDLE 200000 //**< In trigger call allow specified timeout for camera to get out of busy state. Set 0 to fail immideatly */ +#define IPECAMERA_READ_STATUS_DELAY 1000 //**< According to Uros, 1ms delay needed before consequitive reads from status registers */ + +#define IPECAMERA_NOFRAME_SLEEP 100 +#define IPECAMERA_NOFRAME_PREPROC_SLEEP 100 + +//#define IPECAMERA_MAX_LINES 1088 +#define IPECAMERA_MAX_LINES 2048 +#define IPECAMERA_EXPECTED_STATUS_4 0x08409FFFF +#define IPECAMERA_EXPECTED_STATUS 0x08449FFFF + +#define IPECAMERA_END_OF_SEQUENCE 0x1F001001 + +#define IPECAMERA_MAX_CHANNELS 16 +#define IPECAMERA_PIXELS_PER_CHANNEL 128 +#define IPECAMERA_WIDTH (IPECAMERA_MAX_CHANNELS * IPECAMERA_PIXELS_PER_CHANNEL) + +#define IPECAMERA_FRAME_REQUEST 0x80000209 // 0x1E9 +#define IPECAMERA_IDLE 0x80000201 // 0x1E1 +#define IPECAMERA_START_INTERNAL_STIMULI 0x1F1 + +#define IPECAMERA_MODE_16_CHAN_IO 0 +#define IPECAMERA_MODE_4_CHAN_IO 2 + +#define IPECAMERA_MODE_12_BIT_ADC 2 +#define IPECAMERA_MODE_11_BIT_ADC 1 +#define IPECAMERA_MODE_10_BIT_ADC 0 + +typedef uint32_t ipecamera_payload_t; + +typedef struct { + pcilib_event_id_t evid; + struct timeval timestamp; +} ipecamera_autostop_t; + +typedef struct { + size_t i; + pthread_t thread; + ipecamera_t *ipecamera; + + int started; /**< flag indicating that join & cleanup is required */ +} ipecamera_preprocessor_t; + + +typedef struct { + ipecamera_event_info_t event; /**< this structure is overwritten by the reader thread, we need a copy */ + pthread_rwlock_t mutex; /**< this mutex protects reconstructed buffers only, the raw data, event_info, etc. will be overwritten by reader thread anyway */ +} ipecamera_frame_t; + +struct ipecamera_s { + pcilib_context_t event; + UfoDecoder *ipedec; + + char *data; + ipecamera_pixel_t *image; + size_t size; + + pcilib_event_callback_t cb; + void *cb_user; + + volatile pcilib_event_id_t event_id; + volatile pcilib_event_id_t preproc_id; + pcilib_event_id_t reported_id; + + pcilib_dma_engine_t rdma, wdma; + + pcilib_register_t packet_len_reg; + pcilib_register_t control_reg, status_reg; + pcilib_register_t status2_reg, status3_reg; + pcilib_register_t n_lines_reg; + uint16_t line_reg; + pcilib_register_t exposure_reg; + pcilib_register_t flip_reg; + + pcilib_register_t firmware_version_reg; + pcilib_register_t adc_resolution_reg; + pcilib_register_t output_mode_reg; + + pcilib_register_t max_frames_reg; + pcilib_register_t num_frames_reg; + + int started; /**< Camera is in grabbing mode (start function is called) */ + int streaming; /**< Camera is in streaming mode (we are within stream call) */ + int parse_data; /**< Indicates if some processing of the data is required, otherwise only rawdata_callback will be called */ + + volatile int run_reader; /**< Instructs the reader thread to stop processing */ + volatile int run_streamer; /**< Indicates request to stop streaming events and can be set by reader_thread upon exit or by user request */ + volatile int run_preprocessors; /**< Instructs preprocessors to exit */ + + ipecamera_autostop_t autostop; + + struct timeval autostop_time; + struct timeval next_trigger; /**< The minimal delay between trigger signals is mandatory, this indicates time when next trigger is possible */ + + size_t buffer_size; /**< How many images to store */ + size_t buffer_pos; /**< Current image offset in the buffer, due to synchronization reasons should not be used outside of reader_thread */ + size_t cur_size; /**< Already written part of data in bytes */ + size_t raw_size; /**< Expected maximum size of raw data in bytes */ + size_t full_size; /**< Expected maximum size of raw data including the padding */ + size_t padded_size; /**< Expected maximum size of buffer for raw data, including additional padding due to the ipecamera bugs */ + size_t cur_raw_size; /**< Expected size (for currently configured ROI) of raw data in bytes */ + size_t cur_full_size; /**< Expected size (for currently configured ROI) of raw data including the padding */ + size_t cur_padded_size; /**< Expected size (for currently configured ROI) of buffer for raw data, including additional padding due to the ipecamera bugs */ + + size_t image_size; /**< Size of a single image in bytes */ + + size_t max_frames; /**< Maximal number of frames what may be buffered in camera DDR memory */ + int firmware; /**< Firmware version */ + int cmosis_outputs; /**< Number of active cmosis outputs: 4 or 16 */ + int width, height; + + +// void *raw_buffer; + void *buffer; + ipecamera_change_mask_t *cmask; + ipecamera_frame_t *frame; + + + ipecamera_image_dimensions_t dim; + + pthread_t rthread; + + size_t n_preproc; + ipecamera_preprocessor_t *preproc; + pthread_mutex_t preproc_mutex; + + int preproc_mutex_destroy; + int frame_mutex_destroy; +}; + +#endif /* _IPECAMERA_PRIVATE_H */ diff --git a/reader.c b/reader.c new file mode 100644 index 0000000..db700cd --- /dev/null +++ b/reader.c @@ -0,0 +1,269 @@ +#define _BSD_SOURCE +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "model.h" +#include "private.h" +#include "reader.h" + + +int ipecamera_compute_buffer_size(ipecamera_t *ctx, size_t lines) { + const size_t header_size = 8 * sizeof(ipecamera_payload_t); + const size_t footer_size = 8 * sizeof(ipecamera_payload_t); + + size_t line_size, raw_size, padded_blocks; + + switch (ctx->firmware) { + case 4: + line_size = IPECAMERA_MAX_CHANNELS * (2 + IPECAMERA_PIXELS_PER_CHANNEL / 3) * sizeof(ipecamera_payload_t); + raw_size = header_size + lines * line_size + footer_size; + break; + default: + line_size = (1 + IPECAMERA_PIXELS_PER_CHANNEL) * 32; + raw_size = lines * line_size; + raw_size *= 16 / ctx->cmosis_outputs; + raw_size += header_size + footer_size; + } + + padded_blocks = raw_size / IPECAMERA_DMA_PACKET_LENGTH + ((raw_size % IPECAMERA_DMA_PACKET_LENGTH)?1:0); + + ctx->cur_raw_size = raw_size; + ctx->cur_full_size = padded_blocks * IPECAMERA_DMA_PACKET_LENGTH; + +#ifdef IPECAMERA_BUG_EXTRA_DATA + ctx->cur_full_size += 8; + padded_blocks ++; +#endif /* IPECAMERA_BUG_EXTRA_DATA */ + + ctx->cur_padded_size = padded_blocks * IPECAMERA_DMA_PACKET_LENGTH; +// printf("%lu %lu %lu\n", ctx->cur_raw_size, ctx->cur_full_size, ctx->cur_padded_size); + + return 0; +} + +static inline int ipecamera_new_frame(ipecamera_t *ctx) { + ctx->frame[ctx->buffer_pos].event.raw_size = ctx->cur_size; + + if (ctx->cur_size < ctx->cur_raw_size) { + ctx->frame[ctx->buffer_pos].event.info.flags |= PCILIB_EVENT_INFO_FLAG_BROKEN; + } + + ctx->buffer_pos = (++ctx->event_id) % ctx->buffer_size; + ctx->cur_size = 0; + + ctx->frame[ctx->buffer_pos].event.info.type = PCILIB_EVENT0; + ctx->frame[ctx->buffer_pos].event.info.flags = 0; + ctx->frame[ctx->buffer_pos].event.image_ready = 0; + + if ((ctx->event_id == ctx->autostop.evid)&&(ctx->event_id)) { + ctx->run_reader = 0; + return 1; + } + + if (pcilib_check_deadline(&ctx->autostop.timestamp, 0)) { + ctx->run_reader = 0; + return 1; + } + + return 0; +} + +static uint32_t frame_magic[5] = { 0x51111111, 0x52222222, 0x53333333, 0x54444444, 0x55555555 }; + +static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t bufsize, void *buf) { + int res; + int eof = 0; + +#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS + size_t real_size; + size_t extra_data = 0; +#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */ + + ipecamera_t *ctx = (ipecamera_t*)user; + +#if defined(IPECAMERA_BUG_INCOMPLETE_PACKETS)||defined(IPECAMERA_BUG_MULTIFRAME_PACKETS) + static pcilib_event_id_t invalid_frame_id = (pcilib_event_id_t)-1; +#endif + +#ifdef IPECAMERA_DEBUG_RAW_PACKETS + char fname[128]; + { + static unsigned long packet_id = 0; + sprintf(fname,"%s/frame%4lu", IPECAMERA_DEBUG_RAW_PACKETS, ctx->event_id); + mkdir(fname, 0755); + sprintf(fname,"%s/frame%4lu/frame%9lu", IPECAMERA_DEBUG_RAW_PACKETS, ctx->event_id, packet_id); + FILE *f = fopen(fname, "w"); + if (f) { + fwrite(buf, 1, bufsize, f); + fclose(f); + } + sprintf(fname,"%s/frame%4lu/frame%9lu.invalid", IPECAMERA_DEBUG_RAW_PACKETS, ctx->event_id, packet_id++); + } +#endif /* IPECAMERA_DEBUG_RAW_PACKETS */ + + if (!ctx->cur_size) { +#if defined(IPECAMERA_BUG_INCOMPLETE_PACKETS)||defined(IPECAMERA_BUG_MULTIFRAME_PACKETS) + size_t startpos; + for (startpos = 0; (startpos + sizeof(frame_magic)) <= bufsize; startpos += sizeof(uint32_t)) { + if (!memcmp(buf + startpos, frame_magic, sizeof(frame_magic))) break; + } + + if ((startpos + sizeof(frame_magic)) > bufsize) { +#ifdef IPECAMERA_DEBUG_RAW_PACKETS + FILE *f = fopen(fname, "w"); + if (f) fclose(f); +#endif /* IPECAMERA_DEBUG_RAW_PACKETS */ + + if (invalid_frame_id != ctx->event_id) { +// pcilib_warning("No frame magic in DMA packet of %u bytes, current event %lu", bufsize, ctx->event_id); + invalid_frame_id = ctx->event_id; + } + + return PCILIB_STREAMING_CONTINUE; + } + + if (startpos) { + // pass padding to rawdata callback + if (ctx->event.params.rawdata.callback) { + res = ctx->event.params.rawdata.callback(0, NULL, PCILIB_EVENT_FLAG_RAW_DATA_ONLY, startpos, buf, ctx->event.params.rawdata.user); + if (res <= 0) { + if (res < 0) return res; + ctx->run_reader = 0; + } + } + + + buf += startpos; + bufsize -= startpos; + } +#endif /* IPECAMERA_BUG_INCOMPLETE_PACKETS */ + + if ((bufsize >= 8)&&(!memcmp(buf, frame_magic, sizeof(frame_magic)))) { + size_t n_lines = ((uint32_t*)buf)[5] & 0x7FF; + ipecamera_compute_buffer_size(ctx, n_lines); + + ctx->frame[ctx->buffer_pos].event.info.seqnum = ((uint32_t*)buf)[6] & 0x1FFFFFF; + ctx->frame[ctx->buffer_pos].event.info.offset = (((uint32_t*)buf)[7] & 0xFFFFFF) * 80; + gettimeofday(&ctx->frame[ctx->buffer_pos].event.info.timestamp, NULL); + } else { +// pcilib_warning("Frame magic is not found, ignoring broken data..."); + return PCILIB_STREAMING_CONTINUE; + } + } + +#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS + // for rawdata_callback with complete padding + real_size = bufsize; + + if (ctx->cur_size + bufsize > ctx->cur_raw_size) { + size_t need; + + for (need = ctx->cur_raw_size - ctx->cur_size; (need + sizeof(frame_magic)) < bufsize; need += sizeof(uint32_t)) { + if (!memcmp(buf + need, frame_magic, sizeof(frame_magic))) break; + } + + if ((need + sizeof(frame_magic)) < bufsize) { + extra_data = bufsize - need; + //bufsize = need; + eof = 1; + } + + // just rip of padding + bufsize = ctx->cur_raw_size - ctx->cur_size; + +#ifdef IPECAMERA_DEBUG_RAW_PACKETS + sprintf(fname + strlen(fname) - 8, ".partial"); + FILE *f = fopen(fname, "w"); + if (f) { + fwrite(buf, 1, bufsize, f); + fclose(f); + } +#endif /* IPECAMERA_DEBUG_RAW_PACKETS */ + } +#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */ + + if (ctx->parse_data) { + if (ctx->cur_size + bufsize > ctx->full_size) { + pcilib_error("Unexpected event data, we are expecting at maximum (%zu) bytes, but (%zu) already read", ctx->full_size, ctx->cur_size + bufsize); + return -PCILIB_ERROR_TOOBIG; + } + + if (bufsize) + memcpy(ctx->buffer + ctx->buffer_pos * ctx->padded_size + ctx->cur_size, buf, bufsize); + } + + ctx->cur_size += bufsize; +// printf("%i: %i %i\n", ctx->buffer_pos, ctx->cur_size, bufsize); + + if (ctx->cur_size >= ctx->cur_raw_size) { + eof = 1; + } + + if (ctx->event.params.rawdata.callback) { + res = ctx->event.params.rawdata.callback(ctx->event_id, (pcilib_event_info_t*)(ctx->frame + ctx->buffer_pos), (eof?PCILIB_EVENT_FLAG_EOF:PCILIB_EVENT_FLAGS_DEFAULT), bufsize, buf, ctx->event.params.rawdata.user); + if (res <= 0) { + if (res < 0) return res; + ctx->run_reader = 0; + } + } + + if (eof) { + if ((ipecamera_new_frame(ctx))||(!ctx->run_reader)) { + return PCILIB_STREAMING_STOP; + } + +#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS + if (extra_data) { + return ipecamera_data_callback(user, flags, extra_data, buf + (real_size - extra_data)); + } +#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */ + } + + return PCILIB_STREAMING_REQ_FRAGMENT; +} + +void *ipecamera_reader_thread(void *user) { + int err; + ipecamera_t *ctx = (ipecamera_t*)user; + + while (ctx->run_reader) { + err = pcilib_stream_dma(ctx->event.pcilib, ctx->rdma, 0, 0, PCILIB_DMA_FLAG_MULTIPACKET, IPECAMERA_DMA_TIMEOUT, &ipecamera_data_callback, user); + if (err) { + if (err == PCILIB_ERROR_TIMEOUT) { + if (ctx->cur_size >= ctx->cur_raw_size) ipecamera_new_frame(ctx); +#ifdef IPECAMERA_BUG_INCOMPLETE_PACKETS + else if (ctx->cur_size > 0) ipecamera_new_frame(ctx); +#endif /* IPECAMERA_BUG_INCOMPLETE_PACKETS */ + if (pcilib_check_deadline(&ctx->autostop.timestamp, 0)) { + ctx->run_reader = 0; + break; + } + usleep(IPECAMERA_NOFRAME_SLEEP); + } else pcilib_error("DMA error while reading IPECamera frames, error: %i", err); + } //else printf("no error\n"); + + //usleep(1000); + } + + ctx->run_streamer = 0; + +// if (ctx->cur_size) +// pcilib_error("partialy read frame after stop signal, %zu bytes in the buffer", ctx->cur_size); + + return NULL; +} diff --git a/reader.h b/reader.h new file mode 100644 index 0000000..5d631c0 --- /dev/null +++ b/reader.h @@ -0,0 +1,8 @@ +#ifndef _IPECAMERA_READER_H +#define _IPECAMERA_READER_H + +int ipecamera_compute_buffer_size(ipecamera_t *ctx, size_t lines); + +void *ipecamera_reader_thread(void *user); + +#endif /* _IPECAMERA_READER_H */ diff --git a/register.c b/register.c deleted file mode 100644 index 7fc689b..0000000 --- a/register.c +++ /dev/null @@ -1,362 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pci.h" - -#include "tools.h" -#include "error.h" - -int pcilib_add_registers(pcilib_t *ctx, size_t n, pcilib_register_description_t *registers) { - pcilib_register_description_t *regs; - size_t size, n_present = 0; - - if (!n) { - for (n = 0; registers[n].bits; n++); - } - - if (ctx->model_info.registers == pcilib_model[ctx->model].registers) { - for (n_present = 0; ctx->model_info.registers[n_present].bits; n_present++); - for (size = 1024; size < 2 * (n + n_present + 1); size<<=1); - regs = (pcilib_register_description_t*)malloc(size * sizeof(pcilib_register_description_t)); - if (!regs) return PCILIB_ERROR_MEMORY; - - ctx->model_info.registers = regs; - ctx->num_reg = n + n_present; - ctx->alloc_reg = size; - - memcpy(ctx->model_info.registers, pcilib_model[ctx->model].registers, (n_present + 1) * sizeof(pcilib_register_description_t)); - } else { - n_present = ctx->num_reg; - if ((n_present + n + 1) > ctx->alloc_reg) { - for (size = ctx->alloc_reg; size < 2 * (n + n_present + 1); size<<=1); - - regs = (pcilib_register_description_t*)realloc(ctx->model_info.registers, size * sizeof(pcilib_register_description_t)); - if (!regs) return PCILIB_ERROR_MEMORY; - - ctx->model_info.registers = regs; - ctx->alloc_reg = size; - } - ctx->num_reg += n; - } - - memcpy(ctx->model_info.registers + ctx->num_reg, ctx->model_info.registers + n_present, sizeof(pcilib_register_description_t)); - memcpy(ctx->model_info.registers + n_present, registers, n * sizeof(pcilib_register_description_t)); - - return 0; -} - -pcilib_register_bank_t pcilib_find_bank_by_addr(pcilib_t *ctx, pcilib_register_bank_addr_t bank) { - pcilib_register_bank_t i; - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - pcilib_register_bank_description_t *banks = model_info->banks; - - for (i = 0; banks[i].access; i++) - if (banks[i].addr == bank) return i; - - return -1; -} - -pcilib_register_bank_t pcilib_find_bank_by_name(pcilib_t *ctx, const char *bankname) { - pcilib_register_bank_t i; - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - pcilib_register_bank_description_t *banks = model_info->banks; - - for (i = 0; banks[i].access; i++) - if (!strcasecmp(banks[i].name, bankname)) return i; - - return -1; -} - -pcilib_register_bank_t pcilib_find_bank(pcilib_t *ctx, const char *bank) { - pcilib_register_bank_t res; - unsigned long addr; - - if (!bank) { - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - pcilib_register_bank_description_t *banks = model_info->banks; - if ((banks)&&(banks[0].access)) return (pcilib_register_bank_t)0; - return -1; - } - - if (pcilib_isxnumber(bank)&&(sscanf(bank,"%lx", &addr) == 1)) { - res = pcilib_find_bank_by_addr(ctx, addr); - if (res != PCILIB_REGISTER_BANK_INVALID) return res; - } - - return pcilib_find_bank_by_name(ctx, bank); -} - - // FIXME create hash during map_register space -pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const char *reg) { - pcilib_register_t i; - pcilib_register_bank_t bank_id; - pcilib_register_bank_addr_t bank_addr = 0; - - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - pcilib_register_description_t *registers = model_info->registers; - - if (bank) { - bank_id = pcilib_find_bank(ctx, bank); - if (bank_id == PCILIB_REGISTER_BANK_INVALID) { - pcilib_error("Invalid bank (%s) is specified", bank); - return -1; - } - - bank_addr = model_info->banks[bank_id].addr; - } - - for (i = 0; registers[i].bits; i++) { - if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i; - } - - if ((ctx->model_info.dma_api)&&(!ctx->dma_ctx)&&(pcilib_get_dma_info(ctx))) { - registers = model_info->registers; - - for (; registers[i].bits; i++) { - if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i; - } - } - - return (pcilib_register_t)-1; -}; - -static int pcilib_read_register_space_internal(pcilib_t *ctx, pcilib_register_bank_t bank, pcilib_register_addr_t addr, size_t n, pcilib_register_size_t offset, pcilib_register_size_t bits, pcilib_register_value_t *buf) { - int err; - size_t i; - - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - pcilib_register_bank_description_t *b = model_info->banks + bank; - - int access = b->access / 8; - - assert(bits < 8 * sizeof(pcilib_register_value_t)); - - if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) { - if ((b->format)&&(strchr(b->format, 'x'))) - pcilib_error("Accessing register (%u regs at addr 0x%x) out of register space (%u registers total)", bits?(n+1):n, addr, b->size); - else - pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size); - return PCILIB_ERROR_OUTOFRANGE; - } - - err = pcilib_map_register_space(ctx); - if (err) { - pcilib_error("Failed to map the register space"); - return err; - } - - //n += bits / b->access; - //bits %= b->access; - - for (i = 0; i < n; i++) { - err = pcilib_protocol[b->protocol].read(ctx, b, addr + i * access, buf + i); - if (err) break; - } - - if ((bits > 0)&&(!err)) { - pcilib_register_value_t val = 0; - err = pcilib_protocol[b->protocol].read(ctx, b, addr + n * access, &val); - - val = (val >> offset)&BIT_MASK(bits); - memcpy(buf + n, &val, sizeof(pcilib_register_value_t)); - } - - return err; -} - -int pcilib_read_register_space(pcilib_t *ctx, const char *bank, pcilib_register_addr_t addr, size_t n, pcilib_register_value_t *buf) { - pcilib_register_bank_t bank_id = pcilib_find_bank(ctx, bank); - if (bank_id == PCILIB_REGISTER_BANK_INVALID) { - if (bank) pcilib_error("Invalid register bank is specified (%s)", bank); - else pcilib_error("Register bank should be specified"); - return PCILIB_ERROR_INVALID_BANK; - } - - return pcilib_read_register_space_internal(ctx, bank_id, addr, n, 0, 0, buf); -} - -int pcilib_read_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_register_value_t *value) { - int err; - size_t i, n; - pcilib_register_size_t bits; - pcilib_register_value_t res; - pcilib_register_bank_t bank; - pcilib_register_description_t *r; - pcilib_register_bank_description_t *b; - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - r = model_info->registers + reg; - - bank = pcilib_find_bank_by_addr(ctx, r->bank); - if (bank == PCILIB_REGISTER_BANK_INVALID) return PCILIB_ERROR_INVALID_BANK; - - b = model_info->banks + bank; - - n = r->bits / b->access; - bits = r->bits % b->access; - - pcilib_register_value_t buf[n + 1]; - err = pcilib_read_register_space_internal(ctx, bank, r->addr, n, r->offset, bits, buf); - - if ((b->endianess == PCILIB_BIG_ENDIAN)||((b->endianess == PCILIB_HOST_ENDIAN)&&(ntohs(1) == 1))) { - pcilib_error("Big-endian byte order support is not implemented"); - return PCILIB_ERROR_NOTSUPPORTED; - } else { - res = 0; - if (bits) ++n; - for (i = 0; i < n; i++) { - res |= buf[i] << (i * b->access); - } - } - - *value = res; - - return err; -} - - -int pcilib_read_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t *value) { - int reg; - - reg = pcilib_find_register(ctx, bank, regname); - if (reg < 0) { - pcilib_error("Register (%s) is not found", regname); - return PCILIB_ERROR_NOTFOUND; - } - - return pcilib_read_register_by_id(ctx, reg, value); -} - - -static int pcilib_write_register_space_internal(pcilib_t *ctx, pcilib_register_bank_t bank, pcilib_register_addr_t addr, size_t n, pcilib_register_size_t offset, pcilib_register_size_t bits, pcilib_register_value_t rwmask, pcilib_register_value_t *buf) { - int err; - size_t i; - - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - pcilib_register_bank_description_t *b = model_info->banks + bank; - - int access = b->access / 8; - - assert(bits < 8 * sizeof(pcilib_register_value_t)); - - if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) { - if ((b->format)&&(strchr(b->format, 'x'))) - pcilib_error("Accessing register (%u regs at addr 0x%x) out of register space (%u registers total)", bits?(n+1):n, addr, b->size); - else - pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size); - return PCILIB_ERROR_OUTOFRANGE; - } - - err = pcilib_map_register_space(ctx); - if (err) { - pcilib_error("Failed to map the register space"); - return err; - } - - //n += bits / b->access; - //bits %= b->access; - - for (i = 0; i < n; i++) { - err = pcilib_protocol[b->protocol].write(ctx, b, addr + i * access, buf[i]); - if (err) break; - } - - if ((bits > 0)&&(!err)) { - pcilib_register_value_t val = (buf[n]&BIT_MASK(bits))<protocol].read(ctx, b, addr + n * access, &rval); - if (err) return err; - - val |= (rval & rwmask & ~mask); - } - - err = pcilib_protocol[b->protocol].write(ctx, b, addr + n * access, val); - } - - return err; -} - -int pcilib_write_register_space(pcilib_t *ctx, const char *bank, pcilib_register_addr_t addr, size_t n, pcilib_register_value_t *buf) { - pcilib_register_bank_t bank_id = pcilib_find_bank(ctx, bank); - if (bank_id == PCILIB_REGISTER_BANK_INVALID) { - if (bank) pcilib_error("Invalid register bank is specified (%s)", bank); - else pcilib_error("Register bank should be specified"); - return PCILIB_ERROR_INVALID_BANK; - } - - return pcilib_write_register_space_internal(ctx, bank_id, addr, n, 0, 0, 0, buf); -} - - -int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_register_value_t value) { - int err; - size_t i, n; - pcilib_register_size_t bits; - pcilib_register_bank_t bank; - pcilib_register_value_t res; - pcilib_register_description_t *r; - pcilib_register_bank_description_t *b; - pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - - r = model_info->registers + reg; - - bank = pcilib_find_bank_by_addr(ctx, r->bank); - if (bank == PCILIB_REGISTER_BANK_INVALID) return PCILIB_ERROR_INVALID_BANK; - - b = model_info->banks + bank; - - n = r->bits / b->access; - bits = r->bits % b->access; - - pcilib_register_value_t buf[n + 1]; - memset(buf, 0, (n + 1) * sizeof(pcilib_register_value_t)); - - if ((b->endianess == PCILIB_BIG_ENDIAN)||((b->endianess == PCILIB_HOST_ENDIAN)&&(ntohs(1) == 1))) { - pcilib_error("Big-endian byte order support is not implemented"); - return PCILIB_ERROR_NOTSUPPORTED; - } else { - if (b->access == sizeof(pcilib_register_value_t) * 8) { - buf[0] = value; - } else { - for (i = 0, res = value; (res > 0)&&(i <= n); ++i) { - buf[i] = res & BIT_MASK(b->access); - res >>= b->access; - } - - if (res) { - pcilib_error("Value %i is too big to fit in the register %s", value, r->name); - return PCILIB_ERROR_OUTOFRANGE; - } - } - } - - err = pcilib_write_register_space_internal(ctx, bank, r->addr, n, r->offset, bits, r->rwmask, buf); - return err; -} - -int pcilib_write_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t value) { - int reg; - - reg = pcilib_find_register(ctx, bank, regname); - if (reg < 0) { - pcilib_error("Register (%s) is not found", regname); - return PCILIB_ERROR_NOTFOUND; - } - - return pcilib_write_register_by_id(ctx, reg, value); -} diff --git a/register.h b/register.h deleted file mode 100644 index b81ae12..0000000 --- a/register.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _PCILIB_REGISTER_H -#define _PCILIB_REGISTER_H - -#include "pcilib.h" - -struct pcilib_protocol_description_s { - int (*read)(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *value); - int (*write)(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t value); -}; - - // we don't copy strings, they should be statically allocated -int pcilib_add_registers(pcilib_t *ctx, size_t n, pcilib_register_description_t *registers); - -#endif /* _PCILIB_REGISTER_H */ diff --git a/tests/autotrigger.sh b/tests/autotrigger.sh new file mode 100755 index 0000000..b7318c8 --- /dev/null +++ b/tests/autotrigger.sh @@ -0,0 +1,19 @@ +#! /bin/bash + +function pci { + PCILIB_PATH=`which pci` + #LD_LIBRARY_PATH="$PCILIB_PATH" + $PCILIB_PATH/pci $* +} + +echo "Starting the grabber" +pci -g -o /dev/null --run-time 12000000 --verbose 10 & +pid=$! + +usleep 100000 +pci -w 9040 80004a01 +usleep 10000000 +pci -w 9040 80000201 + +echo "Waiting grabber to finish" +wait $pid diff --git a/tests/debug/incomplete.sh b/tests/debug/incomplete.sh new file mode 100755 index 0000000..090e638 --- /dev/null +++ b/tests/debug/incomplete.sh @@ -0,0 +1,38 @@ +#! /bin/bash + +function pci { + PCILIB_PATH=`which pci` + #LD_LIBRARY_PATH="$PCILIB_PATH" + $PCILIB_PATH/pci $* +} + +rm -f images.raw +touch images.raw + +echo "Starting the grabber" +pci --stop-dma +pci --start-dma dma1 +pci -g -o images.raw --run-time 1000000000 & +pid=$! + +usleep 1000000 + +for i in `seq 1 100000`; do + old_size=`ls -la images.raw | cut -d " " -f 5` + echo "Trigger $i" + pci --trigger + usleep 100000 + new_size=`ls -la images.raw | cut -d " " -f 5` + if [ $old_size -eq $new_size ]; then + sleep 2 + new_size=`ls -la images.raw | cut -d " " -f 5` + if [ $old_size -eq $new_size ]; then + echo "Incomplete frame..." + killall -SIGINT pci + break + fi + fi +done + +echo "Waiting grabber to finish" +wait $pid diff --git a/tests/dma/debug/test-iommu.sh b/tests/dma/debug/test-iommu.sh deleted file mode 100755 index 74e3ece..0000000 --- a/tests/dma/debug/test-iommu.sh +++ /dev/null @@ -1,19 +0,0 @@ -#! /bin/bash - -i=1 -while [ 1 ]; do - pci --start-dma dma1r - for name in /sys/class/fpga/fpga0/kbuf*; do - bus_addr=0x`cat $name | grep "bus addr" | cut -d ':' -f 2 | sed -e 's/\s\+//g'` - if [ $((bus_addr % 4096)) -ne 0 ]; then - - echo "Failed at iteration $i, $name" - echo "----------------------" - cat $name - exit - fi - - done - pci --stop-dma dma1r - i=$((i + 1)) -done diff --git a/tests/dma/ipe/bench.sh b/tests/dma/ipe/bench.sh deleted file mode 100755 index aa7ec25..0000000 --- a/tests/dma/ipe/bench.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -size=65536 - -function pci { - PCILIB_PATH=`pwd`/../../.. - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci -m kapture $* -} - - -rm -f bench.out - -echo "Stopping DMA and skipping exiting data..." -pci --stop-dma dma0r -echo "Starting DMA..." -pci --start-dma dma0r -echo "Enabling data generation..." -pci -w 0x4 0x1 - -# Clean DMA buffers -#while [ $? -eq 0 ]; do -# pci -r dma0 -s 65536 &> /dev/null -#done - -echo "Reading the data from DMA..." -for i in `seq 1 100`; do - pci -r dma0 --multipacket -s $size -o bench.out - if [ $? -ne 0 ]; then - echo "Stopping DMA due to the error..." - pci --stop-dma dma0r - exit - fi -done - -echo "Stopping DMA..." -pci --stop-dma dma0r - -../../../apps/check_counter bench.out - -#pci -r 0 -s 32 diff --git a/tests/dma/nwl/bench.sh b/tests/dma/nwl/bench.sh deleted file mode 100755 index b36c251..0000000 --- a/tests/dma/nwl/bench.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -function pci { - PCILIB_PATH="/root/pcitool" - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - -size=16 -bytes=`expr $size "*" 4` - -pci -w xrawdata_packet_length $bytes -pci -w xrawdata_enable_loopback 0 -pci -w xrawdata_enable_generator 0 - -pci --start-dma dma1 - -while [ $? -eq 0 ]; do - pci -r dma1 -s 65536 &> /dev/null -done - -pci -w xrawdata_enable_loopback 1 - -for i in `seq 1 10`; do - pci -w dma1 -s $size "*$i" - pci -r dma1 -s $size -o bench.out -done - -pci --stop-dma dma1 - -pci -w xrawdata_enable_loopback 0 diff --git a/tests/dma/nwl/cleanup.sh b/tests/dma/nwl/cleanup.sh deleted file mode 100755 index 5ef568e..0000000 --- a/tests/dma/nwl/cleanup.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -function pci { - PCILIB_PATH="/root/pcitool" - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - -pci --start-dma dma1r -pci -w dma1r_reset_request 1 -pci -w dma1r_reset 1 -pci -r dma1r_running - -pci --free-kernel-memory dma diff --git a/tests/dma/xilinx/xilinx_dma.sh b/tests/dma/xilinx/xilinx_dma.sh deleted file mode 100755 index 6aada8b..0000000 --- a/tests/dma/xilinx/xilinx_dma.sh +++ /dev/null @@ -1,121 +0,0 @@ -#! /bin/bash - -BAR=0 -USE=1 -ITERATIONS=2 -BUFFERS=16 - -function pci { - PCILIB_PATH=`pwd`/.. - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - - -function reset { - pci -b $BAR -w 0 1 - usleep 1000 - pci -b $BAR -w 0 0 - pci -b $BAR -w 4 0 -} - -function read_cfg { -# echo $1 1>&2 - pci -a config -r 0x$1 | awk '{ print $2; }' -} - -function parse_config { - info=0x`pci -b $BAR -r 0 | awk '{ print $2; }'` - model=`printf "%X" $((info>>24))` - if [ $model -eq 14 ]; then - model="Xilinx Virtex-6" - else - model="Xilinx $model" - fi - version=$(((info >> 8) & 0xFF)) - data_width=$((16 * (2 ** ((info >> 16) & 0xF)))) - - echo "$model, build $version, $data_width bits" - - - next=`read_cfg 34 | cut -c 7-8` - - while [ $next -ne 0 ]; do - cap=`read_cfg $next` - capid=`echo $cap | cut -c 7-8` - if [ $capid -eq 10 ]; then - addr=`printf "%X" $((0x$next + 12))` - pcie_link1=`read_cfg $addr` - addr=`printf "%X" $((0x$next + 16))` - pcie_link2=`read_cfg $addr` - - link_speed=$((((0x$pcie_link2 & 0xF0000) >> 16))) - link_width=$((((0x$pcie_link2 & 0x3F00000) >> 20))) - - dev_link_speed=$((((0x$pcie_link1 & 0xF)))) - dev_link_width=$((((0x$pcie_link1 & 0x3F0) >> 4))) - fi - next=`echo $cap | cut -c 5-6` - done - - echo "Link: PCIe gen$link_speed x$link_width" - if [ $link_speed -ne $dev_link_speed -o $link_width -ne $dev_link_width ]; then - echo " * But device capable of gen$dev_link_speed x$dev_link_width" - fi - - info=0x`read_cfg 40` - max_tlp=$((2 ** (5 + ((info & 0xE0) >> 5)))) - echo "TLP: 32 dwords (transfering 32 TLP per request)" - if [ $max_tlp -ne 32 ]; then - echo " * But device is able to transfer TLP up to $max_tlp bytes" - fi - - # 2500 MT/s, but PCIe gen1 and gen2 uses 10 bit encoding - speed=$((link_width * link_speed * 2500 / 10)) -} - -reset -parse_config - -pci --enable-irq -pci --acknowledge-irq - -pci --free-kernel-memory $USE -pci --alloc-kernel-memory $USE --type c2s -s $BUFFERS -bus=`pci --list-kernel-memory 00100001 | awk '{ print $4; }' | grep 00` -#ptr=`pci --list-kernel-memory 00100001 | awk '{ print $2; }' | grep 00` - -# TLP size -pci -b $BAR -w 0x0C 0x20 -# TLP count -pci -b $BAR -w 0x10 0x20 -# Data -pci -b $BAR -w 0x14 0x13131313 - -dmaperf=0 -for i in `seq 1 $ITERATIONS`; do - for addr in $bus; do - pci -b $BAR -w 0x08 0x$addr - -#Trigger - pci -b $BAR -w 0x04 0x01 - pci --wait-irq -# pci -b $BAR -w 0x04 0x00 - - status=`pci -b $BAR -r 0x04 | awk '{print $2; }' | cut -c 5-8` - if [ $status != "0101" ]; then - echo "Read failed, invalid status: $status" - fi - - dmaperf=$((dmaperf + 0x`pci -b $BAR -r 0x28 | awk '{print $2}'`)) - reset - done -done - -pci --free-kernel-memory $USE -pci --disable-irq - -echo -# Don't ask me about this formula -echo "Performance reported by FPGA: $((4096 * BUFFERS * ITERATIONS * $speed / $dmaperf / 8)) MB/s" - -#pci -b $BAR -r 0 -s 32 diff --git a/tests/dma/xilinx/xilinx_dma_static_mem.sh b/tests/dma/xilinx/xilinx_dma_static_mem.sh deleted file mode 100755 index e3ba0f5..0000000 --- a/tests/dma/xilinx/xilinx_dma_static_mem.sh +++ /dev/null @@ -1,117 +0,0 @@ -#! /bin/bash - -BAR=0 -USE=1 -ITERATIONS=1 -TLP_SIZE=32 -BUFFER_SIZE=8 - -function pci { - PCILIB_PATH=`pwd`/.. - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - - -function reset { - pci -b $BAR -w 0 1 - usleep 1000 - pci -b $BAR -w 0 0 - pci -b $BAR -w 4 0 -} - -function read_cfg { -# echo $1 1>&2 - pci -a config -r 0x$1 | awk '{ print $2; }' -} - -function parse_config { - info=0x`pci -b $BAR -r 0 | awk '{ print $2; }'` - model=`printf "%X" $((info>>24))` - if [ $model -eq 14 ]; then - model="Xilinx Virtex-6" - else - model="Xilinx $model" - fi - version=$(((info >> 8) & 0xFF)) - data_width=$((16 * (2 ** ((info >> 16) & 0xF)))) - - echo "$model, build $version, $data_width bits" - - - next=`read_cfg 34 | cut -c 7-8` - - while [ $next -ne 0 ]; do - cap=`read_cfg $next` - capid=`echo $cap | cut -c 7-8` - if [ $capid -eq 10 ]; then - addr=`printf "%X" $((0x$next + 12))` - pcie_link1=`read_cfg $addr` - addr=`printf "%X" $((0x$next + 16))` - pcie_link2=`read_cfg $addr` - - link_speed=$((((0x$pcie_link2 & 0xF0000) >> 16))) - link_width=$((((0x$pcie_link2 & 0x3F00000) >> 20))) - - dev_link_speed=$((((0x$pcie_link1 & 0xF)))) - dev_link_width=$((((0x$pcie_link1 & 0x3F0) >> 4))) - fi - next=`echo $cap | cut -c 5-6` - done - - echo "Link: PCIe gen$link_speed x$link_width" - if [ $link_speed -ne $dev_link_speed -o $link_width -ne $dev_link_width ]; then - echo " * But device capable of gen$dev_link_speed x$dev_link_width" - fi - - info=0x`read_cfg 40` - max_tlp=$((2 ** (5 + ((info & 0xE0) >> 5)))) - echo "TLP: 32 dwords (transfering 32 TLP per request)" - if [ $max_tlp -ne $TLP_SIZE ]; then - echo " * But device is able to transfer TLP up to $max_tlp bytes" - fi - - # 2500 MT/s, but PCIe gen1 and gen2 uses 10 bit encoding - speed=$((link_width * link_speed * 2500 / 10)) -} - -reset -parse_config - -pci --enable-irq -pci --acknowledge-irq - -# TLP size -pci -b $BAR -w 0x0C 0x`echo "obase=16; $TLP_SIZE" | bc` -# TLP count -pci -b $BAR -w 0x10 0x`echo "obase=16; $BUFFER_SIZE * 1024 * 1024 / $TLP_SIZE / 4" | bc` -# Data -pci -b $BAR -w 0x14 0x13131313 - -bus="80000000" -dmaperf=0 -for i in `seq 1 $ITERATIONS`; do - for addr in $bus; do - pci -b $BAR -w 0x08 0x$addr - -#Trigger - pci -b $BAR -w 0x04 0x01 - pci --wait-irq - - status=`pci -b $BAR -r 0x04 | awk '{print $2; }' | cut -c 5-8` - if [ $status != "0101" ]; then - echo "Read failed, invalid status: $status" - fi - - dmaperf=$((dmaperf + 0x`pci -b $BAR -r 0x28 | awk '{print $2}'`)) - reset - done -done - -pci --free-kernel-memory $USE -pci --disable-irq - -echo -# Don't ask me about this formula -echo "Performance reported by FPGA: $(($BUFFER_SIZE * 1024 * 1024 * ITERATIONS * $speed / $dmaperf / 8)) MB/s" - -#pci -b $BAR -r 0 -s 32 diff --git a/tests/dump_file.sh b/tests/dump_file.sh deleted file mode 100755 index 6773a19..0000000 --- a/tests/dump_file.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -hexdump -e ' "0x%08.8_ax: " 4/4 " 0x%08x " "\n" ' $1 | less diff --git a/tests/grab.sh b/tests/grab.sh deleted file mode 100755 index daf142e..0000000 --- a/tests/grab.sh +++ /dev/null @@ -1,24 +0,0 @@ -#! /bin/bash - -function pci { - PCILIB_PATH="/root/pcitool" - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - -rm -f images.raw - - -echo "Starting the grabber" -pci -g -o images.raw --run-time 3000000 & -pid=$! - -usleep 1000000 - -for i in `seq 1 1000`; do - echo "Trigger $i" - pci --trigger - usleep 100000 -done - -echo "Waiting grabber to finish" -wait $pid diff --git a/tests/heb/DataTaking.sh b/tests/heb/DataTaking.sh deleted file mode 100755 index b6046d7..0000000 --- a/tests/heb/DataTaking.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/bin/bash - -#Channel 1 --> 05 -#Channel 2 --> 0B -#Channel 1&2 --> 0F -#Channel 3 --> 13 -#Channel 4 --> 23 -#Channel 3&4 --> 33 -#ALL --> 3F - -#rm *.out -pci -r dma1 --multipacket -o /dev/null - -echo "Start DMA ..... " -#pci --start-dma dma1 -sleep 0.2 - -echo "Data Reset ... " -pci -w 0x9040 000003f1 -sleep 0.1 -pci -w 0x9040 000003f0 - -sleep 0.1 -#echo "Pilot bunch emulator ..... " -#pci -w 0x9040 400003f0 -sleep 0.2 -pci -w 0x9040 03f0 -#pci -r 0x9000 -s 40 -#sleep 0.2 -echo "Start data pci. ..... " -pci -w 0x9040 00bf0 - -sleep 2 - -echo "Stop data acquis...... " -pci -w 0x9040 003f0 -pci -r 0x9000 -s 40 -sleep 0.1 -echo "Enable data transfer.... " -pci -w 0x9040 007f0 -exit -sleep 2 -pci -r dma1 -o run_num_$1.out --multipacket -sleep 2 - -pci -w 0x9040 003f0 -#echo "Status ... " - - - -pci -r 0x9000 -s 40 - - status=`pci -r 0x9050 -s 1 | awk '{print $2$3$4}'` - if [ "$status" != "85000021" ]; then - echo "--------------------------------->>>> ERROR! ... " - error=1 - exit - else - echo " Status 1 -> OK " - fi - - status=`pci -r 0x9000 -s 1 | awk '{print $2$3$4}'` - if [ "$status" != "01000021" ]; then - echo "--------------------------------->>>> ERROR! ... " - error=1 - exit - else - echo " Status 1 Readout -> OK " - fi - -status=`pci -r 0x9008 -s 1 | awk '{print $2$3$4}'` - if [ "$status" != "01000021" ]; then - echo "--------------------------------->>>> ERROR! ... " - error=1 - exit - else - echo " Status 2 Readout -> OK " - fi - -status=`pci -r 0x9010 -s 1 | awk '{print $2$3$4}'` - if [ "$status" != "01000021" ]; then - echo "--------------------------------->>>> ERROR! ... " - error=1 - exit - else - echo " Status 3 Readout -> OK " - fi - -status=`pci -r 0x9018 -s 1 | awk '{print $2$3$4}'` - if [ "$status" != "01000021" ]; then - echo "--------------------------------->>>> ERROR! ... " - error=1 - exit - else - echo " Status 4 Readout -> OK " - fi diff --git a/tests/heb/cfg/BoardOFF.sh b/tests/heb/cfg/BoardOFF.sh deleted file mode 100755 index 351bcb8..0000000 --- a/tests/heb/cfg/BoardOFF.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - - -echo " ************************************************************** " -echo " Board OFF" -echo " ************************************************************** " - -pci -w 0x9040 0x01 -sleep 0.5 - -pci --stop-dma dma1 diff --git a/tests/heb/cfg/BoardOn.sh b/tests/heb/cfg/BoardOn.sh deleted file mode 100755 index b14c73b..0000000 --- a/tests/heb/cfg/BoardOn.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash - -echo " ************************************************************** " -echo " Start DMA" -echo " ************************************************************** " - -pci --start-dma dma1 -sleep 0.5 -pci --list-dma-engines - - -echo " ************************************************************** " -echo " Board ON procedure" -echo " ************************************************************** " - -pci -w 0x9040 0x01 -sleep 1 - -echo "switch ON the power supply --> FIRST <--" -echo "Press a key to continue ...." -read -n 1 -s - -echo "Switch ON T/Hs" -pci -w 0x9040 0x3C1 -pci -r 0x9040 -s1 - -echo "switch ON the power supply --> SECOND <--" -echo "Press a key to continue ...." -read -n 1 -s - -echo "Switch ON ADCs" -pci -w 0x9040 0x3F1 -pci -r 0x9040 -s1 -sleep 0.1 - - -pci -w 0x9040 0x3F0 -pci -r 0x9040 -s1 -sleep 1 - -echo " Status ................... " -pci -r 0x9000 -s 40 - - - -./PLL_conf_calib_3001.sh - -echo " Status ................... " -pci -r 0x9000 -s 40 - - -echo " ************************************************************** " -echo " Board Ready" -echo " ************************************************************** " - - -echo " --> remember to run: ./Set_Default.sh" diff --git a/tests/heb/cfg/README b/tests/heb/cfg/README deleted file mode 100644 index 125bc0d..0000000 --- a/tests/heb/cfg/README +++ /dev/null @@ -1,11 +0,0 @@ - - Initializing - ./BoardOn.sh - ./Set_Default.sh - - - Configuring the size - pci -w 9020 0x20 (linear scale) - - * Number of samples are determined by 0x9020 / 0x9028 (0x0e by default) - * For each sample is descibed by (184 / 2) * 128 bits - * Where most-significant bytes of 4 dwords (128 bit) are iterating - from 0x00 to 0xb8 with step 0x02 diff --git a/tests/heb/cfg/Set_ADC_1_Delay.sh b/tests/heb/cfg/Set_ADC_1_Delay.sh deleted file mode 100755 index bd8f980..0000000 --- a/tests/heb/cfg/Set_ADC_1_Delay.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -echo "Set CH_4 clock ADC 1 delay... " - -upfix=000501 -fixed=4 - - hex_val=$(printf "%01x\n" $1) - echo "Set $hex_val --> Time value picosecond = `expr $1 "*" 150`." - pci -w 0x9060 $upfix$hex_val$fixed diff --git a/tests/heb/cfg/Set_ADC_2_Delay.sh b/tests/heb/cfg/Set_ADC_2_Delay.sh deleted file mode 100755 index d6cdf75..0000000 --- a/tests/heb/cfg/Set_ADC_2_Delay.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -echo "Set CH_5 clock ADC 2 delay... " - -upfix=000501 -fixed=5 - - hex_val=$(printf "%01x\n" $1) - echo "Set $hex_val --> Time value picosecond = `expr $1 "*" 150`." - pci -w 0x9060 $upfix$hex_val$fixed diff --git a/tests/heb/cfg/Set_ADC_3_Delay.sh b/tests/heb/cfg/Set_ADC_3_Delay.sh deleted file mode 100755 index 567b977..0000000 --- a/tests/heb/cfg/Set_ADC_3_Delay.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -echo "Set CH_6 clock ADC 3 delay... " - -upfix=000501 -fixed=6 - - hex_val=$(printf "%01x\n" $1) - echo "Set $hex_val --> Time value picosecond = `expr $1 "*" 150`." - pci -w 0x9060 $upfix$hex_val$fixed diff --git a/tests/heb/cfg/Set_ADC_4_Delay.sh b/tests/heb/cfg/Set_ADC_4_Delay.sh deleted file mode 100755 index d666595..0000000 --- a/tests/heb/cfg/Set_ADC_4_Delay.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -echo "Set CH_7 clock ADC 4 delay... " - -upfix=000501 -fixed=7 - - hex_val=$(printf "%01x\n" $1) - echo "Set $hex_val --> Time value picosecond = `expr $1 "*" 150`." - pci -w 0x9060 $upfix$hex_val$fixed - diff --git a/tests/heb/cfg/Set_Default.sh b/tests/heb/cfg/Set_Default.sh deleted file mode 100755 index 0149bf0..0000000 --- a/tests/heb/cfg/Set_Default.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -echo "Set Defaults delay value in the board... " - -./Set_FPGA_clock_delay.sh 0 -sleep 0.1 - - ./Set_Delay_chip.sh 16 16 16 16 -sleep 0.1 - -./Set_TH_Delay.sh 12 -sleep 0.1 - -./Set_ADC_1_Delay.sh 5 -sleep 0.1 - -./Set_ADC_2_Delay.sh 5 -sleep 0.1 - -./Set_ADC_3_Delay.sh 5 -sleep 0.1 - -./Set_ADC_4_Delay.sh 5 - -#pci -w 0x9020 200b20 -pci -w 0x9020 20 -pci -w 0x9028 e - -echo " DONE ................ " - diff --git a/tests/heb/cfg/Set_Delay_chip.sh b/tests/heb/cfg/Set_Delay_chip.sh deleted file mode 100755 index 3d15cad..0000000 --- a/tests/heb/cfg/Set_Delay_chip.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - - zero=0 - hex_val1=$(printf "%02x\n" $1) - hex_val2=$(printf "%02x\n" $2) - hex_val3=$(printf "%02x\n" $3) - hex_val4=$(printf "%02x\n" $4) - - pci -w 0x9080 $zero$hex_val4$hex_val3$hex_val2$hex_val1 - pci -r 0x9080 -s 1 - sleep 0.5 diff --git a/tests/heb/cfg/Set_FPGA_clock_delay.sh b/tests/heb/cfg/Set_FPGA_clock_delay.sh deleted file mode 100755 index f4d0f46..0000000 --- a/tests/heb/cfg/Set_FPGA_clock_delay.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -echo "Set delay on T/Hs signals... " - -upfix=000501 -fixed=0 - - hex_val=$(printf "%01x\n" $1) - echo "Set $hex_val --> Time picosecond = `expr $1 "*" 150`." - pci -w 0x9060 $upfix$hex_val$fixed diff --git a/tests/heb/cfg/Set_TH_Delay.sh b/tests/heb/cfg/Set_TH_Delay.sh deleted file mode 100755 index 9a6e58f..0000000 --- a/tests/heb/cfg/Set_TH_Delay.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -echo "Set delay on T/Hs signals... " - -upfix=000501 -fixed=3 - - hex_val=$(printf "%01x\n" $1) - echo "Set $hex_val --> Time picosecond = `expr $1 "*" 150`." - pci -w 0x9060 $upfix$hex_val$fixed diff --git a/tests/heb/debug/debug.sh b/tests/heb/debug/debug.sh deleted file mode 100755 index 2db21d4..0000000 --- a/tests/heb/debug/debug.sh +++ /dev/null @@ -1,45 +0,0 @@ -#! /bin/bash - -SCRIPT_PATH="`dirname \"$0\"`" -SCRIPT_PATH="`( cd \"$TESTS_PATH\" && pwd )`" -PCILIB_PATH=${SCRIPT_PATH%/tests/*} - -function pci { - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - -function strip_bad_values { - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/apps/heb_strip_bad_values $* -} - -function request_data { - $PCILIB_PATH/tests/heb/debug/request_data.sh $* -} - -while [ 1 ]; do - from=`pci --list-dma-engines | grep C2S | sed -s 's/\s\+/ /g' | cut -d ' ' -f 6` - to=`pci --list-dma-engines | grep C2S | sed -s 's/\s\+/ /g' | cut -d ' ' -f 8` - - if [ $from -gt $to ]; then - buffers="`seq $from 255` `seq 0 $to`" - else - buffers=`seq $from $to` - fi - - echo $buffers - - rm data.out - for i in $buffers; do - pci --read-dma-buffer dma1r:$i -o data.out - done - - - error=`strip_bad_values data.out | head -n 1 | cut -f 1 -d ':'` - if [ $error != "0x1140" ]; then - echo "Problems found" - exit - else - echo "Fine" - request_data - fi -done diff --git a/tests/heb/debug/request_data.sh b/tests/heb/debug/request_data.sh deleted file mode 100755 index b751f5d..0000000 --- a/tests/heb/debug/request_data.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -pci -r dma1 --multipacket -o /dev/null - -#echo "Data Reset ... " -pci -w 0x9040 000003f1 -sleep 0.1 -pci -w 0x9040 000003f0 - -sleep 0.1 -#echo "Pilot bunch emulator ..... " -#pci -w 0x9040 400003f0 -sleep 0.2 -pci -w 0x9040 03f0 -#pci -r 0x9000 -s 40 -#sleep 0.2 -#echo "Start data pci. ..... " -pci -w 0x9040 00bf0 - -sleep 2 - -#echo "Stop data acquis...... " -pci -w 0x9040 003f0 -pci -r 0x9000 -s 40 -sleep 0.1 -#echo "Enable data transfer.... " -pci -w 0x9040 007f0 diff --git a/tests/ipecamera/autotrigger.sh b/tests/ipecamera/autotrigger.sh deleted file mode 100755 index 5f8b4db..0000000 --- a/tests/ipecamera/autotrigger.sh +++ /dev/null @@ -1,18 +0,0 @@ -#! /bin/bash - -function pci { - PCILIB_PATH="../../" - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - -echo "Starting the grabber" -pci -g -o /dev/null --run-time 12000000 --verbose 10 & -pid=$! - -usleep 100000 -pci -w 9040 80004a01 -usleep 10000000 -pci -w 9040 80000201 - -echo "Waiting grabber to finish" -wait $pid diff --git a/tests/ipecamera/bench.sh b/tests/ipecamera/bench.sh deleted file mode 100755 index 09edae9..0000000 --- a/tests/ipecamera/bench.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -function pci { - PCILIB_PATH="/root/pcitool" - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - -size=16 -bytes=`expr $size "*" 4` - -rm -f bench.out -pci --stop-dma dma1 -pci --reset - -#pci -w xrawdata_packet_length $bytes - -pci --start-dma dma1 -pci -w control 0x1e5 -sleep 1 -pci -w control 0x1e1 - -sleep 1 -pci -w control 0x3e1 -for i in `seq 1 10`; do -# pci -w control 0x1e1 - pci -w dma1 -s $size "*$i" -# pci -w control 0x3e1 - usleep 100000 - pci -r dma1 -s $size -o bench.out -done - -pci -w control 0x1e1 -pci --stop-dma dma1 - diff --git a/tests/ipecamera/cfg/Reset_Init_all_reg_10bit.sh b/tests/ipecamera/cfg/Reset_Init_all_reg_10bit.sh deleted file mode 100755 index f4afa06..0000000 --- a/tests/ipecamera/cfg/Reset_Init_all_reg_10bit.sh +++ /dev/null @@ -1,326 +0,0 @@ -#!/bin/bash - -###################### by Michele Caselle and Uros Stafanovic ################################################## -############ Resent procedure and camera initialization for 10 -bit mode ###################################### - -error=0 -echo " Reset Readout and CMOSIS " -pci -w 0x9040 80000204 -sleep .1 -#echo " Release Reset for Readout" -#pci -w 0x9040 800001e0 -sleep .1 -##################### PLL SET ##################################### -val=f501 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -echo " Start CMOSIS Configuration .." -pci -w 0x9000 f301 -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "bf301" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -val=d207 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 - -# Michele 10 - 12 bit mode # -# ################################################################################################### -echo " 10 - bit mode, set Bit_mode " -val=ef00 ###################################################### -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -# Michele set ADC_resolution @ 12 bits -echo " 10 bit mode, set ADC resolution 10 bits " -val=f000 # qui for 10 - 11 - 12 bits ######################################################## -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 - -# adc recommended 28=44 -val=e72c -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val " - error=1 - # exit -fi -sleep 0.01 -# #################################################################################################### - -################# CAMERA CONFIGURATION ############################################ -val=e603 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 - -val=d404 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -val=d501 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -# recommended is d840 -val=d840 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -# sleep 0.01 -# recommended is db40 -val=db40 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -val=de65 -# val=de0 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -sleep 0.01 -val=df6a -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -echo " End CMOSIS Configuration .." -######################################################################################################## -echo " Write exp time......" - -######################################### EXP TIME ####################################################### -val=aa25 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -# val=ab2c -val=ab00 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -# val=acaa -val=ac00 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -#################################################################################################################### - -sleep 0.01 -#pci -w 0x9040 80000201 -sleep 0.01 -########################## WRITE THE READOUT NUMBER OF LINE ####################################################### -pci -w cmosis_number_lines 1088 -#pci -w number_lines 8 -sleep 0.01 -################################################################################################################# -pci --start-dma dma1 -sleep 0.01 -#VRAMP 6c is 108 -val=e26c -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -#VRAMP 6c is 108 -val=e36c -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -###################################### NUMBER OF OUTPUT ############################################################ -##pci -w 0x9000 0xc803 -sleep 0.01 -val=c800 -pci -w 0x9000 $val -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -#pci -r 0x9000 -s 10 - -sleep 0.01 -#pci -w 0x9000 0xd011 -sleep 0.01 -#pci -r 0x9000 -s 10 - -sleep 0.01 -#pci -w 0x9000 0xd111 -######################################################################################################### -sleep 0.01 - - - -################################################## -#SET the max number of frame in DDR -pci -w 0x91a0 0x71 - -#echo " Reset Readout and CMOSIS " -pci -w 0x9040 0x80000204 -sleep .1 -echo " Release Reset for Readout" -pci -w 0x9040 0x80000201 -sleep .1 - -status=`pci -r 0x9050 -s 4 | awk '{print $2$3$4}'` -if [ "$status" != "8449ffff0f0010013ffff111" ]; then - echo "--------------------------------->>>> ERROR! in the camera status ... " - echo " $status " - error=1 - # exit -fi - -#echo "--> $status" - -if [ "$error" = "1" ]; then - echo " Error in the reset and initialization" -else - echo " Camera READY ........................... OK" -fi -echo - -echo "DMA reset ... " -pci --stop-dma dma1 -sleep 0.5 -pci --start-dma dma1 - - diff --git a/tests/ipecamera/cfg/Reset_Init_all_reg_10bit_4Mp.sh b/tests/ipecamera/cfg/Reset_Init_all_reg_10bit_4Mp.sh deleted file mode 100755 index 5a4e582..0000000 --- a/tests/ipecamera/cfg/Reset_Init_all_reg_10bit_4Mp.sh +++ /dev/null @@ -1,325 +0,0 @@ -#!/bin/bash - -###################### by Michele Caselle and Uros Stafanovic ################################################## -############ Resent procedure and camera initialization for 10 -bit mode ###################################### - -error=0 -echo " Reset Readout and CMOSIS " -pci -w 0x9040 80000204 -sleep .1 -#echo " Release Reset for Readout" -#pci -w 0x9040 800001e0 -sleep .1 -##################### PLL SET ##################################### -val=f501 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -echo " Start CMOSIS Configuration .." -pci -w 0x9000 f301 -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "bf301" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -val=d207 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 - -# Michele 10 - 12 bit mode # -# ################################################################################################### -echo " 10 - bit mode, set Bit_mode " -val=ef00 ###################################################### -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -# Michele set ADC_resolution @ 12 bits -echo " 10 bit mode, set ADC resolution 10 bits " -val=f000 # qui for 10 - 11 - 12 bits ######################################################## -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 - -# adc recommended 28=44 -val=e72c -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val " - error=1 - # exit -fi -sleep 0.01 -# #################################################################################################### - -################# CAMERA CONFIGURATION ############################################ -val=e603 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 - -val=d404 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -val=d501 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -# recommended is d840 -val=d840 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -# sleep 0.01 -# recommended is db40 -val=db40 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -val=de65 -# val=de0 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -sleep 0.01 -val=df6a -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -echo " End CMOSIS Configuration .." -######################################################################################################## -echo " Write exp time......" - -######################################### EXP TIME ####################################################### -val=aa25 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -# val=ab2c -val=ab00 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -# val=acaa -val=ac00 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -#################################################################################################################### - -sleep 0.01 -#pci -w 0x9040 80000201 -sleep 0.01 -########################## WRITE THE READOUT NUMBER OF LINE ####################################################### -pci -w cmosis_number_lines 2047 -#pci -w number_lines 8 -sleep 0.01 -################################################################################################################# -pci --start-dma dma1 -sleep 0.01 -#VRAMP 6c is 108 -val=e26c -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -#VRAMP 6c is 108 -val=e36c -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -sleep 0.01 -###################################### NUMBER OF OUTPUT ############################################################ -##pci -w 0x9000 0xc803 -sleep 0.01 -val=c800 -pci -w 0x9000 $val -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error=1 - # exit -fi -#pci -r 0x9000 -s 10 - -sleep 0.01 -#pci -w 0x9000 0xd011 -sleep 0.01 -#pci -r 0x9000 -s 10 - -sleep 0.01 -#pci -w 0x9000 0xd111 -######################################################################################################### -sleep 0.01 - - - -################################################## -#SET the max number of frame in DDR -pci -w 0x91a0 0x71 - -#echo " Reset Readout and CMOSIS " -pci -w 0x9040 0x80000204 -sleep .1 -echo " Release Reset for Readout" -pci -w 0x9040 0x80000201 -sleep .1 - -status=`pci -r 0x9050 -s 4 | awk '{print $2$3$4}'` -if [ "$status" != "8449ffff0f0010013ffff111" ]; then - echo "--------------------------------->>>> ERROR! in the camera status ... " - error=1 - # exit -fi - -#echo "--> $status" - -if [ "$error" = "1" ]; then - echo " Error in the reset and initialization" -else - echo " Camera READY ........................... OK" -fi -echo - -echo "DMA reset ... " -pci --stop-dma dma1 -sleep 0.5 -pci --start-dma dma1 - - diff --git a/tests/ipecamera/cfg/Reset_Init_all_reg_11bit.sh b/tests/ipecamera/cfg/Reset_Init_all_reg_11bit.sh deleted file mode 100755 index 3c4af0e..0000000 --- a/tests/ipecamera/cfg/Reset_Init_all_reg_11bit.sh +++ /dev/null @@ -1,318 +0,0 @@ -#!/bin/bash - -###################### by Michele Caselle and Uros Stafanovic ################################################## -############ Resent procedure and camera initialization for 12 -bit mode ###################################### - -error=0 -echo " Reset Readout and CMOSIS " -pci -w 0x9040 1e4 -sleep .1 -echo " Release Reset for Readout" -pci -w 0x9040 1e0 -sleep .1 -##################### PLL SET ##################################### -val=f501 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -echo " Start CMOSIS Configuration .." -pci -w 0x9000 f301 -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "bf301" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -val=d207 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 - -# Michele 10 - 12 bit mode # -# ################################################################################################### -echo " 11 - bit mode, set Bit_mode " -val=ef00 ###################################################### -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -# Michele set ADC_resolution @ 12 bits -echo " 11 bit mode, set ADC resolution 11 bits " -val=f001 # qui for 10 - 11 - 12 bits ######################################################## -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 - -# adc recommended 28=44 -val=e72c -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val " - error =1 - # exit -fi -sleep 0.01 -# #################################################################################################### - -################# CAMERA CONFIGURATION ############################################ -val=e603 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 - -val=d404 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -val=d501 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -# recommended is d840 -val=d840 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -# sleep 0.01 -# recommended is db40 -val=db40 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -val=de65 -# val=de0 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -sleep 0.01 -val=df6a -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -echo " End CMOSIS Configuration .." -######################################################################################################## -echo " Write exp time......" - -######################################### EXP TIME ####################################################### -val=aa25 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -# val=ab2c -val=ab02 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -# val=acaa -val=ac00 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -#################################################################################################################### - -sleep 0.01 -pci -w 0x9040 201 -sleep 0.01 -########################## WRITE THE READOUT NUMBER OF LINE ####################################################### -pci -w cmosis_number_lines 1088 -#pci -w number_lines 8 -sleep 0.01 -################################################################################################################# -pci --start-dma dma1 -sleep 0.01 -#VRAMP 6c is 108 -val=e26c -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -#VRAMP 6c is 108 -val=e36c -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -######################################################################################################## -#pci -w 0x9000 0xc802 -##pci -w 0x9000 0xc803 -sleep 0.01 -val=c802 -pci -w 0x9000 $val -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -#pci -r 0x9000 -s 10 - -################################################## -#SET the max number of frame in DDR -pci -w 0x91a0 0x1C - -sleep 0.01 -#pci -w 0x9000 0xd011 -sleep 0.01 -#pci -r 0x9000 -s 10 - -sleep 0.01 -#pci -w 0x9000 0xd111 -#pci -r 0x9000 -s 10 -######################################################################################################### -sleep 0.01 - -status=`pci -r 0x9050 -s 4 | awk '{print $2$3$4}'` -if [ "$status" != "8449ffff0f0010013ffff111" ]; then - echo "--------------------------------->>>> ERROR! in the camera status ... " - error =1 - # exit -fi - -#echo "--> $status" - -if [ "$error" = "1" ]; then - echo " Error in the resetand initialization" -else - echo " Camera READY ........ OK" -fi -echo - - -echo "DMA reset ... " -pci --stop-dma dma1 -sleep 0.5 -pci --start-dma dma1 - diff --git a/tests/ipecamera/cfg/Reset_Init_all_reg_12bit.sh b/tests/ipecamera/cfg/Reset_Init_all_reg_12bit.sh deleted file mode 100755 index b04f2cd..0000000 --- a/tests/ipecamera/cfg/Reset_Init_all_reg_12bit.sh +++ /dev/null @@ -1,323 +0,0 @@ -#!/bin/bash - -###################### by Michele Caselle and Uros Stafanovic ################################################## -############ Resent procedure and camera initialization for 12 -bit mode ###################################### - -error=0 -echo " Reset Readout and CMOSIS " -pci -w 0x9040 1e4 -sleep .1 -echo " Release Reset for Readout" -pci -w 0x9040 1e0 -sleep .1 -##################### PLL SET ##################################### -val=f501 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -echo " Start CMOSIS Configuration .." -pci -w 0x9000 f301 -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "bf301" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -val=d207 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 - -# Michele 10 - 12 bit mode # -# ################################################################################################### -echo " 12 - bit mode, set Bit_mode " -val=ef00 ###################################################### -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -# Michele set ADC_resolution @ 12 bits -echo " 12 bit mode, set ADC resolution 12 bits " -val=f002 # qui for 10 - 11 - 12 bits ######################################################## -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 - -# adc recommended 28=44 -val=e72c -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val " - error =1 - # exit -fi -sleep 0.01 -# #################################################################################################### - -################# CAMERA CONFIGURATION ############################################ -val=e603 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 - -val=d404 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -val=d501 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -# recommended is d840 -val=d840 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -# sleep 0.01 -# recommended is db40 -val=db40 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -val=de65 -# val=de0 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -sleep 0.01 -val=df6a -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -echo " End CMOSIS Configuration .." -######################################################################################################## -echo " Write exp time......" - -######################################### EXP TIME ####################################################### -val=aa0f -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -# val=ab2c -val=ab00 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -# val=acaa -val=ac00 -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -#################################################################################################################### - -sleep 0.01 -pci -w 0x9040 201 -sleep 0.01 -########################## WRITE THE READOUT NUMBER OF LINE ####################################################### -pci -w cmosis_number_lines 1088 -#pci -w number_lines 8 -sleep 0.01 -################################################################################################################# -pci --start-dma dma1 -sleep 0.01 -#VRAMP 6c is 108 -val=e26c -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -#VRAMP 6c is 108 -val=e36c -pci -w 0x9000 $val -sleep 0.01 -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -sleep 0.01 -######################################################################################################## -#pci -w 0x9000 0xc802 -##pci -w 0x9000 0xc803 -sleep 0.01 -val=c802 -pci -w 0x9000 $val -#pci -r 0x9000 -s 10 -sleep 0.01 -value=`pci -r 0x9000 -s 8 | grep 9010 | awk '{print $2}' | cut -c 4-8` -if [ "$value" != "b$val" ]; then - echo "--------------------------------->>>> ERROR! read value: ${value:1:4}, written value: $val" - error =1 - # exit -fi -#pci -r 0x9000 -s 10 - -sleep 0.01 - -################################################## -#SET the max number of frame in DDR -pci -w 0x91a0 0x1C - - -#pci -w 0x9000 0xd011 -sleep 0.01 -pci -r 0x9000 -s 10 - -sleep 0.01 -#pci -w 0x9000 0xd111 -sleep 0.01 -pci -r 0x9000 -s 10 -######################################################################################################### -sleep 0.1 - -status=`pci -r 0x9050 -s 4 | awk '{print $2$3$4}'` -if [ "$status" != "844950280f0010013ffff111" ]; then - - echo "--------------------------------->>>> ERROR! in the camera status ... " - echo $status - error=1 - # exit -fi - -#echo "--> $status" - -if [ "$error" = "1" ]; then - echo " Error in the resetand initialization" -else - echo " Camera READY ........ OK" -fi -echo - - - -echo "DMA reset ... " -pci --stop-dma dma1 -sleep 0.5 -pci --start-dma dma1 diff --git a/tests/ipecamera/debug/incomplete.sh b/tests/ipecamera/debug/incomplete.sh deleted file mode 100755 index 5c80198..0000000 --- a/tests/ipecamera/debug/incomplete.sh +++ /dev/null @@ -1,37 +0,0 @@ -#! /bin/bash - -function pci { - PCILIB_PATH="/root/pcitool" - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - -rm -f images.raw -touch images.raw - -echo "Starting the grabber" -pci --stop-dma -pci --start-dma dma1 -pci -g -o images.raw --run-time 1000000000 & -pid=$! - -usleep 1000000 - -for i in `seq 1 100000`; do - old_size=`ls -la images.raw | cut -d " " -f 5` - echo "Trigger $i" - pci --trigger - usleep 100000 - new_size=`ls -la images.raw | cut -d " " -f 5` - if [ $old_size -eq $new_size ]; then - sleep 2 - new_size=`ls -la images.raw | cut -d " " -f 5` - if [ $old_size -eq $new_size ]; then - echo "Incomplete frame..." - killall -SIGINT pci - break - fi - fi -done - -echo "Waiting grabber to finish" -wait $pid diff --git a/tests/ipecamera/frame.sh b/tests/ipecamera/frame.sh deleted file mode 100755 index 679817b..0000000 --- a/tests/ipecamera/frame.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -TESTS_PATH="`dirname \"$0\"`" -TESTS_PATH="`( cd \"$TESTS_PATH\" && pwd )`" - -function pci { - PCILIB_PATH=$TESTS_PATH/.. - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - -pci --stop-dma dma1 -#pci --reset - -echo "Set packet size 1024 .. " -pci -w cmosis_number_lines 1088 -#pci -w xrawdata_packet_length 4096 -pci --start-dma dma1 -usleep 1000 - -echo "Send frame request ... " -pci -w control 1e9 -usleep 100000 -pci -w control 1e1 -usleep 100000 - -echo "Enable Readout ... " -pci -w control 3e1 - -usleep 100000 - -pci -r dma1 -o bench.out --multipacket - -pci -w control 1e1 - -pci --stop-dma dma1 - diff --git a/tests/ipecamera/frame_req.sh b/tests/ipecamera/frame_req.sh deleted file mode 100755 index bce89c3..0000000 --- a/tests/ipecamera/frame_req.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -function pci { - PCILIB_PATH="/root/pcitool" - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - -#pci --stop-dma dma1 -#pci --reset - -echo "Set packet size 1024 .. " -pci -w cmosis_number_lines 1088 -#pci -w xrawdata_packet_length 4096 -pci --start-dma dma1 -usleep 1000 - -echo "Send frame request ... " -pci -w control 1e9 -usleep 100000 -pci -w control 1e1 -usleep 100000 - -echo "Enable Readout 3... " -pci -w control 3e1 -usleep 1000000 -pci -w control 1e1 - diff --git a/tests/ipecamera/grab-hwtrigger.sh b/tests/ipecamera/grab-hwtrigger.sh deleted file mode 100755 index 0279ab4..0000000 --- a/tests/ipecamera/grab-hwtrigger.sh +++ /dev/null @@ -1,20 +0,0 @@ -#! /bin/bash - -function pci { - PCILIB_PATH="/root/pcitool" - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - -function enable_hw_trigger { - usleep 100000 - pci -w control 0xa01 -} - -rm -f images.raw - -enable_hw_trigger & -pid=$! - -echo "Starting the grabber" -pci -g -o images.raw --run-time 60000000 --verbose 10 -o /dev/null -wait $pid diff --git a/tests/ipecamera/stimuli.sh b/tests/ipecamera/stimuli.sh deleted file mode 100755 index 33e99e1..0000000 --- a/tests/ipecamera/stimuli.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -function pci { - PCILIB_PATH="/root/pcitool" - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - -rm -f bench.out - -echo "Set FFFF the frame space .." -pci -w 0x9180 fff - -echo "Set the number of frames .." -pci -w reg9170 55 - -pci --start-dma dma1 - -echo "Send frame request ... " -pci -w control 1f1 -usleep 100000 -pci -w control 1e1 - - -echo "Enable Readout ... " -pci -w control 3e1 -pci -r dma1 -o bench.out --multipacket -pci -w control 1e1 - -pci --stop-dma dma1 - diff --git a/tests/ipecamera/tests/loopback-test.sh b/tests/ipecamera/tests/loopback-test.sh deleted file mode 100755 index 1c033cc..0000000 --- a/tests/ipecamera/tests/loopback-test.sh +++ /dev/null @@ -1,87 +0,0 @@ -#! /bin/bash - -TESTS_PATH="`dirname \"$0\"`" -TESTS_PATH="`( cd \"$TESTS_PATH\" && pwd )`" - -function pci { - PCILIB_PATH=$TESTS_PATH/.. - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - -function compare { - PCILIB_PATH=$TESTS_PATH/.. - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/apps/compare_to_value $* -} - -#size=`expr 1024 "*" 1024` -size=`expr 1024 "*" 1` -multiplier=2 -wait=0 - -/root/pcitool/tests/ipecamera/frame.sh &> /dev/null -rm -f bench.out - -pci --stop-dma dma1 -pci --start-dma dma1 - -pci -r dma1 -s 16777216 --multipacket -o /dev/null &> /dev/null - -pci -r dma1 -s 1024 -o /dev/null | grep -i "Error (62)" &> /dev/null -if [ $? -ne 0 ]; then - echo "There is data on dma..." - exit -fi - -failed=0 -send=0 -errors=0 -err_num=0 - -print_iters=`expr 2 + 1024 '*' 100 / $size` - -read_size=`expr $multiplier '*' $size` -echo "Starting..." -i=1 - -pci -w 0x9040 0x201 - -while [ 1 ]; do - if [ $wait -gt 0 ]; then - pci -w 0x9040 0x1 - fi - - pci -w dma1 -s $size "*0x$i" - rm -f /tmp/camera-test.out - pci -r dma1 --wait --multipacket -s $read_size -o /tmp/camera-test.out -t 1000000 &> /dev/null - if [ $wait -gt 0 ]; then - wrdone=0 - while [ $wrdone -eq 0 ]; do -# pci --list-dma-engines - pci --list-dma-engines | grep "DMA1 S2C" | grep "SD" #&> /dev/null - wrdone=$? - done - pci -w 0x9040 0x201 - fi - - res=`compare /tmp/camera-test.out $read_size "$i" 6 2 6` - if [ $? -eq 0 ]; then - err_cnt=`echo $res | cut -f 1 -d ' '` - if [ "$err_cnt" -ne 0 ]; then - pci -r dma1 --wait --multipacket -o /tmp/camera-test.out -t 1000000 &> /dev/null - cp /tmp/camera-test.out /tmp/camera-test.out.$err_num - err_num=$(($err_num + 1)) - fi - byte_cnt=`echo $res | cut -f 3 -d ' '` - send=$(($send + $byte_cnt * 4)) - errors=$(($errors + $err_cnt * 4)) - else - failed=$(($failed + 1)) - fi - - i=$((i + 1)) - if [ $i -eq $print_iters ]; then - echo "Data send: $send bytes, Errors: $errors bytes, Failed exchanges: $failed" -# pci -r 0x9070 -s 4 - i=1 - fi -done diff --git a/tests/ipecamera/tests/run-and-decode-test.sh b/tests/ipecamera/tests/run-and-decode-test.sh deleted file mode 100755 index d355475..0000000 --- a/tests/ipecamera/tests/run-and-decode-test.sh +++ /dev/null @@ -1,103 +0,0 @@ -#! /bin/bash - -location=/mnt/fast/ -#location="./" -duration=10000000 -wait_frame=1000000 - -TESTS_PATH="`dirname \"$0\"`" -TESTS_PATH="`( cd \"$TESTS_PATH\" && pwd )`" - -function pci { - PCILIB_PATH=$TESTS_PATH/.. - LD_LIBRARY_PATH="$PCILIB_PATH" $PCILIB_PATH/pci $* -} - -function stop { - usleep $duration - pci -w control 0x201 &> /dev/null -} - -function reset { - pci -r 0x9000 -s 256 > $1.status - $TESTS_PATH/ipecamera/Reset_Init_all_reg_10bit.sh &> $1.reset -} - - -$TESTS_PATH/ipecamera/cfg/Reset_Init_all_reg_10bit.sh &> /dev/null -$TESTS_PATH/ipecamera/frame.sh &> /dev/null -rm -f bench.out - -pci --stop-dma -pci --start-dma dma1 - - -pci -r dma1 -s 16777216 --multipacket -o /dev/null &> /dev/null - -pci -r dma1 -s 1 | grep -i "Error (62)" &> /dev/null -if [ $? -ne 0 ]; then - echo "There is data on dma..." - exit -fi - -echo "Starting ... " - -decode_failures=0 -failures=0 -failed=0 -frames=0 -fpga_failures=0 -cmosis_failures=0 -frame_rate_failures=0 - -iter=0 -while [ 1 ]; do - pci -w control 0xa01 &> /dev/null - stop & - - output="$location/test$iter.out" - rm -f $output - pci -r dma1 -o $output --wait --multipacket -t $wait_frame &> /dev/null - - killall -9 usleep &> /dev/null - usleep 100000 - pci -w control 0x201 &> /dev/null - - if [ -f $output ]; then - result=`ipedec -d -v --continue $output 2>&1 | grep -iE "failed|decoded"` - cur_failed=`echo $result | wc -l` - cur_decoded=`echo $result | tail -n 1 | grep -i decoded` - if [ $? -ne 0 -o $cur_failed -eq 0 ]; then - ipedec -d -v --continue $output > $output.decode - decode_failures=$(($decode_failures + 1)) - reset $output - else - cur_failed=$(($cur_failed - 1)) - cur_frames=`echo $cur_decoded | cut -f 2 -d ' '` - failed=$(($failed + $cur_failed)) - frames=$(($frames + $cur_frames)) - fpga_status=`pci -r 0x9054 | awk '{print $2;}' | cut -c 2` - cmosis_status=`pci -r 0x9050 | awk '{print $2;}' | cut -c 3-4` - if [ "$fpga_status" != "f" ]; then - fpga_failures=$(($fpga_failures + 1)) - reset $output - elif [ "$cmosis_status" == "7d" ]; then - cmosis_failures=$(($cmosis_failures + 1)) - reset $output - elif [ $cur_frames -lt 10 ]; then - frame_rate_failures=$(($frame_rate_failures + 1)) - reset $output - elif [ $cur_failed -eq 0 ]; then - rm -f $output - else - reset $output - fi - fi - else - failures=$(($failures + 1)) - reset $output - fi - - echo "Frames: $frames, Failed Frames: $failed, Failed Exchanges: $failures, Failed Decodings: $decode_failures, FPGA Failures: $fpga_failures, CMOSIS Failures: $cmosis_failures, Low Frame Rate: $frame_rate_failures" - iter=`expr $iter + 1` -done diff --git a/tests/new_device.sh b/tests/new_device.sh deleted file mode 100755 index 3545321..0000000 --- a/tests/new_device.sh +++ /dev/null @@ -1,3 +0,0 @@ -#! /bin/bash - -echo "10ee 6028" > /sys/bus/pci/drivers/pciDriver/new_id diff --git a/tools.c b/tools.c deleted file mode 100644 index e0789fb..0000000 --- a/tools.c +++ /dev/null @@ -1,354 +0,0 @@ -#define _POSIX_C_SOURCE 200112L -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tools.h" -#include "error.h" - -int pcilib_isnumber(const char *str) { - int i = 0; - for (i = 0; str[i]; i++) - if (!isdigit(str[i])) return 0; - return 1; -} - -int pcilib_isxnumber(const char *str) { - int i = 0; - - if ((str[0] == '0')&&((str[1] == 'x')||(str[1] == 'X'))) i += 2; - - for (; str[i]; i++) - if (!isxdigit(str[i])) return 0; - - return 1; -} - -int pcilib_isnumber_n(const char *str, size_t len) { - int i = 0; - for (i = 0; (str[i])&&(i < len); i++) - if (!isdigit(str[i])) return 0; - return 1; -} - -int pcilib_isxnumber_n(const char *str, size_t len) { - int i = 0; - - if ((len > 1)&&(str[0] == '0')&&((str[1] == 'x')||(str[1] == 'X'))) i += 2; - - for (; (str[i])&&(i < len); i++) - if (!isxdigit(str[i])) return 0; - - return 1; -} - - -uint16_t pcilib_swap16(uint16_t x) { - return (((x<<8)&0xFFFF) | ((x>>8)&0xFFFF)); -} - -uint32_t pcilib_swap32(uint32_t x) { - return ((x & 0xFF) << 24) | \ - ((x & 0xFF00) << 8) | \ - ((x & 0xFF0000) >> 8) | \ - ((x & 0xFF000000) >> 24); -} - -uint64_t pcilib_swap64(uint64_t x) { - return (((uint64_t)(x) << 56) | \ - (((uint64_t)(x) << 40) & 0xff000000000000ULL) | \ - (((uint64_t)(x) << 24) & 0xff0000000000ULL) | \ - (((uint64_t)(x) << 8) & 0xff00000000ULL) | \ - (((uint64_t)(x) >> 8) & 0xff000000ULL) | \ - (((uint64_t)(x) >> 24) & 0xff0000ULL) | \ - (((uint64_t)(x) >> 40) & 0xff00ULL) | \ - ((uint64_t)(x) >> 56)); -} - -void pcilib_swap(void *dst, void *src, size_t size, size_t n) { - int i; - switch (size) { - case 1: - if (src != dst) memcpy(dst, src, n); - break; - case 2: - for (i = 0; i < n; i++) { - ((uint16_t*)dst)[i] = pcilib_swap16(((uint16_t*)src)[i]); - } - break; - case 4: - for (i = 0; i < n; i++) { - ((uint32_t*)dst)[i] = pcilib_swap32(((uint32_t*)src)[i]); - } - break; - case 8: - for (i = 0; i < n; i++) { - ((uint64_t*)dst)[i] = pcilib_swap64(((uint64_t*)src)[i]); - } - break; - default: - pcilib_error("Invalid word size: %i", size); - } -} - -void *pcilib_memcpy8(void * dst, void const * src, size_t len) { - int i; - for (i = 0; i < len; i++) ((char*)dst)[i] = ((char*)src)[i]; - return dst; -} - -void *pcilib_memcpy32(void * dst, void const * src, size_t len) { - uint32_t * plDst = (uint32_t *) dst; - uint32_t const * plSrc = (uint32_t const *) src; - - while (len >= 4) { -// *plDst = ntohl(*plSrc); - *plDst = *plSrc; - plSrc++; - plDst++; - len -= 4; - } - - char * pcDst = (char *) plDst; - char const * pcSrc = (char const *) plSrc; - - while (len--) { - *pcDst++ = *pcSrc++; - } - - return (dst); -} - - -void *pcilib_memcpy64(void * dst, void const * src, size_t len) { - uint64_t * plDst = (uint64_t *) dst; - uint64_t const * plSrc = (uint64_t const *) src; - - while (len >= 8) { - *plDst++ = *plSrc++; - len -= 8; - } - - char * pcDst = (char *) plDst; - char const * pcSrc = (char const *) plSrc; - - while (len--) { - *pcDst++ = *pcSrc++; - } - - return (dst); -} - -/* -void *memcpy128(void * dst, void const * src, size_t len) { - - long pos = - (len>>2); - char * plDst = (char *) dst - 4 * pos; - char const * plSrc = (char const *) src - 4 * pos; - - if (pos) { - __asm__ __volatile__ ( - "1: \n\t" - "mov (%0,%2,4), %%edi \n\t" - "mov %%edi, (%1,%2,4) \n\t" - "inc %2 \n\t" - "jnz 1b \n\t" - : - : "r" (plSrc), "r" (plDst), "r" (pos) - : "%edi" - ); - } - - - - long pos = - ((len>>4)<<4); - char * plDst = (char *) dst - pos; - char const * plSrc = (char const *) src - pos; - - if (pos) { - __asm__ __volatile__ ( - "1: \n\t" -// "movdqa (%0,%2), %%xmm0 \n\t" - "mov (%0,%2), %%esi \n\t" - "movd %%esi, %%xmm0 \n\t" - "mov 4(%0,%2), %%esi \n\t" - "movd %%esi, %%xmm1 \n\t" - "mov 8(%0,%2), %%esi \n\t" - "movd %%esi, %%xmm2 \n\t" - "mov 12(%0,%2), %%esi \n\t" - "movd %%esi, %%xmm3 \n\t" - "pslldq $4, %%xmm1 \n\t" - "por %%xmm1, %%xmm0 \n\t" - "pslldq $8, %%xmm2 \n\t" - "por %%xmm2, %%xmm0 \n\t" - "pslldq $12, %%xmm3 \n\t" - "por %%xmm3, %%xmm0 \n\t" - - "movntdq %%xmm0, (%1,%2) \n\t" - "add $16, %2 \n\t" - "jnz 1b \n\t" - : - : "r" (plSrc), "r" (plDst), "r" (pos) - : "%rsi" - ); - } - - - - len &= 0x3; - - char * pcDst = (char *) plDst; - char const * pcSrc = (char const *) plSrc; - - while (len--) { - *pcDst++ = *pcSrc++; - } - - return (dst); -} -*/ - -void *pcilib_datacpy32(void * dst, void const * src, uint8_t size, size_t n, pcilib_endianess_t endianess) { - uint32_t * plDst = (uint32_t *) dst; - uint32_t const * plSrc = (uint32_t const *) src; - - int swap = 0; - - if (endianess) - swap = (endianess == PCILIB_BIG_ENDIAN)?(ntohs(1)!=1):(ntohs(1)==1); - - assert(size == 4); // only 32 bit at the moment - - if (swap) { - while (n > 0) { - *plDst = ntohl(*plSrc); - ++plSrc; - ++plDst; - --n; - } - } else { - while (n > 0) { - *plDst = *plSrc; - ++plSrc; - ++plDst; - --n; - } - } - - return dst; -} - -int pcilib_get_page_mask() { - int pagesize,pagemask,temp; - - pagesize = sysconf(_SC_PAGESIZE); - - for( pagemask=0, temp = pagesize; temp != 1; ) { - temp = (temp >> 1); - pagemask = (pagemask << 1)+1; - } - return pagemask; -} - -int pcilib_get_cpu_count() { - int err; - - int cpu_count; - cpu_set_t mask; - - err = sched_getaffinity(getpid(), sizeof(mask), &mask); - if (err) return 1; - -#ifdef CPU_COUNT - cpu_count = CPU_COUNT(&mask); -#else - for (cpu_count = 0; cpu_count < CPU_SETSIZE; cpu_count++) { - if (!CPU_ISSET(cpu_count, &mask)) break; - } -#endif - - if (!cpu_count) cpu_count = PCILIB_DEFAULT_CPU_COUNT; - return cpu_count; -} - - -int pcilib_add_timeout(struct timeval *tv, pcilib_timeout_t timeout) { - tv->tv_usec += timeout%1000000; - if (tv->tv_usec > 999999) { - tv->tv_usec -= 1000000; - tv->tv_sec += 1 + timeout/1000000; - } else { - tv->tv_sec += timeout/1000000; - } - - return 0; -} - -int pcilib_calc_deadline(struct timeval *tv, pcilib_timeout_t timeout) { - gettimeofday(tv, NULL); - pcilib_add_timeout(tv, timeout); - - return 0; -} - -int pcilib_check_deadline(struct timeval *tve, pcilib_timeout_t timeout) { - int64_t res; - struct timeval tvs; - - if (!tve->tv_sec) return 0; - - gettimeofday(&tvs, NULL); - res = ((tve->tv_sec - tvs.tv_sec)*1000000 + (tve->tv_usec - tvs.tv_usec)); - // Hm... Some problems comparing signed and unsigned. So, sign check first - if ((res < 0)||(res < timeout)) { - return 1; - } - - return 0; -} - -pcilib_timeout_t pcilib_calc_time_to_deadline(struct timeval *tve) { - int64_t res; - struct timeval tvs; - - gettimeofday(&tvs, NULL); - res = ((tve->tv_sec - tvs.tv_sec)*1000000 + (tve->tv_usec - tvs.tv_usec)); - - if (res < 0) return 0; - return res; -} - -int pcilib_sleep_until_deadline(struct timeval *tv) { - struct timespec wait; - pcilib_timeout_t duration; - - duration = pcilib_calc_time_to_deadline(tv); - if (duration > 0) { - wait.tv_sec = duration / 1000000; - wait.tv_nsec = 1000 * (duration % 1000000); - nanosleep(&wait, NULL); - } - - return 0; -} - -pcilib_timeout_t pcilib_timediff(struct timeval *tvs, struct timeval *tve) { - return ((tve->tv_sec - tvs->tv_sec)*1000000 + (tve->tv_usec - tvs->tv_usec)); -} - -int pcilib_timecmp(struct timeval *tv1, struct timeval *tv2) { - if (tv1->tv_sec > tv2->tv_sec) return 1; - else if (tv1->tv_sec < tv2->tv_sec) return -1; - else if (tv1->tv_usec > tv2->tv_usec) return 1; - else if (tv1->tv_usec < tv2->tv_usec) return -1; - return 0; -} diff --git a/tools.h b/tools.h deleted file mode 100644 index 28f8b0a..0000000 --- a/tools.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _PCITOOL_TOOLS_H -#define _PCITOOL_TOOLS_H - -#include -#include - -#define BIT_MASK(bits) ((1ll << (bits)) - 1) - -#define min2(a, b) (((a)<(b))?(a):(b)) - -typedef enum { - PCILIB_TRISTATE_NO = 0, - PCILIB_TRISTATE_PARTIAL = 1, - PCILIB_TRISTATE_YES = 2 -} pcilib_tristate_t; - -#include "pci.h" - -int pcilib_isnumber(const char *str); -int pcilib_isxnumber(const char *str); -int pcilib_isnumber_n(const char *str, size_t len); -int pcilib_isxnumber_n(const char *str, size_t len); - -uint16_t pcilib_swap16(uint16_t x); -uint32_t pcilib_swap32(uint32_t x); -uint64_t pcilib_swap64(uint64_t x); -void pcilib_swap(void *dst, void *src, size_t size, size_t n); - -void * pcilib_memcpy8(void * dst, void const * src, size_t len); -void * pcilib_memcpy32(void * dst, void const * src, size_t len); -void * pcilib_memcpy64(void * dst, void const * src, size_t len); -void * pcilib_datacpy32(void * dst, void const * src, uint8_t size, size_t n, pcilib_endianess_t endianess); - -int pcilib_get_page_mask(); -int pcilib_get_cpu_count(); - - -int pcilib_add_timeout(struct timeval *tv, pcilib_timeout_t timeout); -int pcilib_calc_deadline(struct timeval *tv, pcilib_timeout_t timeout); -int pcilib_check_deadline(struct timeval *tve, pcilib_timeout_t timeout); -pcilib_timeout_t pcilib_calc_time_to_deadline(struct timeval *tve); -int pcilib_sleep_until_deadline(struct timeval *tv); -int pcilib_timecmp(struct timeval *tv1, struct timeval *tv2); -pcilib_timeout_t pcilib_timediff(struct timeval *tve, struct timeval *tvs); - -#endif /* _PCITOOL_TOOS_H */ -- cgit v1.2.1