removal of EXPRESS MIMO HW drivers/libraries, same for mobipass.
This commit is contained in:
@@ -522,7 +522,7 @@ add_library(F1AP
|
||||
add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4")
|
||||
add_list1_option(NB_ANTENNAS_TX "4" "Number of antennas in transmission" "1" "2" "4")
|
||||
|
||||
add_list2_option(RF_BOARD "EXMIMO" "RF head type" "None" "EXMIMO" "OAI_USRP" "OAI_BLADERF" "CPRIGW" "OAI_LMSSDR" "OAI_SIMU")
|
||||
add_list2_option(RF_BOARD "RF head type" "None" "OAI_USRP" "OAI_BLADERF" "CPRIGW" "OAI_LMSSDR" "OAI_SIMU")
|
||||
|
||||
|
||||
add_list2_option(TRANSP_PRO "None" "Transport protocol type" "None" "ETHERNET")
|
||||
@@ -547,15 +547,6 @@ set (SHLIB_LOADER_SOURCES
|
||||
# include RF devices / transport protocols library modules
|
||||
######################################################################
|
||||
|
||||
include_directories("${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/")
|
||||
include_directories ("${OPENAIR_TARGETS}/ARCH/EXMIMO/DEFS/")
|
||||
#set (option_HWEXMIMOLIB_lib "-l ")
|
||||
set(HWLIB_EXMIMO_SOURCE
|
||||
${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
|
||||
# ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/gain_control.c
|
||||
)
|
||||
add_library(oai_exmimodevif MODULE ${HWLIB_EXMIMO_SOURCE} )
|
||||
|
||||
include_directories("${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/")
|
||||
set(HWLIB_USRP_SOURCE
|
||||
${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
|
||||
@@ -596,20 +587,6 @@ add_library(oai_irisdevif MODULE ${HWLIB_IRIS_SOURCE})
|
||||
target_include_directories(oai_irisdevif PRIVATE /usr/local/lib/SoapySDR/modules0.7/)
|
||||
target_link_libraries(oai_irisdevif SoapySDR)
|
||||
|
||||
include_directories("${OPENAIR_TARGETS}/ARCH/mobipass/")
|
||||
set(TPLIB_MOBIPASS_SOURCE
|
||||
${OPENAIR_TARGETS}/ARCH/mobipass/interface.c
|
||||
${OPENAIR_TARGETS}/ARCH/mobipass/mobipass.c
|
||||
${OPENAIR_TARGETS}/ARCH/mobipass/queues.c
|
||||
)
|
||||
add_library(oai_mobipass MODULE ${TPLIB_MOBIPASS_SOURCE} )
|
||||
|
||||
# Hide all functions/variables in the mobipass library.
|
||||
# Use __attribute__((__visibility__("default")))
|
||||
# in the source code to unhide a function/variable.
|
||||
get_target_property(mobipas_cflags oai_mobipass COMPILE_FLAGS)
|
||||
set_target_properties(oai_mobipass PROPERTIES COMPILE_FLAGS "${mobipass_cflags} -fvisibility=hidden")
|
||||
|
||||
# TCP bridge libraries
|
||||
######################################################################
|
||||
|
||||
@@ -819,8 +796,6 @@ include_directories("${OPENAIR3_DIR}/UDP")
|
||||
include_directories("${OPENAIR3_DIR}/GTPV1-U")
|
||||
include_directories("${OPENAIR_DIR}/targets/COMMON")
|
||||
include_directories("${OPENAIR_DIR}/targets/ARCH/COMMON")
|
||||
include_directories("${OPENAIR_DIR}/targets/ARCH/EXMIMO/USERSPACE/LIB/")
|
||||
include_directories("${OPENAIR_DIR}/targets/ARCH/EXMIMO/DEFS")
|
||||
include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PHY")
|
||||
include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC")
|
||||
include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/RRC")
|
||||
@@ -1875,10 +1850,6 @@ ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/bypass_session_layer.c
|
||||
#${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/emu_transport.c
|
||||
)
|
||||
|
||||
add_library(OPENAIR0_LIB
|
||||
${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
|
||||
)
|
||||
|
||||
include_directories("${NFAPI_DIR}/nfapi/public_inc")
|
||||
include_directories("${NFAPI_DIR}/common/public_inc")
|
||||
include_directories("${NFAPI_DIR}/pnf/public_inc")
|
||||
@@ -2452,14 +2423,6 @@ if(OAI_NW_DRIVER_USE_NETLINK)
|
||||
endif()
|
||||
make_driver(oai_nw_drv ${OPENAIR2_DIR}/NETWORK_DRIVER/LTE ${oai_nw_drv_src})
|
||||
|
||||
# Exmimo board drivers
|
||||
#########################
|
||||
list(APPEND openair_rf_src module_main.c irq.c fileops.c exmimo_fw.c)
|
||||
make_driver(openair_rf ${OPENAIR_TARGETS}/ARCH/EXMIMO/DRIVER/eurecom ${openair_rf_src})
|
||||
|
||||
add_executable(updatefw
|
||||
${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/OAI_FW_INIT/updatefw.c
|
||||
)
|
||||
|
||||
# ue_ip: purpose ???
|
||||
###############
|
||||
@@ -2470,22 +2433,6 @@ endif()
|
||||
make_driver(ue_ip ${OPENAIR2_DIR}/NETWORK_DRIVER/UE_IP ${ue_ip_src})
|
||||
|
||||
|
||||
# OCTAVE tools
|
||||
###############
|
||||
set(OCT_INCL -I${OPENAIR_TARGETS}/ARCH/EXMIMO/DEFS -I${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB -I${OPENAIR_TARGETS}/ARCH/COMMON)
|
||||
set(OCT_LIBS -L${CMAKE_CURRENT_BINARY_DIR} -lm -lOPENAIR0_LIB)
|
||||
set(OCT_FLAGS -DEXMIMO)
|
||||
set(OCT_DIR ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/OCTAVE)
|
||||
set(OCT_FILES
|
||||
oarf_config_exmimo.oct
|
||||
oarf_config_exmimo.oct
|
||||
oarf_get_frame.oct
|
||||
oarf_stop.oct
|
||||
oarf_send_frame.oct
|
||||
oarf_get_num_detected_cards.oct
|
||||
oarf_stop_without_reset.oct
|
||||
)
|
||||
|
||||
foreach(file IN ITEMS ${OCT_FILES})
|
||||
string(REGEX REPLACE "oct *$" "cc" src ${file})
|
||||
add_custom_command(
|
||||
|
||||
+6
-47
@@ -110,7 +110,7 @@ Options
|
||||
Rel8 limits the implementation to 3GPP Release 8 version
|
||||
Rel10 limits the implementation to 3GPP Release 10 version
|
||||
-w | --hardware
|
||||
EXMIMO, USRP, BLADERF, ETHERNET, LMSSDR, IRIS, None (Default)
|
||||
USRP, BLADERF, ETHERNET, LMSSDR, IRIS, None (Default)
|
||||
Adds this RF board support (in external packages installation and in compilation)
|
||||
-t | --transport protocol
|
||||
ETHERNET , None
|
||||
@@ -173,10 +173,9 @@ Options
|
||||
Generate virtual RF driver
|
||||
to use it, set the environement variable RFSIMULATOR to \"enb\" in the eNB and to the eNB IP address in the UEs
|
||||
Usage (first build):
|
||||
NI/ETTUS B201 + COTS UE : ./build_oai -I --eNB -x --install-system-files -w USRP
|
||||
NI/ETTUS B210 + COTS UE : ./build_oai -I --eNB -x --install-system-files -w USRP
|
||||
Usage (Regular):
|
||||
Eurecom EXMIMO + OAI ENB : ./build_oai --eNB -x
|
||||
NI/ETTUS B201 + OAI ENB : ./build_oai --eNB -x -w USRP"
|
||||
NI/ETTUS B210 + OAI ENB : ./build_oai --eNB -x -w USRP"
|
||||
}
|
||||
|
||||
|
||||
@@ -241,9 +240,6 @@ function main() {
|
||||
-w | --hardware)
|
||||
# Use OAI_USRP as the key word USRP is used inside UHD driver
|
||||
case "$2" in
|
||||
"EXMIMO")
|
||||
HW="EXMIMO"
|
||||
;;
|
||||
"USRP" | "BLADERF" | "LMSSDR" | "IRIS" | "SIMU")
|
||||
HW="OAI_"$2
|
||||
;;
|
||||
@@ -398,7 +394,7 @@ function main() {
|
||||
|
||||
if [ "$eNB" = "1" ] ; then
|
||||
if [ "$HW" = "None" -a "$TP" = "None" ] ; then
|
||||
echo_fatal "Define a local radio head (e.g. -w EXMIMO) or a transport protocol (e.g. -t ETHERNET) to communicate with a remote radio head!"
|
||||
echo_fatal "Define a local radio head (e.g. -w USRP) or a transport protocol (e.g. -t ETHERNET) to communicate with a remote radio head!"
|
||||
fi
|
||||
if [ "$HW" = "None" ] ; then
|
||||
echo_info "No radio head has been selected (HW set to $HW)"
|
||||
@@ -411,14 +407,7 @@ function main() {
|
||||
echo_info "RF HW set to $HW"
|
||||
# If the user doesn't specify the Linux scheduler to use, we set a value
|
||||
if [ "$DEADLINE_SCHEDULER_FLAG_USER" = "" ]; then
|
||||
case "$HW" in
|
||||
"EXMIMO")
|
||||
DEADLINE_SCHEDULER_FLAG_USER="True"
|
||||
;;
|
||||
*)
|
||||
DEADLINE_SCHEDULER_FLAG_USER="False"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
#Disable CPU Affinity for deadline scheduler
|
||||
if [ "$DEADLINE_SCHEDULER_FLAG_USER" = "True" ] ; then
|
||||
@@ -517,7 +506,7 @@ function main() {
|
||||
config_libconfig_shlib=params_libconfig
|
||||
|
||||
# first generate the CMakefile in the right directory
|
||||
if [ "$eNB" = "1" -o "$UE" = "1" -o "$HW" = "EXMIMO" ] ; then
|
||||
if [ "$eNB" = "1" -o "$UE" = "1" ] ; then
|
||||
|
||||
# LTE softmodem compilation
|
||||
[ "$CLEAN" = "1" ] && rm -rf $DIR/$lte_build_dir/build
|
||||
@@ -687,28 +676,6 @@ function main() {
|
||||
done
|
||||
fi
|
||||
|
||||
# EXMIMO drivers & firmware loader
|
||||
###############
|
||||
if [ "$HW" = "EXMIMO" ] ; then
|
||||
|
||||
echo_info "Compiling Express MIMO 2 board drivers"
|
||||
compilations \
|
||||
$lte_build_dir openair_rf \
|
||||
CMakeFiles/openair_rf/openair_rf.ko $dbin/openair_rf.ko
|
||||
compilations \
|
||||
$lte_build_dir updatefw \
|
||||
updatefw $dbin/updatefw
|
||||
echo_info "Compiling oarf tools. The logfile for compilation is here: $dlog/oarf.txt"
|
||||
make -C $OPENAIR_DIR/cmake_targets/$lte_build_dir/build oarf > $dlog/oarf.txt 2>&1
|
||||
cp $OPENAIR_DIR/cmake_targets/$lte_build_dir/build/*.oct $dbin
|
||||
if [ -s $dbin/oarf_config_exmimo.oct ] ; then
|
||||
echo_success "oarf tools compiled"
|
||||
else
|
||||
echo_error "oarf tools compilation failed"
|
||||
fi
|
||||
cp $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 $dbin
|
||||
fi
|
||||
|
||||
# Telnet server compilation
|
||||
#####################
|
||||
if [ "$BUILD_TELNETSRV" = "1" ] ; then
|
||||
@@ -735,15 +702,7 @@ function main() {
|
||||
rm -f $dbin/liboai_device.so
|
||||
|
||||
# link liboai_device.so with the selected RF device library
|
||||
if [ "$HW" == "EXMIMO" ] ; then
|
||||
compilations \
|
||||
$lte_build_dir oai_exmimodevif \
|
||||
liboai_exmimodevif.so $dbin/liboai_exmimodevif.so.$REL
|
||||
|
||||
ln -sf liboai_exmimodevif.so liboai_device.so
|
||||
ln -sf $dbin/liboai_exmimodevif.so.$REL $dbin/liboai_device.so
|
||||
echo_info "liboai_device.so is linked to EXMIMO device library"
|
||||
elif [ "$HW" == "OAI_USRP" ] ; then
|
||||
if [ "$HW" == "OAI_USRP" ] ; then
|
||||
compilations \
|
||||
$lte_build_dir oai_usrpdevif \
|
||||
liboai_usrpdevif.so $dbin/liboai_usrpdevif.so.$REL
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
# PROMGEN: Xilinx Prom Generator O.76xd
|
||||
# Copyright (c) 1995-2011 Xilinx, Inc. All rights reserved.
|
||||
|
||||
SOFTWARE_VERSION O.76xd
|
||||
DATE 1/ 3/2017 - 11:49
|
||||
SOURCE /homes/kaltenbe/Devel/openair/openairinterface5g/targets/ARCH/EXMIMO/BITSTREAM/exmimo2_prom.mcs
|
||||
DEVICE 8192K
|
||||
DATA_WIDTH 4
|
||||
FILL_DATA 0xFF
|
||||
SIGNATURE 0x416AB633
|
||||
START_ADDRESS 0x00000000 END_ADDRESS 0x00406577 DIRECTION_UP "express-mimo2.bit" 6slx150tfgg900
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,17 +0,0 @@
|
||||
PROMGEN: Xilinx Prom Generator O.76xd
|
||||
Copyright (c) 1995-2011 Xilinx, Inc. All rights reserved.
|
||||
|
||||
promgen -w -p mcs -c FF -o /homes/kaltenbe/Devel/openair/openairinterface5g/targets/ARCH/EXMIMO/BITSTREAM//exmimo2_prom -s 8192 -u 0000 express-mimo2.bit -spi
|
||||
|
||||
PROM /homes/kaltenbe/Devel/openair/openairinterface5g/targets/ARCH/EXMIMO/BITSTREAM/exmimo2_prom.prm map: Tue Jan 3 11:49:20 2017
|
||||
|
||||
Calculating PROM checksum with fill value ff
|
||||
|
||||
Format Mcs86 (32-bit)
|
||||
Size 8192K
|
||||
PROM start 0000:0000
|
||||
PROM end 007f:ffff
|
||||
PROM checksum 416ab633
|
||||
|
||||
Addr1 Addr2 Date File(s)
|
||||
0000:0000 0040:6577 Jan 3 10:48:16 2017 express-mimo2.bit
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,7 +0,0 @@
|
||||
setMode -bs
|
||||
setCable -port auto
|
||||
Identify
|
||||
identifyMPM
|
||||
assignFile -p 1 -file "express-mimo2.bit"
|
||||
Program -p 1 -defaultVersion 0
|
||||
quit
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
impact -batch prom_generate.cmd
|
||||
impact -batch prom_load.cmd
|
||||
@@ -1,34 +0,0 @@
|
||||
setMode -pff
|
||||
addConfigDevice -name "exmimo2_prom"
|
||||
setSubmode -pffspi
|
||||
setAttribute -configdevice -attr multibootBpiType -value ""
|
||||
addDesign -version 0 -name "0"
|
||||
setMode -pff
|
||||
addDeviceChain -index 0
|
||||
setMode -pff
|
||||
addDeviceChain -index 0
|
||||
setAttribute -configdevice -attr compressed -value "FALSE"
|
||||
setAttribute -configdevice -attr compressed -value "FALSE"
|
||||
setAttribute -configdevice -attr autoSize -value "FALSE"
|
||||
setAttribute -configdevice -attr fileFormat -value "mcs"
|
||||
setAttribute -configdevice -attr fillValue -value "FF"
|
||||
setAttribute -configdevice -attr swapBit -value "FALSE"
|
||||
setAttribute -configdevice -attr dir -value "UP"
|
||||
setAttribute -configdevice -attr multiboot -value "FALSE"
|
||||
setAttribute -configdevice -attr multiboot -value "FALSE"
|
||||
setAttribute -configdevice -attr spiSelected -value "TRUE"
|
||||
setAttribute -configdevice -attr spiSelected -value "TRUE"
|
||||
addPromDevice -p 1 -size 8192 -name 8M
|
||||
setMode -pff
|
||||
addDeviceChain -index 0
|
||||
setMode -pff
|
||||
addDeviceChain -index 0
|
||||
setSubmode -pffspi
|
||||
setMode -pff
|
||||
setAttribute -design -attr name -value "0000"
|
||||
addDevice -p 1 -file "express-mimo2.bit"
|
||||
setMode -pff
|
||||
setSubmode -pffspi
|
||||
generate
|
||||
setCurrentDesign -version 0
|
||||
quit
|
||||
@@ -1,10 +0,0 @@
|
||||
setMode -bs
|
||||
setCable -port auto
|
||||
Identify -inferir
|
||||
identifyMPM
|
||||
assignFile -p 1 -file "express-mimo2.bit"
|
||||
attachflash -position 1 -spi "W25Q64BV"
|
||||
assignfiletoattachedflash -position 1 -file "exmimo2_prom.mcs"
|
||||
attachflash -position 1 -spi "W25Q64BV"
|
||||
Program -p 1 -dataWidth 4 -spionly -e -v -loadfpga
|
||||
quit
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef OPENAIR_DEVICE_H
|
||||
#define OPENAIR_DEVICE_H
|
||||
|
||||
|
||||
// Maximum number of concurrently supported cards
|
||||
#define MAX_CARDS 16
|
||||
#define INIT_ZEROS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
|
||||
/** PCIe subsystem configuration Space
|
||||
*/
|
||||
// Vendor and System IDs
|
||||
//
|
||||
#define XILINX_VENDOR 0x10ee
|
||||
#define XILINX_ID 0x0007
|
||||
//
|
||||
// PCIe Subsystem Vendor ID
|
||||
#define EURECOM_VENDOR 0x0001
|
||||
#define TELECOM_PARISTECH_VENDOR 0x0002
|
||||
/*
|
||||
PCIe Subsystem ID = exmimo_id.board_exmimoversion(1,2) (4 bits) | exmimo_id.board_hwrev (4 bits) | exmimo_id.board_swrev (Protocol Revision, 8 bits)
|
||||
|
||||
Board IDs (exmimo_id.board_exmimoversion(1,2) (4 bits) + exmimo_id.board_hwrev (4 bits))
|
||||
0x11 => ExpressMIMO-1, first run/HW revision
|
||||
0x12 => ExpressMIMO-1, second run
|
||||
0x21 => ExpressMIMO-2, first run
|
||||
0x22 => ExpressMIMO-2, second run
|
||||
|
||||
SW/Protocol revisions: (exmimo_id.board_swrev (Protocol Revision, 8 bits)
|
||||
|
||||
BOARD_SWREV_LEGACY:
|
||||
- IRQ Leon->PC Bit 7 (AHBPCIE_INTERRUPT_ASSERT_BIT) must be cleared in PC kernel driver
|
||||
- PC->Leon and Leon->PC commands share a single register CONTROL1
|
||||
|
||||
BOARD_SWREV_CMDREGISTERS:
|
||||
- IRQ Leon->PC Bit 7 (AHBPCIE_INTERRUPT_ASSERT_BIT) is automatically cleared on PCIe read
|
||||
- PC->Leon and Leon->PC commands have separete command registers CONTROL1 (PC->Leon) and CONTROL2 (Leon->PC)
|
||||
|
||||
BOARD_SWREV_CMDFIFOS:
|
||||
- uses two command FIFOs (for PC->Leon and Leon->PC), by Telecom Paristech
|
||||
*/
|
||||
#define BOARD_SWREV_LEGACY 0x07
|
||||
#define BOARD_SWREV_CMDREGISTERS 0x08
|
||||
#define BOARD_SWREV_CNTL2 0x0A
|
||||
#define BOARD_SWREV_CMDFIFOS 0x11
|
||||
|
||||
|
||||
|
||||
// ExpressMIMO PCIe register offsets to bar0
|
||||
//
|
||||
#define PCIE_CONTROL0 0x00
|
||||
#define PCIE_CONTROL1 0x04
|
||||
#define PCIE_CONTROL2 0x64
|
||||
#define PCIE_STATUS 0x08
|
||||
#define PCIE_PCIBASEL 0x1c
|
||||
#define PCIE_PCIBASEH 0x20
|
||||
|
||||
|
||||
// Device IO definitions and operations
|
||||
//
|
||||
#define openair_MAJOR 127
|
||||
|
||||
//#define openair_writel(dev,offset,val) pci_write_config_dword(dev,(int)offset,(unsigned int)val)//{writel((uclong)(val),(ulong)(port)); mb();}
|
||||
|
||||
//#define openair_readl(dev,offset,val) pci_read_config_dword(dev,(int)offset,(unsigned int*)val)//{writel((uclong)(val),(ulong)(port)); mb();}
|
||||
|
||||
#define openair_IOC_MAGIC 'm'
|
||||
|
||||
#define openair_GET_BIGSHMTOPS_KVIRT _IOR(openair_IOC_MAGIC,1,int)
|
||||
#define openair_GET_PCI_INTERFACE_BOTS_KVIRT _IOR(openair_IOC_MAGIC,2,int)
|
||||
#define openair_GET_NUM_DETECTED_CARDS _IOR(openair_IOC_MAGIC,3,int)
|
||||
|
||||
#define openair_DUMP_CONFIG _IOR(openair_IOC_MAGIC,18,int)
|
||||
#define openair_GET_FRAME _IOR(openair_IOC_MAGIC,6,int)
|
||||
#define openair_START_RT_ACQUISITION _IOR(openair_IOC_MAGIC,28,int)
|
||||
#define openair_STOP _IOR(openair_IOC_MAGIC,5,int)
|
||||
#define openair_STOP_WITHOUT_RESET _IOR(openair_IOC_MAGIC,9,int)
|
||||
#define openair_RECONFIGURE _IOR(openair_IOC_MAGIC,10,int)
|
||||
#define openair_UPDATE_FIRMWARE _IOR(openair_IOC_MAGIC,40,int)
|
||||
|
||||
|
||||
/* Update firmware commands */
|
||||
#define UPDATE_FIRMWARE_TRANSFER_BLOCK 0x1
|
||||
#define UPDATE_FIRMWARE_CLEAR_BSS 0x2
|
||||
#define UPDATE_FIRMWARE_START_EXECUTION 0x3
|
||||
#define UPDATE_FIRMWARE_FORCE_REBOOT 0x4
|
||||
#define UPDATE_FIRMWARE_TEST_GOK 0x5
|
||||
|
||||
|
||||
// mmap page offset vg_pgoff is used to pass arguments to kernel
|
||||
// bit0..3: memory block: BIGSHM:0, RX:1,3,5,7, TX:2,4,6,8
|
||||
// bit4..7: card_id
|
||||
#define openair_mmap_BIGSHM 0
|
||||
#define openair_mmap_RX(ant) (((ant)<<1)+1)
|
||||
#define openair_mmap_TX(ant) (((ant)<<1)+2)
|
||||
|
||||
#define openair_mmap_getMemBlock(o) ((o)&0xF)
|
||||
#define openair_mmap_getAntRX(o) (((o)-1)>>1)
|
||||
#define openair_mmap_getAntTX(o) (((o)-2)>>1)
|
||||
|
||||
#define openair_mmap_Card(c) ( ((c)&0xF)<<4 )
|
||||
#define openair_mmap_getCard(o) ( ((o)>>4)&0xF )
|
||||
|
||||
|
||||
#endif /* OPENAIR_DEVICE_H */
|
||||
@@ -1,406 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** pcie_interface.h
|
||||
|
||||
Interface definitions to handle communication between PC (kernel driver & SDR application) and Leon3
|
||||
|
||||
- commands from PC->Leon and Leon->PC passed through CONTROL1 register (or new: FIFOs)
|
||||
- structure for passing initial (shared PC memory) buffer pointers
|
||||
- #defines for buffer sizes
|
||||
|
||||
This is now the CENTRAL header file for all structs and defines that are
|
||||
requires on both LEON and Kernel and PC Application
|
||||
|
||||
Changelog:
|
||||
01.12.2012: Fix: RXEN and TXEN were swapped
|
||||
New rf_mode flag: use DMAMODE_RX and DMAMODE_TX to selectively enable DMA transfers (only used on ExpressMIMO2)
|
||||
use RXOUTSW to close Lime baseband RXout switch between RFFE and ADC
|
||||
09.01.2013: Renamed exmimo_rf_t.mbox --> .p_mbox to indicate this is a pointer to the mbox and not the mbox itself
|
||||
15.01.2013: added command (EXMIMO_GET_SYSTEMID) and structure (exmimo_system_id_t)
|
||||
to get system ID and bitstream and software versions on PC
|
||||
22.01.2013: Moved structures into pcie/pcie_interface.h to have all these spread-out definitions in a single place
|
||||
|
||||
Author: Matthias Ihmig <matthias.ihmig@mytum.de>, 2012
|
||||
Raymond Knopp <raymond.knopp@eurecom.fr>
|
||||
Riadh Ghaddab <riadh.ghaddab@eurecom.fr>
|
||||
*/
|
||||
|
||||
#ifndef PCIE_INTERFACE_H
|
||||
#define PCIE_INTERFACE_H
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
// ------------------------------
|
||||
// Buffer sizes
|
||||
// ------------------------------
|
||||
#define MAX_ANTENNAS 4
|
||||
#define MAX_FIRMWARE_BLOCK_SIZE_B 262144
|
||||
#define MAX_PRINTK_BUFFER_B 1024
|
||||
|
||||
// #define FRAME_LENGTH_COMPLEX_SAMPLES 76800
|
||||
// Buffer size per channel: FRAME_LENGTH_COMPLEX_SAMPLES+2048 smp/frame: LTE frame+tail, *4 (7.68*4 MsmpPS), *4 Bytes/smp
|
||||
#define ADAC_BUFFERSZ_PERCHAN_B ((76800+2048)*4*4)
|
||||
|
||||
#define BIGSHM_SIZE_PAGES ((( MAX_FIRMWARE_BLOCK_SIZE_B + \
|
||||
MAX_PRINTK_BUFFER_B + \
|
||||
sizeof(exmimo_pci_interface_bot_t) + \
|
||||
sizeof(exmimo_config_t) + \
|
||||
sizeof(exmimo_id_t) + \
|
||||
2*MAX_ANTENNAS*sizeof(uint32_t)*4 + \
|
||||
16*256 /* alignment overhead */ ) >> PAGE_SHIFT ) +1 )
|
||||
|
||||
/*
|
||||
* Commands exchanged between PC <--> LEON
|
||||
*
|
||||
* Idle/Ready: EXMIMO_NOP
|
||||
*/
|
||||
#define EXMIMO_NOP 0x9999
|
||||
|
||||
// Commands from PC --> LEON, passed through ahbpcie_control1 register (must be smaller than 0x1000 !
|
||||
|
||||
#define EXMIMO_PCIE_INIT 0x0000
|
||||
#define EXMIMO_FW_INIT 0x0001
|
||||
#define EXMIMO_FW_CLEAR_BSS 0x0002
|
||||
#define EXMIMO_FW_START_EXEC 0x0003
|
||||
#define EXMIMO_REBOOT 0x0004
|
||||
#define EXMIMO_CONFIG 0x0005
|
||||
#define EXMIMO_GET_FRAME 0x0006
|
||||
#define EXMIMO_START_RT_ACQUISITION 0x0007
|
||||
#define EXMIMO_STOP 0x0008
|
||||
#define EXMIMO_STOP_WITHOUT_RESET 0x0009
|
||||
|
||||
#define IS_EXMIMOCMD_FROM_PC(x) ( (x)<0x1000 ? 1 : 0)
|
||||
|
||||
// Commands from LEON --> PC, passed through ahbpcie_control2 register
|
||||
|
||||
#define PCI_PRINTK 0x2222
|
||||
#define GET_FRAME_DONE 0x3333
|
||||
|
||||
#define EXMIMO_CONTROL2_COOKIE 0x43545232
|
||||
|
||||
// Default MODEM configuration in TV whitespace(400.850MHz), using RX/TX switch
|
||||
#define TVWS_TDD 0xF7E04002
|
||||
|
||||
// 850MHz .. 865MHz
|
||||
#define DD_FDD 0xFAE40041
|
||||
#define DD_TDD 0xF7E04000
|
||||
#define B19G_TDD 0xCBC20084
|
||||
#define B24G_TDD 0xCBA20084
|
||||
#define B26G_TDD 0xCB820084
|
||||
#define B26G_FDD 0xDEE60108
|
||||
#define B35G_TDD 0xE9F01810
|
||||
#define B50G_TDD 0xC079A020
|
||||
|
||||
|
||||
// used for DPD and dirty RF validation, TX fed back to RX through attenuators
|
||||
#define TVWS_TDD_DPD 0xF5E04000
|
||||
#define DD_TDD_DPD 0xF5E04000
|
||||
#define B19G_TDD_DPD 0xCDC20080
|
||||
#define B24G_TDD_DPD 0xCDA20080
|
||||
#define B26G_TDD_DPD 0xCD820080
|
||||
#define B35G_TDD_DPD 0xEDF01880
|
||||
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// structures for communication between ExMIMO and kernel
|
||||
// -----------------------------------------------------------
|
||||
|
||||
/*
|
||||
* struct exmimo_system_id_t:
|
||||
* Contains information on the bitstream, filled by Leon,
|
||||
* based on data stored in an APB block on FPGA (TODO)
|
||||
*
|
||||
* struct exmimo_id_t:
|
||||
* Compound structure, also includes information
|
||||
* from PCI configuration space (board_)
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t bitstream_id;
|
||||
uint32_t bitstream_build_date;
|
||||
uint32_t software_id;
|
||||
uint32_t software_build_date;
|
||||
uint32_t dsp_bitstream_id;
|
||||
uint32_t dsp_bitstream_build_date;
|
||||
} exmimo_system_id_t;
|
||||
|
||||
typedef struct {
|
||||
exmimo_system_id_t system_id;
|
||||
uint32_t board_vendor;
|
||||
uint32_t board_exmimoversion;
|
||||
uint32_t board_hwrev;
|
||||
uint32_t board_swrev;
|
||||
} exmimo_id_t;
|
||||
|
||||
|
||||
/****************************************************
|
||||
* Structure and flags for configuring RF and LIME
|
||||
* (struct exmimo_rf_t)
|
||||
*/
|
||||
//
|
||||
// register values and masks for rf_mode
|
||||
//
|
||||
#define RXEN 1
|
||||
#define TXEN 2
|
||||
|
||||
#define TXLPFENMASK 4
|
||||
#define TXLPFEN 4
|
||||
|
||||
#define TXLPFMASK (15<<3)
|
||||
#define TXLPF14 0
|
||||
#define TXLPF10 (1<<3)
|
||||
#define TXLPF7 (2<<3)
|
||||
#define TXLPF6 (3<<3)
|
||||
#define TXLPF5 (4<<3)
|
||||
#define TXLPF4375 (5<<3)
|
||||
#define TXLPF35 (6<<3)
|
||||
#define TXLPF3 (7<<3)
|
||||
#define TXLPF275 (8<<3)
|
||||
#define TXLPF25 (9<<3)
|
||||
#define TXLPF192 (10<<3)
|
||||
#define TXLPF15 (11<<3)
|
||||
#define TXLPF1375 (12<<3)
|
||||
#define TXLPF125 (13<<3)
|
||||
#define TXLPF0875 (14<<3)
|
||||
#define TXLPF075 (15<<3)
|
||||
|
||||
|
||||
#define RXLPFENMASK (1<<7)
|
||||
#define RXLPFEN 128
|
||||
|
||||
#define RXLPFMASK (15<<8)
|
||||
#define RXLPF14 0
|
||||
#define RXLPF10 (1<<8)
|
||||
#define RXLPF7 (2<<8)
|
||||
#define RXLPF6 (3<<8)
|
||||
#define RXLPF5 (4<<8)
|
||||
#define RXLPF4375 (5<<8)
|
||||
#define RXLPF35 (6<<8)
|
||||
#define RXLPF3 (7<<8)
|
||||
#define RXLPF275 (8<<8)
|
||||
#define RXLPF25 (9<<8)
|
||||
#define RXLPF192 (10<<8)
|
||||
#define RXLPF15 (11<<8)
|
||||
#define RXLPF1375 (12<<8)
|
||||
#define RXLPF125 (13<<8)
|
||||
#define RXLPF0875 (14<<8)
|
||||
#define RXLPF075 (15<<8)
|
||||
|
||||
#define LNAMASK (3<<12)
|
||||
#define LNADIS 0
|
||||
#define LNA1ON (1<<12)
|
||||
#define LNA2ON (2<<12)
|
||||
#define LNA3ON (3<<12)
|
||||
|
||||
#define LNAGAINMASK (3<<14)
|
||||
#define LNAByp (1<<14)
|
||||
#define LNAMed (2<<14)
|
||||
#define LNAMax (3<<14)
|
||||
|
||||
// RFBBMASK: enable different loopback modes for calibration and testing. Use RFBBNORM for normal operation
|
||||
#define RFBBMASK (7<<16)
|
||||
#define RFBBNORM 0
|
||||
#define RFBBRXLPF (1<<16)
|
||||
#define RFBBRXVGA (2<<16)
|
||||
#define RFBBOUTPUT (3<<16)
|
||||
#define RFBBLNA1 (4<<16)
|
||||
#define RFBBLNA2 (5<<16)
|
||||
#define RFBBLNA3 (6<<16)
|
||||
|
||||
#define RXLPFMODEMASK (3<<19)
|
||||
#define RXLPFNORM 0
|
||||
#define RXLPFBYP (1<<19)
|
||||
#define RXLPFBPY2 (3<<19)
|
||||
|
||||
#define TXLPFMODEMASK (1<<21)
|
||||
#define TXLPFNORM 0
|
||||
#define TXLPFBYP (1<<21)
|
||||
|
||||
#define RXOUTSW (1<<22)
|
||||
|
||||
#define DMAMODE_TRXMASK (3<<23)
|
||||
#define DMAMODE_RX (1<<23)
|
||||
#define DMAMODE_TX (2<<23)
|
||||
|
||||
|
||||
// register values and masks for rf_local
|
||||
#define TXLOIMASK 63
|
||||
#define TXLOQMASK (63<<6)
|
||||
#define RXLOIMASK (63<<12)
|
||||
#define RXLOQMASK (63<<18)
|
||||
|
||||
typedef struct {
|
||||
uint32_t do_autocal[MAX_ANTENNAS];
|
||||
uint32_t rf_freq_rx[MAX_ANTENNAS];
|
||||
uint32_t rf_freq_tx[MAX_ANTENNAS];
|
||||
|
||||
// TX Gain [Chain0..3][0=LIME Gain, 1=currently ignored]
|
||||
uint32_t tx_gain[MAX_ANTENNAS][2];
|
||||
|
||||
// RX Gain [Chain0..3][0=LIME Gain, 1=currently ignored]
|
||||
uint32_t rx_gain[MAX_ANTENNAS][2];
|
||||
|
||||
//LIME RF modes
|
||||
// 21 | 20:19 | 18:16 |15:14 | 13:12|11:8 | 7 |6:3 |2 |1 |0 |
|
||||
// TXBYP | RXBYP | RF/BB |LNAMode| LNA |RXLPF|RXLPFen|TXLPF|TXLPFen|TXen|RXen|
|
||||
uint32_t rf_mode[MAX_ANTENNAS];
|
||||
|
||||
// LIME LO Calibration Constants
|
||||
// | RXLOQ | RXLOI | TXLOQ | TXLOI |
|
||||
// | 23:18 | 17:12 | 11:6 | 5:0 |
|
||||
uint32_t rf_local[MAX_ANTENNAS];
|
||||
|
||||
// LIME RX DC OFFSET
|
||||
// | RXDCQ | RXDCI |
|
||||
// | 15:8 | 7:0 |
|
||||
uint32_t rf_rxdc[MAX_ANTENNAS];
|
||||
|
||||
// LIME VCO Calibration Constants
|
||||
// | RXVCOCAP | TXVCOCAP |
|
||||
// | 11:6 | 5:0 |
|
||||
uint32_t rf_vcocal[MAX_ANTENNAS];
|
||||
|
||||
// External RF Frontend, as used on ExpressMIMO-2
|
||||
uint32_t rffe_gain_txlow[MAX_ANTENNAS];
|
||||
uint32_t rffe_gain_txhigh[MAX_ANTENNAS];
|
||||
uint32_t rffe_gain_rxfinal[MAX_ANTENNAS];
|
||||
uint32_t rffe_gain_rxlow[MAX_ANTENNAS];
|
||||
uint32_t rffe_band_mode[MAX_ANTENNAS];
|
||||
|
||||
} exmimo_rf_t;
|
||||
|
||||
|
||||
/*********************************************************
|
||||
* Structure and flags for configuring Framing and Sync
|
||||
* (struct exmimo_framing_t)
|
||||
*/
|
||||
//
|
||||
// ** multicard synchronization mode (framing.multicard_syncmode)
|
||||
//
|
||||
// slave: take sync_newframe & sync_getframe from IO_SYNC header pin
|
||||
// master: enable IO_SYNC header OUTPUT (do this only on a single card!) for sync_newframe & sync_getframe
|
||||
#define SYNCMODE_FREE 0
|
||||
#define SYNCMODE_MASTER 1
|
||||
#define SYNCMODE_SLAVE 2
|
||||
|
||||
//
|
||||
// ** register values and masks for tdd_config
|
||||
//
|
||||
// In TDD mode, there are two ways to control the RX/TX switch:
|
||||
// 1. using the LSB from the TX data (TXRXSWITCH_LSB)
|
||||
// only the LSB from RF chain set in the ACTIVE_RF register controls the switch on all the chains
|
||||
// 2. using FPGA logic, based on switch_offset[0..3]
|
||||
// this mode is not tested well and should be used with care
|
||||
#define DUPLEXMODE_MASK (1<<0)
|
||||
#define DUPLEXMODE_FDD 0
|
||||
#define DUPLEXMODE_TDD (1<<0)
|
||||
#define TXRXSWITCH_MASK (3<<1)
|
||||
#define TXRXSWITCH_LSB 0
|
||||
#define TXRXSWITCH_FPGA (1<<1)
|
||||
#define TXRXSWITCH_TESTRX (2<<1)
|
||||
#define TXRXSWITCH_TESTTX (3<<1)
|
||||
#define SWITCHSTATE_MASK (1<<3)
|
||||
#define SWITCHSTATE_0 0
|
||||
#define SWITCHSTATE_1 (1<<3)
|
||||
#define TEST_ADACLOOP_MASK (1<<4)
|
||||
#define TEST_ADACLOOP_EN (1<<4)
|
||||
#define RF_ACTIVE_MASK (15<<5)
|
||||
#define RF_ACTIVE_1 (1<<5)
|
||||
#define RF_ACTIVE_2 (2<<5)
|
||||
#define RF_ACTIVE_3 (4<<5)
|
||||
#define RF_ACTIVE_4 (8<<5)
|
||||
|
||||
typedef enum {
|
||||
BW5,
|
||||
BW10,
|
||||
BW20
|
||||
} exmimo_bw_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t multicard_syncmode;
|
||||
|
||||
uint32_t eNB_flag;
|
||||
|
||||
uint32_t tdd_config;
|
||||
|
||||
uint32_t frame_length; // e.g. 76800
|
||||
uint32_t frame_start; // e.g. 18
|
||||
uint32_t adac_buffer_period; // e.g. 2048
|
||||
uint32_t adac_intr_period; // e.g. 1024
|
||||
|
||||
uint32_t switch_offset[4]; // sample offsets (relative to start of frame) used to control the RX/TX switch in TDD mode
|
||||
uint32_t resampling_factor[4]; // 0=>1, 1=>2, 2=>4, applied equally to each chain and TX/RX
|
||||
} exmimo_framing_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
exmimo_rf_t rf;
|
||||
exmimo_framing_t framing;
|
||||
} exmimo_config_t;
|
||||
|
||||
|
||||
|
||||
/*****************************************
|
||||
* Structures to pass pointers
|
||||
* between Leon, Kernel and Userspace
|
||||
*/
|
||||
|
||||
/*
|
||||
* struct exmimo_pci_interface_bot_t:
|
||||
* Main structure to exchange physical(DMA) pointers between kernel and Leon
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t firmware_block_ptr;
|
||||
uint32_t printk_buffer_ptr;
|
||||
|
||||
uint32_t exmimo_config_ptr;
|
||||
uint32_t exmimo_id_ptr;
|
||||
|
||||
// rxcnt / txcnt: stores the current ring buffer position indicators (formerly mbox)
|
||||
// - increment by one for every 512 samples (512 DW)
|
||||
// - currently wraps at 150 (0..149) to cover 1 LTE frame in the buffer
|
||||
// - in current sdr LEON code: only rxcnt_ptr[0] is used
|
||||
uint32_t rxcnt_ptr[MAX_ANTENNAS]; // points to uint32_t RX ring buffer position for each antenna
|
||||
uint32_t txcnt_ptr[MAX_ANTENNAS]; // points to uint32_t TX ring buffer position for each antenna
|
||||
uint32_t adc_head[MAX_ANTENNAS]; // address of start of ADC (RX) buffer in PC memory
|
||||
uint32_t dac_head[MAX_ANTENNAS]; // address of start of DAC (TX) buffer in PC memory
|
||||
|
||||
#ifdef NOINIT
|
||||
uint32_t dummy[13]; // used only in simulation for Modelsim memcopy tests
|
||||
#endif
|
||||
} exmimo_pci_interface_bot_t;
|
||||
/*
|
||||
* Equivalent structure to exmimo_pci_interface_bot, which keeps type-specific virtual pointers
|
||||
*/
|
||||
typedef struct {
|
||||
char *firmware_block_ptr;
|
||||
char *printk_buffer_ptr;
|
||||
exmimo_config_t *exmimo_config_ptr;
|
||||
exmimo_id_t *exmimo_id_ptr;
|
||||
uint32_t *rxcnt_ptr[MAX_ANTENNAS]; // points to uint32_t RX ring buffer position for each antenna
|
||||
uint32_t *txcnt_ptr[MAX_ANTENNAS]; // points to uint32_t TX ring buffer position for each antenna
|
||||
uint32_t *adc_head[MAX_ANTENNAS]; // address of start of ADC (RX) buffer in PC memory
|
||||
uint32_t *dac_head[MAX_ANTENNAS]; // address of start of DAC (TX) buffer in PC memory
|
||||
} exmimo_pci_interface_bot_virtual_t;
|
||||
|
||||
#endif
|
||||
@@ -1,23 +0,0 @@
|
||||
CCC = gcc
|
||||
include $(OPENAIR_DIR)/common/utils/Makefile.inc
|
||||
KERNEL_MAIN_TYPE:=$(shell echo `uname -r | cut -d. -f-2 | tr "." "_"`)
|
||||
export KERNEL_MAIN_TYPE
|
||||
|
||||
EXTRA_CFLAGS = -ggdb -D__KERNEL__ -DMODULE -D_LOOSE_KERNEL_NAMES -I$(KERNEL_DIR)/build/include -I$(KERNEL_DIR)/build/include/asm/mach-default -include $(KERNEL_DIR)/build/include/linux/autoconf.h
|
||||
|
||||
EXTRA_CFLAGS += -I$(PWD)/../../DEFS
|
||||
|
||||
ccflags-y= $(CFLAGS) $(EXTRA_CFLAGS)
|
||||
CFLAGS=
|
||||
|
||||
obj-m += openair_rf.o
|
||||
|
||||
openair_rf-objs += module_main.o irq.o fileops.o exmimo_fw.o
|
||||
|
||||
all:
|
||||
make -C $(KERNEL_DIR)/build M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
rm -rf *.o
|
||||
make -C $(KERNEL_DIR)/build M=$(PWD) clean
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
echo "Hint: this may not work if /usr/src/linux is not set to currently booted kernel."
|
||||
echo "Try 'make' instead."
|
||||
|
||||
make -C /usr/src/linux V=1 M=`pwd`
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef __DEFS_H__
|
||||
#define __DEFS_H__
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/delay.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
//#include <linux/config.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#include <linux/errno.h>
|
||||
|
||||
#ifdef KERNEL2_6
|
||||
#include <linux/slab.h>
|
||||
#endif
|
||||
|
||||
#include "openair_device.h"
|
||||
|
||||
#include "linux/moduleparam.h"
|
||||
|
||||
|
||||
/*------------------------------------------------*/
|
||||
/* Prototypes */
|
||||
/*------------------------------------------------*/
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
|
||||
long openair_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
||||
#else
|
||||
int openair_device_ioctl(struct inode *inode,struct file *filp, unsigned int cmd, unsigned long arg);
|
||||
#endif
|
||||
int openair_device_open (struct inode *inode,struct file *filp);
|
||||
int openair_device_release (struct inode *inode,struct file *filp);
|
||||
int openair_device_mmap (struct file *filp, struct vm_area_struct *vma);
|
||||
|
||||
int exmimo_memory_alloc(int card);
|
||||
int exmimo_firmware_init(int card);
|
||||
int exmimo_firmware_cleanup(int card_id);
|
||||
|
||||
int exmimo_send_pccmd(int card_id, unsigned int cmd);
|
||||
|
||||
#endif
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Re-Enumerate FPGA card
|
||||
|
||||
# After resetting or powering up the card or after reloading the FPGA bitstream,
|
||||
# run this script to re-enumerate the PCIe device in Linux.
|
||||
|
||||
# You may need to change the device path. Check lspci output for this.
|
||||
|
||||
# You need to run this as root:
|
||||
# sudo ./do_reenumerate_expressmimo.sh
|
||||
|
||||
# Matthias <ihmig@eurecom.fr>, 2013
|
||||
|
||||
rmmod openair_rf
|
||||
echo 1 > /sys/bus/pci/devices/0000\:01\:00.0/remove
|
||||
echo 1 > /sys/bus/pci/devices/0000\:05\:00.0/remove
|
||||
echo 1 > /sys/bus/pci/rescan
|
||||
|
||||
insmod openair_rf.ko
|
||||
@@ -1 +0,0 @@
|
||||
rmmod openair_rf && sleep 1 ; insmod openair_rf.ko
|
||||
@@ -1,353 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** exmimo_fw.c
|
||||
*
|
||||
* Initialization routines for
|
||||
* Shared Memory management for ExMIMO and PC(kernel) data exchange
|
||||
* (memory allocation, pointer management)
|
||||
*
|
||||
* There is now one pci_alloc_consistent for each RX and TX buffer
|
||||
* and one for all structures, including pointers, printk, firmware_dump and config
|
||||
*
|
||||
* Authors: Matthias Ihmig <matthias.ihmig@mytum.de>, 2012, 2013
|
||||
* Riadh Ghaddab <riadh.ghaddab@eurecom.fr>
|
||||
* Raymond Knopp <raymond.knopp@eurecom.fr>
|
||||
*
|
||||
* Changelog:
|
||||
* 24.01.2013: added memory management functions for bigshm, lots of cleanups
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include "extern.h"
|
||||
#include "defs.h"
|
||||
#include "pcie_interface.h"
|
||||
|
||||
/*****************************************************
|
||||
* Private functions within this file
|
||||
*/
|
||||
|
||||
void mem_SetPageReserved(void *kvirt_addr, unsigned int size_pages)
|
||||
{
|
||||
size_t temp_size = size_pages << PAGE_SHIFT;
|
||||
void *adr = kvirt_addr;
|
||||
|
||||
while (temp_size > 0) {
|
||||
SetPageReserved( virt_to_page(adr) );
|
||||
adr += PAGE_SIZE;
|
||||
temp_size -= PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void mem_ClearPageReserved(void *kvirt_addr, unsigned int size_pages)
|
||||
{
|
||||
size_t temp_size = size_pages << PAGE_SHIFT;
|
||||
void *adr = kvirt_addr;
|
||||
|
||||
while (temp_size > 0) {
|
||||
ClearPageReserved( virt_to_page(adr) );
|
||||
adr += PAGE_SIZE;
|
||||
temp_size -= PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
// allocates big shared memory, to be used for structures, pointers, etc.
|
||||
// bigshm allocs a single larger memory block for shared structures and pointers, one per card, except: ADC+DAC buffers!
|
||||
// returns -1 on error, 0 on success
|
||||
int bigshm_init(int card)
|
||||
{
|
||||
printk("[openair][module] calling pci_alloc_consistent for card %d, bigshm (size: %lu*%lu bytes)...\n", card, BIGSHM_SIZE_PAGES, PAGE_SIZE);
|
||||
|
||||
if ( sizeof(dma_addr_t) != 4)
|
||||
printk("!!! WARNING: sizeof (dma_addr_t) = %lu! Only 32bit mode (= 4) (also: no PAE) is supported at this time!\n", sizeof(dma_addr_t));
|
||||
|
||||
if ( bigshm_head[card] == NULL )
|
||||
bigshm_head[card] = pci_alloc_consistent( pdev[card], BIGSHM_SIZE_PAGES<<PAGE_SHIFT, &bigshm_head_phys[card] );
|
||||
|
||||
if (bigshm_head[card] == NULL) {
|
||||
printk("[openair][MODULE][ERROR] Cannot Allocate Memory (%lu bytes) for shared data (bigshm)\n", BIGSHM_SIZE_PAGES<<PAGE_SHIFT);
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
printk("[openair][MODULE][INFO] Bigshm at %p (phys %x)\n", bigshm_head[card], (unsigned int) bigshm_head_phys[card]);
|
||||
|
||||
bigshm_currentptr[card] = bigshm_head[card];
|
||||
|
||||
mem_SetPageReserved( bigshm_head[card], BIGSHM_SIZE_PAGES);
|
||||
memset(bigshm_head[card], 0, BIGSHM_SIZE_PAGES << PAGE_SHIFT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// use this instead of pci_alloc_consistent to assign memory from the bigshm block
|
||||
// return kernel virtual pointer and sets physical DMA address in dma_handle
|
||||
void *bigshm_assign( int card, size_t size_bytes, dma_addr_t *dma_handle_ptr )
|
||||
{
|
||||
void *ret;
|
||||
size_t size = size_bytes;
|
||||
|
||||
//size = (size-1) + 4 - ( (size-1) % 4); // round up to keep addresses aligned to DWs
|
||||
//size = (size-1) + 16 - ( (size-1) % 16); // round up to keep addresses aligned to 4 DWs
|
||||
|
||||
// round up to the next 64 DW (workaround for current bug in DMA on ExMIMO2)
|
||||
size = (size-1) + 256 - ( (size-1) % 256);
|
||||
|
||||
if ( (bigshm_currentptr[card] - bigshm_head[card]) > (BIGSHM_SIZE_PAGES<<PAGE_SHIFT) -size ) {
|
||||
printk("Not enough memory in bigshm! Make BIGSHM_SIZE_PAGES bigger!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*dma_handle_ptr = bigshm_head_phys[card] + ( (dma_addr_t)bigshm_currentptr[card] - (dma_addr_t)bigshm_head[card] );
|
||||
ret = bigshm_currentptr[card];
|
||||
bigshm_currentptr[card] = (char *)bigshm_currentptr[card] + size;
|
||||
|
||||
//printk("bigshm_assign: size %d, virt = %p, dma = %x, bigshm_phys=%x, _current=%p, _head=%p\n",
|
||||
// size, ret, *dma_handle_ptr, bigshm_head_phys[card], bigshm_currentptr[card], bigshm_head[card]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// assign shared memory between card an PC for data exchange: interface structure with pointers,
|
||||
// firmware- and printk buffers, configuration structure
|
||||
// returns -1 on error, 0 on success
|
||||
int exmimo_assign_shm_vars(int card_id)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (p_exmimo_pci_phys[card_id] == NULL) {
|
||||
p_exmimo_pci_phys[card_id] = (exmimo_pci_interface_bot_t *) bigshm_assign( card_id,
|
||||
sizeof(exmimo_pci_interface_bot_t),
|
||||
&pphys_exmimo_pci_phys[card_id]);
|
||||
printk("Intializing EXMIMO interface support (exmimo_pci_bot at %p, phys %x, size %lu bytes)\n",p_exmimo_pci_phys[card_id],(unsigned int)pphys_exmimo_pci_phys[card_id],
|
||||
sizeof(exmimo_pci_interface_bot_t));
|
||||
|
||||
exmimo_pci_kvirt[card_id].firmware_block_ptr = (char *) bigshm_assign( card_id,
|
||||
MAX_FIRMWARE_BLOCK_SIZE_B,
|
||||
(dma_addr_t*)&(p_exmimo_pci_phys[card_id]->firmware_block_ptr));
|
||||
printk("firmware_code_block_ptr : %p (phys = %08x)\n", exmimo_pci_kvirt[card_id].firmware_block_ptr, p_exmimo_pci_phys[card_id]->firmware_block_ptr);
|
||||
|
||||
|
||||
exmimo_pci_kvirt[card_id].printk_buffer_ptr = (char *) bigshm_assign( card_id,
|
||||
MAX_PRINTK_BUFFER_B,
|
||||
(dma_addr_t*)&(p_exmimo_pci_phys[card_id]->printk_buffer_ptr));
|
||||
printk("printk_buffer_ptr : %p (phys = %08x)\n", exmimo_pci_kvirt[card_id].printk_buffer_ptr, p_exmimo_pci_phys[card_id]->printk_buffer_ptr);
|
||||
|
||||
|
||||
exmimo_pci_kvirt[card_id].exmimo_config_ptr = (exmimo_config_t *) bigshm_assign( card_id,
|
||||
sizeof(exmimo_config_t),
|
||||
(dma_addr_t*)&(p_exmimo_pci_phys[card_id]->exmimo_config_ptr));
|
||||
printk("exmimo_config_ptr : %p (phys = %08x)\n", exmimo_pci_kvirt[card_id].exmimo_config_ptr, p_exmimo_pci_phys[card_id]->exmimo_config_ptr);
|
||||
|
||||
|
||||
exmimo_pci_kvirt[card_id].exmimo_id_ptr = (exmimo_id_t *) bigshm_assign( card_id,
|
||||
sizeof(exmimo_id_t),
|
||||
(dma_addr_t*)&(p_exmimo_pci_phys[card_id]->exmimo_id_ptr));
|
||||
printk("exmimo_id_ptr : %p (phys = %08x)\n", exmimo_pci_kvirt[card_id].exmimo_id_ptr, p_exmimo_pci_phys[card_id]->exmimo_id_ptr);
|
||||
|
||||
|
||||
if ( p_exmimo_pci_phys[card_id] == NULL || exmimo_pci_kvirt[card_id].firmware_block_ptr == NULL
|
||||
|| exmimo_pci_kvirt[card_id].printk_buffer_ptr == NULL || exmimo_pci_kvirt[card_id].exmimo_config_ptr == NULL
|
||||
|| exmimo_pci_kvirt[card_id].exmimo_id_ptr == NULL )
|
||||
return -1;
|
||||
|
||||
for (j=0; j<MAX_ANTENNAS; j++) {
|
||||
// size 4*1 should be sufficient, but just to make sure we can also use DMA of size 4DW as fallback
|
||||
exmimo_pci_kvirt[card_id].rxcnt_ptr[j] = (uint32_t *) bigshm_assign( card_id, 4*4,
|
||||
(dma_addr_t*)&(p_exmimo_pci_phys[card_id]->rxcnt_ptr[j]) );
|
||||
printk("exmimo_pci_kvirt[%d].rxcnt_ptr[%d] = %p (phys = %08x)\n", card_id, j, exmimo_pci_kvirt[card_id].rxcnt_ptr[j], p_exmimo_pci_phys[card_id]->rxcnt_ptr[j]);
|
||||
|
||||
exmimo_pci_kvirt[card_id].txcnt_ptr[j] = (uint32_t *) bigshm_assign( card_id, 4*4,
|
||||
(dma_addr_t*)&(p_exmimo_pci_phys[card_id]->txcnt_ptr[j]) );
|
||||
printk("exmimo_pci_kvirt[%d].txcnt_ptr[%d] = %p (phys = %08x)\n", card_id, j, exmimo_pci_kvirt[card_id].txcnt_ptr[j], p_exmimo_pci_phys[card_id]->txcnt_ptr[j]);
|
||||
|
||||
if ( exmimo_pci_kvirt[card_id].rxcnt_ptr[j] == NULL || exmimo_pci_kvirt[card_id].txcnt_ptr[j] == NULL)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// allocate memory for RX and TX chains for all antennas
|
||||
// returns -1 on error, 0 on success
|
||||
int exmimo_allocate_rx_tx_buffers(int card_id)
|
||||
{
|
||||
size_t size;
|
||||
int j;
|
||||
dma_addr_t dma_addr_dummy;
|
||||
// Round up to the next PAGE_SIZE (typ. 4096 bytes)
|
||||
size = (ADAC_BUFFERSZ_PERCHAN_B >> PAGE_SHIFT) + 1;
|
||||
size <<= PAGE_SHIFT;
|
||||
|
||||
for (j=0; j<MAX_ANTENNAS; j++) {
|
||||
|
||||
exmimo_pci_kvirt[card_id].adc_head[j] = (uint32_t *)pci_alloc_consistent( pdev[card_id], size, &dma_addr_dummy);
|
||||
p_exmimo_pci_phys[card_id]->adc_head[j]=((uint32_t*)&dma_addr_dummy)[0];
|
||||
|
||||
printk("exmimo_pci_kvirt[%d].adc_head[%d] = %p (phys = %08x)\n", card_id, j, exmimo_pci_kvirt[card_id].adc_head[j], p_exmimo_pci_phys[card_id]->adc_head[j]);
|
||||
|
||||
if ( exmimo_pci_kvirt[card_id].adc_head[j] == NULL)
|
||||
return -1;
|
||||
|
||||
// printk("[MODULE MAIN0]Phys address TX[0] : (%8lx)\n",p_exmimo_pci_phys[0]->dac_head[ openair_mmap_getAntTX(2) ]);
|
||||
|
||||
mem_SetPageReserved( exmimo_pci_kvirt[card_id].adc_head[j], size >> PAGE_SHIFT );
|
||||
memset( exmimo_pci_kvirt[card_id].adc_head[j], 0x10+j, size);
|
||||
|
||||
// printk("[MODULE MAIN1]Phys address TX[0] : (%8lx)\n",p_exmimo_pci_phys[0]->dac_head[ openair_mmap_getAntTX(2) ]);
|
||||
|
||||
exmimo_pci_kvirt[card_id].dac_head[j] = (uint32_t *)pci_alloc_consistent( pdev[card_id], size,&dma_addr_dummy);
|
||||
p_exmimo_pci_phys[card_id]->dac_head[j]=((uint32_t*)&dma_addr_dummy)[0];
|
||||
|
||||
// printk("exmimo_pci_kvirt[%d].dac_head[%d] = %p (phys = %08x)\n", card_id, j, exmimo_pci_kvirt[card_id].dac_head[j], p_exmimo_pci_phys[card_id]->dac_head[j]);
|
||||
if ( exmimo_pci_kvirt[card_id].dac_head[j] == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
// printk("[MODULE MAIN2]Phys address TX[0] : (%8lx)\n",p_exmimo_pci_phys[0]->dac_head[ openair_mmap_getAntTX(2) ]);
|
||||
|
||||
mem_SetPageReserved( exmimo_pci_kvirt[card_id].dac_head[j], size >> PAGE_SHIFT );
|
||||
memset( exmimo_pci_kvirt[card_id].dac_head[j], 0x20+j, size);
|
||||
// printk("[MODULE MAIN3]Phys address TX[0] : (%8lx)\n",p_exmimo_pci_phys[0]->dac_head[ openair_mmap_getAntTX(2) ]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************
|
||||
* Public functions ExpressMIMO Interface
|
||||
*/
|
||||
|
||||
/* Allocates buffer and assigns pointers
|
||||
*
|
||||
* return 0 on success
|
||||
*/
|
||||
int exmimo_memory_alloc(int card)
|
||||
{
|
||||
if ( bigshm_init( card ) ) {
|
||||
printk("exmimo_memory_alloc(): bigshm_init failed for card %d.\n", card);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if ( exmimo_assign_shm_vars( card ) ) {
|
||||
printk("exmimo_memory_alloc(): exmimo_assign_shm_vars failed to assign enough shared memory for all variables and structures for card %i!\n", card);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if ( exmimo_allocate_rx_tx_buffers( card ) ) {
|
||||
printk("exmimo_memory_alloc(): exmimo_allocate_rx_tx_buffers() failed to allocate enough memory for RX and TX buffers for card %i!\n", card);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies pointer to Leon
|
||||
*/
|
||||
int exmimo_firmware_init(int card)
|
||||
{
|
||||
/* pci_dma_sync_single_for_device(pdev[card],
|
||||
pphys_exmimo_pci_phys[card],
|
||||
sizeof(exmimo_pci_interface_bot_t),
|
||||
PCI_DMA_TODEVICE); */
|
||||
|
||||
// put DMA pointer to exmimo_pci_interface_bot into LEON register
|
||||
iowrite32( pphys_exmimo_pci_phys[card], (bar[card]+PCIE_PCIBASEL) ); // lower 32bit of address
|
||||
iowrite32( 0, (bar[card]+PCIE_PCIBASEH) ); // higher 32bit of address
|
||||
|
||||
if (exmimo_pci_kvirt[card].exmimo_id_ptr->board_swrev == BOARD_SWREV_CMDREGISTERS)
|
||||
iowrite32( EXMIMO_CONTROL2_COOKIE, bar[card]+ PCIE_CONTROL2);
|
||||
|
||||
//printk("exmimo_firmware_init(): initializing Leon (EXMIMO_PCIE_INIT)...\n");
|
||||
exmimo_send_pccmd(card, EXMIMO_PCIE_INIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free memory on unloading the kernel driver
|
||||
*/
|
||||
int exmimo_firmware_cleanup(int card)
|
||||
{
|
||||
size_t size;
|
||||
int j;
|
||||
|
||||
// free exmimo_allocate_rx_tx_buffers
|
||||
|
||||
size = (ADAC_BUFFERSZ_PERCHAN_B >> PAGE_SHIFT) + 1;
|
||||
size <<= PAGE_SHIFT;
|
||||
|
||||
for (j=0; j<MAX_ANTENNAS; j++) {
|
||||
if ( exmimo_pci_kvirt[card].adc_head[j] ) {
|
||||
mem_ClearPageReserved( exmimo_pci_kvirt[card].adc_head[j], size >> PAGE_SHIFT );
|
||||
pci_free_consistent( pdev[card], size, exmimo_pci_kvirt[card].adc_head[j], p_exmimo_pci_phys[card]->adc_head[j] );
|
||||
}
|
||||
|
||||
if ( exmimo_pci_kvirt[card].dac_head[j] ) {
|
||||
mem_ClearPageReserved( exmimo_pci_kvirt[card].dac_head[j], size >> PAGE_SHIFT );
|
||||
pci_free_consistent( pdev[card], size, exmimo_pci_kvirt[card].dac_head[j], p_exmimo_pci_phys[card]->dac_head[j] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( bigshm_head[card] ) {
|
||||
printk("free bigshm_head[%d] pdev %p, size %lu, head %p, phys %x\n", card, pdev[card], BIGSHM_SIZE_PAGES<<PAGE_SHIFT, bigshm_head[card], (unsigned int)bigshm_head_phys[card]);
|
||||
mem_ClearPageReserved( bigshm_head[card], BIGSHM_SIZE_PAGES );
|
||||
|
||||
pci_free_consistent( pdev[card], BIGSHM_SIZE_PAGES<<PAGE_SHIFT, bigshm_head[card], bigshm_head_phys[card]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Send command to Leon and wait until command is completed
|
||||
*/
|
||||
int exmimo_send_pccmd(int card_id, unsigned int cmd)
|
||||
{
|
||||
unsigned int val;
|
||||
unsigned int cnt=0;
|
||||
|
||||
//printk("Sending command to ExpressMIMO (card %d) : %x\n",card_id, cmd);
|
||||
iowrite32(cmd,(bar[card_id]+PCIE_CONTROL1));
|
||||
// printk("Readback of control1 %x\n",ioread32(bar[0]+PCIE_CONTROL1));
|
||||
|
||||
val = ioread32(bar[card_id]+PCIE_CONTROL0); // this is only necessary for ExMIMO1. ExMIMO2 will not overwrite any bits in CONTROL0 whenever bit0 is set.
|
||||
// set interrupt bit to trigger LEON interrupt
|
||||
iowrite32(val|0x1,bar[card_id]+PCIE_CONTROL0);
|
||||
// printk("Readback of control0 %x\n",ioread32(bar[0]+PCIE_CONTROL0));
|
||||
|
||||
// workaround for ExMIMO1: no command ack -> sleep
|
||||
while (cnt<100 && ( ioread32(bar[card_id]+PCIE_CONTROL1) != EXMIMO_NOP )) {
|
||||
//printk("ctrl0: %08x, ctrl1: %08x, ctrl2: %08x, status: %08x\n", ioread32(bar[card_id]+PCIE_CONTROL0), ioread32(bar[card_id]+PCIE_CONTROL1), ioread32(bar[card_id]+PCIE_CONTROL2), ioread32(bar[card_id]+PCIE_STATUS));
|
||||
msleep(100);
|
||||
cnt++;
|
||||
}
|
||||
|
||||
if (cnt==100)
|
||||
printk("exmimo_send_pccmd error: Timeout: no EXMIMO_NOP received within 10sec for card%d, pccmd=%x\n", card_id, cmd);
|
||||
|
||||
//printk("Ctrl0: %08x, ctrl1: %08x, ctrl2: %08x, status: %08x\n", ioread32(bar[card_id]+PCIE_CONTROL0), ioread32(bar[card_id]+PCIE_CONTROL1), ioread32(bar[card_id]+PCIE_CONTROL2), ioread32(bar[card_id]+PCIE_STATUS));
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef __EXTERN_H__
|
||||
#define __EXTERN_H__
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#ifdef KERNEL2_6
|
||||
#include <linux/slab.h>
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
#include "pcie_interface.h"
|
||||
|
||||
extern char number_of_cards;
|
||||
|
||||
extern int major;
|
||||
|
||||
extern struct pci_dev *pdev[MAX_CARDS];
|
||||
extern void __iomem *bar[MAX_CARDS];
|
||||
|
||||
extern void *bigshm_head[MAX_CARDS];
|
||||
extern void *bigshm_currentptr[MAX_CARDS];
|
||||
extern dma_addr_t bigshm_head_phys[MAX_CARDS];
|
||||
|
||||
extern dma_addr_t pphys_exmimo_pci_phys[MAX_CARDS];
|
||||
extern exmimo_pci_interface_bot_t *p_exmimo_pci_phys[MAX_CARDS];
|
||||
extern exmimo_pci_interface_bot_virtual_t exmimo_pci_kvirt[MAX_CARDS];
|
||||
|
||||
#endif // __EXTERN_H__
|
||||
@@ -1,488 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** fileops.c
|
||||
*
|
||||
* Device IOCTL File Operations on character device /dev/openair0
|
||||
*
|
||||
* Authors: Matthias Ihmig <matthias.ihmig@mytum.de>, 2012, 2013
|
||||
* Riadh Ghaddab <riadh.ghaddab@eurecom.fr>
|
||||
* Raymond Knopp <raymond.knopp@eurecom.fr>
|
||||
*
|
||||
* Changelog:
|
||||
* 14.01.2013: removed remaining of BIGPHYS stuff and replaced with pci_alloc_consistent
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "openair_device.h"
|
||||
#include "defs.h"
|
||||
#include "extern.h"
|
||||
|
||||
#include "pcie_interface.h"
|
||||
|
||||
#define invert4(x) { \
|
||||
unsigned int ltmp; \
|
||||
ltmp=x; x=((ltmp & 0xff)<<24) | ((ltmp & 0xff00)<<8) | \
|
||||
((ltmp & 0xff0000)>>8) | ((ltmp & 0xff000000)>>24); \
|
||||
}
|
||||
|
||||
extern int get_frame_done;
|
||||
|
||||
|
||||
int is_card_num_invalid(int card)
|
||||
{
|
||||
if (card<0 || card>=number_of_cards) {
|
||||
printk("[openair][IOCTL]: ERROR: received invalid card number (%d)!\n", card);
|
||||
return -1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int openair_device_open (struct inode *inode,struct file *filp)
|
||||
{
|
||||
//printk("[openair][MODULE] openair_open()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int openair_device_release (struct inode *inode,struct file *filp)
|
||||
{
|
||||
// printk("[openair][MODULE] openair_release(), MODE = %d\n",openair_daq_vars.mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int openair_device_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
unsigned long phys;
|
||||
unsigned long start = (unsigned long)vma->vm_start;
|
||||
unsigned long size = (unsigned long)(vma->vm_end-vma->vm_start);
|
||||
unsigned long maxsize;
|
||||
unsigned int memblock_ind;
|
||||
unsigned int card;
|
||||
|
||||
memblock_ind = openair_mmap_getMemBlock( vma->vm_pgoff );
|
||||
card = openair_mmap_getCard( vma->vm_pgoff );
|
||||
|
||||
/*printk("[openair][MMAP] called (start %lx, end %lx, pg_off %lx, size %lx)\n",
|
||||
vma->vm_start,
|
||||
vma->vm_end,
|
||||
vma->vm_pgoff,
|
||||
size);
|
||||
*/
|
||||
vma->vm_pgoff = 0;
|
||||
|
||||
// not supported by 64 bit kernels
|
||||
//vma->vm_flags |= VM_RESERVED;
|
||||
vma->vm_flags |= VM_IO;
|
||||
|
||||
if ( is_card_num_invalid(card) )
|
||||
return -EINVAL;
|
||||
|
||||
if (memblock_ind == openair_mmap_BIGSHM) {
|
||||
// map a buffer from bigshm
|
||||
maxsize = BIGSHM_SIZE_PAGES<<PAGE_SHIFT;
|
||||
|
||||
if ( size > maxsize) {
|
||||
printk("[openair][MMAP][ERROR] Trying to map more than %d bytes (req size=%d)\n",
|
||||
(unsigned int)(BIGSHM_SIZE_PAGES<<PAGE_SHIFT), (unsigned int)size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
phys = bigshm_head_phys[card];
|
||||
} else if ( (memblock_ind & 1) == 1) {
|
||||
// mmap a RX buffer
|
||||
maxsize = ADAC_BUFFERSZ_PERCHAN_B;
|
||||
|
||||
if ( size > maxsize) {
|
||||
printk("[openair][MMAP][ERROR] Trying to map more than %d bytes (req size=%d)\n",
|
||||
(unsigned int)(ADAC_BUFFERSZ_PERCHAN_B), (unsigned int)size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
phys = p_exmimo_pci_phys[card]->adc_head[ openair_mmap_getAntRX(memblock_ind) ];
|
||||
} else {
|
||||
// mmap a TX buffer
|
||||
maxsize = ADAC_BUFFERSZ_PERCHAN_B;
|
||||
|
||||
if ( size > maxsize) {
|
||||
printk("[openair][MMAP][ERROR] Trying to map more than %d bytes (%d)\n",
|
||||
(unsigned int)(ADAC_BUFFERSZ_PERCHAN_B), (unsigned int)size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
phys = p_exmimo_pci_phys[card]->dac_head[ openair_mmap_getAntTX(memblock_ind) ];
|
||||
}
|
||||
|
||||
if (0)
|
||||
printk("[openair][MMAP] card%d: map phys (%08lx) at start %lx, end %lx, pg_off %lx, size %lx\n",
|
||||
card,
|
||||
phys,
|
||||
vma->vm_start,
|
||||
vma->vm_end,
|
||||
vma->vm_pgoff,
|
||||
size);
|
||||
|
||||
/* loop through all the physical pages in the buffer */
|
||||
/* Remember this won't work for vmalloc()d memory ! */
|
||||
if (remap_pfn_range(vma,
|
||||
start,
|
||||
phys>>PAGE_SHIFT,
|
||||
vma->vm_end-vma->vm_start,
|
||||
vma->vm_page_prot)) {
|
||||
printk("[openair][MMAP] ERROR EAGAIN\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
|
||||
long openair_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
#else
|
||||
int openair_device_ioctl(struct inode *inode,struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
#endif
|
||||
{
|
||||
/* arg is not meaningful if no arg is passed in user space */
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int i, c;
|
||||
|
||||
int tmp;
|
||||
|
||||
unsigned int user_args[4];
|
||||
|
||||
static unsigned int update_firmware_command;
|
||||
static unsigned int update_firmware_address;
|
||||
static unsigned int update_firmware_length;
|
||||
static unsigned int* update_firmware_kbuffer;
|
||||
static unsigned int* __user update_firmware_ubuffer;
|
||||
static unsigned int update_firmware_start_address;
|
||||
static unsigned int update_firmware_stack_pointer;
|
||||
static unsigned int update_firmware_bss_address;
|
||||
static unsigned int update_firmware_bss_size;
|
||||
unsigned int *fw_block;
|
||||
unsigned int sparc_tmp_0;
|
||||
unsigned int sparc_tmp_1;
|
||||
static unsigned int lendian_length;
|
||||
|
||||
unsigned int get_frame_cnt=0;
|
||||
|
||||
switch(cmd) {
|
||||
case openair_STOP:
|
||||
|
||||
printk("[openair][IOCTL] openair_STOP(card%d)\n", (int)arg);
|
||||
|
||||
if ( is_card_num_invalid((int)arg) )
|
||||
return -EINVAL;
|
||||
|
||||
exmimo_send_pccmd((int)arg, EXMIMO_STOP);
|
||||
|
||||
break;
|
||||
|
||||
case openair_STOP_WITHOUT_RESET:
|
||||
|
||||
printk("[openair][IOCTL] openair_STOP_WITHOUT_RESET(card%d)\n", (int)arg);
|
||||
|
||||
if ( is_card_num_invalid((int)arg) )
|
||||
return -EINVAL;
|
||||
|
||||
exmimo_send_pccmd((int)arg, EXMIMO_STOP_WITHOUT_RESET);
|
||||
|
||||
break;
|
||||
|
||||
case openair_GET_FRAME:
|
||||
|
||||
get_frame_cnt=0;
|
||||
get_frame_done = 0;
|
||||
printk("[openair][IOCTL] : openair_GET_FRAME: calling exmimo_send_pccmd(%d, EXMIMO_GET_FRAME)\n", (int)arg);
|
||||
|
||||
if ( is_card_num_invalid((int)arg) )
|
||||
return -EINVAL;
|
||||
|
||||
exmimo_send_pccmd((int)arg, EXMIMO_GET_FRAME);
|
||||
|
||||
while (get_frame_cnt<10 && !get_frame_done) {
|
||||
msleep(10);
|
||||
get_frame_cnt++;
|
||||
}
|
||||
|
||||
if (get_frame_cnt==200)
|
||||
printk("[openair][IOCTL] : Get frame error: no IRQ received within 2000ms.\n");
|
||||
|
||||
get_frame_done = 0;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case openair_GET_BIGSHMTOPS_KVIRT:
|
||||
|
||||
//printk("[openair][IOCTL] : openair_GET_BIGSHMTOPS_KVIRT (0x%p)[0] = %p[0] (bigshm_head) for 0..3 (sizeof %d) \n", (void *)arg, bigshm_head[0], sizeof(bigshm_head));
|
||||
copy_to_user((void *)arg, bigshm_head, sizeof(bigshm_head));
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case openair_GET_PCI_INTERFACE_BOTS_KVIRT:
|
||||
|
||||
//printk("[openair][IOCTL] : openair_GET_PCI_INTERFACE_BOTS_KVIRT: copying exmimo_pci_kvirt(@%8p) to %lx (sizeof %d)\n", &exmimo_pci_kvirt[0], arg, sizeof(exmimo_pci_kvirt));
|
||||
copy_to_user((void *)arg, exmimo_pci_kvirt, sizeof(exmimo_pci_kvirt));
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case openair_GET_NUM_DETECTED_CARDS:
|
||||
|
||||
//printk("[openair][IOCTL] : openair_GET_NUM_DETECTED_CARDS: *(0x%p) = %d\n", (void *)arg, number_of_cards);
|
||||
copy_to_user((void *)arg, &number_of_cards, sizeof(number_of_cards));
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case openair_DUMP_CONFIG:
|
||||
|
||||
//printk("[openair][IOCTL] openair_DUMP_CONFIG(%d)\n", (int)arg);
|
||||
if ( is_card_num_invalid((int)arg) ) {
|
||||
printk("[openair][IOCTL] openair_DUMP_CONFIG: Invalid card number %d.\n", (int)arg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
printk("[openair][IOCTL] : openair_DUMP_CONFIG(%d): exmimo_pci_kvirt[%d].exmimo_config_ptr = %p (phys %08x)\n",
|
||||
(int)arg, (int)arg, exmimo_pci_kvirt[(int)arg].exmimo_config_ptr, p_exmimo_pci_phys[(int)arg]->exmimo_config_ptr);
|
||||
|
||||
printk("[openair][IOCTL]: EXMIMO_CONFIG: freq0 %u Hz, freq1 %u Hz, freqtx0 %u Hz, freqtx1 %u Hz, \nRX gain0 %d dB, RX Gain1 %d dB, autocal (%d,%d,%d,%d)\n",
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rf_freq_rx[0],
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rf_freq_rx[1],
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rf_freq_tx[0],
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rf_freq_tx[1],
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rx_gain[0][0],
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rx_gain[1][0],
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.do_autocal[0],
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.do_autocal[1],
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.do_autocal[2],
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.do_autocal[3]);
|
||||
|
||||
|
||||
exmimo_send_pccmd((int)arg, EXMIMO_CONFIG);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case openair_START_RT_ACQUISITION:
|
||||
|
||||
printk("[openair][IOCTL] openair_START_TX_SIG(%d): send_pccmd(EXMIMO_START_RT_ACQUISITION).\n", (int) arg);
|
||||
|
||||
if ( is_card_num_invalid((int)arg) )
|
||||
return -EINVAL;
|
||||
|
||||
exmimo_send_pccmd((int)arg, EXMIMO_START_RT_ACQUISITION);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case openair_UPDATE_FIRMWARE:
|
||||
|
||||
printk("[openair][IOCTL] openair_UPDATE_FIRMWARE\n");
|
||||
/***************************************************
|
||||
* Updating the firmware of Cardbus-MIMO-1 or ExpressMIMO SoC *
|
||||
***************************************************/
|
||||
/* 1st argument of this ioctl indicates the action to perform among these:
|
||||
- Transfer a block of data at a specified address (given as the 2nd argument)
|
||||
and for a specified length (given as the 3rd argument, in number of 32-bit words).
|
||||
The USER-SPACE address where to find the block of data is given as the 4th
|
||||
argument.
|
||||
- Ask the Leon processor to clear the .bss section. In this case, the base
|
||||
address of section .bss is given as the 2nd argument, and its size is
|
||||
given as the 3rd one.
|
||||
- Ask the Leon processor to jump at a specified address (given as the 2nd
|
||||
argument, most oftenly expected to be the top address of Ins, Scratch Pad
|
||||
Ram), after having set the stack pointer (given as the 3rd argument).
|
||||
For the openair_UPDATE_FIRMWARE ioctl, we perform a partial infinite loop
|
||||
while acknowledging the PCI irq from Leon software: the max number of loop
|
||||
is yielded by preprocessor constant MAX_IOCTL_ACK_CNT. This avoids handing
|
||||
the kernel with an infinite polling loop. An exception is the case of clearing
|
||||
the bss: it takes time to Leon3 to perform this operation, so we poll te
|
||||
acknowledge with no limit */
|
||||
|
||||
#define MAX_IOCTL_ACK_CNT 500
|
||||
|
||||
/* 'arg' is an unsigned long and is supposed to be big enough
|
||||
* to hold an address - this hypothesis is okay for i386 and x86_64
|
||||
* maybe not somewhere else
|
||||
* this will probably fail with older kernels
|
||||
* (works with 3.17 on x86_64)
|
||||
*/
|
||||
tmp = copy_from_user(&user_args, (void*)arg, 4*sizeof(unsigned int));
|
||||
if (tmp) {
|
||||
printk("[openair][IOCTL] UPDATE_FIRMWARE: error copying parameters to kernel-space (%d bytes uncopied).\n", tmp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
update_firmware_command = user_args[0];
|
||||
|
||||
switch (update_firmware_command) {
|
||||
case UPDATE_FIRMWARE_TRANSFER_BLOCK:
|
||||
update_firmware_address = user_args[1];
|
||||
update_firmware_length = user_args[2];
|
||||
|
||||
/* This is totally wrong on x86_64: a pointer is 64 bits and
|
||||
* unsigned int is 32 bits. The userspace program has to ensure
|
||||
* that its buffer address fits into 32 bits.
|
||||
* If it proves a too strong requirement, we may change things
|
||||
* in the future.
|
||||
* The compiler emits a warning here. Do not remove this warning!
|
||||
* This is to clearly remember this problem.
|
||||
* If you require the compilation to work with zero warning,
|
||||
* consider this one as an exception and find a proper workaround.
|
||||
*/
|
||||
update_firmware_ubuffer = user_args[3];
|
||||
|
||||
update_firmware_kbuffer = (unsigned int*)kmalloc(update_firmware_length * 4 /* 4 because kmalloc expects bytes */,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!update_firmware_kbuffer) {
|
||||
printk("[openair][IOCTL] Could NOT allocate %u bytes from kernel memory (kmalloc failed).\n", lendian_length * 4);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
// update all cards at the same time
|
||||
for (c=0; c<number_of_cards; c++) {
|
||||
fw_block = (unsigned int *)exmimo_pci_kvirt[c].firmware_block_ptr;
|
||||
/* Copy the data block from user space */
|
||||
fw_block[0] = update_firmware_address;
|
||||
fw_block[1] = update_firmware_length;
|
||||
//printk("copy_from_user %p => %p (pci) => fw[0]=fw_addr=%08x (ahb), fw[1]=fw_length=%d DW\n",update_firmware_ubuffer,&fw_block[16],update_firmware_address,update_firmware_length);
|
||||
tmp = copy_from_user(update_firmware_kbuffer,
|
||||
update_firmware_ubuffer, /* from */
|
||||
update_firmware_length * 4 /* in bytes */
|
||||
);
|
||||
|
||||
if (tmp) {
|
||||
printk("[openair][IOCTL] Could NOT copy all data from user-space to kernel-space (%d bytes remained uncopied).\n", tmp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// pci_map_single(pdev[0],(void*)fw_block, update_firmware_length*4,PCI_DMA_BIDIRECTIONAL);
|
||||
for (i=0; i<update_firmware_length; i++) {
|
||||
fw_block[32+i] = ((unsigned int *)update_firmware_kbuffer)[i];
|
||||
// Endian flipping is done in user-space so undo it
|
||||
invert4(fw_block[32+i]);
|
||||
}
|
||||
|
||||
exmimo_send_pccmd(c, EXMIMO_FW_INIT);
|
||||
printk("[openair][IOCTL] card%d: ok %u DW copied to address 0x%08x (fw_block_ptr %p)\n",
|
||||
c, fw_block[1], fw_block[0],fw_block);
|
||||
}
|
||||
|
||||
kfree(update_firmware_kbuffer);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
for (i=0; i<update_firmware_length;i++) {
|
||||
printk("%08x ", fw_block[32+i]);
|
||||
if ((i % 8) == 7)
|
||||
printk("\n");
|
||||
}*/
|
||||
|
||||
break;
|
||||
|
||||
case UPDATE_FIRMWARE_CLEAR_BSS:
|
||||
|
||||
update_firmware_bss_address = user_args[1];
|
||||
update_firmware_bss_size = user_args[2];
|
||||
sparc_tmp_0 = update_firmware_bss_address;
|
||||
sparc_tmp_1 = update_firmware_bss_size;
|
||||
|
||||
printk("[openair][IOCTL] ok asked Leon to clear .bss (addr 0x%08x, size %d bytes)\n", sparc_tmp_0, sparc_tmp_1);
|
||||
|
||||
// update all cards at the same time
|
||||
for (c=0; c<number_of_cards; c++) {
|
||||
fw_block = (unsigned int *)exmimo_pci_kvirt[c].firmware_block_ptr;
|
||||
fw_block[0] = update_firmware_bss_address;
|
||||
fw_block[1] = update_firmware_bss_size;
|
||||
|
||||
exmimo_send_pccmd(c, EXMIMO_FW_CLEAR_BSS);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case UPDATE_FIRMWARE_START_EXECUTION:
|
||||
|
||||
update_firmware_start_address = user_args[1];
|
||||
update_firmware_stack_pointer = user_args[2];
|
||||
sparc_tmp_0 = update_firmware_start_address;
|
||||
sparc_tmp_1 = update_firmware_stack_pointer;
|
||||
|
||||
printk("[openair][IOCTL] ok asked Leon to set stack and start execution (addr 0x%08x, stackptr %08x)\n", sparc_tmp_0, sparc_tmp_1);
|
||||
|
||||
for (c=0; c<number_of_cards; c++) {
|
||||
fw_block = (unsigned int *)exmimo_pci_kvirt[c].firmware_block_ptr;
|
||||
fw_block[0] = update_firmware_start_address;
|
||||
fw_block[1] = update_firmware_stack_pointer;
|
||||
|
||||
exmimo_send_pccmd(c, EXMIMO_FW_START_EXEC);
|
||||
msleep(10);
|
||||
exmimo_firmware_init(c);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case UPDATE_FIRMWARE_FORCE_REBOOT:
|
||||
|
||||
printk("[openair][IOCTL] ok asked Leon to reboot.\n");
|
||||
|
||||
for (c=0; c<number_of_cards; c++) {
|
||||
exmimo_send_pccmd(c, EXMIMO_REBOOT);
|
||||
|
||||
exmimo_firmware_init(c);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case UPDATE_FIRMWARE_TEST_GOK:
|
||||
printk("[openair][IOCTL] TEST_GOK command doesn't work with ExpressMIMO. Ignored.\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
//----------------------
|
||||
printk("[IOCTL] openair_IOCTL unknown: basecmd = %i (cmd=%X)\n", _IOC_NR(cmd), cmd );
|
||||
return -EPERM;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** irq.c
|
||||
- IRQ Handler: IRQ from Leon to PCIe/Kernel: exmimo_irq_handler
|
||||
- sends received packets to userspace
|
||||
|
||||
- send command from PC to Leon and trigger IRQ on Leon using CONTROL1 register
|
||||
- commands are defined in $OPENAIR0/express-mimo/software/pcie_interface.h
|
||||
|
||||
- added: pass card_id as parameter to tasklet and irq handler
|
||||
|
||||
Authors:
|
||||
Raymond Knopp <raymond.knopp@eurecom.fr>
|
||||
Matthias Ihmig <matthias.ihmig@mytum.de>, 2011, 2013
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/swab.h>
|
||||
|
||||
#include "openair_device.h"
|
||||
#include "extern.h"
|
||||
|
||||
unsigned int openair_bh_cnt;
|
||||
|
||||
int get_frame_done = 0;
|
||||
|
||||
void pcie_printk(int card_id);
|
||||
|
||||
void openair_do_tasklet (unsigned long card_id);
|
||||
DECLARE_TASKLET (openair_tasklet, openair_do_tasklet, 0);
|
||||
|
||||
irqreturn_t openair_irq_handler(int irq, void *cookie)
|
||||
{
|
||||
unsigned int irqval;
|
||||
unsigned int irqcmd = EXMIMO_NOP;
|
||||
unsigned long card_id; // = (unsigned long) cookie;
|
||||
unsigned int pcie_control = PCIE_CONTROL2;
|
||||
|
||||
// check interrupt status register
|
||||
//pci_read_config_word(pdev[0],6 , &irqval);
|
||||
|
||||
// find card_id. cookie is set by request_irq and static, so we will always find it
|
||||
for (card_id=0; card_id<MAX_CARDS; card_id++)
|
||||
if ( pdev[card_id] == cookie )
|
||||
break;
|
||||
|
||||
if (exmimo_pci_kvirt[card_id].exmimo_id_ptr->board_swrev == BOARD_SWREV_LEGACY)
|
||||
pcie_control = PCIE_CONTROL1;
|
||||
else
|
||||
pcie_control = PCIE_CONTROL2;
|
||||
|
||||
//printk("irq hndl called: card_id=%i, irqval=%i\n", card_id, irqval);
|
||||
|
||||
// get AHBPCIE interrupt line (bit 7) to determine if IRQ was for us from ExMIMO card, or from a different device
|
||||
// reading CONTROL0 will also clear this bit and the LEON-to-PC IRQ line
|
||||
irqval = ioread32(bar[card_id]+PCIE_CONTROL0);
|
||||
|
||||
irqcmd = ioread32(bar[card_id]+pcie_control);
|
||||
//printk("IRQ handler: ctrl0: %08x, ctrl1: %08x, ctrl2: %08x, status: %08x\n", irqval, ioread32(bar[card_id]+PCIE_CONTROL1), ioread32(bar[card_id]+PCIE_CONTROL2), ioread32(bar[card_id]+PCIE_STATUS));
|
||||
|
||||
if ( (irqval & 0x80) == 0 ) { // CTRL0.bit7 is no set -> IRQ is not from ExMIMO i.e. not for us
|
||||
if (exmimo_pci_kvirt[card_id].exmimo_id_ptr->board_swrev == BOARD_SWREV_CMDREGISTERS) {
|
||||
if (irqcmd != EXMIMO_NOP && irqcmd != EXMIMO_CONTROL2_COOKIE) {
|
||||
if (irqcmd == GET_FRAME_DONE) {
|
||||
get_frame_done = 1;
|
||||
}
|
||||
|
||||
openair_tasklet.data = card_id;
|
||||
tasklet_schedule(&openair_tasklet);
|
||||
openair_bh_cnt++;
|
||||
return IRQ_HANDLED;
|
||||
} else {
|
||||
return IRQ_NONE;
|
||||
}
|
||||
} else
|
||||
return IRQ_NONE;
|
||||
} else {
|
||||
if (exmimo_pci_kvirt[card_id].exmimo_id_ptr->board_swrev == BOARD_SWREV_LEGACY) {
|
||||
// clear PCIE interrupt (bit 7 of register 0x0)
|
||||
iowrite32(irqval&0xffffff7f,bar[card_id]+PCIE_CONTROL0);
|
||||
}
|
||||
|
||||
if (irqcmd == GET_FRAME_DONE) {
|
||||
get_frame_done = 1;
|
||||
}
|
||||
|
||||
openair_tasklet.data = card_id;
|
||||
tasklet_schedule(&openair_tasklet);
|
||||
openair_bh_cnt++;
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
void openair_do_tasklet (unsigned long card_id)
|
||||
{
|
||||
int save_irq_cnt = openair_bh_cnt;
|
||||
unsigned int irqcmd;
|
||||
unsigned int pcie_control = PCIE_CONTROL2;
|
||||
openair_bh_cnt = 0;
|
||||
|
||||
if (exmimo_pci_kvirt[card_id].exmimo_id_ptr->board_swrev == BOARD_SWREV_LEGACY)
|
||||
pcie_control = PCIE_CONTROL1;
|
||||
else
|
||||
pcie_control = PCIE_CONTROL2;
|
||||
|
||||
irqcmd = ioread32(bar[card_id]+pcie_control);
|
||||
|
||||
if (save_irq_cnt > 1)
|
||||
printk("[openair][IRQ tasklet(%ld)]: Warning: received more than 1 PCIE IRQ (openair_bh_cnt=%i), only the last one is acted upon(irqcmd= %i (0x%X)\n", card_id, openair_bh_cnt, irqcmd, irqcmd);
|
||||
|
||||
switch( irqcmd ) {
|
||||
case PCI_PRINTK:
|
||||
// printk("Got PCIe interrupt for printk ...\n");
|
||||
pcie_printk((int) card_id);
|
||||
break;
|
||||
|
||||
case GET_FRAME_DONE:
|
||||
printk("[openair][IRQ tasklet] : Got PCIe interrupt for GET_FRAME_DONE ...\n");
|
||||
break;
|
||||
|
||||
case EXMIMO_NOP:
|
||||
printk("[openair][IRQ tasklet] : Received IRQ, with CONTROL0.bit7(IRQ Leon2PC) set, but irqcmd = EXMIMO_NOP. This should not happen with bitstreams built after June 3rd 2013.\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("[openair][IRQ tasklet] : Got unknown PCIe cmd: card_id = %li, irqcmd(CONTROL1) = %i (0x%X)\n", card_id, irqcmd, irqcmd);
|
||||
}
|
||||
|
||||
iowrite32(EXMIMO_NOP, bar[card_id]+pcie_control);
|
||||
}
|
||||
|
||||
void pcie_printk(int card_id)
|
||||
{
|
||||
char *buffer = exmimo_pci_kvirt[card_id].printk_buffer_ptr;
|
||||
unsigned int len = ((unsigned int *)buffer)[0];
|
||||
unsigned int off=0,i;
|
||||
unsigned char *dword;
|
||||
unsigned char tmp;
|
||||
|
||||
//printk("In pci_fifo_printk : buffer %p, len %d: \n",buffer,len);
|
||||
printk("[LEON card%d]: ", card_id);
|
||||
|
||||
if (len<1024) {
|
||||
if ( (len&3) >0 )
|
||||
off=1;
|
||||
|
||||
for (i=0; i<(off+(len>>2)); i++) {
|
||||
dword = &((unsigned char *)buffer)[(1+i)<<2];
|
||||
tmp = dword[3];
|
||||
dword[3] = dword[0];
|
||||
dword[0] = tmp;
|
||||
tmp = dword[2];
|
||||
dword[2] = dword[1];
|
||||
dword[1] = tmp;
|
||||
}
|
||||
|
||||
for (i=0; i<len; i++)
|
||||
printk("%c",((char*)&buffer[4])[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,356 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** module_main.c (was: device.c)
|
||||
*
|
||||
* Main Kernel module functions for load/init and cleanup of the kernel driver
|
||||
*
|
||||
* Supports multiple ExpressMIMO cards
|
||||
*
|
||||
* Authors: Matthias Ihmig <matthias.ihmig@mytum.de>, 2012, 2013
|
||||
* Riadh Ghaddab <riadh.ghaddab@eurecom.fr>
|
||||
* Raymond Knopp <raymond.knopp@eurecom.fr>
|
||||
*
|
||||
* Changelog:
|
||||
* 14.01.2013: removed remaining of BIGPHYS stuff and replaced with pci_alloc_consistent
|
||||
* 20.01.2013: added support for multiple cards
|
||||
* 24.01.2013: restructured interfaces & structures of how physical and virtual pointers are handled
|
||||
*/
|
||||
|
||||
#include "openair_device.h"
|
||||
#include "defs.h"
|
||||
#include "vars.h"
|
||||
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/aer.h>
|
||||
#include <linux/pci_regs.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
static void openair_cleanup(void);
|
||||
|
||||
extern irqreturn_t openair_irq_handler(int irq, void *cookie);
|
||||
|
||||
static int irq = 0;
|
||||
module_param(irq,int,S_IRUSR|S_IWUSR);
|
||||
|
||||
|
||||
static struct file_operations openair_fops = {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
|
||||
unlocked_ioctl:openair_device_ioctl,
|
||||
#else
|
||||
ioctl: openair_device_ioctl,
|
||||
#endif
|
||||
open: openair_device_open,
|
||||
release:openair_device_release,
|
||||
mmap: openair_device_mmap
|
||||
};
|
||||
|
||||
static int __init openair_init_module( void )
|
||||
{
|
||||
int res = 0;
|
||||
unsigned int readback;
|
||||
unsigned int card, j;
|
||||
unsigned int vid,did;
|
||||
unsigned int val;
|
||||
unsigned short vendor, subid;
|
||||
exmimo_id_t exmimo_id_tmp[MAX_CARDS];
|
||||
|
||||
//------------------------------------------------
|
||||
// Find and enable ExpressMIMO PCI cards
|
||||
//------------------------------------------------
|
||||
//
|
||||
card = 0;
|
||||
|
||||
pdev[card] = pci_get_device(XILINX_VENDOR, XILINX_ID, NULL);
|
||||
|
||||
if( pdev[card] ) {
|
||||
// This print does not work for 64 bit kernels
|
||||
// printk("[openair][INIT_MODULE][INFO]: openair card (ExpressMIMO) %d found, bus 0x%x, primary 0x%x, secondary 0x%x\n",card,
|
||||
// pdev[card]->bus->number, pdev[card]->bus->primary,pdev[card]->bus->secondary);
|
||||
|
||||
pci_read_config_word(pdev[card], PCI_SUBSYSTEM_ID, &subid);
|
||||
pci_read_config_word(pdev[card], PCI_SUBSYSTEM_VENDOR_ID, &vendor);
|
||||
exmimo_id_tmp[card].board_vendor = vendor;
|
||||
|
||||
if ( exmimo_id_tmp[card].board_vendor == XILINX_VENDOR )
|
||||
exmimo_id_tmp[card].board_vendor = EURECOM_VENDOR; // set default to EURECOM
|
||||
|
||||
exmimo_id_tmp[card].board_exmimoversion = (subid >> 12) & 0x0F;
|
||||
|
||||
if (exmimo_id_tmp[card].board_exmimoversion == 0)
|
||||
exmimo_id_tmp[card].board_exmimoversion = 1; // default (for old bitstreams) is ExpressMIMO-1
|
||||
|
||||
exmimo_id_tmp[card].board_hwrev = (subid >> 8) & 0x0F;
|
||||
exmimo_id_tmp[card].board_swrev = (subid ) & 0xFF;
|
||||
|
||||
printk("[openair][INIT_MODULE][INFO]: card %d: ExpressMIMO-%i (HW Rev %i), Bitstream: %s, SW/Protocol Revision: 0x%02X\n", card,
|
||||
exmimo_id_tmp[card].board_exmimoversion, exmimo_id_tmp[card].board_hwrev, ( (exmimo_id_tmp[card].board_vendor == EURECOM_VENDOR) ? "Eurecom" : "Telecom Paristech"), exmimo_id_tmp[card].board_swrev );
|
||||
|
||||
card++;
|
||||
vid = XILINX_VENDOR;
|
||||
did = XILINX_ID;
|
||||
} else {
|
||||
printk("[openair][INIT_MODULE][INFO]: no card found, stopping.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
// Now look for more cards on the same bus
|
||||
while (card<MAX_CARDS) {
|
||||
pdev[card] = pci_get_device(vid,did, pdev[card-1]);
|
||||
|
||||
if(pdev[card]) {
|
||||
// This print does not work for 64 bit kernels
|
||||
// printk("[openair][INIT_MODULE][INFO]: openair card %d found, bus 0x%x, primary 0x%x, secondary 0x%x\n",card,
|
||||
// pdev[card]->bus->number,pdev[card]->bus->primary,pdev[card]->bus->secondary);
|
||||
|
||||
|
||||
pci_read_config_word(pdev[card], PCI_SUBSYSTEM_ID, &subid);
|
||||
pci_read_config_word(pdev[card], PCI_SUBSYSTEM_VENDOR_ID, &vendor);
|
||||
exmimo_id_tmp[card].board_vendor = vendor;
|
||||
|
||||
if ( exmimo_id_tmp[card].board_vendor == XILINX_VENDOR )
|
||||
exmimo_id_tmp[card].board_vendor = EURECOM_VENDOR; // default (for old bitstreams) is EURECOM_VENDOR
|
||||
|
||||
exmimo_id_tmp[card].board_exmimoversion = (subid >> 12) & 0x0F;
|
||||
|
||||
if (exmimo_id_tmp[card].board_exmimoversion == 0)
|
||||
exmimo_id_tmp[card].board_exmimoversion = 1; // default (for old bitstreams) is ExpressMIMO-1
|
||||
|
||||
exmimo_id_tmp[card].board_hwrev = (subid >> 8) & 0x0F;
|
||||
exmimo_id_tmp[card].board_swrev = (subid ) & 0xFF;
|
||||
printk("[openair][INIT_MODULE][INFO]: card %d: ExpressMIMO-%i (HW Rev %i), Bitstream: %s, SW/Protocol Revision: 0x%02X\n", card,
|
||||
exmimo_id_tmp[card].board_exmimoversion, exmimo_id_tmp[card].board_hwrev, ( (exmimo_id_tmp[card].board_vendor == EURECOM_VENDOR) ? "Eurecom" : "Telecom Paristech"), exmimo_id_tmp[card].board_swrev );
|
||||
|
||||
card++;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
// at least one device found, enable it
|
||||
number_of_cards = card;
|
||||
|
||||
for (card=0; card<number_of_cards; card++) {
|
||||
if( pci_enable_device(pdev[card]) ) {
|
||||
printk("[openair][INIT_MODULE][INFO]: Could not enable PCI card device %d\n",card);
|
||||
openair_cleanup();
|
||||
return -ENODEV;
|
||||
} else {
|
||||
printk("[openair][INIT_MODULE][INFO]: *** CARD DEVICE %d (pdev=%p) ENABLED, irq %d\n",card,pdev[card],irq);
|
||||
printk("[openair][INIT_MODULE][INFO]: *** CARD DEVICE %d (pdev=%p) ENABLED, irq %d\n",card,pdev[card],pdev[card]->irq);
|
||||
openair_pci_device_enabled[card] = 1;
|
||||
}
|
||||
|
||||
// Make the FPGA to a PCI master
|
||||
pci_set_master(pdev[card]);
|
||||
|
||||
// set DMA mask
|
||||
if (!pci_set_dma_mask(pdev[card], DMA_BIT_MASK(32))) {
|
||||
if (pci_set_consistent_dma_mask(pdev[card], DMA_BIT_MASK(32))) {
|
||||
printk(KERN_INFO "[openair][INIT_MODULE]: Unable to obtain 32bit DMA for consistent allocations\n");
|
||||
openair_cleanup();
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
//if (pci_enable_pcie_error_reporting(pdev[card]) > 0)
|
||||
// printk("[openair][INIT_MODULE][INFO]: Enabled PCIe error reporting\n");
|
||||
//else
|
||||
// printk("[openair][INIT_MODULE][INFO]: Failed to enable PCIe error reporting\n");
|
||||
|
||||
//pci_cleanup_aer_uncorrect_error_status(pdev[card]);
|
||||
|
||||
mmio_start[card] = pci_resource_start(pdev[card], 0); // get start of BAR0
|
||||
mmio_length[card] = pci_resource_len (pdev[card], 0);
|
||||
mmio_flags[card] = pci_resource_flags(pdev[card], 0);
|
||||
|
||||
if (request_mem_region(mmio_start[card],256,"openair_rf") == NULL) {
|
||||
printk("[openair][INIT_MODULE][FATAL] : Cannot get memory region 0, aborting\n");
|
||||
mmio_start[card] = 0;
|
||||
openair_cleanup();
|
||||
return -EBUSY;
|
||||
} else
|
||||
printk("[openair][INIT_MODULE][INFO] : Reserved memory region 0 : mmio_start = 0x%x\n",(unsigned int)mmio_start[card]);
|
||||
|
||||
bar[card] = pci_iomap( pdev[card], 0, mmio_length[card] ); // get virtual kernel address for BAR0
|
||||
|
||||
printk("[openair][INIT_MODULE][INFO]: BAR0 card %d = 0x%p\n", card, bar[card]);
|
||||
|
||||
printk("[openair][INIT_MODULE][INFO]: Writing 0x%x to BAR0+0x1c (PCIBASEL)\n", 0x12345678);
|
||||
|
||||
iowrite32( 0x12345678, (bar[card]+PCIE_PCIBASEL) );
|
||||
udelay(100);
|
||||
readback = ioread32( bar[card]+PCIE_PCIBASEL );
|
||||
|
||||
if (readback != 0x12345678) {
|
||||
printk("[openair][INIT_MODULE][INFO]: Readback of FPGA register failed (%x)\n",readback);
|
||||
openair_cleanup();
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
iowrite32((1<<8), bar[card] +PCIE_CONTROL0 ); // bit8=AHBPCIE_CTL0_SOFTRESET, but what is bit9 and bit10?
|
||||
udelay(1000);
|
||||
readback = ioread32( bar[card] +PCIE_CONTROL0);
|
||||
printk("CONTROL0 readback %x\n",readback);
|
||||
|
||||
// This is for displaying the card number in the leds of the exmimo card
|
||||
val = ioread32(bar[card]+PCIE_CONTROL0);
|
||||
iowrite32(val| ((card & 0x1F) << 9),bar[card]+PCIE_CONTROL0);
|
||||
//val = ioread32(bar[card]+PCIE_CONTROL0);
|
||||
//printk("[openair][INIT_MODULE][INFO]: writing leds for card %d control0 %x\n",card,val);
|
||||
|
||||
// allocating buffers
|
||||
if ( exmimo_memory_alloc( card ) ) {
|
||||
printk("[openair][MODULE][ERROR] exmimo_memory_alloc() failed!\n");
|
||||
openair_cleanup();
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
exmimo_pci_kvirt[card].exmimo_id_ptr->board_vendor = exmimo_id_tmp[card].board_vendor;
|
||||
exmimo_pci_kvirt[card].exmimo_id_ptr->board_exmimoversion = exmimo_id_tmp[card].board_exmimoversion;
|
||||
exmimo_pci_kvirt[card].exmimo_id_ptr->board_hwrev = exmimo_id_tmp[card].board_hwrev;
|
||||
exmimo_pci_kvirt[card].exmimo_id_ptr->board_swrev = exmimo_id_tmp[card].board_swrev;
|
||||
|
||||
if (irq!=0)
|
||||
printk("[OPENAIR][SCHED][INIT] card %d: Trying to get IRQ %d\n", card,irq);
|
||||
else
|
||||
printk("[OPENAIR][SCHED][INIT] card %d: Trying to get IRQ %d\n", card, pdev[card]->irq);
|
||||
|
||||
openair_irq_enabled[card] = 0;
|
||||
|
||||
// #ifdef CONFIG_PREEMPT_RT doesn't work -> fix misconfigured header files?
|
||||
#if 1
|
||||
|
||||
if (irq!=0) {
|
||||
if ( (res = request_irq(irq, openair_irq_handler,
|
||||
IRQF_SHARED , "openair_rf", pdev[card] )) == 0) {
|
||||
openair_irq_enabled[card] = 1;
|
||||
} else {
|
||||
printk("[EXMIMO][SCHED][INIT] Cannot get IRQ %d for HW, error: %d\n", irq, res);
|
||||
openair_cleanup();
|
||||
return -EBUSY;
|
||||
}
|
||||
} else {
|
||||
if ( (res = request_irq(pdev[card]->irq, openair_irq_handler,
|
||||
IRQF_SHARED , "openair_rf", pdev[card] )) == 0) {
|
||||
openair_irq_enabled[card] = 1;
|
||||
} else {
|
||||
printk("[EXMIMO][SCHED][INIT] Cannot get IRQ %d for HW, error: %d\n", pdev[card]->irq, res);
|
||||
openair_cleanup();
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
printk("Warning: didn't request IRQ for PREEMPT_REALTIME\n");
|
||||
#endif
|
||||
|
||||
} // for (i=0; i<number_of_cards; i++)
|
||||
|
||||
//------------------------------------------------
|
||||
// Register the device in /dev
|
||||
//------------------------------------------------
|
||||
//
|
||||
major = openair_MAJOR;
|
||||
|
||||
if( (res = register_chrdev(major, "openair", &openair_fops )) < 0) {
|
||||
printk("[openair][INIT_MODULE][ERROR]: can't register char device driver, major : %d, error: %d\n", major, res);
|
||||
|
||||
for (j=0; j<=number_of_cards; j++)
|
||||
release_mem_region(mmio_start[j],256);
|
||||
|
||||
return -EBUSY;
|
||||
} else {
|
||||
printk("[openair][INIT_MODULE][INFO]: char device driver registered major : %d\n", major);
|
||||
openair_chrdev_registered = 1;
|
||||
}
|
||||
|
||||
printk("[openair][MODULE][INFO] Initializing Leon (EXMIMO_PCIE_INIT) on all cards...\n");
|
||||
|
||||
for (card=0; card<number_of_cards; card++)
|
||||
exmimo_firmware_init( card );
|
||||
|
||||
printk("[openair][MODULE][INFO] Done module init\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void __exit openair_cleanup_module(void)
|
||||
{
|
||||
//int card;
|
||||
printk("[openair][CLEANUP MODULE]\n");
|
||||
|
||||
// stop any ongoing acquisition
|
||||
//for (card = 0; card < number_of_cards; card++)
|
||||
// exmimo_send_pccmd(card, EXMIMO_STOP);
|
||||
|
||||
openair_cleanup();
|
||||
}
|
||||
|
||||
static void openair_cleanup(void)
|
||||
{
|
||||
int card;
|
||||
|
||||
if ( openair_chrdev_registered )
|
||||
unregister_chrdev(major,"openair");
|
||||
|
||||
openair_chrdev_registered = 0;
|
||||
|
||||
for (card=0; card<number_of_cards; card++) {
|
||||
// unregister interrupt
|
||||
if ( openair_irq_enabled[card] ) {
|
||||
printk("[openair][CLEANUP] disabling interrupt card %d\n", card);
|
||||
|
||||
if (irq!=0)
|
||||
free_irq(irq, pdev[card] );
|
||||
else
|
||||
free_irq( pdev[card]->irq, pdev[card] );
|
||||
|
||||
openair_irq_enabled[card] = 0;
|
||||
}
|
||||
|
||||
exmimo_firmware_cleanup( card );
|
||||
|
||||
if ( bar[card] ) {
|
||||
printk("unmap bar[%d] %p\n", card, bar[card]);
|
||||
iounmap((void *)bar[card]);
|
||||
}
|
||||
|
||||
if ( mmio_start[card] ) {
|
||||
printk("release mem[%d] %x\n", card, (unsigned int)mmio_start[card]);
|
||||
release_mem_region(mmio_start[card],256);
|
||||
}
|
||||
|
||||
if ( openair_pci_device_enabled[card] ) {
|
||||
printk("pci_disable_device %i\n", card);
|
||||
pci_disable_device( pdev[card] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MODULE_AUTHOR ("Raymond KNOPP <raymond.knopp@eurecom.fr>, Matthias IHMIG <matthias.ihmig@eurecom.fr>, Florian KALTENBERGER <florian.kaltenberger@eurecom.fr>");
|
||||
MODULE_DESCRIPTION ("openair ExpressMIMO/ExpressMIMO2 driver");
|
||||
MODULE_LICENSE ("GPL");
|
||||
module_init (openair_init_module);
|
||||
module_exit (openair_cleanup_module);
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef __VARS_H__
|
||||
#define __VARS_H__
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#ifdef KERNEL2_6
|
||||
#include <linux/slab.h>
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
#include "pcie_interface.h"
|
||||
|
||||
unsigned int openair_irq_enabled[MAX_CARDS] = INIT_ZEROS;
|
||||
unsigned int openair_chrdev_registered = 0;
|
||||
unsigned int openair_pci_device_enabled[MAX_CARDS] = INIT_ZEROS;
|
||||
|
||||
struct pci_dev *pdev[MAX_CARDS] = INIT_ZEROS;
|
||||
void __iomem *bar[MAX_CARDS] = INIT_ZEROS;
|
||||
|
||||
resource_size_t mmio_start[MAX_CARDS] = INIT_ZEROS;
|
||||
resource_size_t mmio_length[MAX_CARDS];
|
||||
unsigned int mmio_flags[MAX_CARDS];
|
||||
|
||||
int major;
|
||||
|
||||
char number_of_cards;
|
||||
|
||||
// bigshm allocs a single larger block, used for shared structures and pointers
|
||||
dma_addr_t bigshm_head_phys[MAX_CARDS] = INIT_ZEROS;
|
||||
void *bigshm_head[MAX_CARDS] = INIT_ZEROS;
|
||||
void *bigshm_currentptr[MAX_CARDS];
|
||||
|
||||
dma_addr_t pphys_exmimo_pci_phys[MAX_CARDS]; // phys pointer to pci_bot structure in shared mem
|
||||
|
||||
exmimo_pci_interface_bot_t *p_exmimo_pci_phys[MAX_CARDS] = INIT_ZEROS; // inside struct has physical (DMA) pointers to pci_bot memory blocks
|
||||
|
||||
exmimo_pci_interface_bot_virtual_t exmimo_pci_kvirt[MAX_CARDS]; // has virtual pointers to pci_bot memory blocks
|
||||
|
||||
#endif
|
||||
@@ -1,20 +0,0 @@
|
||||
CCC = gcc
|
||||
include $(OPENAIR_DIR)/common/utils/Makefile.inc
|
||||
KERNEL_MAIN_TYPE=$(shell echo `uname -r | cut -d. -f-2 | tr "." "_"`)
|
||||
export KERNEL_MAIN_TYPE
|
||||
|
||||
EXTRA_CFLAGS = -ggdb -D__KERNEL__ -DMODULE -D_LOOSE_KERNEL_NAMES -I$(KERNEL_DIR)/build/include -I$(KERNEL_DIR)/build/include/asm/mach-default -include $(KERNEL_DIR)/build/include/linux/autoconf.h
|
||||
|
||||
EXTRA_CFLAGS += -I$(PWD)/../../DEFS
|
||||
|
||||
obj-m += openair_rf.o
|
||||
|
||||
openair_rf-objs += module_main.o irq.o fileops.o exmimo_fw.o
|
||||
|
||||
all:
|
||||
make -C $(KERNEL_DIR)/build M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
rm -rf *.o
|
||||
make -C $(KERNEL_DIR)/build M=$(PWD) clean
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
echo "Hint: this may not work if /usr/src/linux is not set to currently booted kernel."
|
||||
echo "Try 'make' instead."
|
||||
|
||||
make -C /usr/src/linux V=1 M=`pwd`
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef __DEFS_H__
|
||||
#define __DEFS_H__
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/delay.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
//#include <linux/config.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#include <linux/errno.h>
|
||||
|
||||
#ifdef KERNEL2_6
|
||||
#include <linux/slab.h>
|
||||
#endif
|
||||
|
||||
#include "openair_device.h"
|
||||
|
||||
#include "linux/moduleparam.h"
|
||||
|
||||
|
||||
/*------------------------------------------------*/
|
||||
/* Prototypes */
|
||||
/*------------------------------------------------*/
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
|
||||
long openair_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
||||
#else
|
||||
int openair_device_ioctl(struct inode *inode,struct file *filp, unsigned int cmd, unsigned long arg);
|
||||
#endif
|
||||
int openair_device_open (struct inode *inode,struct file *filp);
|
||||
int openair_device_release (struct inode *inode,struct file *filp);
|
||||
int openair_device_mmap (struct file *filp, struct vm_area_struct *vma);
|
||||
|
||||
int exmimo_memory_alloc(int card);
|
||||
int exmimo_firmware_init(int card);
|
||||
int exmimo_firmware_cleanup(int card_id);
|
||||
|
||||
int exmimo_send_pccmd(int card_id, unsigned int cmd);
|
||||
|
||||
#endif
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Re-Enumerate FPGA card
|
||||
|
||||
# After resetting or powering up the card or after reloading the FPGA bitstream,
|
||||
# run this script to re-enumerate the PCIe device in Linux.
|
||||
|
||||
# You may need to change the device path. Check lspci output for this.
|
||||
|
||||
# You need to run this as root:
|
||||
# sudo ./do_reenumerate_expressmimo.sh
|
||||
|
||||
# Matthias <ihmig@eurecom.fr>, 2013
|
||||
|
||||
rmmod openair_rf
|
||||
echo 1 > /sys/bus/pci/devices/0000\:01\:00.0/remove
|
||||
echo 1 > /sys/bus/pci/devices/0000\:05\:00.0/remove
|
||||
echo 1 > /sys/bus/pci/rescan
|
||||
|
||||
insmod openair_rf.ko
|
||||
@@ -1 +0,0 @@
|
||||
rmmod openair_rf && sleep 1 ; insmod openair_rf.ko
|
||||
@@ -1,360 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** exmimo_fw.c
|
||||
*
|
||||
* Initialization routines for
|
||||
* Shared Memory management for ExMIMO and PC(kernel) data exchange
|
||||
* (memory allocation, pointer management)
|
||||
*
|
||||
* There is now one pci_alloc_consistent for each RX and TX buffer
|
||||
* and one for all structures, including pointers, printk, firmware_dump and config
|
||||
*
|
||||
* Authors: Matthias Ihmig <matthias.ihmig@mytum.de>, 2012, 2013
|
||||
* Riadh Ghaddab <riadh.ghaddab@eurecom.fr>
|
||||
* Raymond Knopp <raymond.knopp@eurecom.fr>
|
||||
*
|
||||
* Changelog:
|
||||
* 24.01.2013: added memory management functions for bigshm, lots of cleanups
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include "extern.h"
|
||||
#include "defs.h"
|
||||
#include "pcie_interface.h"
|
||||
|
||||
/*****************************************************
|
||||
* Private functions within this file
|
||||
*/
|
||||
|
||||
void mem_SetPageReserved(void *kvirt_addr, unsigned int size_pages)
|
||||
{
|
||||
size_t temp_size = size_pages << PAGE_SHIFT;
|
||||
void *adr = kvirt_addr;
|
||||
|
||||
while (temp_size > 0) {
|
||||
SetPageReserved( virt_to_page(adr) );
|
||||
adr += PAGE_SIZE;
|
||||
temp_size -= PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void mem_ClearPageReserved(void *kvirt_addr, unsigned int size_pages)
|
||||
{
|
||||
size_t temp_size = size_pages << PAGE_SHIFT;
|
||||
void *adr = kvirt_addr;
|
||||
|
||||
while (temp_size > 0) {
|
||||
ClearPageReserved( virt_to_page(adr) );
|
||||
adr += PAGE_SIZE;
|
||||
temp_size -= PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
// allocates big shared memory, to be used for structures, pointers, etc.
|
||||
// bigshm allocs a single larger memory block for shared structures and pointers, one per card, except: ADC+DAC buffers!
|
||||
// returns -1 on error, 0 on success
|
||||
int bigshm_init(int card)
|
||||
{
|
||||
printk("[openair][module] calling pci_alloc_consistent for card %d, bigshm (size: %lu*%lu bytes)...\n", card, BIGSHM_SIZE_PAGES, PAGE_SIZE);
|
||||
|
||||
if ( sizeof(dma_addr_t) != 4)
|
||||
printk("!!! WARNING: sizeof (dma_addr_t) = %lu! Only 32bit mode (= 4) (also: no PAE) is supported at this time!\n", sizeof(dma_addr_t));
|
||||
|
||||
if ( bigshm_head[card] == NULL )
|
||||
bigshm_head[card] = pci_alloc_consistent( pdev[card], BIGSHM_SIZE_PAGES<<PAGE_SHIFT, &bigshm_head_phys[card] );
|
||||
|
||||
if (bigshm_head[card] == NULL) {
|
||||
printk("[openair][MODULE][ERROR] Cannot Allocate Memory (%lu bytes) for shared data (bigshm)\n", BIGSHM_SIZE_PAGES<<PAGE_SHIFT);
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
printk("[openair][MODULE][INFO] Bigshm at %p (phys %x)\n", bigshm_head[card], (unsigned int) bigshm_head_phys[card]);
|
||||
|
||||
bigshm_currentptr[card] = bigshm_head[card];
|
||||
|
||||
mem_SetPageReserved( bigshm_head[card], BIGSHM_SIZE_PAGES);
|
||||
memset(bigshm_head[card], 0, BIGSHM_SIZE_PAGES << PAGE_SHIFT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// use this instead of pci_alloc_consistent to assign memory from the bigshm block
|
||||
// return kernel virtual pointer and sets physical DMA address in dma_handle
|
||||
void *bigshm_assign( int card, size_t size_bytes, dma_addr_t *dma_handle_ptr )
|
||||
{
|
||||
void *ret;
|
||||
size_t size = size_bytes;
|
||||
|
||||
//size = (size-1) + 4 - ( (size-1) % 4); // round up to keep addresses aligned to DWs
|
||||
//size = (size-1) + 16 - ( (size-1) % 16); // round up to keep addresses aligned to 4 DWs
|
||||
|
||||
// round up to the next 64 DW (workaround for current bug in DMA on ExMIMO2)
|
||||
size = (size-1) + 256 - ( (size-1) % 256);
|
||||
|
||||
if ( (bigshm_currentptr[card] - bigshm_head[card]) > (BIGSHM_SIZE_PAGES<<PAGE_SHIFT) -size ) {
|
||||
printk("Not enough memory in bigshm! Make BIGSHM_SIZE_PAGES bigger!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*dma_handle_ptr = bigshm_head_phys[card] + ( (dma_addr_t)bigshm_currentptr[card] - (dma_addr_t)bigshm_head[card] );
|
||||
ret = bigshm_currentptr[card];
|
||||
bigshm_currentptr[card] = (char *)bigshm_currentptr[card] + size;
|
||||
|
||||
//printk("bigshm_assign: size %d, virt = %p, dma = %x, bigshm_phys=%x, _current=%p, _head=%p\n",
|
||||
// size, ret, *dma_handle_ptr, bigshm_head_phys[card], bigshm_currentptr[card], bigshm_head[card]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// assign shared memory between card an PC for data exchange: interface structure with pointers,
|
||||
// firmware- and printk buffers, configuration structure
|
||||
// returns -1 on error, 0 on success
|
||||
int exmimo_assign_shm_vars(int card_id)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (p_exmimo_pci_phys[card_id] == NULL) {
|
||||
p_exmimo_pci_phys[card_id] = (exmimo_pci_interface_bot_t *) bigshm_assign( card_id,
|
||||
sizeof(exmimo_pci_interface_bot_t),
|
||||
&pphys_exmimo_pci_phys[card_id]);
|
||||
printk("Intializing EXMIMO interface support (exmimo_pci_bot at %p, phys %x, size %lu bytes)\n",p_exmimo_pci_phys[card_id],(unsigned int)pphys_exmimo_pci_phys[card_id],
|
||||
sizeof(exmimo_pci_interface_bot_t));
|
||||
|
||||
exmimo_pci_kvirt[card_id].firmware_block_ptr = (char *) bigshm_assign( card_id,
|
||||
MAX_FIRMWARE_BLOCK_SIZE_B,
|
||||
(dma_addr_t*)&(p_exmimo_pci_phys[card_id]->firmware_block_ptr));
|
||||
printk("firmware_code_block_ptr : %p (phys = %08x)\n", exmimo_pci_kvirt[card_id].firmware_block_ptr, p_exmimo_pci_phys[card_id]->firmware_block_ptr);
|
||||
|
||||
|
||||
exmimo_pci_kvirt[card_id].printk_buffer_ptr = (char *) bigshm_assign( card_id,
|
||||
MAX_PRINTK_BUFFER_B,
|
||||
(dma_addr_t*)&(p_exmimo_pci_phys[card_id]->printk_buffer_ptr));
|
||||
printk("printk_buffer_ptr : %p (phys = %08x)\n", exmimo_pci_kvirt[card_id].printk_buffer_ptr, p_exmimo_pci_phys[card_id]->printk_buffer_ptr);
|
||||
|
||||
|
||||
exmimo_pci_kvirt[card_id].exmimo_config_ptr = (exmimo_config_t *) bigshm_assign( card_id,
|
||||
sizeof(exmimo_config_t),
|
||||
(dma_addr_t*)&(p_exmimo_pci_phys[card_id]->exmimo_config_ptr));
|
||||
printk("exmimo_config_ptr : %p (phys = %08x)\n", exmimo_pci_kvirt[card_id].exmimo_config_ptr, p_exmimo_pci_phys[card_id]->exmimo_config_ptr);
|
||||
|
||||
|
||||
exmimo_pci_kvirt[card_id].exmimo_id_ptr = (exmimo_id_t *) bigshm_assign( card_id,
|
||||
sizeof(exmimo_id_t),
|
||||
(dma_addr_t*)&(p_exmimo_pci_phys[card_id]->exmimo_id_ptr));
|
||||
printk("exmimo_id_ptr : %p (phys = %08x)\n", exmimo_pci_kvirt[card_id].exmimo_id_ptr, p_exmimo_pci_phys[card_id]->exmimo_id_ptr);
|
||||
|
||||
|
||||
if ( p_exmimo_pci_phys[card_id] == NULL || exmimo_pci_kvirt[card_id].firmware_block_ptr == NULL
|
||||
|| exmimo_pci_kvirt[card_id].printk_buffer_ptr == NULL || exmimo_pci_kvirt[card_id].exmimo_config_ptr == NULL
|
||||
|| exmimo_pci_kvirt[card_id].exmimo_id_ptr == NULL )
|
||||
return -1;
|
||||
|
||||
for (j=0; j<MAX_ANTENNAS; j++) {
|
||||
// size 4*1 should be sufficient, but just to make sure we can also use DMA of size 4DW as fallback
|
||||
exmimo_pci_kvirt[card_id].rxcnt_ptr[j] = (uint32_t *) bigshm_assign( card_id, 4*4,
|
||||
(dma_addr_t*)&(p_exmimo_pci_phys[card_id]->rxcnt_ptr[j]) );
|
||||
printk("exmimo_pci_kvirt[%d].rxcnt_ptr[%d] = %p (phys = %08x)\n", card_id, j, exmimo_pci_kvirt[card_id].rxcnt_ptr[j], p_exmimo_pci_phys[card_id]->rxcnt_ptr[j]);
|
||||
|
||||
exmimo_pci_kvirt[card_id].txcnt_ptr[j] = (uint32_t *) bigshm_assign( card_id, 4*4,
|
||||
(dma_addr_t*)&(p_exmimo_pci_phys[card_id]->txcnt_ptr[j]) );
|
||||
printk("exmimo_pci_kvirt[%d].txcnt_ptr[%d] = %p (phys = %08x)\n", card_id, j, exmimo_pci_kvirt[card_id].txcnt_ptr[j], p_exmimo_pci_phys[card_id]->txcnt_ptr[j]);
|
||||
|
||||
if ( exmimo_pci_kvirt[card_id].rxcnt_ptr[j] == NULL || exmimo_pci_kvirt[card_id].txcnt_ptr[j] == NULL)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// allocate memory for RX and TX chains for all antennas
|
||||
// returns -1 on error, 0 on success
|
||||
int exmimo_allocate_rx_tx_buffers(int card_id)
|
||||
{
|
||||
size_t size;
|
||||
int j,i;
|
||||
dma_addr_t dma_addr_dummy;
|
||||
// Round up to the next PAGE_SIZE (typ. 4096 bytes)
|
||||
size = (ADAC_BUFFERSZ_PERCHAN_B >> PAGE_SHIFT) + 1;
|
||||
size <<= PAGE_SHIFT;
|
||||
|
||||
for (j=0; j<MAX_ANTENNAS; j++) {
|
||||
|
||||
exmimo_pci_kvirt[card_id].adc_head[j] = (uint32_t *)pci_alloc_consistent( pdev[card_id], size, &dma_addr_dummy);
|
||||
p_exmimo_pci_phys[card_id]->adc_head[j]=((uint32_t*)&dma_addr_dummy)[0];
|
||||
|
||||
printk("exmimo_pci_kvirt[%d].adc_head[%d] = %p (phys = %08x)\n", card_id, j, exmimo_pci_kvirt[card_id].adc_head[j], p_exmimo_pci_phys[card_id]->adc_head[j]);
|
||||
|
||||
if ( exmimo_pci_kvirt[card_id].adc_head[j] == NULL)
|
||||
return -1;
|
||||
|
||||
// printk("[MODULE MAIN0]Phys address TX[0] : (%8lx)\n",p_exmimo_pci_phys[0]->dac_head[ openair_mmap_getAntTX(2) ]);
|
||||
|
||||
mem_SetPageReserved( exmimo_pci_kvirt[card_id].adc_head[j], size >> PAGE_SHIFT );
|
||||
memset( exmimo_pci_kvirt[card_id].adc_head[j], 0x10+j, size);
|
||||
|
||||
// printk("[MODULE MAIN1]Phys address TX[0] : (%8lx)\n",p_exmimo_pci_phys[0]->dac_head[ openair_mmap_getAntTX(2) ]);
|
||||
|
||||
exmimo_pci_kvirt[card_id].dac_head[j] = (uint32_t *)pci_alloc_consistent( pdev[card_id], size,&dma_addr_dummy);
|
||||
p_exmimo_pci_phys[card_id]->dac_head[j]=((uint32_t*)&dma_addr_dummy)[0];
|
||||
|
||||
// printk("exmimo_pci_kvirt[%d].dac_head[%d] = %p (phys = %08x)\n", card_id, j, exmimo_pci_kvirt[card_id].dac_head[j], p_exmimo_pci_phys[card_id]->dac_head[j]);
|
||||
if ( exmimo_pci_kvirt[card_id].dac_head[j] == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
// printk("[MODULE MAIN2]Phys address TX[0] : (%8lx)\n",p_exmimo_pci_phys[0]->dac_head[ openair_mmap_getAntTX(2) ]);
|
||||
|
||||
mem_SetPageReserved( exmimo_pci_kvirt[card_id].dac_head[j], size >> PAGE_SHIFT );
|
||||
memset( exmimo_pci_kvirt[card_id].dac_head[j], 0x20+j, size);
|
||||
// printk("[MODULE MAIN3]Phys address TX[0] : (%8lx)\n",p_exmimo_pci_phys[0]->dac_head[ openair_mmap_getAntTX(2) ]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************
|
||||
* Public functions ExpressMIMO Interface
|
||||
*/
|
||||
|
||||
/* Allocates buffer and assigns pointers
|
||||
*
|
||||
* return 0 on success
|
||||
*/
|
||||
int exmimo_memory_alloc(int card)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( bigshm_init( card ) ) {
|
||||
printk("exmimo_memory_alloc(): bigshm_init failed for card %d.\n", card);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if ( exmimo_assign_shm_vars( card ) ) {
|
||||
printk("exmimo_memory_alloc(): exmimo_assign_shm_vars failed to assign enough shared memory for all variables and structures for card %i!\n", card);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if ( exmimo_allocate_rx_tx_buffers( card ) ) {
|
||||
printk("exmimo_memory_alloc(): exmimo_allocate_rx_tx_buffers() failed to allocate enough memory for RX and TX buffers for card %i!\n", card);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies pointer to Leon
|
||||
*/
|
||||
int exmimo_firmware_init(int card)
|
||||
{
|
||||
|
||||
// put DMA pointer to exmimo_pci_interface_bot into LEON register
|
||||
iowrite32( pphys_exmimo_pci_phys[card], (bar[card]+PCIE_PCIBASEL) ); // lower 32bit of address
|
||||
iowrite32( 0, (bar[card]+PCIE_PCIBASEH) ); // higher 32bit of address
|
||||
|
||||
for (j=0; j<MAX_ANTENNAS; j++) {
|
||||
iowrite32(p_exmimo_pci_phys[card]->adc_head[j], (bar[card]+));
|
||||
iowrite32(p_exmimo_pci_phys[card]->dac_head[j], (bar[card]+));
|
||||
}
|
||||
|
||||
exmimo_send_pccmd(card, EXMIMO_PCIE_INIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free memory on unloading the kernel driver
|
||||
*/
|
||||
int exmimo_firmware_cleanup(int card)
|
||||
{
|
||||
size_t size;
|
||||
int j;
|
||||
|
||||
// free exmimo_allocate_rx_tx_buffers
|
||||
|
||||
size = (ADAC_BUFFERSZ_PERCHAN_B >> PAGE_SHIFT) + 1;
|
||||
size <<= PAGE_SHIFT;
|
||||
|
||||
for (j=0; j<MAX_ANTENNAS; j++) {
|
||||
if ( exmimo_pci_kvirt[card].adc_head[j] ) {
|
||||
mem_ClearPageReserved( exmimo_pci_kvirt[card].adc_head[j], size >> PAGE_SHIFT );
|
||||
pci_free_consistent( pdev[card], size, exmimo_pci_kvirt[card].adc_head[j], p_exmimo_pci_phys[card]->adc_head[j] );
|
||||
}
|
||||
|
||||
if ( exmimo_pci_kvirt[card].dac_head[j] ) {
|
||||
mem_ClearPageReserved( exmimo_pci_kvirt[card].dac_head[j], size >> PAGE_SHIFT );
|
||||
pci_free_consistent( pdev[card], size, exmimo_pci_kvirt[card].dac_head[j], p_exmimo_pci_phys[card]->dac_head[j] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( bigshm_head[card] ) {
|
||||
printk("free bigshm_head[%d] pdev %p, size %lu, head %p, phys %x\n", card, pdev[card], BIGSHM_SIZE_PAGES<<PAGE_SHIFT, bigshm_head[card], (unsigned int)bigshm_head_phys[card]);
|
||||
mem_ClearPageReserved( bigshm_head[card], BIGSHM_SIZE_PAGES );
|
||||
|
||||
pci_free_consistent( pdev[card], BIGSHM_SIZE_PAGES<<PAGE_SHIFT, bigshm_head[card], bigshm_head_phys[card]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Send command to Leon and wait until command is completed
|
||||
*/
|
||||
int exmimo_send_pccmd(int card_id, unsigned int cmd)
|
||||
{
|
||||
unsigned int val;
|
||||
unsigned int cnt=0;
|
||||
|
||||
//printk("Sending command to ExpressMIMO (card %d) : %x\n",card_id, cmd);
|
||||
iowrite32(cmd,(bar[card_id]+PCIE_CONTROL1));
|
||||
// printk("Readback of control1 %x\n",ioread32(bar[0]+PCIE_CONTROL1));
|
||||
|
||||
|
||||
switch(cmd) {
|
||||
case EXMIMO_CONFIG :
|
||||
|
||||
break;
|
||||
|
||||
case EXMIMO_PCIE_INIT :
|
||||
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// workaround for ExMIMO1&2: no command ack -> sleep
|
||||
while (cnt<100 && ( ioread32(bar[card_id]+PCIE_CONTROL1) != EXMIMO_NOP )) {
|
||||
//printk("ctrl0: %08x, ctrl1: %08x, ctrl2: %08x, status: %08x\n", ioread32(bar[card_id]+PCIE_CONTROL0), ioread32(bar[card_id]+PCIE_CONTROL1), ioread32(bar[card_id]+PCIE_CONTROL2), ioread32(bar[card_id]+PCIE_STATUS));
|
||||
msleep(100);
|
||||
cnt++;
|
||||
}
|
||||
|
||||
if (cnt==100)
|
||||
printk("exmimo_send_pccmd error: Timeout: no EXMIMO_NOP received within 10sec for card%d, pccmd=%x\n", card_id, cmd);
|
||||
|
||||
//printk("Ctrl0: %08x, ctrl1: %08x, ctrl2: %08x, status: %08x\n", ioread32(bar[card_id]+PCIE_CONTROL0), ioread32(bar[card_id]+PCIE_CONTROL1), ioread32(bar[card_id]+PCIE_CONTROL2), ioread32(bar[card_id]+PCIE_STATUS));
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef __EXTERN_H__
|
||||
#define __EXTERN_H__
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#ifdef KERNEL2_6
|
||||
#include <linux/slab.h>
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
#include "pcie_interface.h"
|
||||
|
||||
extern char number_of_cards;
|
||||
|
||||
extern int major;
|
||||
|
||||
extern struct pci_dev *pdev[MAX_CARDS];
|
||||
extern void __iomem *bar[MAX_CARDS];
|
||||
|
||||
extern void *bigshm_head[MAX_CARDS];
|
||||
extern void *bigshm_currentptr[MAX_CARDS];
|
||||
extern dma_addr_t bigshm_head_phys[MAX_CARDS];
|
||||
|
||||
extern dma_addr_t pphys_exmimo_pci_phys[MAX_CARDS];
|
||||
extern exmimo_pci_interface_bot_t *p_exmimo_pci_phys[MAX_CARDS];
|
||||
extern exmimo_pci_interface_bot_virtual_t exmimo_pci_kvirt[MAX_CARDS];
|
||||
|
||||
#endif // __EXTERN_H__
|
||||
@@ -1,459 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** fileops.c
|
||||
*
|
||||
* Device IOCTL File Operations on character device /dev/openair0
|
||||
*
|
||||
* Authors: Matthias Ihmig <matthias.ihmig@mytum.de>, 2012, 2013
|
||||
* Riadh Ghaddab <riadh.ghaddab@eurecom.fr>
|
||||
* Raymond Knopp <raymond.knopp@eurecom.fr>
|
||||
*
|
||||
* Changelog:
|
||||
* 14.01.2013: removed remaining of BIGPHYS stuff and replaced with pci_alloc_consistent
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "openair_device.h"
|
||||
#include "defs.h"
|
||||
#include "extern.h"
|
||||
|
||||
#include "pcie_interface.h"
|
||||
|
||||
#define invert4(x) { \
|
||||
unsigned int ltmp; \
|
||||
ltmp=x; x=((ltmp & 0xff)<<24) | ((ltmp & 0xff00)<<8) | \
|
||||
((ltmp & 0xff0000)>>8) | ((ltmp & 0xff000000)>>24); \
|
||||
}
|
||||
|
||||
extern int get_frame_done;
|
||||
|
||||
|
||||
int is_card_num_invalid(int card)
|
||||
{
|
||||
if (card<0 || card>=number_of_cards) {
|
||||
printk("[openair][IOCTL]: ERROR: received invalid card number (%d)!\n", card);
|
||||
return -1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int openair_device_open (struct inode *inode,struct file *filp)
|
||||
{
|
||||
//printk("[openair][MODULE] openair_open()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int openair_device_release (struct inode *inode,struct file *filp)
|
||||
{
|
||||
// printk("[openair][MODULE] openair_release(), MODE = %d\n",openair_daq_vars.mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int openair_device_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
unsigned long phys;
|
||||
unsigned long start = (unsigned long)vma->vm_start;
|
||||
unsigned long size = (unsigned long)(vma->vm_end-vma->vm_start);
|
||||
unsigned long maxsize;
|
||||
unsigned int memblock_ind;
|
||||
unsigned int card;
|
||||
|
||||
memblock_ind = openair_mmap_getMemBlock( vma->vm_pgoff );
|
||||
card = openair_mmap_getCard( vma->vm_pgoff );
|
||||
|
||||
/*printk("[openair][MMAP] called (start %lx, end %lx, pg_off %lx, size %lx)\n",
|
||||
vma->vm_start,
|
||||
vma->vm_end,
|
||||
vma->vm_pgoff,
|
||||
size);
|
||||
*/
|
||||
vma->vm_pgoff = 0;
|
||||
|
||||
// not supported by 64 bit kernels
|
||||
//vma->vm_flags |= VM_RESERVED;
|
||||
vma->vm_flags |= VM_IO;
|
||||
|
||||
if ( is_card_num_invalid(card) )
|
||||
return -EINVAL;
|
||||
|
||||
if (memblock_ind == openair_mmap_BIGSHM) {
|
||||
// map a buffer from bigshm
|
||||
maxsize = BIGSHM_SIZE_PAGES<<PAGE_SHIFT;
|
||||
|
||||
if ( size > maxsize) {
|
||||
printk("[openair][MMAP][ERROR] Trying to map more than %d bytes (req size=%d)\n",
|
||||
(unsigned int)(BIGSHM_SIZE_PAGES<<PAGE_SHIFT), (unsigned int)size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
phys = bigshm_head_phys[card];
|
||||
} else if ( (memblock_ind & 1) == 1) {
|
||||
// mmap a RX buffer
|
||||
maxsize = ADAC_BUFFERSZ_PERCHAN_B;
|
||||
|
||||
if ( size > maxsize) {
|
||||
printk("[openair][MMAP][ERROR] Trying to map more than %d bytes (req size=%d)\n",
|
||||
(unsigned int)(ADAC_BUFFERSZ_PERCHAN_B), (unsigned int)size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
phys = p_exmimo_pci_phys[card]->adc_head[ openair_mmap_getAntRX(memblock_ind) ];
|
||||
} else {
|
||||
// mmap a TX buffer
|
||||
maxsize = ADAC_BUFFERSZ_PERCHAN_B;
|
||||
|
||||
if ( size > maxsize) {
|
||||
printk("[openair][MMAP][ERROR] Trying to map more than %d bytes (%d)\n",
|
||||
(unsigned int)(ADAC_BUFFERSZ_PERCHAN_B), (unsigned int)size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
phys = p_exmimo_pci_phys[card]->dac_head[ openair_mmap_getAntTX(memblock_ind) ];
|
||||
}
|
||||
|
||||
if (0)
|
||||
printk("[openair][MMAP] card%d: map phys (%08lx) at start %lx, end %lx, pg_off %lx, size %lx\n",
|
||||
card,
|
||||
phys,
|
||||
vma->vm_start,
|
||||
vma->vm_end,
|
||||
vma->vm_pgoff,
|
||||
size);
|
||||
|
||||
/* loop through all the physical pages in the buffer */
|
||||
/* Remember this won't work for vmalloc()d memory ! */
|
||||
if (remap_pfn_range(vma,
|
||||
start,
|
||||
phys>>PAGE_SHIFT,
|
||||
vma->vm_end-vma->vm_start,
|
||||
vma->vm_page_prot)) {
|
||||
printk("[openair][MMAP] ERROR EAGAIN\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
|
||||
long openair_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
#else
|
||||
int openair_device_ioctl(struct inode *inode,struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
#endif
|
||||
{
|
||||
/* arg is not meaningful if no arg is passed in user space */
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int i, c;
|
||||
|
||||
int tmp;
|
||||
|
||||
static unsigned int update_firmware_command;
|
||||
static unsigned int update_firmware_address;
|
||||
static unsigned int update_firmware_length;
|
||||
static unsigned int* update_firmware_kbuffer;
|
||||
static unsigned int* __user update_firmware_ubuffer;
|
||||
static unsigned int update_firmware_start_address;
|
||||
static unsigned int update_firmware_stack_pointer;
|
||||
static unsigned int update_firmware_bss_address;
|
||||
static unsigned int update_firmware_bss_size;
|
||||
unsigned int *fw_block;
|
||||
unsigned int sparc_tmp_0;
|
||||
unsigned int sparc_tmp_1;
|
||||
static unsigned int lendian_length;
|
||||
|
||||
unsigned int get_frame_cnt=0;
|
||||
|
||||
switch(cmd) {
|
||||
case openair_STOP:
|
||||
|
||||
printk("[openair][IOCTL] openair_STOP(card%d)\n", (int)arg);
|
||||
|
||||
if ( is_card_num_invalid((int)arg) )
|
||||
return -EINVAL;
|
||||
|
||||
exmimo_send_pccmd((int)arg, EXMIMO_STOP);
|
||||
|
||||
break;
|
||||
|
||||
case openair_STOP_WITHOUT_RESET:
|
||||
|
||||
printk("[openair][IOCTL] openair_STOP_WITHOUT_RESET(card%d)\n", (int)arg);
|
||||
|
||||
if ( is_card_num_invalid((int)arg) )
|
||||
return -EINVAL;
|
||||
|
||||
exmimo_send_pccmd((int)arg, EXMIMO_STOP_WITHOUT_RESET);
|
||||
|
||||
break;
|
||||
|
||||
case openair_GET_FRAME:
|
||||
|
||||
get_frame_cnt=0;
|
||||
get_frame_done = 0;
|
||||
printk("[openair][IOCTL] : openair_GET_FRAME: calling exmimo_send_pccmd(%d, EXMIMO_GET_FRAME)\n", (int)arg);
|
||||
|
||||
if ( is_card_num_invalid((int)arg) )
|
||||
return -EINVAL;
|
||||
|
||||
exmimo_send_pccmd((int)arg, EXMIMO_GET_FRAME);
|
||||
|
||||
while (get_frame_cnt<10 && !get_frame_done) {
|
||||
msleep(10);
|
||||
get_frame_cnt++;
|
||||
}
|
||||
|
||||
if (get_frame_cnt==200)
|
||||
printk("[openair][IOCTL] : Get frame error: no IRQ received within 2000ms.\n");
|
||||
|
||||
get_frame_done = 0;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case openair_GET_BIGSHMTOPS_KVIRT:
|
||||
|
||||
//printk("[openair][IOCTL] : openair_GET_BIGSHMTOPS_KVIRT (0x%p)[0] = %p[0] (bigshm_head) for 0..3 (sizeof %d) \n", (void *)arg, bigshm_head[0], sizeof(bigshm_head));
|
||||
copy_to_user((void *)arg, bigshm_head, sizeof(bigshm_head));
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case openair_GET_PCI_INTERFACE_BOTS_KVIRT:
|
||||
|
||||
//printk("[openair][IOCTL] : openair_GET_PCI_INTERFACE_BOTS_KVIRT: copying exmimo_pci_kvirt(@%8p) to %lx (sizeof %d)\n", &exmimo_pci_kvirt[0], arg, sizeof(exmimo_pci_kvirt));
|
||||
copy_to_user((void *)arg, exmimo_pci_kvirt, sizeof(exmimo_pci_kvirt));
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case openair_GET_NUM_DETECTED_CARDS:
|
||||
|
||||
//printk("[openair][IOCTL] : openair_GET_NUM_DETECTED_CARDS: *(0x%p) = %d\n", (void *)arg, number_of_cards);
|
||||
copy_to_user((void *)arg, &number_of_cards, sizeof(number_of_cards));
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case openair_DUMP_CONFIG:
|
||||
|
||||
//printk("[openair][IOCTL] openair_DUMP_CONFIG(%d)\n", (int)arg);
|
||||
if ( is_card_num_invalid((int)arg) ) {
|
||||
printk("[openair][IOCTL] openair_DUMP_CONFIG: Invalid card number %d.\n", (int)arg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
printk("[openair][IOCTL] : openair_DUMP_CONFIG(%d): exmimo_pci_kvirt[%d].exmimo_config_ptr = %p (phys %08x)\n",
|
||||
(int)arg, (int)arg, exmimo_pci_kvirt[(int)arg].exmimo_config_ptr, p_exmimo_pci_phys[(int)arg]->exmimo_config_ptr);
|
||||
|
||||
/*printk("EXMIMO_CONFIG: freq0 %d Hz, freq1 %d Hz, freqtx0 %d Hz, freqtx1 %d Hz, \nRX gain0 %d dB, RX Gain1 %d dB\n",
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rf_freq_rx[0],
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rf_freq_rx[1],
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rf_freq_tx[0],
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rf_freq_tx[1],
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rx_gain[0][0],
|
||||
exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rx_gain[1][0]);
|
||||
*/
|
||||
|
||||
exmimo_send_pccmd((int)arg, EXMIMO_CONFIG);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case openair_START_RT_ACQUISITION:
|
||||
|
||||
printk("[openair][IOCTL] openair_START_TX_SIG(%d): send_pccmd(EXMIMO_START_RT_ACQUISITION).\n", (int) arg);
|
||||
|
||||
if ( is_card_num_invalid((int)arg) )
|
||||
return -EINVAL;
|
||||
|
||||
exmimo_send_pccmd((int)arg, EXMIMO_START_RT_ACQUISITION);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case openair_UPDATE_FIRMWARE:
|
||||
|
||||
printk("[openair][IOCTL] openair_UPDATE_FIRMWARE\n");
|
||||
/***************************************************
|
||||
* Updating the firmware of Cardbus-MIMO-1 or ExpressMIMO SoC *
|
||||
***************************************************/
|
||||
/* 1st argument of this ioctl indicates the action to perform among these:
|
||||
- Transfer a block of data at a specified address (given as the 2nd argument)
|
||||
and for a specified length (given as the 3rd argument, in number of 32-bit words).
|
||||
The USER-SPACE address where to find the block of data is given as the 4th
|
||||
argument.
|
||||
- Ask the Leon processor to clear the .bss section. In this case, the base
|
||||
address of section .bss is given as the 2nd argument, and its size is
|
||||
given as the 3rd one.
|
||||
- Ask the Leon processor to jump at a specified address (given as the 2nd
|
||||
argument, most oftenly expected to be the top address of Ins, Scratch Pad
|
||||
Ram), after having set the stack pointer (given as the 3rd argument).
|
||||
For the openair_UPDATE_FIRMWARE ioctl, we perform a partial infinite loop
|
||||
while acknowledging the PCI irq from Leon software: the max number of loop
|
||||
is yielded by preprocessor constant MAX_IOCTL_ACK_CNT. This avoids handing
|
||||
the kernel with an infinite polling loop. An exception is the case of clearing
|
||||
the bss: it takes time to Leon3 to perform this operation, so we poll te
|
||||
acknowledge with no limit */
|
||||
|
||||
#define MAX_IOCTL_ACK_CNT 500
|
||||
update_firmware_command = *((unsigned int*)arg);
|
||||
|
||||
|
||||
switch (update_firmware_command) {
|
||||
case UPDATE_FIRMWARE_TRANSFER_BLOCK:
|
||||
update_firmware_address = ((unsigned int*)arg)[1];
|
||||
update_firmware_length = ((unsigned int*)arg)[2];
|
||||
|
||||
update_firmware_ubuffer = (unsigned int*)((unsigned int*)arg)[3];
|
||||
update_firmware_kbuffer = (unsigned int*)kmalloc(update_firmware_length * 4 /* 4 because kmalloc expects bytes */,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!update_firmware_kbuffer) {
|
||||
printk("[openair][IOCTL] Could NOT allocate %u bytes from kernel memory (kmalloc failed).\n", lendian_length * 4);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
// update all cards at the same time
|
||||
for (c=0; c<number_of_cards; c++) {
|
||||
fw_block = (unsigned int *)exmimo_pci_kvirt[c].firmware_block_ptr;
|
||||
/* Copy the data block from user space */
|
||||
fw_block[0] = update_firmware_address;
|
||||
fw_block[1] = update_firmware_length;
|
||||
//printk("copy_from_user %p => %p (pci) => fw[0]=fw_addr=%08x (ahb), fw[1]=fw_length=%d DW\n",update_firmware_ubuffer,&fw_block[16],update_firmware_address,update_firmware_length);
|
||||
tmp = copy_from_user(update_firmware_kbuffer,
|
||||
update_firmware_ubuffer, /* from */
|
||||
update_firmware_length * 4 /* in bytes */
|
||||
);
|
||||
|
||||
if (tmp) {
|
||||
printk("[openair][IOCTL] Could NOT copy all data from user-space to kernel-space (%d bytes remained uncopied).\n", tmp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// pci_map_single(pdev[0],(void*)fw_block, update_firmware_length*4,PCI_DMA_BIDIRECTIONAL);
|
||||
for (i=0; i<update_firmware_length; i++) {
|
||||
fw_block[32+i] = ((unsigned int *)update_firmware_kbuffer)[i];
|
||||
// Endian flipping is done in user-space so undo it
|
||||
invert4(fw_block[32+i]);
|
||||
}
|
||||
|
||||
exmimo_send_pccmd(c, EXMIMO_FW_INIT);
|
||||
printk("[openair][IOCTL] card%d: ok %u DW copied to address 0x%08x (fw_block_ptr %p)\n",
|
||||
c, fw_block[1], fw_block[0],fw_block);
|
||||
}
|
||||
|
||||
kfree(update_firmware_kbuffer);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
for (i=0; i<update_firmware_length;i++) {
|
||||
printk("%08x ", fw_block[32+i]);
|
||||
if ((i % 8) == 7)
|
||||
printk("\n");
|
||||
}*/
|
||||
|
||||
break;
|
||||
|
||||
case UPDATE_FIRMWARE_CLEAR_BSS:
|
||||
|
||||
update_firmware_bss_address = ((unsigned int*)arg)[1];
|
||||
update_firmware_bss_size = ((unsigned int*)arg)[2];
|
||||
sparc_tmp_0 = update_firmware_bss_address;
|
||||
sparc_tmp_1 = update_firmware_bss_size;
|
||||
|
||||
printk("[openair][IOCTL] ok asked Leon to clear .bss (addr 0x%08x, size %d bytes)\n", sparc_tmp_0, sparc_tmp_1);
|
||||
|
||||
// update all cards at the same time
|
||||
for (c=0; c<number_of_cards; c++) {
|
||||
fw_block = (unsigned int *)exmimo_pci_kvirt[c].firmware_block_ptr;
|
||||
fw_block[0] = update_firmware_bss_address;
|
||||
fw_block[1] = update_firmware_bss_size;
|
||||
|
||||
exmimo_send_pccmd(c, EXMIMO_FW_CLEAR_BSS);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case UPDATE_FIRMWARE_START_EXECUTION:
|
||||
|
||||
update_firmware_start_address = ((unsigned int*)arg)[1];
|
||||
update_firmware_stack_pointer = ((unsigned int*)arg)[2];
|
||||
sparc_tmp_0 = update_firmware_start_address;
|
||||
sparc_tmp_1 = update_firmware_stack_pointer;
|
||||
|
||||
printk("[openair][IOCTL] ok asked Leon to set stack and start execution (addr 0x%08x, stackptr %08x)\n", sparc_tmp_0, sparc_tmp_1);
|
||||
|
||||
for (c=0; c<number_of_cards; c++) {
|
||||
fw_block = (unsigned int *)exmimo_pci_kvirt[c].firmware_block_ptr;
|
||||
fw_block[0] = update_firmware_start_address;
|
||||
fw_block[1] = update_firmware_stack_pointer;
|
||||
|
||||
exmimo_send_pccmd(c, EXMIMO_FW_START_EXEC);
|
||||
msleep(10);
|
||||
exmimo_firmware_init(c);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case UPDATE_FIRMWARE_FORCE_REBOOT:
|
||||
|
||||
printk("[openair][IOCTL] ok asked Leon to reboot.\n");
|
||||
|
||||
for (c=0; c<number_of_cards; c++) {
|
||||
exmimo_send_pccmd(c, EXMIMO_REBOOT);
|
||||
|
||||
exmimo_firmware_init(c);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case UPDATE_FIRMWARE_TEST_GOK:
|
||||
printk("[openair][IOCTL] TEST_GOK command doesn't work with ExpressMIMO. Ignored.\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
//----------------------
|
||||
printk("[IOCTL] openair_IOCTL unknown: basecmd = %i (cmd=%X)\n", _IOC_NR(cmd), cmd );
|
||||
return -EPERM;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** irq.c
|
||||
- IRQ Handler: IRQ from Leon to PCIe/Kernel: exmimo_irq_handler
|
||||
- sends received packets to userspace
|
||||
|
||||
- send command from PC to Leon and trigger IRQ on Leon using CONTROL1 register
|
||||
- commands are defined in $OPENAIR0/express-mimo/software/pcie_interface.h
|
||||
|
||||
- added: pass card_id as parameter to tasklet and irq handler
|
||||
|
||||
Authors:
|
||||
Raymond Knopp <raymond.knopp@eurecom.fr>
|
||||
Matthias Ihmig <matthias.ihmig@mytum.de>, 2011, 2013
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/swab.h>
|
||||
|
||||
#include "openair_device.h"
|
||||
#include "extern.h"
|
||||
|
||||
unsigned int openair_bh_cnt;
|
||||
|
||||
int get_frame_done = 0;
|
||||
|
||||
void pcie_printk(int card_id);
|
||||
|
||||
void openair_do_tasklet (unsigned long card_id);
|
||||
DECLARE_TASKLET (openair_tasklet, openair_do_tasklet, 0);
|
||||
|
||||
irqreturn_t openair_irq_handler(int irq, void *cookie)
|
||||
{
|
||||
unsigned int irqval;
|
||||
unsigned int irqcmd = EXMIMO_NOP;
|
||||
unsigned long card_id; // = (unsigned long) cookie;
|
||||
unsigned int pcie_control = PCIE_CONTROL2;
|
||||
|
||||
// check interrupt status register
|
||||
//pci_read_config_word(pdev[0],6 , &irqval);
|
||||
|
||||
// find card_id. cookie is set by request_irq and static, so we will always find it
|
||||
for (card_id=0; card_id<MAX_CARDS; card_id++)
|
||||
if ( pdev[card_id] == cookie )
|
||||
break;
|
||||
|
||||
if (exmimo_pci_kvirt[card_id].exmimo_id_ptr->board_swrev == BOARD_SWREV_LEGACY)
|
||||
pcie_control = PCIE_CONTROL1;
|
||||
else
|
||||
pcie_control = PCIE_CONTROL2;
|
||||
|
||||
//printk("irq hndl called: card_id=%i, irqval=%i\n", card_id, irqval);
|
||||
|
||||
// get AHBPCIE interrupt line (bit 7) to determine if IRQ was for us from ExMIMO card, or from a different device
|
||||
// reading CONTROL0 will also clear this bit and the LEON-to-PC IRQ line
|
||||
irqval = ioread32(bar[card_id]+PCIE_CONTROL0);
|
||||
|
||||
irqcmd = ioread32(bar[card_id]+pcie_control);
|
||||
//printk("IRQ handler: ctrl0: %08x, ctrl1: %08x, ctrl2: %08x, status: %08x\n", irqval, ioread32(bar[card_id]+PCIE_CONTROL1), ioread32(bar[card_id]+PCIE_CONTROL2), ioread32(bar[card_id]+PCIE_STATUS));
|
||||
|
||||
if ( (irqval & 0x80) == 0 ) { // CTRL0.bit7 is no set -> IRQ is not from ExMIMO i.e. not for us
|
||||
if (exmimo_pci_kvirt[card_id].exmimo_id_ptr->board_swrev == BOARD_SWREV_CMDREGISTERS) {
|
||||
if (irqcmd != EXMIMO_NOP && irqcmd != EXMIMO_CONTROL2_COOKIE) {
|
||||
if (irqcmd == GET_FRAME_DONE) {
|
||||
get_frame_done = 1;
|
||||
}
|
||||
|
||||
openair_tasklet.data = card_id;
|
||||
tasklet_schedule(&openair_tasklet);
|
||||
openair_bh_cnt++;
|
||||
return IRQ_HANDLED;
|
||||
} else {
|
||||
return IRQ_NONE;
|
||||
}
|
||||
} else
|
||||
return IRQ_NONE;
|
||||
} else {
|
||||
if (exmimo_pci_kvirt[card_id].exmimo_id_ptr->board_swrev == BOARD_SWREV_LEGACY) {
|
||||
// clear PCIE interrupt (bit 7 of register 0x0)
|
||||
iowrite32(irqval&0xffffff7f,bar[card_id]+PCIE_CONTROL0);
|
||||
}
|
||||
|
||||
if (irqcmd == GET_FRAME_DONE) {
|
||||
get_frame_done = 1;
|
||||
}
|
||||
|
||||
openair_tasklet.data = card_id;
|
||||
tasklet_schedule(&openair_tasklet);
|
||||
openair_bh_cnt++;
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
void openair_do_tasklet (unsigned long card_id)
|
||||
{
|
||||
int save_irq_cnt = openair_bh_cnt;
|
||||
unsigned int irqcmd;
|
||||
unsigned int pcie_control = PCIE_CONTROL2;
|
||||
openair_bh_cnt = 0;
|
||||
|
||||
if (exmimo_pci_kvirt[card_id].exmimo_id_ptr->board_swrev == BOARD_SWREV_LEGACY)
|
||||
pcie_control = PCIE_CONTROL1;
|
||||
else
|
||||
pcie_control = PCIE_CONTROL2;
|
||||
|
||||
irqcmd = ioread32(bar[card_id]+pcie_control);
|
||||
|
||||
if (save_irq_cnt > 1)
|
||||
printk("[openair][IRQ tasklet(%ld)]: Warning: received more than 1 PCIE IRQ (openair_bh_cnt=%i), only the last one is acted upon(irqcmd= %i (0x%X)\n", card_id, openair_bh_cnt, irqcmd, irqcmd);
|
||||
|
||||
switch( irqcmd ) {
|
||||
case PCI_PRINTK:
|
||||
// printk("Got PCIe interrupt for printk ...\n");
|
||||
pcie_printk((int) card_id);
|
||||
break;
|
||||
|
||||
case GET_FRAME_DONE:
|
||||
printk("[openair][IRQ tasklet] : Got PCIe interrupt for GET_FRAME_DONE ...\n");
|
||||
break;
|
||||
|
||||
case EXMIMO_NOP:
|
||||
printk("[openair][IRQ tasklet] : Received IRQ, with CONTROL0.bit7(IRQ Leon2PC) set, but irqcmd = EXMIMO_NOP. This should not happen with bitstreams built after June 3rd 2013.\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("[openair][IRQ tasklet] : Got unknown PCIe cmd: card_id = %li, irqcmd(CONTROL1) = %i (0x%X)\n", card_id, irqcmd, irqcmd);
|
||||
}
|
||||
|
||||
iowrite32(EXMIMO_NOP, bar[card_id]+pcie_control);
|
||||
}
|
||||
|
||||
void pcie_printk(int card_id)
|
||||
{
|
||||
char *buffer = exmimo_pci_kvirt[card_id].printk_buffer_ptr;
|
||||
unsigned int len = ((unsigned int *)buffer)[0];
|
||||
unsigned int off=0,i;
|
||||
unsigned char *dword;
|
||||
unsigned char tmp;
|
||||
|
||||
//printk("In pci_fifo_printk : buffer %p, len %d: \n",buffer,len);
|
||||
printk("[LEON card%d]: ", card_id);
|
||||
|
||||
if (len<1024) {
|
||||
if ( (len&3) >0 )
|
||||
off=1;
|
||||
|
||||
for (i=0; i<(off+(len>>2)); i++) {
|
||||
dword = &((unsigned char *)buffer)[(1+i)<<2];
|
||||
tmp = dword[3];
|
||||
dword[3] = dword[0];
|
||||
dword[0] = tmp;
|
||||
tmp = dword[2];
|
||||
dword[2] = dword[1];
|
||||
dword[1] = tmp;
|
||||
}
|
||||
|
||||
for (i=0; i<len; i++)
|
||||
printk("%c",((char*)&buffer[4])[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,350 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** module_main.c (was: device.c)
|
||||
*
|
||||
* Main Kernel module functions for load/init and cleanup of the kernel driver
|
||||
*
|
||||
* Supports multiple ExpressMIMO cards
|
||||
*
|
||||
* Authors: Matthias Ihmig <matthias.ihmig@mytum.de>, 2012, 2013
|
||||
* Riadh Ghaddab <riadh.ghaddab@eurecom.fr>
|
||||
* Raymond Knopp <raymond.knopp@eurecom.fr>
|
||||
*
|
||||
* Changelog:
|
||||
* 14.01.2013: removed remaining of BIGPHYS stuff and replaced with pci_alloc_consistent
|
||||
* 20.01.2013: added support for multiple cards
|
||||
* 24.01.2013: restructured interfaces & structures of how physical and virtual pointers are handled
|
||||
*/
|
||||
|
||||
#include "openair_device.h"
|
||||
#include "defs.h"
|
||||
#include "vars.h"
|
||||
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/aer.h>
|
||||
#include <linux/pci_regs.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
static void openair_cleanup(void);
|
||||
|
||||
extern irqreturn_t openair_irq_handler(int irq, void *cookie);
|
||||
|
||||
static int irq = 0;
|
||||
module_param(irq,int,S_IRUSR|S_IWUSR);
|
||||
|
||||
|
||||
static struct file_operations openair_fops = {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
|
||||
unlocked_ioctl:openair_device_ioctl,
|
||||
#else
|
||||
ioctl: openair_device_ioctl,
|
||||
#endif
|
||||
open: openair_device_open,
|
||||
release:openair_device_release,
|
||||
mmap: openair_device_mmap
|
||||
};
|
||||
|
||||
static int __init openair_init_module( void )
|
||||
{
|
||||
int res = 0;
|
||||
unsigned int readback;
|
||||
unsigned int card, j;
|
||||
unsigned int vid,did;
|
||||
unsigned short vendor, subid;
|
||||
exmimo_id_t exmimo_id_tmp[MAX_CARDS];
|
||||
|
||||
//------------------------------------------------
|
||||
// Find and enable ExpressMIMO PCI cards
|
||||
//------------------------------------------------
|
||||
//
|
||||
card = 0;
|
||||
|
||||
pdev[card] = pci_get_device(XILINX_VENDOR, XILINX_ID, NULL);
|
||||
|
||||
if( pdev[card] ) {
|
||||
// This print does not work for 64 bit kernels
|
||||
// printk("[openair][INIT_MODULE][INFO]: openair card (ExpressMIMO) %d found, bus 0x%x, primary 0x%x, secondary 0x%x\n",card,
|
||||
// pdev[card]->bus->number, pdev[card]->bus->primary,pdev[card]->bus->secondary);
|
||||
|
||||
pci_read_config_word(pdev[card], PCI_SUBSYSTEM_ID, &subid);
|
||||
pci_read_config_word(pdev[card], PCI_SUBSYSTEM_VENDOR_ID, &vendor);
|
||||
exmimo_id_tmp[card].board_vendor = vendor;
|
||||
|
||||
if ( exmimo_id_tmp[card].board_vendor == XILINX_VENDOR )
|
||||
exmimo_id_tmp[card].board_vendor = EURECOM_VENDOR; // set default to EURECOM
|
||||
|
||||
exmimo_id_tmp[card].board_exmimoversion = (subid >> 12) & 0x0F;
|
||||
|
||||
if (exmimo_id_tmp[card].board_exmimoversion == 0)
|
||||
exmimo_id_tmp[card].board_exmimoversion = 1; // default (for old bitstreams) is ExpressMIMO-1
|
||||
|
||||
exmimo_id_tmp[card].board_hwrev = (subid >> 8) & 0x0F;
|
||||
exmimo_id_tmp[card].board_swrev = (subid ) & 0xFF;
|
||||
|
||||
printk("[openair][INIT_MODULE][INFO]: card %d: ExpressMIMO-%i (HW Rev %i), Bitstream: %s, SW/Protocol Revision: 0x%02X\n", card,
|
||||
exmimo_id_tmp[card].board_exmimoversion, exmimo_id_tmp[card].board_hwrev, ( (exmimo_id_tmp[card].board_vendor == EURECOM_VENDOR) ? "Eurecom" : "Telecom Paristech"), exmimo_id_tmp[card].board_swrev );
|
||||
|
||||
card++;
|
||||
vid = XILINX_VENDOR;
|
||||
did = XILINX_ID;
|
||||
} else {
|
||||
printk("[openair][INIT_MODULE][INFO]: no card found, stopping.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
// Now look for more cards on the same bus
|
||||
while (card<MAX_CARDS) {
|
||||
pdev[card] = pci_get_device(vid,did, pdev[card-1]);
|
||||
|
||||
if(pdev[card]) {
|
||||
// This print does not work for 64 bit kernels
|
||||
// printk("[openair][INIT_MODULE][INFO]: openair card %d found, bus 0x%x, primary 0x%x, secondary 0x%x\n",card,
|
||||
// pdev[card]->bus->number,pdev[card]->bus->primary,pdev[card]->bus->secondary);
|
||||
|
||||
pci_read_config_word(pdev[card], PCI_SUBSYSTEM_ID, &subid);
|
||||
pci_read_config_word(pdev[card], PCI_SUBSYSTEM_VENDOR_ID, &vendor);
|
||||
exmimo_id_tmp[card].board_vendor = vendor;
|
||||
|
||||
if ( exmimo_id_tmp[card].board_vendor == XILINX_VENDOR )
|
||||
exmimo_id_tmp[card].board_vendor = EURECOM_VENDOR; // default (for old bitstreams) is EURECOM_VENDOR
|
||||
|
||||
exmimo_id_tmp[card].board_exmimoversion = (subid >> 12) & 0x0F;
|
||||
|
||||
if (exmimo_id_tmp[card].board_exmimoversion == 0)
|
||||
exmimo_id_tmp[card].board_exmimoversion = 1; // default (for old bitstreams) is ExpressMIMO-1
|
||||
|
||||
exmimo_id_tmp[card].board_hwrev = (subid >> 8) & 0x0F;
|
||||
exmimo_id_tmp[card].board_swrev = (subid ) & 0xFF;
|
||||
printk("[openair][INIT_MODULE][INFO]: card %d: ExpressMIMO-%i (HW Rev %i), Bitstream: %s, SW/Protocol Revision: 0x%02X\n", card,
|
||||
exmimo_id_tmp[card].board_exmimoversion, exmimo_id_tmp[card].board_hwrev, ( (exmimo_id_tmp[card].board_vendor == EURECOM_VENDOR) ? "Eurecom" : "Telecom Paristech"), exmimo_id_tmp[card].board_swrev );
|
||||
|
||||
card++;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
// at least one device found, enable it
|
||||
number_of_cards = card;
|
||||
|
||||
for (card=0; card<number_of_cards; card++) {
|
||||
if( pci_enable_device(pdev[card]) ) {
|
||||
printk("[openair][INIT_MODULE][INFO]: Could not enable PCI card device %d\n",card);
|
||||
openair_cleanup();
|
||||
return -ENODEV;
|
||||
} else {
|
||||
printk("[openair][INIT_MODULE][INFO]: *** CARD DEVICE %d (pdev=%p) ENABLED, irq %d\n",card,pdev[card],irq);
|
||||
printk("[openair][INIT_MODULE][INFO]: *** CARD DEVICE %d (pdev=%p) ENABLED, irq %d\n",card,pdev[card],pdev[card]->irq);
|
||||
openair_pci_device_enabled[card] = 1;
|
||||
}
|
||||
|
||||
// Make the FPGA to a PCI master
|
||||
pci_set_master(pdev[card]);
|
||||
|
||||
// set DMA mask
|
||||
if (!pci_set_dma_mask(pdev[card], DMA_BIT_MASK(32))) {
|
||||
if (pci_set_consistent_dma_mask(pdev[card], DMA_BIT_MASK(32))) {
|
||||
printk(KERN_INFO "[openair][INIT_MODULE]: Unable to obtain 32bit DMA for consistent allocations\n");
|
||||
openair_cleanup();
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
//if (pci_enable_pcie_error_reporting(pdev[card]) > 0)
|
||||
// printk("[openair][INIT_MODULE][INFO]: Enabled PCIe error reporting\n");
|
||||
//else
|
||||
// printk("[openair][INIT_MODULE][INFO]: Failed to enable PCIe error reporting\n");
|
||||
|
||||
//pci_cleanup_aer_uncorrect_error_status(pdev[card]);
|
||||
|
||||
mmio_start[card] = pci_resource_start(pdev[card], 0); // get start of BAR0
|
||||
mmio_length[card] = pci_resource_len (pdev[card], 0);
|
||||
mmio_flags[card] = pci_resource_flags(pdev[card], 0);
|
||||
|
||||
if (check_mem_region(mmio_start[card],256) < 0) {
|
||||
printk("[openair][INIT_MODULE][FATAL] : Cannot get memory region 0, aborting\n");
|
||||
mmio_start[card] = 0;
|
||||
openair_cleanup();
|
||||
return -EBUSY;
|
||||
} else
|
||||
printk("[openair][INIT_MODULE][INFO] : Reserving memory region 0 : mmio_start = 0x%x\n",(unsigned int)mmio_start[card]);
|
||||
|
||||
request_mem_region(mmio_start[card], 256, "openair_rf");
|
||||
|
||||
bar[card] = pci_iomap( pdev[card], 0, mmio_length[card] ); // get virtual kernel address for BAR0
|
||||
|
||||
printk("[openair][INIT_MODULE][INFO]: BAR0 card %d = 0x%p\n", card, bar[card]);
|
||||
|
||||
printk("[openair][INIT_MODULE][INFO]: Writing 0x%x to BAR0+0x1c (PCIBASEL)\n", 0x12345678);
|
||||
|
||||
iowrite32( 0x12345678, (bar[card]+PCIE_PCIBASEL) );
|
||||
udelay(100);
|
||||
readback = ioread32( bar[card]+PCIE_PCIBASEL );
|
||||
|
||||
if (readback != 0x12345678) {
|
||||
printk("[openair][INIT_MODULE][INFO]: Readback of FPGA register failed (%x)\n",readback);
|
||||
openair_cleanup();
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
iowrite32((1<<8), bar[card] +PCIE_CONTROL0 ); // bit8=AHBPCIE_CTL0_SOFTRESET, but what is bit9 and bit10?
|
||||
udelay(1000);
|
||||
readback = ioread32( bar[card] +PCIE_CONTROL0);
|
||||
printk("CONTROL0 readback %x\n",readback);
|
||||
|
||||
// allocating buffers
|
||||
if ( exmimo_memory_alloc( card ) ) {
|
||||
printk("[openair][MODULE][ERROR] exmimo_memory_alloc() failed!\n");
|
||||
openair_cleanup();
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
exmimo_pci_kvirt[card].exmimo_id_ptr->board_vendor = exmimo_id_tmp[card].board_vendor;
|
||||
exmimo_pci_kvirt[card].exmimo_id_ptr->board_exmimoversion = exmimo_id_tmp[card].board_exmimoversion;
|
||||
exmimo_pci_kvirt[card].exmimo_id_ptr->board_hwrev = exmimo_id_tmp[card].board_hwrev;
|
||||
exmimo_pci_kvirt[card].exmimo_id_ptr->board_swrev = exmimo_id_tmp[card].board_swrev;
|
||||
|
||||
if (irq!=0)
|
||||
printk("[OPENAIR][SCHED][INIT] card %d: Trying to get IRQ %d\n", card,irq);
|
||||
else
|
||||
printk("[OPENAIR][SCHED][INIT] card %d: Trying to get IRQ %d\n", card, pdev[card]->irq);
|
||||
|
||||
openair_irq_enabled[card] = 0;
|
||||
|
||||
// #ifdef CONFIG_PREEMPT_RT doesn't work -> fix misconfigured header files?
|
||||
#if 1
|
||||
|
||||
if (irq!=0) {
|
||||
if ( (res = request_irq(irq, openair_irq_handler,
|
||||
IRQF_SHARED , "openair_rf", pdev[card] )) == 0) {
|
||||
openair_irq_enabled[card] = 1;
|
||||
} else {
|
||||
printk("[EXMIMO][SCHED][INIT] Cannot get IRQ %d for HW, error: %d\n", irq, res);
|
||||
openair_cleanup();
|
||||
return -EBUSY;
|
||||
}
|
||||
} else {
|
||||
if ( (res = request_irq(pdev[card]->irq, openair_irq_handler,
|
||||
IRQF_SHARED , "openair_rf", pdev[card] )) == 0) {
|
||||
openair_irq_enabled[card] = 1;
|
||||
} else {
|
||||
printk("[EXMIMO][SCHED][INIT] Cannot get IRQ %d for HW, error: %d\n", pdev[card]->irq, res);
|
||||
openair_cleanup();
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
printk("Warning: didn't request IRQ for PREEMPT_REALTIME\n");
|
||||
#endif
|
||||
|
||||
} // for (i=0; i<number_of_cards; i++)
|
||||
|
||||
//------------------------------------------------
|
||||
// Register the device in /dev
|
||||
//------------------------------------------------
|
||||
//
|
||||
major = openair_MAJOR;
|
||||
|
||||
if( (res = register_chrdev(major, "openair", &openair_fops )) < 0) {
|
||||
printk("[openair][INIT_MODULE][ERROR]: can't register char device driver, major : %d, error: %d\n", major, res);
|
||||
|
||||
for (j=0; j<=number_of_cards; j++)
|
||||
release_mem_region(mmio_start[j],256);
|
||||
|
||||
return -EBUSY;
|
||||
} else {
|
||||
printk("[openair][INIT_MODULE][INFO]: char device driver registered major : %d\n", major);
|
||||
openair_chrdev_registered = 1;
|
||||
}
|
||||
|
||||
printk("[openair][MODULE][INFO] Initializing Leon (EXMIMO_PCIE_INIT) on all cards...\n");
|
||||
|
||||
for (card=0; card<number_of_cards; card++)
|
||||
exmimo_firmware_init( card );
|
||||
|
||||
printk("[openair][MODULE][INFO] Done module init\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void __exit openair_cleanup_module(void)
|
||||
{
|
||||
//int card;
|
||||
printk("[openair][CLEANUP MODULE]\n");
|
||||
|
||||
// stop any ongoing acquisition
|
||||
//for (card = 0; card < number_of_cards; card++)
|
||||
// exmimo_send_pccmd(card, EXMIMO_STOP);
|
||||
|
||||
openair_cleanup();
|
||||
}
|
||||
|
||||
static void openair_cleanup(void)
|
||||
{
|
||||
int card;
|
||||
|
||||
if ( openair_chrdev_registered )
|
||||
unregister_chrdev(major,"openair");
|
||||
|
||||
openair_chrdev_registered = 0;
|
||||
|
||||
for (card=0; card<number_of_cards; card++) {
|
||||
// unregister interrupt
|
||||
if ( openair_irq_enabled[card] ) {
|
||||
printk("[openair][CLEANUP] disabling interrupt card %d\n", card);
|
||||
|
||||
if (irq!=0)
|
||||
free_irq(irq, pdev[card] );
|
||||
else
|
||||
free_irq( pdev[card]->irq, pdev[card] );
|
||||
|
||||
openair_irq_enabled[card] = 0;
|
||||
}
|
||||
|
||||
exmimo_firmware_cleanup( card );
|
||||
|
||||
if ( bar[card] ) {
|
||||
printk("unmap bar[%d] %p\n", card, bar[card]);
|
||||
iounmap((void *)bar[card]);
|
||||
}
|
||||
|
||||
if ( mmio_start[card] ) {
|
||||
printk("release mem[%d] %x\n", card, (unsigned int)mmio_start[card]);
|
||||
release_mem_region(mmio_start[card],256);
|
||||
}
|
||||
|
||||
if ( openair_pci_device_enabled[card] ) {
|
||||
printk("pci_disable_device %i\n", card);
|
||||
pci_disable_device( pdev[card] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MODULE_AUTHOR ("Raymond KNOPP <raymond.knopp@eurecom.fr>, Matthias IHMIG <matthias.ihmig@eurecom.fr>, Florian KALTENBERGER <florian.kaltenberger@eurecom.fr>, Riadh GHADDAB <riadh.ghaddab@eurecom.fr>");
|
||||
MODULE_DESCRIPTION ("openair ExpressMIMO/ExpressMIMO3 driver");
|
||||
MODULE_LICENSE ("GPL");
|
||||
module_init (openair_init_module);
|
||||
module_exit (openair_cleanup_module);
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
PCI=`lspci -m | grep Xilinx`
|
||||
if [ -z "$PCI" ]; then
|
||||
echo "No card found. Stopping!"
|
||||
return
|
||||
fi
|
||||
|
||||
SLOT_NUMBER=`echo $PCI | awk -F\" '{print $1}'`
|
||||
|
||||
setpci -s $SLOT_NUMBER 60.b=10
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef __VARS_H__
|
||||
#define __VARS_H__
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#ifdef KERNEL2_6
|
||||
#include <linux/slab.h>
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
#include "pcie_interface.h"
|
||||
|
||||
unsigned int openair_irq_enabled[MAX_CARDS] = INIT_ZEROS;
|
||||
unsigned int openair_chrdev_registered = 0;
|
||||
unsigned int openair_pci_device_enabled[MAX_CARDS] = INIT_ZEROS;
|
||||
|
||||
struct pci_dev *pdev[MAX_CARDS] = INIT_ZEROS;
|
||||
void __iomem *bar[MAX_CARDS] = INIT_ZEROS;
|
||||
|
||||
resource_size_t mmio_start[MAX_CARDS] = INIT_ZEROS;
|
||||
resource_size_t mmio_length[MAX_CARDS];
|
||||
unsigned int mmio_flags[MAX_CARDS];
|
||||
|
||||
int major;
|
||||
|
||||
char number_of_cards;
|
||||
|
||||
// bigshm allocs a single larger block, used for shared structures and pointers
|
||||
dma_addr_t bigshm_head_phys[MAX_CARDS] = INIT_ZEROS;
|
||||
void *bigshm_head[MAX_CARDS] = INIT_ZEROS;
|
||||
void *bigshm_currentptr[MAX_CARDS];
|
||||
|
||||
dma_addr_t pphys_exmimo_pci_phys[MAX_CARDS]; // phys pointer to pci_bot structure in shared mem
|
||||
|
||||
exmimo_pci_interface_bot_t *p_exmimo_pci_phys[MAX_CARDS] = INIT_ZEROS; // inside struct has physical (DMA) pointers to pci_bot memory blocks
|
||||
|
||||
exmimo_pci_interface_bot_virtual_t exmimo_pci_kvirt[MAX_CARDS]; // has virtual pointers to pci_bot memory blocks
|
||||
|
||||
#endif
|
||||
@@ -1,19 +0,0 @@
|
||||
Here are the PC kernel drivers.
|
||||
|
||||
Currently, there are two drivers:
|
||||
|
||||
|
||||
telecomparistech/
|
||||
---
|
||||
- supports the new ExpressMIMO-1 bitstream by Telecom Paristech
|
||||
- uses command two command FIFOs to pass commands between Leon<->PC
|
||||
|
||||
|
||||
eurecom/
|
||||
---
|
||||
- supports the legacy ExpressMIMO-1 bitstream
|
||||
- supports ExpressMIMO-2, also multiple cards for sample-synchronous acquisition
|
||||
- uses CONTROLx registers to pass commands between Leon<->PC
|
||||
- allocates buffers in kernel space using pci_alloc_consistent
|
||||
- used by ../USERSPACE/LIB/openair0_lib for simple access through userspace
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
obj-m += em1.o
|
||||
em1-objs = em1_drv.o em1_fifos.o em1_rw.o em1_dev.o em1_ioctl.o em1_mmap.o
|
||||
|
||||
default:
|
||||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
|
||||
clean:
|
||||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "em1_drv.h"
|
||||
|
||||
static irqreturn_t irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
uint32_t irqval;
|
||||
irqreturn_t res = IRQ_NONE;
|
||||
struct em1_private_s *pv = dev_id;
|
||||
|
||||
spin_lock(&pv->lock);
|
||||
irqval = ioread32(pv->base + REG_ISTATUS);
|
||||
|
||||
if (irqval & IRQ_MSK) {
|
||||
// printk(KERN_DEBUG "em1 irqval 0x%x", irqval);
|
||||
|
||||
if ((irqval & EM1_NOTFULL_IRQ) && (pv->busy & EM1_BUSY_FIFO_W)) {
|
||||
wake_up_all(&pv->rq_wait_fifo_w);
|
||||
res = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if ((irqval & EM1_NOTEMPTY_IRQ) && (pv->busy & EM1_BUSY_FIFO_R)) {
|
||||
wake_up_all(&pv->rq_wait_fifo_r);
|
||||
res = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (irqval & EM1_DMA_IRQ) {
|
||||
pv->dma_done = irqval >> 16;
|
||||
wake_up_all(&pv->rq_wait_dma);
|
||||
res = IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&pv->lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
int __devinit em1_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
{
|
||||
int ret, i;
|
||||
resource_size_t len, start;
|
||||
struct em1_private_s *pv;
|
||||
|
||||
for (i = 0; i < MAX_EM1_DEVICES; i++)
|
||||
if (em1_devices[i] == NULL)
|
||||
goto found;
|
||||
|
||||
printk("exmimo1 : Too many devices");
|
||||
return -ENOENT;
|
||||
found:
|
||||
|
||||
pv = kmalloc(sizeof(struct em1_private_s), GFP_KERNEL);
|
||||
em1_devices[i] = pv;
|
||||
|
||||
if (pv == NULL) {
|
||||
printk(KERN_ERR "exmimo1 : Out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pci_set_drvdata(dev, pv);
|
||||
|
||||
ret = pci_enable_device(dev);
|
||||
|
||||
if (ret <0) {
|
||||
printk(KERN_WARNING "exmimo1 : Problem when enabling PCI device\n");
|
||||
goto err_kfree;
|
||||
}
|
||||
|
||||
/* Set interrupt handler function */
|
||||
ret = request_irq(dev->irq, &irq_handler, IRQF_SHARED, "exmimo1", pv);
|
||||
|
||||
if (ret <0) {
|
||||
printk(KERN_WARNING "exmimo1 : Problem when requesting interrupt for PCI device\n");
|
||||
goto err_disable;
|
||||
}
|
||||
|
||||
/* Address of first PCI BAR region */
|
||||
len = pci_resource_len(dev, 0);
|
||||
start = pci_resource_start(dev, 0);
|
||||
printk("exmimo1 : len : %d\n", len);
|
||||
printk("exmimo1 : start : %x\n", start);
|
||||
|
||||
if (check_mem_region(start, len) < 0) {
|
||||
printk(KERN_ERR "exmimo1 : Cannot check memory region 0, already in use\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_req_irq;
|
||||
}
|
||||
|
||||
if (request_mem_region(start, len, "exmimo") == NULL) {
|
||||
printk(KERN_ERR "exmimo1 : Cannot get memory region 0, already in use\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_req_irq;
|
||||
}
|
||||
|
||||
pv->base = pci_iomap(dev, 0, len);
|
||||
printk(KERN_DEBUG "exmimo1 : base address := 0x%x\n", (unsigned int)pv->base);
|
||||
|
||||
pci_set_master(dev);
|
||||
|
||||
init_waitqueue_head(&pv->rq_wait_fifo_r);
|
||||
init_waitqueue_head(&pv->rq_wait_fifo_w);
|
||||
init_waitqueue_head(&pv->rq_wait_dma);
|
||||
|
||||
pv->ie = 0;
|
||||
pv->busy = 0;
|
||||
pv->fifo_read_left = 0;
|
||||
pv->fifo_write_left = 0;
|
||||
spin_lock_init(&pv->lock);
|
||||
pv->dev = &dev->dev;
|
||||
pv->pdev = dev;
|
||||
|
||||
/* Get DMA done counter */
|
||||
pv->dma_started = pv->dma_done = ioread32(pv->base + REG_ISTATUS) >> 16;
|
||||
|
||||
/* Disable interrupt */
|
||||
iowrite32(pv->ie, pv->base + REG_FSTATUS);
|
||||
|
||||
return 0;
|
||||
|
||||
err_req_irq:
|
||||
free_irq(dev->irq, pv);
|
||||
err_disable:
|
||||
pci_disable_device(dev);
|
||||
err_kfree:
|
||||
kfree(pv);
|
||||
em1_devices[i] = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __devexit em1_remove(struct pci_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
struct em1_private_s *pv = pci_get_drvdata(dev);
|
||||
resource_size_t len, start;
|
||||
|
||||
printk(KERN_DEBUG "exmimo1 : remove()\n");
|
||||
|
||||
iounmap((void*)pv->base);
|
||||
/* Address of first PCI BAR region */
|
||||
|
||||
len = pci_resource_len(dev, 0);
|
||||
start = pci_resource_start(dev, 0);
|
||||
release_mem_region(start, len);
|
||||
|
||||
// Unregister interrupt
|
||||
free_irq(dev->irq, pv);
|
||||
|
||||
pci_disable_device(dev);
|
||||
|
||||
//Free private data
|
||||
kfree(pv);
|
||||
|
||||
for (i = 0; i < MAX_EM1_DEVICES; i++)
|
||||
if (em1_devices[i] == pv)
|
||||
em1_devices[i] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* c-file-style: "linux"
|
||||
* indent-tabs-mode: t
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -1,181 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "em1_drv.h"
|
||||
|
||||
MODULE_AUTHOR("Alexandre Becoulet, Cerdan Sebastien");
|
||||
MODULE_DESCRIPTION("Driver for Express-Mimo 1 board");
|
||||
MODULE_SUPPORTED_DEVICE("Express-Mimo 1");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
static int major = 256;
|
||||
struct em1_private_s *em1_devices[MAX_EM1_DEVICES] = {};
|
||||
|
||||
int em1_user_op_enter(struct em1_private_s *pv, wait_queue_t *wait,
|
||||
wait_queue_head_t *wh, int busy_flag, int new_state)
|
||||
{
|
||||
add_wait_queue(wh, wait);
|
||||
|
||||
spin_lock_irq(&pv->lock);
|
||||
|
||||
/* wait for other tasks to leave */
|
||||
while (pv->busy & busy_flag) {
|
||||
if (new_state == TASK_INTERRUPTIBLE &&
|
||||
signal_pending(current))
|
||||
return 1;
|
||||
|
||||
set_current_state(new_state);
|
||||
spin_unlock_irq(&pv->lock);
|
||||
schedule();
|
||||
spin_lock_irq(&pv->lock);
|
||||
}
|
||||
|
||||
pv->busy |= busy_flag;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void em1_user_op_leave(struct em1_private_s *pv, wait_queue_t *wait,
|
||||
wait_queue_head_t *wh)
|
||||
{
|
||||
set_current_state(TASK_RUNNING);
|
||||
spin_unlock_irq(&pv->lock);
|
||||
|
||||
remove_wait_queue(wh, wait);
|
||||
|
||||
// wake other waiting tasks
|
||||
wake_up_all(wh);
|
||||
}
|
||||
|
||||
static int em1_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int i;
|
||||
//FIXME Lock list access
|
||||
|
||||
for (i = 0; i < MAX_EM1_DEVICES; i++) {
|
||||
struct em1_private_s *pv = em1_devices[i];
|
||||
|
||||
if (pv != NULL && i == iminor(inode)) {
|
||||
struct em1_file_s *fpv = kmalloc(sizeof(struct em1_file_s), GFP_KERNEL);
|
||||
|
||||
if (!fpv)
|
||||
return -ENOMEM;
|
||||
|
||||
printk(KERN_DEBUG "exmimo1 : open()\n");
|
||||
|
||||
fpv->pv = pv;
|
||||
file->private_data = fpv;
|
||||
fpv->read.addr = 0;
|
||||
fpv->write.addr = 0;
|
||||
memset(fpv->mmap_list, 0, sizeof(fpv->mmap_list));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int em1_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
int i;
|
||||
struct em1_file_s *fpv = file->private_data;
|
||||
|
||||
em1_unlock_user_page(&fpv->read);
|
||||
em1_unlock_user_page(&fpv->write);
|
||||
|
||||
for (i = 0; i < MAX_EM1_MMAP; i++)
|
||||
if (fpv->mmap_list[i].virt) {
|
||||
struct em1_mmap_ctx * mctx = fpv->mmap_list + i;
|
||||
pci_free_consistent(fpv->pv->pdev, mctx->size, mctx->virt, mctx->phys);
|
||||
}
|
||||
|
||||
kfree(fpv);
|
||||
|
||||
printk(KERN_DEBUG "exmimo1 : release()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations em1_fops = {
|
||||
.read = em1_read,
|
||||
.write = em1_write,
|
||||
.open = em1_open,
|
||||
.release = em1_release,
|
||||
.ioctl = em1_ioctl,
|
||||
.mmap = em1_mmap,
|
||||
};
|
||||
|
||||
/* Supported devices */
|
||||
static struct pci_device_id em1_pci_tbl[] = {
|
||||
{ XILINX_VENDOR, XILINX_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
|
||||
{0,}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, em1_pci_tbl);
|
||||
|
||||
|
||||
static struct pci_driver em1_driver = {
|
||||
.name = "exmimo1",
|
||||
.id_table = em1_pci_tbl,
|
||||
.probe = em1_probe,
|
||||
.remove = em1_remove,
|
||||
};
|
||||
|
||||
static int __init em1_init(void)
|
||||
{
|
||||
int ret;
|
||||
printk(KERN_DEBUG "exmimo1 : Hello world!\n");
|
||||
|
||||
ret = pci_register_driver(&em1_driver);
|
||||
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "exmimo1 : Error when registering PCI driver\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = register_chrdev(major, "exmimo1", &em1_fops);
|
||||
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "exmimo1 : Error when registering char device\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit em1_cleanup(void)
|
||||
{
|
||||
printk(KERN_DEBUG "exmimo1 : Goodbye world!\n");
|
||||
unregister_chrdev(major, "exmimo1");
|
||||
pci_unregister_driver(&em1_driver);
|
||||
|
||||
}
|
||||
|
||||
module_init(em1_init);
|
||||
module_exit(em1_cleanup);
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* c-file-style: "linux"
|
||||
* indent-tabs-mode: t
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef USER_APP
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock_types.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
|
||||
/*
|
||||
Operations:
|
||||
|
||||
- DMA from pc to em1: The Linux driver writes a 4 words command to
|
||||
the control fifo [0x103 phys_hi phys_lo size] and waits for a DMA
|
||||
end interrupt from the em1 board.
|
||||
|
||||
This operation is requested by the user application using the
|
||||
write syscall. The buffer provided by the application must not
|
||||
span across multiple pages.
|
||||
|
||||
- DMA from em1 to pc: The Linux driver writes a 4 words command to
|
||||
the control fifo [0x203 phys_hi phys_lo size] and waits for a DMA
|
||||
end interrupt from the em1 board.
|
||||
|
||||
This operation is requested by the user application using the read
|
||||
syscall. The buffer provided by the application must not span
|
||||
across multiple pages.
|
||||
*/
|
||||
|
||||
#define XILINX_VENDOR 0x10ee
|
||||
#define XILINX_ID 0x0007
|
||||
|
||||
#define REG_FCMD 0x0
|
||||
#define REG_FSTATUS 0x4
|
||||
#define REG_ISTATUS 0x8
|
||||
#define REG_STATUS 0x10
|
||||
#define REG_PCI_BASE_L 0x28
|
||||
#define REG_PCI_BASE_H 0x2c
|
||||
|
||||
#define PUSH_FULL_STATUS_MSK (1 << 3)
|
||||
#define POP_EMPTY_STATUS_MSK (1 << 2)
|
||||
|
||||
#define EM1_NOTFULL_IRQ (1 << 0)
|
||||
#define EM1_NOTEMPTY_IRQ (1 << 1)
|
||||
#define EM1_DMA_IRQ (1 << 2)
|
||||
|
||||
#define PUSH_NO_FULL_IRQ_MSK (1 << 19)
|
||||
#define POP_NO_EMPTY_IRQ_MSK (1 << 18)
|
||||
|
||||
#define IRQ_MSK 7
|
||||
|
||||
#define EM1_CMD_OP_DMA_PC2EM1 0x0100
|
||||
#define EM1_CMD_OP_DMA_EM12PC 0x0200
|
||||
|
||||
#define MAX_EM1_DEVICES 8
|
||||
#define MAX_EM1_MMAP 4
|
||||
|
||||
#define EM1_BUSY_FIFO_R 1
|
||||
#define EM1_BUSY_FIFO_W 2
|
||||
#define EM1_BUSY_DMA 4
|
||||
|
||||
struct em1_private_s;
|
||||
|
||||
struct em1_page_s {
|
||||
uintptr_t addr;
|
||||
struct page *page;
|
||||
};
|
||||
|
||||
struct em1_mmap_ctx {
|
||||
void* virt;
|
||||
dma_addr_t phys;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct em1_file_s {
|
||||
struct em1_private_s *pv;
|
||||
struct em1_page_s read;
|
||||
struct em1_page_s write;
|
||||
struct em1_mmap_ctx mmap_list[MAX_EM1_MMAP];
|
||||
};
|
||||
|
||||
struct em1_private_s {
|
||||
struct pci_dev *pdev;
|
||||
struct device *dev;
|
||||
spinlock_t lock;
|
||||
|
||||
/* memeory mapped device base address */
|
||||
void * base;
|
||||
|
||||
/* wait queues */
|
||||
wait_queue_head_t rq_wait_fifo_r;
|
||||
wait_queue_head_t rq_wait_fifo_w;
|
||||
wait_queue_head_t rq_wait_dma;
|
||||
|
||||
/* Number of fifo words left to read or write */
|
||||
size_t fifo_read_left;
|
||||
size_t fifo_write_left;
|
||||
|
||||
/* Cached interrupt enabled value */
|
||||
uint32_t ie;
|
||||
/* Driver busy operations flags */
|
||||
int busy;
|
||||
|
||||
/* Completed DMA transfer counters */
|
||||
uint16_t dma_started, dma_done;
|
||||
};
|
||||
|
||||
extern struct em1_private_s *em1_devices[MAX_EM1_DEVICES];
|
||||
|
||||
/* em1_drv.c */
|
||||
int em1_user_op_enter(struct em1_private_s *pv, wait_queue_t *wait,
|
||||
wait_queue_head_t *wh, int busy_flag, int new_state);
|
||||
void em1_user_op_leave(struct em1_private_s *pv, wait_queue_t *wait,
|
||||
wait_queue_head_t *wh);
|
||||
|
||||
/* em1_rw.c: read and write syscalls */
|
||||
int em1_lock_user_page(struct em1_page_s *ep, uintptr_t addr, int direction);
|
||||
void em1_unlock_user_page(struct em1_page_s *fpv);
|
||||
ssize_t em1_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos);
|
||||
ssize_t em1_read(struct file *file, char __user *buf, size_t size, loff_t *ppos);
|
||||
|
||||
/* em1_dev.c */
|
||||
int __devinit em1_probe(struct pci_dev *dev, const struct pci_device_id *id);
|
||||
void __devexit em1_remove(struct pci_dev *dev);
|
||||
|
||||
/* em1_fifos.c */
|
||||
int em1_fifo_write(struct em1_private_s *pv, const uint32_t *buf, size_t count);
|
||||
int em1_fifo_read(struct em1_private_s *pv, uint32_t *buf, size_t count);
|
||||
|
||||
/* em1_ioctl.c */
|
||||
int em1_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
/* em1_mmap.c */
|
||||
int em1_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
|
||||
#endif
|
||||
|
||||
enum em1_ioctl_cmd {
|
||||
EM1_IOCTL_FIFO_WRITE,
|
||||
EM1_IOCTL_FIFO_READ,
|
||||
};
|
||||
|
||||
#define EM1_MAX_FIFO_PAYLOAD 128
|
||||
|
||||
struct em1_ioctl_fifo_params {
|
||||
uint32_t *words;
|
||||
size_t count;
|
||||
};
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* c-file-style: "linux"
|
||||
* indent-tabs-mode: t
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
sudo insmod em1.ko
|
||||
sudo mknod /dev/exmimo1 c 256 0
|
||||
sudo chmod 666 /dev/exmimo1
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "em1_drv.h"
|
||||
|
||||
int em1_fifo_write(struct em1_private_s *pv, const uint32_t *buf, size_t count)
|
||||
{
|
||||
int retval = 0;
|
||||
size_t cnt = count;
|
||||
|
||||
while (cnt > 0) {
|
||||
//read fifo state register
|
||||
uint32_t data = ioread32(pv->base + REG_FSTATUS);
|
||||
|
||||
if (data & PUSH_FULL_STATUS_MSK) {
|
||||
/* Enable push fifo no full interrupt */
|
||||
pv->ie |= PUSH_NO_FULL_IRQ_MSK;
|
||||
iowrite32(pv->ie, pv->base + REG_FSTATUS);
|
||||
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
spin_unlock_irq(&pv->lock);
|
||||
// printk(KERN_DEBUG "sleep %08x %i", data, current->state);
|
||||
schedule();
|
||||
// printk(KERN_DEBUG "wake");
|
||||
|
||||
spin_lock_irq(&pv->lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
data = *buf++;
|
||||
cnt--;
|
||||
iowrite32(data, pv->base + REG_FCMD);
|
||||
|
||||
if (!pv->fifo_write_left) {
|
||||
/* Size must be retrieved from POP fifo entry */
|
||||
pv->fifo_write_left = data & 0xFF;
|
||||
} else {
|
||||
pv->fifo_write_left--;
|
||||
}
|
||||
|
||||
if (!pv->fifo_write_left)
|
||||
break;
|
||||
}
|
||||
|
||||
pv->ie &= ~PUSH_NO_FULL_IRQ_MSK;
|
||||
iowrite32(pv->ie, pv->base + REG_FSTATUS);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int em1_fifo_read(struct em1_private_s *pv, uint32_t *buf, size_t count)
|
||||
{
|
||||
int retval = 0;
|
||||
size_t cnt = count;
|
||||
|
||||
while (cnt > 0) {
|
||||
//read fifo state register
|
||||
uint32_t data = ioread32(pv->base + REG_FSTATUS);
|
||||
|
||||
if (data & POP_EMPTY_STATUS_MSK) {
|
||||
/* Enable pop fifo no empty interrupt */
|
||||
pv->ie |= POP_NO_EMPTY_IRQ_MSK;
|
||||
iowrite32(pv->ie, pv->base + REG_FSTATUS);
|
||||
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
spin_unlock_irq(&pv->lock);
|
||||
schedule();
|
||||
spin_lock_irq(&pv->lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
data = ioread32(pv->base + REG_FCMD);
|
||||
*buf++ = data;
|
||||
cnt--;
|
||||
|
||||
if (!pv->fifo_read_left) {
|
||||
/* Size must be retrieved from POP fifo entry */
|
||||
pv->fifo_read_left = data & 0xFF;
|
||||
} else {
|
||||
pv->fifo_read_left--;
|
||||
}
|
||||
|
||||
if (!pv->fifo_read_left)
|
||||
break;
|
||||
}
|
||||
|
||||
pv->ie &= ~POP_NO_EMPTY_IRQ_MSK;
|
||||
iowrite32(pv->ie, pv->base + REG_FSTATUS);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "em1_drv.h"
|
||||
|
||||
static int em1_ioctl_fifo_write(struct em1_private_s *pv, size_t size, uint32_t *words)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
int res = -ERESTARTSYS;
|
||||
|
||||
if (!em1_user_op_enter(pv, &wait, &pv->rq_wait_fifo_w,
|
||||
EM1_BUSY_FIFO_W, TASK_INTERRUPTIBLE)) {
|
||||
res = em1_fifo_write(pv, words, size);
|
||||
res = 0;
|
||||
pv->busy &= ~EM1_BUSY_FIFO_W;
|
||||
}
|
||||
|
||||
em1_user_op_leave(pv, &wait, &pv->rq_wait_fifo_w);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int em1_ioctl_fifo_read(struct em1_private_s *pv, size_t size, uint32_t *words)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
int res = -ERESTARTSYS;
|
||||
|
||||
if (!em1_user_op_enter(pv, &wait, &pv->rq_wait_fifo_r,
|
||||
EM1_BUSY_FIFO_R, TASK_INTERRUPTIBLE)) {
|
||||
res = em1_fifo_read(pv, words, size);
|
||||
pv->busy &= ~EM1_BUSY_FIFO_R;
|
||||
}
|
||||
|
||||
em1_user_op_leave(pv, &wait, &pv->rq_wait_fifo_r);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int em1_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct em1_file_s *fpv = file->private_data;
|
||||
struct em1_private_s *pv = fpv->pv;
|
||||
|
||||
switch ((enum em1_ioctl_cmd)cmd) {
|
||||
case EM1_IOCTL_FIFO_WRITE: {
|
||||
struct em1_ioctl_fifo_params p;
|
||||
uint32_t w[EM1_MAX_FIFO_PAYLOAD];
|
||||
|
||||
if (copy_from_user(&p, (void*)arg, sizeof(p)))
|
||||
return -EFAULT;
|
||||
|
||||
if (p.count > EM1_MAX_FIFO_PAYLOAD)
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(w, p.words, p.count * sizeof(uint32_t)))
|
||||
return -EFAULT;
|
||||
|
||||
return em1_ioctl_fifo_write(pv, p.count, w);
|
||||
}
|
||||
|
||||
case EM1_IOCTL_FIFO_READ: {
|
||||
struct em1_ioctl_fifo_params p;
|
||||
uint32_t w[EM1_MAX_FIFO_PAYLOAD];
|
||||
int res;
|
||||
|
||||
if (copy_from_user(&p, (void*)arg, sizeof(p)))
|
||||
return -EFAULT;
|
||||
|
||||
if (p.count > EM1_MAX_FIFO_PAYLOAD)
|
||||
return -EINVAL;
|
||||
|
||||
res = em1_ioctl_fifo_read(pv, p.count, w);
|
||||
|
||||
if (!res && copy_to_user(p.words, w, p.count * sizeof(uint32_t)))
|
||||
return -EFAULT;
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* c-file-style: "linux"
|
||||
* indent-tabs-mode: t
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "em1_drv.h"
|
||||
|
||||
|
||||
int em1_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
|
||||
int i;
|
||||
struct em1_file_s *fpv = filp->private_data;
|
||||
struct em1_mmap_ctx * mctx;
|
||||
size_t size = vma->vm_end - vma->vm_start;
|
||||
void * virt;
|
||||
dma_addr_t phys;
|
||||
|
||||
printk(KERN_DEBUG "exmimo1 : mmap()\n");
|
||||
|
||||
if (vma->vm_end <= vma->vm_start)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < MAX_EM1_MMAP; i++) {
|
||||
mctx = fpv->mmap_list + i;
|
||||
|
||||
if (mctx->virt == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == MAX_EM1_MMAP)
|
||||
return -ENOMEM;
|
||||
|
||||
virt = pci_alloc_consistent(fpv->pv->pdev, size, &phys);
|
||||
|
||||
if (virt < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (remap_pfn_range(vma, vma->vm_start, phys >> PAGE_SHIFT, size, vma->vm_page_prot))
|
||||
return -EAGAIN;
|
||||
|
||||
mctx->virt = virt;
|
||||
mctx->phys = phys;
|
||||
mctx->size = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* c-file-style: "linux"
|
||||
* indent-tabs-mode: t
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "em1_drv.h"
|
||||
|
||||
void em1_unlock_user_page(struct em1_page_s *ep)
|
||||
{
|
||||
if (ep->addr != 0) {
|
||||
// printk(KERN_DEBUG "unlocking user read page");
|
||||
page_cache_release(ep->page);
|
||||
ep->addr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int em1_lock_user_page(struct em1_page_s *ep, uintptr_t addr, int direction)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (ep->addr == addr)
|
||||
return 0;
|
||||
|
||||
em1_unlock_user_page(ep);
|
||||
|
||||
// printk(KERN_DEBUG "locking user page for addr %p", addr);
|
||||
|
||||
down_read(¤t->mm->mmap_sem);
|
||||
res = get_user_pages(current, current->mm, addr & ~(PAGE_SIZE-1),
|
||||
1, direction == DMA_FROM_DEVICE,
|
||||
0, /* don't force */ &ep->page, NULL);
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
|
||||
if (res != 1) {
|
||||
printk(KERN_ERR "exmimo1: get_user_pages error");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ep->addr = addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t em1_dma_access(struct em1_file_s *fpv, char __user *buf,
|
||||
size_t size, int direction, int opcode)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
struct em1_private_s *pv = fpv->pv;
|
||||
uint32_t cmd[4];
|
||||
uintptr_t addr = (uintptr_t)buf;
|
||||
uintptr_t end = (uintptr_t)buf + size - 1;
|
||||
struct em1_page_s *page;
|
||||
int fres = -ERESTARTSYS;
|
||||
uint16_t dma_this;
|
||||
|
||||
/* check single page span */
|
||||
if ((addr & ~(PAGE_SIZE-1)) != (end & ~(PAGE_SIZE-1)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!access_ok(direction == DMA_FROM_DEVICE ? VERIFY_WRITE : VERIFY_READ, buf, size))
|
||||
return -EFAULT;
|
||||
|
||||
page = direction == DMA_FROM_DEVICE ? &fpv->read : &fpv->write;
|
||||
|
||||
if (em1_lock_user_page(page, addr, direction))
|
||||
return -EFAULT;
|
||||
|
||||
addr = dma_map_page(pv->dev, page->page, 0, PAGE_SIZE, direction);
|
||||
|
||||
/* prepare command for em1 */
|
||||
cmd[0] = opcode | 3;
|
||||
cmd[1] = sizeof(addr) > 4 ? (uint32_t)(addr >> 32) : 0;
|
||||
cmd[2] = (uint32_t)addr;
|
||||
cmd[3] = size;
|
||||
|
||||
if (!em1_user_op_enter(pv, &wait, &pv->rq_wait_fifo_w,
|
||||
EM1_BUSY_FIFO_W, TASK_INTERRUPTIBLE)) {
|
||||
/* send command */
|
||||
fres = em1_fifo_write(pv, cmd, 4);
|
||||
pv->busy &= ~EM1_BUSY_FIFO_W;
|
||||
dma_this = ++pv->dma_started;
|
||||
}
|
||||
|
||||
em1_user_op_leave(pv, &wait, &pv->rq_wait_fifo_w);
|
||||
|
||||
// printk(KERN_DEBUG "exmimo1: dma fifo write %i, addr %x", fres, addr);
|
||||
|
||||
if (!fres) {
|
||||
if (!em1_user_op_enter(pv, &wait, &pv->rq_wait_dma,
|
||||
EM1_BUSY_DMA, TASK_UNINTERRUPTIBLE)) {
|
||||
// printk(KERN_DEBUG "wait dma");
|
||||
|
||||
/* wait for DMA end irq */
|
||||
while ((int16_t)(dma_this - pv->dma_done) > 0) {
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
spin_unlock_irq(&pv->lock);
|
||||
schedule();
|
||||
spin_lock_irq(&pv->lock);
|
||||
}
|
||||
|
||||
pv->busy &= ~EM1_BUSY_DMA;
|
||||
fres = size;
|
||||
}
|
||||
|
||||
em1_user_op_leave(pv, &wait, &pv->rq_wait_dma);
|
||||
}
|
||||
|
||||
dma_unmap_page(pv->dev, addr, PAGE_SIZE, direction);
|
||||
|
||||
if (direction == DMA_FROM_DEVICE)
|
||||
SetPageDirty(page->page);
|
||||
|
||||
return fres;
|
||||
}
|
||||
|
||||
ssize_t em1_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos)
|
||||
{
|
||||
return em1_dma_access(file->private_data, (char*)buf, size,
|
||||
DMA_TO_DEVICE, EM1_CMD_OP_DMA_PC2EM1);
|
||||
}
|
||||
|
||||
ssize_t em1_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
|
||||
{
|
||||
return em1_dma_access(file->private_data, buf, size,
|
||||
DMA_FROM_DEVICE, EM1_CMD_OP_DMA_EM12PC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* c-file-style: "linux"
|
||||
* indent-tabs-mode: t
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
# compiles the example
|
||||
|
||||
OPENAIRTARGETS_DIR ?=../../../..
|
||||
|
||||
OPENAIROBJS += $(OPENAIRTARGETS_DIR)/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.o
|
||||
CFLAGS += -I$(OPENAIRTARGETS_DIR)/ARCH/EXMIMO/USERSPACE/LIB -I$(OPENAIRTARGETS_DIR)/ARCH/EXMIMO/DEFS
|
||||
|
||||
|
||||
example: example.o $(OPENAIROBJS)
|
||||
gcc -o $@ $(CFLAGS) -lm $(OPENAIROBJS) $<
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o *~
|
||||
rm -f example
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "openair0_lib.h"
|
||||
|
||||
exmimo_config_t *p_exmimo_config;
|
||||
exmimo_id_t *p_exmimo_id;
|
||||
|
||||
unsigned int build_rflocal(txi, txq, rxi, rxq)
|
||||
{
|
||||
return (txi + txq<<6 + rxi<<12 + rxq<<18);
|
||||
}
|
||||
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe)
|
||||
{
|
||||
return (dcoff_i_rxfe + dcoff_q_rxfe<<8);
|
||||
}
|
||||
|
||||
void test_config(int card, int ant, unsigned int rf_mode)
|
||||
{
|
||||
p_exmimo_config->framing.eNB_flag = 0;
|
||||
p_exmimo_config->framing.tdd_config = 0;
|
||||
|
||||
p_exmimo_config->rf.rf_freq_rx[ant] = 1907600000;
|
||||
p_exmimo_config->rf.rf_freq_tx[ant] = 1907600000;;
|
||||
p_exmimo_config->rf.rx_gain[ant][0] = 20;
|
||||
p_exmimo_config->rf.tx_gain[ant][0] = 10;
|
||||
p_exmimo_config->rf.rf_mode[ant] = rf_mode;
|
||||
|
||||
p_exmimo_config->rf.rf_local[ant] = build_rflocal(20,25,26,04);
|
||||
p_exmimo_config->rf.rf_rxdc[ant] = build_rfdc(128, 128);
|
||||
p_exmimo_config->rf.rf_vcocal[ant] = 0xE<<6 + 0xE;
|
||||
|
||||
openair0_dump_config( card );
|
||||
}
|
||||
|
||||
void read_firmware_buffer(int card)
|
||||
{
|
||||
int i;
|
||||
unsigned int *p= (unsigned int *) (openair0_exmimo_pci[card].firmware_block_ptr);
|
||||
printf("firmware_buffer: \n");
|
||||
|
||||
for (i=0; i<0x30; i++)
|
||||
printf("u32 fwbuf[%d]: value=%08X\n", i, p[i]);
|
||||
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int ret, card, ant;
|
||||
unsigned int my_rf_mode;
|
||||
|
||||
unsigned int *p_rx_ant0, *p_tx_ant0;
|
||||
|
||||
|
||||
ret = openair0_open();
|
||||
|
||||
if ( ret != 0 ) {
|
||||
if (ret == -1)
|
||||
printf("Error opening /dev/openair0");
|
||||
|
||||
if (ret == -2)
|
||||
printf("Error mapping bigshm");
|
||||
|
||||
if (ret == -3)
|
||||
printf("Error mapping RX or TX buffer");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
my_rf_mode = RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM;
|
||||
my_rf_mode += DMAMODE_RX + DMAMODE_TX;
|
||||
|
||||
printf ("Detected %d number of cards.\n", openair0_num_detected_cards);
|
||||
|
||||
card =0;
|
||||
ant =0;
|
||||
|
||||
printf ("Will configure card %d, antenna %d\n", card, ant);
|
||||
|
||||
p_exmimo_config = openair0_exmimo_pci[card].exmimo_config_ptr;
|
||||
p_exmimo_id = openair0_exmimo_pci[card].exmimo_id_ptr;
|
||||
|
||||
printf("Card %d: ExpressMIMO %d, HW Rev %d, SW Rev 0x%d\n", card, p_exmimo_id->board_exmimoversion, p_exmimo_id->board_hwrev, p_exmimo_id->board_swrev);
|
||||
|
||||
|
||||
//read_firmware_buffer(card);
|
||||
|
||||
|
||||
test_config( card, ant, my_rf_mode);
|
||||
|
||||
// pointer to data
|
||||
|
||||
p_rx_ant0 = openair0_exmimo_pci[ card ].adc_head[ ant ];
|
||||
p_tx_ant0 = openair0_exmimo_pci[ card ].dac_head[ ant ];
|
||||
|
||||
// do something with the data here
|
||||
|
||||
|
||||
openair0_close();
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "openair0_lib.h"
|
||||
#include "gain_control.h"
|
||||
//#define DEBUG_PHY
|
||||
#ifdef DEBUG_PHY
|
||||
#include "UTIL/LOG/log_extern.h"
|
||||
#endif
|
||||
|
||||
void gain_control_all (unsigned int rx_power_fil_dB, unsigned int card) {
|
||||
unsigned int ant;
|
||||
|
||||
for (ant=0; ant<4; ant++)
|
||||
gain_control (rx_power_fil_dB,ant,card);
|
||||
}
|
||||
|
||||
void gain_control (unsigned int rx_power_fil_dB, unsigned int ant, unsigned int card) {
|
||||
|
||||
exmimo_config_t *p_exmimo_config = openair0_exmimo_pci[card].exmimo_config_ptr;
|
||||
unsigned int rf_mode, rx_gain, LNA;
|
||||
|
||||
rx_gain = p_exmimo_config->rf.rx_gain[ant][0];
|
||||
rf_mode = p_exmimo_config->rf.rf_mode[ant];
|
||||
LNA = rf_mode & LNAGAINMASK;
|
||||
|
||||
// Gain control with hysterisis
|
||||
|
||||
if (rx_power_fil_dB < TARGET_RX_POWER_MIN) { //increase gain
|
||||
switch (LNA) {
|
||||
case LNAByp:
|
||||
p_exmimo_config->rf.rf_mode[ant] = (rf_mode & (~LNAGAINMASK)) | LNAMed;
|
||||
break;
|
||||
|
||||
case LNAMed:
|
||||
p_exmimo_config->rf.rf_mode[ant] = (rf_mode & (~LNAGAINMASK)) | LNAMax;
|
||||
break;
|
||||
|
||||
case LNAMax:
|
||||
p_exmimo_config->rf.rx_gain[ant][0] = min(30,rx_gain+5);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (rx_power_fil_dB > TARGET_RX_POWER_MAX) { //decrease gain
|
||||
if (rx_gain==0) {
|
||||
switch (LNA) {
|
||||
case LNAMax:
|
||||
p_exmimo_config->rf.rf_mode[ant] = (rf_mode & (~LNAGAINMASK)) | LNAMed;
|
||||
break;
|
||||
|
||||
case LNAMed:
|
||||
p_exmimo_config->rf.rf_mode[ant] = (rf_mode & (~LNAGAINMASK)) | LNAByp;
|
||||
break;
|
||||
|
||||
case LNAByp:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
p_exmimo_config->rf.rx_gain[ant][0] = max(0,(int)rx_gain-5);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PHY
|
||||
LOG_D(PHY,"AGC for chain %d: rx_power_fil_dB=%d, rx_gain=%d, LNA=%d (1=Byp,2=Med,3=Max)\n",ant,rx_power_fil_dB,p_exmimo_config->rf.rx_gain[ant][0],(p_exmimo_config->rf.rf_mode[ant]&LNAGAINMASK)>>14);
|
||||
#endif //DEBUG_PHY
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#define TARGET_RX_POWER 50 // Target digital power for the AGC
|
||||
#define TARGET_RX_POWER_MAX 53 // Maximum digital power for AGC
|
||||
#define TARGET_RX_POWER_MIN 48 // Minimum digital power for AGC
|
||||
#ifndef min
|
||||
#define min(a,b) (((a)<(b))?(a):(b))
|
||||
#define max(a,b) (((a)>(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
void gain_control_all (unsigned int rx_power_fil_dB, unsigned int card);
|
||||
void gain_control (unsigned int rx_power_fil_dB, unsigned int ant, unsigned int card);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** openair0_lib : API to interface with ExpressMIMO kernel driver
|
||||
*
|
||||
* Authors: Matthias Ihmig <matthias.ihmig@mytum.de>, 2013
|
||||
* Raymond Knopp <raymond.knopp@eurecom.fr>
|
||||
*
|
||||
* Changelog:
|
||||
* 28.01.2013: Initial version
|
||||
*/
|
||||
|
||||
#ifndef __OPENAIR0_LIB_H__
|
||||
#define __OPENAIR0_LIB_H__
|
||||
|
||||
#include "pcie_interface.h"
|
||||
#include "openair_device.h"
|
||||
#include "common_lib.h"
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
typedef enum {
|
||||
idle=0,
|
||||
waiting_for_synch,
|
||||
running
|
||||
} exmimo_daq_state_t;
|
||||
|
||||
typedef struct {
|
||||
pthread_t watchdog;
|
||||
pthread_attr_t watchdog_attr;
|
||||
struct sched_param watchdog_sched_param;
|
||||
pthread_mutex_t watchdog_mutex;
|
||||
int watchdog_exit;
|
||||
int wait_first_read;
|
||||
exmimo_daq_state_t daq_state;
|
||||
openair0_timestamp ts;
|
||||
openair0_timestamp last_ts_rx;
|
||||
int samples_per_tick;
|
||||
int samples_per_frame;
|
||||
int last_mbox;
|
||||
} exmimo_state_t;
|
||||
|
||||
// Use this to access shared memory (configuration structures, adc/dac data buffers, ...)
|
||||
// contains userspace pointers
|
||||
extern exmimo_pci_interface_bot_virtual_t openair0_exmimo_pci[MAX_CARDS];
|
||||
|
||||
extern int openair0_fd;
|
||||
|
||||
extern int openair0_num_antennas[MAX_CARDS];
|
||||
|
||||
extern int openair0_num_detected_cards;
|
||||
|
||||
// opens device and mmaps kernel memory and calculates interface and system_id userspace pointers
|
||||
// return 0 on success
|
||||
int openair0_open(void);
|
||||
|
||||
// close device and unmaps kernel memory
|
||||
// return 0 on success
|
||||
int openair0_close(void);
|
||||
|
||||
// trigger config update on card
|
||||
// return 0 on success
|
||||
int openair0_dump_config(int card);
|
||||
|
||||
// wrapper function for openair0_open (defined in common_lib.h)
|
||||
// int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg);
|
||||
|
||||
// copies data from openair0_cfg into exmimo_config and calls openair0_dump_config (for all cards)
|
||||
int openair0_config(openair0_config_t *openair0_cfg, int UE_flag);
|
||||
|
||||
// copies data from openair0_cfg into exmimo_config (frequencies and gains only); does not call openair0_dump_configu (no IOCTL)
|
||||
int openair0_reconfig(openair0_config_t *openair0_cfg);
|
||||
|
||||
// triggers recording of exactly 1 frame
|
||||
// in case of synchronized multiple cards, send this only to the master card
|
||||
// return 0 on success
|
||||
int openair0_get_frame(int card);
|
||||
|
||||
// starts continuous acquisition/transmission
|
||||
// in case of synchronized multiple cards, send this only to the master card
|
||||
// return 0 on success
|
||||
int openair0_start_rt_acquisition(int card);
|
||||
|
||||
// stops continuous acquitision/transmission and reset the RF chips
|
||||
// return 0 on success
|
||||
int openair0_stop(int card);
|
||||
|
||||
// stops continuous acquitision/transmission without resetting the RF chips
|
||||
// return 0 on success
|
||||
int openair0_stop_without_reset(int card);
|
||||
|
||||
// return the DAQ block counter
|
||||
unsigned int *openair0_daq_cnt(void);
|
||||
|
||||
// set the TX and RX frequencies (card 0 only for now, to retain USRP compatibility)
|
||||
int openair0_set_frequencies(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config);
|
||||
|
||||
int openair0_set_gains(openair0_device* device, openair0_config_t *openair0_cfg);
|
||||
|
||||
#endif
|
||||
@@ -1,6 +0,0 @@
|
||||
updatefw: updatefw.c
|
||||
$(CC) updatefw.c -o updatefw -I../../DEFS
|
||||
|
||||
clean:
|
||||
rm -f updatefw
|
||||
|
||||
@@ -1,577 +0,0 @@
|
||||
/*============================================================================
|
||||
File: elf.h
|
||||
Include file for ELF file. Defines both 32-/64-bit files.
|
||||
Copyright Hewlett-Packard Co. 1996. All rights reserved.
|
||||
============================================================================*/
|
||||
|
||||
#ifndef ELF_INCLUDED
|
||||
#define ELF_INCLUDED
|
||||
|
||||
#include "elftypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*============================================================================
|
||||
Constant values for the sizes of fundamental types
|
||||
============================================================================*/
|
||||
|
||||
#define ELF64_FSZ_ADDR 8
|
||||
#define ELF64_FSZ_HALF 2
|
||||
#define ELF64_FSZ_OFF 8
|
||||
#define ELF64_FSZ_SWORD 4
|
||||
#define ELF64_FSZ_WORD 4
|
||||
#define ELF64_FSZ_SXWORD 8
|
||||
#define ELF64_FSZ_XWORD 8
|
||||
|
||||
#define ELF32_FSZ_ADDR 4
|
||||
#define ELF32_FSZ_HALF 2
|
||||
#define ELF32_FSZ_OFF 4
|
||||
#define ELF32_FSZ_SWORD 4
|
||||
#define ELF32_FSZ_WORD 4
|
||||
#define ELF32_FSZ_XWORD 4
|
||||
|
||||
/*============================================================================
|
||||
The EI_* macros define indices into the e_ident[] array of the
|
||||
ElfXX_Ehdr structure.
|
||||
============================================================================*/
|
||||
|
||||
#define EI_MAG0 0 /* File identification */
|
||||
#define EI_MAG1 1 /* File identification */
|
||||
#define EI_MAG2 2 /* File identification */
|
||||
#define EI_MAG3 3 /* File identification */
|
||||
#define EI_CLASS 4 /* File class */
|
||||
#define EI_DATA 5 /* Data encoding */
|
||||
#define EI_VERSION 6 /* File version */
|
||||
#define EI_OSABI 7 /* OS/ABI identification */
|
||||
#define EI_ABIVERSION 8 /* ABI version */
|
||||
#define EI_PAD 9 /* Start of padding bytes */
|
||||
|
||||
#define EI_NIDENT 16 /* Size of e_ident[] */
|
||||
|
||||
|
||||
/*============================================================================
|
||||
ElfXX_Ehdr - ELF file header structure.
|
||||
============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
unsigned char e_ident[EI_NIDENT]; /* ELF identification */
|
||||
Elf64_Half e_type; /* Object file type */
|
||||
Elf64_Half e_machine; /* Machine type */
|
||||
Elf64_Word e_version; /* Object file version */
|
||||
Elf64_Addr e_entry; /* Entry point address */
|
||||
Elf64_Off e_phoff; /* Program header offset */
|
||||
Elf64_Off e_shoff; /* Section header offset */
|
||||
Elf64_Word e_flags; /* Processor-specific flags */
|
||||
Elf64_Half e_ehsize; /* ELF header size */
|
||||
Elf64_Half e_phentsize; /* Size of program header entry */
|
||||
Elf64_Half e_phnum; /* Number of program header entries */
|
||||
Elf64_Half e_shentsize; /* Size of section header entry */
|
||||
Elf64_Half e_shnum; /* Number of section header entries */
|
||||
Elf64_Half e_shstrndx; /* Section name string table index */
|
||||
} Elf64_Ehdr;
|
||||
|
||||
typedef struct {
|
||||
unsigned char e_ident[EI_NIDENT]; /*16/ ELF "magic number" */
|
||||
Elf32_Half e_type; /* 2/ Identifies object file type */
|
||||
Elf32_Half e_machine; /* 2/ Specifies required architecture */
|
||||
Elf32_Word e_version; /* 4/ Identifies object file version */
|
||||
Elf32_Addr e_entry; /* 4/ Entry point virtual address */
|
||||
Elf32_Off e_phoff; /* 4/ Program header table file offset */
|
||||
Elf32_Off e_shoff; /* 4/ Section header table file offset */
|
||||
Elf32_Word e_flags; /* 4/ Processor-specific flags */
|
||||
Elf32_Half e_ehsize; /* 2/ ELF header size in bytes */
|
||||
Elf32_Half e_phentsize; /* 2/ Program header table entry size */
|
||||
Elf32_Half e_phnum; /* 2/ Program header table entry count */
|
||||
Elf32_Half e_shentsize; /* 2/ Section header table entry size */
|
||||
Elf32_Half e_shnum; /* 2/ Section header table entry count */
|
||||
Elf32_Half e_shstrndx; /* 2/ Section header string table index */
|
||||
} Elf32_Ehdr;
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The ELFCLASS* macros are the defined values of e_ident[EI_CLASS].
|
||||
============================================================================*/
|
||||
|
||||
#define ELFCLASSNONE 0 /* Invalid class */
|
||||
#define ELFCLASS32 1 /* 32-bit objects */
|
||||
#define ELFCLASS64 2 /* 64-bit objects */
|
||||
|
||||
#define ELFCLASS64_A 200 /* 64-bit objects (interim definition) */
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The ELFDATA* macros are the allowed values of e_ident[EI_DATA].
|
||||
============================================================================*/
|
||||
|
||||
#define ELFDATANONE 0 /* Invalid data encoding */
|
||||
#define ELFDATA2LSB 1 /* 2's complement, LSB at lowest byte address */
|
||||
#define ELFDATA2MSB 2 /* 2's complement, MSB at lowest byte address */
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The ELFOSIABI* macros are the allowed values of e_ident[EI_OSABI].
|
||||
============================================================================*/
|
||||
|
||||
#define ELFOSABI_SYSV 0 /* System V ABI, third edition, no checking */
|
||||
#define ELFOSABI_HPUX 1 /* HP-UX operating system */
|
||||
|
||||
#define ELFOSABI_STANDALONE 255 /* STANDALONE operating system */
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The ELFABIVERSION* macros are the allowed values of e_ident[EI_ABIVERSION].
|
||||
============================================================================*/
|
||||
|
||||
#define ELFABI_HPUX_NONE 0 /* None specified */
|
||||
#define ELFABI_HPUX_REL11 1
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The ET_* macros define the values of the e_type field of the ElfXX_Ehdr
|
||||
structure.
|
||||
============================================================================*/
|
||||
|
||||
#define ET_NONE 0 /* No file type */
|
||||
#define ET_REL 1 /* Relocatable file */
|
||||
#define ET_EXEC 2 /* Executable file */
|
||||
#define ET_DYN 3 /* Shared object file */
|
||||
#define ET_CORE 4 /* Core file */
|
||||
|
||||
#define ET_LOOS 0xfe00 /* OS-specific lowest value */
|
||||
#define ET_HIOS 0xfeff /* OS-specific highest value */
|
||||
|
||||
#define ET_LOPROC 0xff00 /* Processor-specific lowest value */
|
||||
#define ET_HIPROC 0xffff /* Processor-specific highest value */
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The EV_* macros are the allowed values of the e_version field of
|
||||
ElfXX_Ehdr;
|
||||
============================================================================*/
|
||||
|
||||
#define EV_NONE 0 /* Invalid version */
|
||||
#define EV_CURRENT 1 /* Current version */
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The ELFMAG* macros are the values of e_ident[EI_MAG0-4]
|
||||
============================================================================*/
|
||||
|
||||
#define ELFMAG0 0x7f /* magic number, byte 0 */
|
||||
#define ELFMAG1 'E' /* magic number, byte 1 */
|
||||
#define ELFMAG2 'L' /* magic number, byte 2 */
|
||||
#define ELFMAG3 'F' /* magic number, byte 3 */
|
||||
#define ELFMAG "\177ELF" /* magic string */
|
||||
#define SELFMAG 4 /* magic string length */
|
||||
|
||||
|
||||
/*============================================================================
|
||||
ElfXX_Phdr - program header structure. Element of the array of
|
||||
program headers.
|
||||
============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
Elf64_Word p_type; /* Type of segment */
|
||||
Elf64_Word p_flags; /* Segment attributes */
|
||||
Elf64_Off p_offset; /* Offset in file */
|
||||
Elf64_Addr p_vaddr; /* Virtual address in memory */
|
||||
Elf64_Addr p_paddr; /* Reserved */
|
||||
Elf64_Xword p_filesz; /* Size of segment in file */
|
||||
Elf64_Xword p_memsz; /* Size of segment in memory */
|
||||
Elf64_Xword p_align; /* Alignment of segment */
|
||||
} Elf64_Phdr;
|
||||
|
||||
typedef struct {
|
||||
Elf32_Word p_type; /* Type of segment */
|
||||
Elf32_Off p_offset; /* Offset in file */
|
||||
Elf32_Addr p_vaddr; /* Virtual address in memory */
|
||||
Elf32_Addr p_paddr; /* Reserved */
|
||||
Elf32_Xword p_filesz; /* Size of segment in file */
|
||||
Elf32_Xword p_memsz; /* Size of segment in memory */
|
||||
Elf32_Word p_flags; /* Segment attributes */
|
||||
Elf32_Xword p_align; /* Alignment of segment */
|
||||
} Elf32_Phdr;
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The PF_* macros are the segment flag bits in p_flags of ElfXX_Phdr.
|
||||
============================================================================*/
|
||||
|
||||
#define PF_X 0x1 /* Execute */
|
||||
#define PF_W 0x2 /* Write */
|
||||
#define PF_R 0x4 /* Read */
|
||||
|
||||
#define PF_MASKOS 0x0ff00000 /* OS-specific */
|
||||
|
||||
#define PF_MASKPROC 0xf0000000 /* Processor-specific */
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The PT_* macros are the values of p_type in ElfXX_Phdr.
|
||||
============================================================================*/
|
||||
|
||||
#define PT_NULL 0 /* Array element is unused. Ignore. */
|
||||
#define PT_LOAD 1 /* Loadable segment. */
|
||||
#define PT_DYNAMIC 2 /* Dynamic Section */
|
||||
#define PT_INTERP 3 /* Section is a path to an interpreter */
|
||||
#define PT_NOTE 4 /* Note Section */
|
||||
#define PT_SHLIB 5 /* Currently unspecified semantics */
|
||||
#define PT_PHDR 6 /* Program header table. */
|
||||
|
||||
#define PT_LOOS 0x60000000 /* Lowest OS-specific type */
|
||||
#define PT_HIOS 0x6fffffff /* Highest OS-specific type */
|
||||
|
||||
#define PT_LOPROC 0x70000000 /* Lowest Processor-specific type */
|
||||
#define PT_HIPROC 0x7fffffff /* Highest Processor-specific type */
|
||||
|
||||
|
||||
/*============================================================================
|
||||
ElfXX_Shdr - structure for an ELF section header. Element of the array
|
||||
of section headers.
|
||||
============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
Elf64_Word sh_name; /* Section name */
|
||||
Elf64_Word sh_type; /* Section type */
|
||||
Elf64_Xword sh_flags; /* Section attributes */
|
||||
Elf64_Addr sh_addr; /* Virtual address in memory */
|
||||
Elf64_Off sh_offset; /* Offset in file */
|
||||
Elf64_Xword sh_size; /* Size of section */
|
||||
Elf64_Word sh_link; /* Link to other section */
|
||||
Elf64_Word sh_info; /* Miscellaneous information */
|
||||
Elf64_Xword sh_addralign; /* Address alignment boundary */
|
||||
Elf64_Xword sh_entsize; /* Entry size, if section has table */
|
||||
} Elf64_Shdr;
|
||||
|
||||
typedef struct {
|
||||
Elf32_Word sh_name; /* Section name */
|
||||
Elf32_Word sh_type; /* Section type */
|
||||
Elf32_Xword sh_flags; /* Section attributes */
|
||||
Elf32_Addr sh_addr; /* Virtual address in memory */
|
||||
Elf32_Off sh_offset; /* Offset in file */
|
||||
Elf32_Xword sh_size; /* Size of section */
|
||||
Elf32_Word sh_link; /* Link to other section */
|
||||
Elf32_Word sh_info; /* Miscellaneous information */
|
||||
Elf32_Xword sh_addralign; /* Address alignment boundary*/
|
||||
Elf32_Xword sh_entsize; /* Entry size, if section has table */
|
||||
} Elf32_Shdr;
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The ELF_STRING_xxx macros are names of common sections
|
||||
============================================================================*/
|
||||
|
||||
#define ELF_STRING_bss ".bss"
|
||||
#define ELF_STRING_hbss ".hbss"
|
||||
#define ELF_STRING_sbss ".sbss"
|
||||
#define ELF_STRING_tbss ".tbss"
|
||||
#define ELF_STRING_data ".data"
|
||||
#define ELF_STRING_hdata ".hdata"
|
||||
#define ELF_STRING_sdata ".sdata"
|
||||
#define ELF_STRING_fini ".fini"
|
||||
#define ELF_STRING_init ".init"
|
||||
#define ELF_STRING_interp ".interp"
|
||||
#define ELF_STRING_rodata ".rodata"
|
||||
#define ELF_STRING_text ".text"
|
||||
#define ELF_STRING_comment ".comment"
|
||||
#define ELF_STRING_dynamic ".dynamic"
|
||||
#define ELF_STRING_dynstr ".dynstr"
|
||||
#define ELF_STRING_dynsym ".dynsym"
|
||||
#define ELF_STRING_dlt ".dlt"
|
||||
#define ELF_STRING_note ".note"
|
||||
#define ELF_STRING_opd ".opd"
|
||||
#define ELF_STRING_plt ".plt"
|
||||
#define ELF_STRING_bss_rela ".rela.bss"
|
||||
#define ELF_STRING_hbss_rela ".rela.hbss"
|
||||
#define ELF_STRING_data_rela ".rela.data"
|
||||
#define ELF_STRING_dlt_rela ".rela.dlt"
|
||||
#define ELF_STRING_plt_rela ".rela.plt"
|
||||
#define ELF_STRING_sdata_rela ".rela.sdata"
|
||||
#define ELF_STRING_strtab ".strtab"
|
||||
#define ELF_STRING_symtab ".symtab"
|
||||
#define ELF_STRING_hash ".hash"
|
||||
#define ELF_STRING_shstrtab ".shstrtab"
|
||||
#define ELF_STRING_shsymtab ".shsymtab"
|
||||
#define ELF_STRING_rela ".rela"
|
||||
#define ELF_STRING_rel ".rel"
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The SHF_* macros are the allowed values of the sh_flags field of
|
||||
ElfXX_Shdr. These 1-bit flags define attributes of a section.
|
||||
============================================================================*/
|
||||
|
||||
#define SHF_WRITE 0x1 /* Writable during execution */
|
||||
#define SHF_ALLOC 0x2 /* Occupies memory during execution */
|
||||
#define SHF_EXECINSTR 0x4 /* Contains executable instructions */
|
||||
|
||||
#define SHF_MASKPROC 0xf0000000 /* mask for processor-specific bits */
|
||||
|
||||
|
||||
/*============================================================================
|
||||
SHN_* macros are reserved section header indices. An object file will
|
||||
not have sections for these special indices.
|
||||
============================================================================*/
|
||||
|
||||
#define SHN_UNDEF 0 /* undefined, e.g. undefined symbol */
|
||||
|
||||
#define SHN_LORESERVE 0xff00 /* Lower bound of reserved indices */
|
||||
|
||||
#define SHN_LOPROC 0xff00 /* Lower bound processor-specific index */
|
||||
#define SHN_HIPROC 0xff1f/* Upper bound processor-specific index */
|
||||
|
||||
#define SHN_LOOS 0xff20 /* Lower bound OS-specific index */
|
||||
#define SHN_HIOS 0xff3f /* Upper bound OS-specific index */
|
||||
|
||||
#define SHN_ABS 0xfff1 /* Absolute value, not relocated */
|
||||
#define SHN_COMMON 0xfff2/* FORTRAN common or unallocated C */
|
||||
|
||||
#define SHN_HIRESERVE 0xffff /* Upper bound of reserved indices */
|
||||
|
||||
|
||||
/*============================================================================
|
||||
SHT_* macros are the values of sh_type in ElfXX_Shdr
|
||||
============================================================================*/
|
||||
|
||||
#define SHT_NULL 0 /* Inactive section header */
|
||||
#define SHT_PROGBITS 1 /* Information defined by the program */
|
||||
#define SHT_SYMTAB 2 /* Symbol table - not DLL */
|
||||
#define SHT_STRTAB 3 /* String table */
|
||||
#define SHT_RELA 4 /* Explicit addend relocations, Elf64_Rela */
|
||||
#define SHT_HASH 5 /* Symbol hash table */
|
||||
#define SHT_DYNAMIC 6 /* Information for dynamic linking */
|
||||
#define SHT_NOTE 7 /* A Note section */
|
||||
#define SHT_NOBITS 8 /* Like SHT_PROGBITS with no data */
|
||||
#define SHT_REL 9 /* Implicit addend relocations, Elf64_Rel */
|
||||
#define SHT_SHLIB 10 /* Currently unspecified semantics */
|
||||
#define SHT_DYNSYM 11 /* Symbol table for a DLL */
|
||||
|
||||
#define SHT_LOOS 0x60000000 /* Lowest OS-specific section type */
|
||||
#define SHT_HIOS 0x6fffffff /* Highest OS-specific section type */
|
||||
|
||||
#define SHT_LOPROC 0x70000000 /* Lowest processor-specific section type */
|
||||
#define SHT_HIPROC 0x7fffffff /* Highest processor-specific section type */
|
||||
|
||||
|
||||
/*============================================================================
|
||||
ElfXX_Sym - ELF symbol structure.
|
||||
============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
Elf64_Word st_name; /* Symbol name */
|
||||
unsigned char st_info; /* Type and Binding attributes */
|
||||
unsigned char st_other; /* Reserved */
|
||||
Elf64_Half st_shndx; /* Section table index */
|
||||
Elf64_Addr st_value; /* Symbol value */
|
||||
Elf64_Xword st_size; /* Size of object (e.g., common) */
|
||||
} Elf64_Sym;
|
||||
|
||||
typedef struct {
|
||||
Elf32_Word st_name; /* Symbol name */
|
||||
Elf32_Addr st_value; /* Symbol value */
|
||||
Elf32_Xword st_size; /* Size of object (e.g., common) */
|
||||
unsigned char st_info; /* Type and Binding attributes */
|
||||
unsigned char st_other; /* Reserved */
|
||||
Elf32_Half st_shndx; /* Section table index */
|
||||
} Elf32_Sym;
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The ELFXX_ST_* macros operate on the st_info field of ElfXX_Sym
|
||||
to extract binding attributes, type information and how to build
|
||||
an st_info value from binding and type information.
|
||||
============================================================================*/
|
||||
|
||||
#define ELF64_ST_BIND(val) ((val) >> 4)
|
||||
#define ELF64_ST_TYPE(val) ((val) & 0xf)
|
||||
#define ELF64_ST_INFO(bind,type) (((bind) << 4) + ((type) & 0xf))
|
||||
|
||||
#define ELF32_ST_BIND(val) ((val) >> 4)
|
||||
#define ELF32_ST_TYPE(val) ((val) & 0xf)
|
||||
#define ELF32_ST_INFO(bind,type) (((bind) << 4) + ((type) & 0xf))
|
||||
|
||||
|
||||
/*============================================================================
|
||||
STN_UNDEF (zero) designeates the first entry in the symbol table and serves
|
||||
as the undefined symbol index.
|
||||
============================================================================*/
|
||||
|
||||
#define STN_UNDEF 0
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The STB_* macros are the defined values of the binding information part
|
||||
of st_info in ElfXX_Sym.
|
||||
============================================================================*/
|
||||
|
||||
#define STB_LOCAL 0 /* Local symbols */
|
||||
#define STB_GLOBAL 1 /* Globally visible symbols */
|
||||
#define STB_WEAK 2 /* Global symbols with lower precedence */
|
||||
|
||||
#define STB_LOOS 10 /* Lowest OS-specific value */
|
||||
#define STB_HIOS 12 /* Highest OS-specific value */
|
||||
|
||||
#define STB_LOPROC 13 /* Lowest processor-specific value */
|
||||
#define STB_HIPROC 15 /* Highest processor-specific value */
|
||||
|
||||
|
||||
/*===========================================================================
|
||||
The STT_* macros are the allowed values of the type information part of
|
||||
st_info in ElfXX_Sym.
|
||||
============================================================================*/
|
||||
|
||||
#define STT_NOTYPE 0 /* Undefined symbol type */
|
||||
#define STT_OBJECT 1 /* A data object, variable, array, etc. */
|
||||
#define STT_FUNC 2 /* A function or other executable code */
|
||||
#define STT_SECTION 3 /* Symbol associated with a section */
|
||||
#define STT_FILE 4 /* Typically the name of the source file */
|
||||
|
||||
#define STT_LOOS 10 /* Lowest OS-specific symbol type */
|
||||
#define STT_HIOS 12 /* Highest OS-specific symbol type */
|
||||
|
||||
#define STT_LOPROC 13 /* Lowest processor-specific symbol type */
|
||||
#define STT_HIPROC 15 /* Highest processor-specific symbol type */
|
||||
|
||||
|
||||
/*============================================================================
|
||||
ElfXX_Rel - ELF relocation without an explicit addend.
|
||||
============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
Elf64_Addr r_offset; /* Address of reference */
|
||||
Elf64_Xword r_info; /* Symbol index, relocation type */
|
||||
} Elf64_Rel;
|
||||
|
||||
typedef struct {
|
||||
Elf32_Addr r_offset; /* Address of reference */
|
||||
Elf32_Xword r_info; /* Symbol index, reloc. type */
|
||||
} Elf32_Rel;
|
||||
|
||||
/*============================================================================
|
||||
ElfXX_Rela - ELF relocation with an explicit addend.
|
||||
============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
Elf64_Addr r_offset; /* Address of reference */
|
||||
Elf64_Xword r_info; /* Symbol index, relocation type */
|
||||
Elf64_Sxword r_addend; /* Constant part of expression */
|
||||
} Elf64_Rela;
|
||||
|
||||
typedef struct {
|
||||
Elf32_Addr r_offset; /* Address of reference */
|
||||
Elf32_Xword r_info; /* Symbol index, reloc. type */
|
||||
Elf32_Sword r_addend; /* Constant part of expression */
|
||||
} Elf32_Rela;
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The ELFXX_R_* macros show how to extract the type and index parts
|
||||
of r_info in ElfXX_Rel and ElfXX_Rela and how to build r_info
|
||||
from a symbol index and type.
|
||||
============================================================================*/
|
||||
|
||||
#define ELF64_R_INFO(sym,type) \
|
||||
((((Elf64_Addr) (sym)) << 32) + ((Elf64_Addr) (type)))
|
||||
#define ELF64_R_SYM(info) \
|
||||
((Elf64_Sword) (((Elf64_Addr) (info)) >> 32))
|
||||
#define ELF64_R_TYPE(info) \
|
||||
((Elf64_Word) (((Elf64_Addr) (info)) & 0xffffffffLL))
|
||||
|
||||
#define ELF32_R_INFO(sym,type) (((sym) << 8) + ((unsigned char) (type)))
|
||||
#define ELF32_R_SYM(info) ((info) >> 8)
|
||||
#define ELF32_R_TYPE(info) ((unsigned char) (info))
|
||||
|
||||
|
||||
/*============================================================================
|
||||
ElfXX_Dyn - dynamic array entry.
|
||||
============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
Elf32_Sword d_tag;
|
||||
union {
|
||||
Elf32_Word d_val; /* unsigned word */
|
||||
Elf32_Addr d_ptr; /* address */
|
||||
} d_un;
|
||||
} Elf32_Dyn;
|
||||
|
||||
extern Elf32_Dyn _DYNAMIC32[];
|
||||
|
||||
typedef struct {
|
||||
Elf64_Sxword d_tag;
|
||||
union {
|
||||
Elf64_Xword d_val; /* unsigned word */
|
||||
Elf64_Addr d_ptr; /* address */
|
||||
} d_un;
|
||||
} Elf64_Dyn;
|
||||
|
||||
extern Elf64_Dyn _DYNAMIC[];
|
||||
|
||||
|
||||
/*============================================================================
|
||||
The DT_* defines are the allowed values of d_tag in ElfXX_dyn.
|
||||
These are the Dynamic Array types.
|
||||
============================================================================*/
|
||||
|
||||
/* (i)gnore (m)andatory (o)ptional */
|
||||
/* d_un Exec DLL */
|
||||
/* ---- ---- --- */
|
||||
#define DT_NULL 0 /* ignored m m */
|
||||
#define DT_NEEDED 1 /* d_val o o */
|
||||
#define DT_PLTRELSZ 2 /* d_val o o */
|
||||
#define DT_PLTGOT 3 /* d_ptr o o */
|
||||
#define DT_HASH 4 /* d_ptr m m */
|
||||
#define DT_STRTAB 5 /* d_ptr m m */
|
||||
#define DT_SYMTAB 6 /* d_ptr m m */
|
||||
#define DT_RELA 7 /* d_ptr m o */
|
||||
#define DT_RELASZ 8 /* d_val m o */
|
||||
#define DT_RELAENT 9 /* d_val m o */
|
||||
#define DT_STRSZ 10 /* d_val m m */
|
||||
#define DT_SYMENT 11 /* d_val m m */
|
||||
#define DT_INIT 12 /* d_ptr o o */
|
||||
#define DT_FINI 13 /* d_ptr o o */
|
||||
#define DT_SONAME 14 /* d_val i o */
|
||||
#define DT_RPATH 15 /* d_val o i */
|
||||
#define DT_SYMBOLIC 16 /* ignored i o */
|
||||
#define DT_REL 17 /* d_ptr m o */
|
||||
#define DT_RELSZ 18 /* d_val m o */
|
||||
#define DT_RELENT 19 /* d_val m o */
|
||||
#define DT_PLTREL 20 /* d_val o o */
|
||||
#define DT_DEBUG 21 /* d_ptr o i */
|
||||
#define DT_TEXTREL 22 /* ignored o o */
|
||||
#define DT_JMPREL 23 /* d_ptr o o */
|
||||
#define DT_BIND_NOW 24 /* ignored */
|
||||
#define DT_INIT_ARRAY 25 /* d_ptr o o */
|
||||
#define DT_FINI_ARRAY 26 /* d_ptr o o */
|
||||
#define DT_INIT_ARRAYSZ 27 /* d_val o o */
|
||||
#define DT_FINI_ARRAYSZ 28 /* d_val o o */
|
||||
|
||||
#define DT_LOOS 0x60000000 /* unspecified - OS specific */
|
||||
#define DT_HIOS 0x6fffffff /* unspecified - OS specific */
|
||||
|
||||
#define DT_LOPROC 0x70000000 /* unspecified - processor specific */
|
||||
#define DT_HIPROC 0x7fffffff /* unspecified - processor specific */
|
||||
|
||||
|
||||
#ifndef _HP_NO_ELF_DEPRICATED
|
||||
|
||||
/* These defines have been depricated and will be removed in a future release.*/
|
||||
|
||||
#define ELFOSABI_NONE 0 /* None specified */
|
||||
#define ELFOSABI_NT 2 /* NT operating system */
|
||||
#define ELFOSABI_SCOUNIX 3 /* SCO UNIX operating system */
|
||||
#define SHF_COMDAT 0x8 /* Is a member of a COMDAT group */
|
||||
#define SHT_COMDAT 12 /* COMDAT group directory -> SHT_HP_COMDAT */
|
||||
|
||||
#endif /* ifndef _HP_NO_ELF_DEPRICATED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* ifndef _HP_NO_ELF_DEPRICATED */
|
||||
|
||||
#if defined(ELF_TARGET_ALL) || defined(ELF_TARGET_PARISC)
|
||||
#include <elf_parisc.h>
|
||||
#endif
|
||||
|
||||
#endif /* ELF_INCLUDED */
|
||||
@@ -1,52 +0,0 @@
|
||||
/*============================================================================
|
||||
File: elftypes.h
|
||||
Include file for Elf types. Define elf types for Elf structures.
|
||||
Copyright Hewlett-Packard Co. 1995. All rights reserved.
|
||||
============================================================================*/
|
||||
|
||||
#ifndef ELFTYPES_INCLUDED
|
||||
#define ELFTYPES_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __LP64__
|
||||
typedef unsigned int Elf32_Addr; /* Unsigned program address */
|
||||
typedef unsigned int Elf32_Off; /* Unsigned file offset */
|
||||
typedef int Elf32_Sword; /* Signed large integer */
|
||||
typedef unsigned int Elf32_Xword; /* Unsigned large integer */
|
||||
#else
|
||||
typedef unsigned long Elf32_Addr; /* Unsigned program address */
|
||||
typedef unsigned long Elf32_Off; /* Unsigned file offset */
|
||||
typedef long Elf32_Sword; /* Signed large integer */
|
||||
typedef unsigned long Elf32_Xword; /* Unsigned large integer */
|
||||
#endif
|
||||
|
||||
typedef unsigned int Elf32_Word; /* Unsigned large integer */
|
||||
typedef unsigned short Elf32_Half; /* Unsigned medium integer */
|
||||
typedef unsigned char Elf32_Char; /* Unsigned tiny integer */
|
||||
typedef unsigned char Elf32_Byte; /* Unsigned tiny integer */
|
||||
|
||||
#ifdef __LP64__
|
||||
typedef unsigned long Elf64_Addr;
|
||||
typedef unsigned long Elf64_Off;
|
||||
typedef unsigned long Elf64_Xword;
|
||||
typedef long Elf64_Sxword;
|
||||
#else
|
||||
typedef unsigned long long Elf64_Addr;
|
||||
typedef unsigned long long Elf64_Off;
|
||||
typedef unsigned long long Elf64_Xword;
|
||||
typedef long long Elf64_Sxword;
|
||||
#endif
|
||||
|
||||
typedef unsigned short Elf64_Half;
|
||||
typedef int Elf64_Sword;
|
||||
typedef unsigned int Elf64_Word;
|
||||
typedef unsigned char Elf64_Byte; /* Unsigned tiny integer */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ELFTYPES_INCLUDED */
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,687 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*
|
||||
C Header file <updatefw.h> for updatefw tool.
|
||||
|
||||
K. Khalfallah, Aug, 2007
|
||||
kkhalfallah@free.fr
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include "openair_device.h"
|
||||
|
||||
#include "elf.h"
|
||||
#include "elftypes.h"
|
||||
#define EM_SPARC 2
|
||||
#define MAX_SIZE_STRING_TABLE 1024
|
||||
#define MAX_SIZE_SECTION_NAME 32
|
||||
|
||||
#include "updatefw.h"
|
||||
|
||||
/* Interface with OpenAirInterface driver */
|
||||
#define DEVICE_NAME "/dev/openair0"
|
||||
#define ACCESS_MODE O_RDONLY
|
||||
|
||||
#define SWITCH_IS_OFF 0
|
||||
#define SWITCH_IS_ON 1
|
||||
static unsigned int helpflag = SWITCH_IS_OFF;
|
||||
static unsigned int pflag = SWITCH_IS_OFF;
|
||||
static unsigned int noexecflag = SWITCH_IS_OFF;
|
||||
static unsigned int fflag = SWITCH_IS_OFF;
|
||||
static unsigned int sflag = SWITCH_IS_OFF;
|
||||
static unsigned int rebootflag = SWITCH_IS_OFF;
|
||||
static FILE* p_elfimage;
|
||||
static Elf32_Ehdr elf_Ehdr;
|
||||
static Elf32_Shdr elf_Shdr;
|
||||
long Shdr_pos, StringSec_pos, StringSec_size;
|
||||
//char section_name[MAX_SIZE_SECTION_NAME];
|
||||
char SecNameStnTable[MAX_SIZE_STRING_TABLE];
|
||||
unsigned int ioctl_params[4];
|
||||
|
||||
#define LONGOPTIONS_NB 6
|
||||
struct option updatefw_longopts[LONGOPTIONS_NB+1] = {
|
||||
{ .name = "help", .has_arg = no_argument, .flag = &helpflag, .val = SWITCH_IS_ON },
|
||||
{ .name = "firmware", .has_arg = required_argument, .flag = NULL, .val = 'f' },
|
||||
{ .name = "pretend", .has_arg = no_argument, .flag = &pflag, .val = SWITCH_IS_ON },
|
||||
{ .name = "noexec", .has_arg = no_argument, .flag = &noexecflag, .val = SWITCH_IS_ON },
|
||||
{ .name = "stackptr", .has_arg = required_argument, .flag = NULL, .val = 's' },
|
||||
{ .name = "forcereboot", .has_arg = no_argument, .flag = &rebootflag, .val = SWITCH_IS_ON },
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
void show_usage(char* pgname) {
|
||||
unsigned int i;
|
||||
fprintf(stderr, " %s : Tool to update firmware of Cardbus-MIMO-1/Leon3 card through the PCI interface,\n", pgname);
|
||||
fprintf(stderr, " ");
|
||||
|
||||
for (i=0; i<strlen(pgname); i++) fprintf(stderr, " ");
|
||||
|
||||
fprintf(stderr, " that is, even without using the Xilinx parallel cable. The tool performs sequentially\n");
|
||||
fprintf(stderr, " ");
|
||||
|
||||
for (i=0; i<strlen(pgname); i++) fprintf(stderr, " ");
|
||||
|
||||
fprintf(stderr, " the 5 following operations:\n");
|
||||
fprintf(stderr, " ");
|
||||
|
||||
for (i=0; i<strlen(pgname); i++) fprintf(stderr, " ");
|
||||
|
||||
fprintf(stderr, " 1) Ask card driver to reboot (optionally)\n");
|
||||
fprintf(stderr, " ");
|
||||
|
||||
for (i=0; i<strlen(pgname); i++) fprintf(stderr, " ");
|
||||
|
||||
fprintf(stderr, " 2) Ask card driver to transfer .text section\n");
|
||||
fprintf(stderr, " ");
|
||||
|
||||
for (i=0; i<strlen(pgname); i++) fprintf(stderr, " ");
|
||||
|
||||
fprintf(stderr, " 3) Ask card driver to transfer .data section\n");
|
||||
fprintf(stderr, " ");
|
||||
|
||||
for (i=0; i<strlen(pgname); i++) fprintf(stderr, " ");
|
||||
|
||||
fprintf(stderr, " 4) Ask card driver to clear .bss section\n");
|
||||
fprintf(stderr, " ");
|
||||
|
||||
for (i=0; i<strlen(pgname); i++) fprintf(stderr, " ");
|
||||
|
||||
fprintf(stderr, " 5) Ask card driver to have Leon processor set stack-pointer\n");
|
||||
fprintf(stderr, " ");
|
||||
|
||||
for (i=0; i<strlen(pgname); i++) fprintf(stderr, " ");
|
||||
|
||||
fprintf(stderr, " and jump to firmware entry.\n");
|
||||
fprintf(stderr, "Usage:\n");
|
||||
fprintf(stderr, " %s [-f|--firmware 'filename'] [-s|--stackptr value] [-b|--forcereboot]\n",pgname);
|
||||
fprintf(stderr, " ");
|
||||
|
||||
for (i=0; i<strlen(pgname); i++) fprintf(stderr, " ");
|
||||
|
||||
fprintf(stderr, "[-v|-vv|-vvv|-vvvv] [-h|--help] [-p|--pretend]\n\n");
|
||||
fprintf(stderr, " [-f|--firmware ] Mandatory option, to set the name of the executable file\n");
|
||||
fprintf(stderr, " of the firmware to update the remote card with.\n");
|
||||
fprintf(stderr, " The file should be an executable file in the Sparc32 ELF binary\n");
|
||||
fprintf(stderr, " format, containing at least the 3 mandatory sections .text, .data & .bss\n");
|
||||
fprintf(stderr, " [-s|--stackptr] Mandatory option, to set the value of the stack pointer before\n");
|
||||
fprintf(stderr, " giving hand to the firmware. The specified value must be an integer\n");
|
||||
fprintf(stderr, " number of 8 hexadecimal digits preceded by token '0x'.\n");
|
||||
fprintf(stderr, " [-b|--forcereboot] Force reboot of Leon processor before updating the firmware.\n");
|
||||
fprintf(stderr, " [-p|--pretend] Just pretend to transfer commands (ioctls) to driver, don't do it\n");
|
||||
fprintf(stderr, " actually. Useful together with verbose -vv switch.\n");
|
||||
fprintf(stderr, " [-n|--noexec] Transfer all data and text segments, but don't do actually start the code on Leon (no START_EXEC).\n");
|
||||
fprintf(stderr, " [-v|-vv|-vvv|-vvvv] Verbose modes.\n");
|
||||
fprintf(stderr, " [-h|--help] Displays this help.\n");
|
||||
}
|
||||
|
||||
int get_elf_header(Elf32_Ehdr* p_Elf32_hdr, FILE* p_file) {
|
||||
int nbread;
|
||||
nbread = fread(p_Elf32_hdr, sizeof(elf_Ehdr), 1, p_file);
|
||||
|
||||
if (nbread != 1) {
|
||||
fprintf(stderr, "Error : while reading ELF header (fread() returned %d)\n", nbread);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
invert2(p_Elf32_hdr->e_type); /* $$$$KMK: bad code !!! Endianess dependant ! */
|
||||
invert2(p_Elf32_hdr->e_machine);
|
||||
invert4(p_Elf32_hdr->e_version);
|
||||
invert4(p_Elf32_hdr->e_entry);
|
||||
invert4(p_Elf32_hdr->e_phoff);
|
||||
invert4(p_Elf32_hdr->e_shoff);
|
||||
invert4(p_Elf32_hdr->e_flags);
|
||||
invert2(p_Elf32_hdr->e_ehsize);
|
||||
invert2(p_Elf32_hdr->e_phentsize);
|
||||
invert2(p_Elf32_hdr->e_phnum);
|
||||
invert2(p_Elf32_hdr->e_shentsize);
|
||||
invert2(p_Elf32_hdr->e_shnum);
|
||||
invert2(p_Elf32_hdr->e_shstrndx);
|
||||
return (p_Elf32_hdr->e_type == ET_EXEC)
|
||||
&& (p_Elf32_hdr->e_machine == EM_SPARC)
|
||||
&& (p_Elf32_hdr->e_version == EV_CURRENT)
|
||||
&& (p_Elf32_hdr->e_ident[EI_CLASS] == ELFCLASS32)
|
||||
&& (p_Elf32_hdr->e_ident[EI_DATA] == ELFDATA2MSB)
|
||||
&& (p_Elf32_hdr->e_ident[EI_VERSION] == EV_CURRENT);
|
||||
}
|
||||
|
||||
int get_elf_section_header(Elf32_Shdr* p_Elf32_Shdr, FILE* p_file, unsigned int section_ndx) {
|
||||
int nbread;
|
||||
/* retrieve the position of the section header table */
|
||||
fseek(p_file, Shdr_pos + (section_ndx * elf_Ehdr.e_shentsize), 0);
|
||||
/* set file pointer to the position of the section header section_ndx */
|
||||
// seekrst = fseek(p_file, (long), 0);
|
||||
nbread = fread(p_Elf32_Shdr, sizeof(elf_Shdr), 1, p_file);
|
||||
|
||||
if (nbread != 1) {
|
||||
fprintf(stderr, "Error : while reading elf section header (fread() returned %d)\n", nbread);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
invert4(p_Elf32_Shdr->sh_name); /* $$$$KMK: bad code !!! Endianess dependant ! */
|
||||
invert4(p_Elf32_Shdr->sh_type);
|
||||
invert4(p_Elf32_Shdr->sh_flags);
|
||||
invert4(p_Elf32_Shdr->sh_addr);
|
||||
invert4(p_Elf32_Shdr->sh_offset);
|
||||
invert4(p_Elf32_Shdr->sh_size);
|
||||
invert4(p_Elf32_Shdr->sh_link);
|
||||
invert4(p_Elf32_Shdr->sh_info);
|
||||
invert4(p_Elf32_Shdr->sh_addralign);
|
||||
invert4(p_Elf32_Shdr->sh_entsize);
|
||||
//fseek(p_file, StringSec_pos + p_Elf32_Shdr->sh_name, 0);
|
||||
//fread();
|
||||
//strcpy(sname, );
|
||||
return nbread;
|
||||
}
|
||||
|
||||
void find_and_transfer_section(char* section_name, unsigned int verboselevel) {
|
||||
/* Interface with driver */
|
||||
int ioctlretval;
|
||||
int ifile;
|
||||
char* section_content;
|
||||
int nbread;
|
||||
unsigned int secnb = 0;
|
||||
|
||||
if(p_elfimage == NULL) {
|
||||
fprintf(stderr, "%s %d:Error, firmware file not opened\n",__FILE__,__LINE__);
|
||||
}
|
||||
for (secnb = 0 ; secnb < elf_Ehdr.e_shnum; secnb++) {
|
||||
get_elf_section_header(&elf_Shdr, p_elfimage, secnb);
|
||||
|
||||
if (!strcmp(SecNameStnTable + elf_Shdr.sh_name, section_name)) {
|
||||
if (verboselevel >= VERBOSE_LEVEL_SECTION_DETAILS)
|
||||
printf("Info: ok, found section %s (as section nb. %u)\n", SecNameStnTable + elf_Shdr.sh_name, secnb);
|
||||
|
||||
/* Check that section size is a multiple of 4 bytes. */
|
||||
if (elf_Shdr.sh_size % 4) {
|
||||
fprintf(stderr, "Error: section %s has a non-multiple-of-4-bytes size (%lu).\n",
|
||||
SecNameStnTable + elf_Shdr.sh_name, (unsigned long)elf_Shdr.sh_size);
|
||||
fclose(p_elfimage);
|
||||
exit(-1);
|
||||
} else if (verboselevel >= VERBOSE_LEVEL_SECTION_DETAILS) {
|
||||
printf("Info: ok, section %s has size %lu bytes (multiple of 4 bytes).\n",
|
||||
SecNameStnTable + elf_Shdr.sh_name, (unsigned long)elf_Shdr.sh_size);
|
||||
}
|
||||
|
||||
/* Dynamically allocate a chunk of memory to store the section into. */
|
||||
section_content = (char*)malloc(elf_Shdr.sh_size);
|
||||
|
||||
/* Fail if the address returned by malloc does not fit in 32 bits.
|
||||
* The kernel driver gets this address as 32 bits and uses it to copy
|
||||
* from userspace. If the address does not fit into 32 bits the kernel
|
||||
* will copy garbage or fail to copy completely.
|
||||
* To be reworked if things do not work on some setups.
|
||||
*/
|
||||
if (sizeof(char*) > 4 && (((uintptr_t)section_content)>>32)) {
|
||||
fprintf(stderr, "FATAL ERROR: an internal serious problem has been encountered.\n");
|
||||
fprintf(stderr, "Contact the authors so as to solve this issue.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!section_content) {
|
||||
fprintf(stderr, "Error: could not dynamically allocate %lu bytes for section %s.\n",
|
||||
(unsigned long)elf_Shdr.sh_size, (SecNameStnTable + elf_Shdr.sh_name));
|
||||
fclose(p_elfimage);
|
||||
exit(-1);
|
||||
} else if (verboselevel >= VERBOSE_LEVEL_IOCTL) {
|
||||
printf("Info: ok, dynamically allocated a %lu bytes buffer for section %s.\n",
|
||||
(unsigned long)elf_Shdr.sh_size, SecNameStnTable + elf_Shdr.sh_name);
|
||||
}
|
||||
|
||||
/* Position the file cursor at the begining of proper section. */
|
||||
fseek(p_elfimage, (long)(elf_Shdr.sh_offset), 0);
|
||||
/* Copy the section's content into this temporary buffer. */
|
||||
nbread = fread(section_content, elf_Shdr.sh_size, 1, p_elfimage);
|
||||
|
||||
if (nbread != 1) {
|
||||
fprintf(stderr, "Error: could not read %lu bytes from ELF file into dynamic buffer.\n", (unsigned long)elf_Shdr.sh_size);
|
||||
free(section_content);
|
||||
fclose(p_elfimage);
|
||||
exit(-1);
|
||||
} else if (verboselevel >= VERBOSE_LEVEL_IOCTL) {
|
||||
printf("Info: ok, copied content of section %s into dynamic buffer (%lu bytes copied).\n",
|
||||
SecNameStnTable + elf_Shdr.sh_name, (unsigned long)elf_Shdr.sh_size);
|
||||
}
|
||||
|
||||
/* Open the special device file. */
|
||||
if (!pflag) {
|
||||
ifile = open(DEVICE_NAME, ACCESS_MODE, 0);
|
||||
|
||||
if (ifile<0) {
|
||||
fprintf(stderr, "Error: could not open %s (open() returned %d, errno=%u)\n", DEVICE_NAME, ifile, errno);
|
||||
free(section_content);
|
||||
fclose(p_elfimage);
|
||||
exit(-1);
|
||||
} else if (verboselevel >= VERBOSE_LEVEL_IOCTL) {
|
||||
printf("Info: ok, successfully opened %s.\n", DEVICE_NAME);
|
||||
}
|
||||
|
||||
/* Collect control data for ioctl. */
|
||||
ioctl_params[0] = UPDATE_FIRMWARE_TRANSFER_BLOCK;
|
||||
ioctl_params[1] = elf_Shdr.sh_addr;
|
||||
ioctl_params[2] = elf_Shdr.sh_size / 4;
|
||||
/* This is wrong on x86_64 because a pointer is 64 bits and
|
||||
* an unsigned int is only 32 bits.
|
||||
* The compiler emits a warning, but the test
|
||||
* above on the value of section_content makes it work
|
||||
* (hopefully).
|
||||
* To be changed if things do not work.
|
||||
*/
|
||||
ioctl_params[3] = (unsigned int)((unsigned int*)section_content);
|
||||
//invert4(ioctl_params[1]);
|
||||
//invert4(ioctl_params[2]);
|
||||
/* Call ioctl driver */
|
||||
ioctlretval = ioctl(ifile, openair_UPDATE_FIRMWARE, ioctl_params);
|
||||
|
||||
if (ioctlretval) {
|
||||
fprintf(stderr, "Error: ioctl on %s failed.\n", DEVICE_NAME);
|
||||
close(ifile);
|
||||
free(section_content);
|
||||
fclose(p_elfimage);
|
||||
exit(-1);
|
||||
} else if (verboselevel >= VERBOSE_LEVEL_IOCTL) {
|
||||
printf("Info: ok, successful ioctl on %s for section %s.\n",
|
||||
DEVICE_NAME, SecNameStnTable + elf_Shdr.sh_name);
|
||||
}
|
||||
|
||||
close(ifile);
|
||||
} /* pflag */
|
||||
|
||||
free(section_content);
|
||||
} /* section_name */
|
||||
} /* for secnb */
|
||||
}
|
||||
|
||||
void find_and_clear_section_bss(unsigned int verboselevel) {
|
||||
/* Interface with driver */
|
||||
int ioctlretval;
|
||||
int ifile;
|
||||
unsigned int secnb = 0;
|
||||
|
||||
if(p_elfimage == NULL) {
|
||||
fprintf(stderr, "%s %d:Error, firmware file not opened\n",__FILE__,__LINE__);
|
||||
}
|
||||
for (secnb = 0 ; secnb < elf_Ehdr.e_shnum; secnb++) {
|
||||
get_elf_section_header(&elf_Shdr, p_elfimage, secnb);
|
||||
|
||||
if (!strcmp(SecNameStnTable + elf_Shdr.sh_name, ".bss")) {
|
||||
if (verboselevel >= VERBOSE_LEVEL_SECTION_DETAILS)
|
||||
printf("Info: ok, found section %s (as section nb. %u)\n", SecNameStnTable + elf_Shdr.sh_name, secnb);
|
||||
|
||||
/* Open the special device file. */
|
||||
if (!pflag) {
|
||||
ifile = open(DEVICE_NAME, ACCESS_MODE, 0);
|
||||
|
||||
if (ifile<0) {
|
||||
fprintf(stderr, "Error: could not open %s (open() returned %d, errno=%u)\n", DEVICE_NAME, ifile, errno);
|
||||
fclose(p_elfimage);
|
||||
exit(-1);
|
||||
} else if (verboselevel >= VERBOSE_LEVEL_IOCTL) {
|
||||
printf("Info: ok, successfully opened %s.\n", DEVICE_NAME);
|
||||
}
|
||||
|
||||
/* Collect control data for ioctl. */
|
||||
ioctl_params[0] = UPDATE_FIRMWARE_CLEAR_BSS;
|
||||
ioctl_params[1] = elf_Shdr.sh_addr;
|
||||
ioctl_params[2] = elf_Shdr.sh_size;
|
||||
//invert4(ioctl_params[1]);
|
||||
//invert4(ioctl_params[2]);
|
||||
/* Call ioctl driver */
|
||||
ioctlretval = ioctl(ifile, openair_UPDATE_FIRMWARE, ioctl_params);
|
||||
|
||||
if (ioctlretval) {
|
||||
fprintf(stderr, "Error: ioctl on %s failed.\n", DEVICE_NAME);
|
||||
close(ifile);
|
||||
fclose(p_elfimage);
|
||||
exit(-1);
|
||||
} else if (verboselevel >= VERBOSE_LEVEL_IOCTL) {
|
||||
printf("Info: ok, successful ioctl on %s for section %s.\n",
|
||||
DEVICE_NAME, SecNameStnTable + elf_Shdr.sh_name);
|
||||
}
|
||||
|
||||
close(ifile);
|
||||
} /* pflag */
|
||||
} /* section_name */
|
||||
} /* for secnb */
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
/* Interface with driver */
|
||||
int ioctlretval;
|
||||
int ifile;
|
||||
/* Interface with getopt_long() libC function */
|
||||
int getoptret;
|
||||
int indexptr;
|
||||
int erroroption = FALSE;
|
||||
char* p_str_fwn = NULL;
|
||||
char* p_str_stkptr = NULL;
|
||||
char* filename;
|
||||
unsigned int verboselevel = 0;
|
||||
unsigned int i;
|
||||
char* c;
|
||||
unsigned int stackpointer = 0;
|
||||
unsigned int ioctl_test_gok = 0;
|
||||
unsigned int do_UPDATE_FIRMWARE_START_EXECUTION = 1;
|
||||
|
||||
/*****************
|
||||
* Parse options *
|
||||
*****************/
|
||||
while ((getoptret = getopt_long_only (argc, argv, "f:vhpns:b", updatefw_longopts, &indexptr)) != -1)
|
||||
switch (getoptret) {
|
||||
/* Without-argument options */
|
||||
case 0: /* means that the option just sets a flag. Nothing has to be done,
|
||||
since getopt_long already sets the flag. */
|
||||
break;
|
||||
|
||||
/* With-argument options & equivalent short options */
|
||||
case 'v':
|
||||
verboselevel++;
|
||||
break;
|
||||
|
||||
case 'h': /* short switch -h was used */
|
||||
helpflag = SWITCH_IS_ON;
|
||||
break;
|
||||
|
||||
case 'p': /* short switch -p was used */
|
||||
pflag = SWITCH_IS_ON;
|
||||
break;
|
||||
|
||||
case 'n': /* short switch -n was used */
|
||||
noexecflag = SWITCH_IS_ON;
|
||||
break;
|
||||
|
||||
case 'f': /* short switch -f was used */
|
||||
fflag = SWITCH_IS_ON;
|
||||
p_str_fwn = optarg;
|
||||
break;
|
||||
|
||||
case 's': /* short switch -s was used */
|
||||
sflag = SWITCH_IS_ON;
|
||||
p_str_stkptr = optarg;
|
||||
break;
|
||||
|
||||
case 'b': /* short switch -b was used */
|
||||
rebootflag = SWITCH_IS_ON;
|
||||
break;
|
||||
|
||||
default:
|
||||
erroroption = TRUE;
|
||||
break;
|
||||
};
|
||||
|
||||
/* End of while */
|
||||
|
||||
/********************************
|
||||
* Check consistency of options *
|
||||
********************************/
|
||||
/* First, any irregularity in the use of the options ? Leave. */
|
||||
if (erroroption == TRUE) {
|
||||
fprintf(stderr, "%s: Misuse (--help to show usage)\n", argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Let print the help if it has been explicitly asked for */
|
||||
if (helpflag == SWITCH_IS_ON) {
|
||||
show_usage(argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Check that mandatory firmware option was specified */
|
||||
if (fflag != SWITCH_IS_ON) {
|
||||
fprintf(stderr, "%s: missing mandatory [-f|--firmware] option (--help to show usage).\n", argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Check that mandatory stack pointer option was specified */
|
||||
if (sflag != SWITCH_IS_ON) {
|
||||
fprintf(stderr, "%s: missing mandatory [-s|--stackptr] option (--help to show usage).\n", argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Check consistency of stack pointer value. */
|
||||
/* 1/2 - The address must start with the 2 characters '0x' and be exactly 10 characters long. */
|
||||
if ((strncmp(p_str_stkptr, "0x", 2)) || (strlen(p_str_stkptr) != 10)) { /* 10 is for 0x + 8 hex digits. */
|
||||
fprintf(stderr, "%s: Invalid value to [s|--stackptr] option (--help to show usage).\n", argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* 2/2 - The address must only be made of hexadecimal digits. */
|
||||
for (i=0,c=p_str_stkptr+2; i < 8 ; i++,c++) {
|
||||
if (!
|
||||
( ((*c >= '0') && (*c <= '9'))
|
||||
|| ((*c >= 'a') && (*c <= 'f'))
|
||||
|| ((*c >= 'A') && (*c <= 'F'))
|
||||
)
|
||||
) {
|
||||
fprintf(stderr, "%s: Invalid value to [s|--stackptr] option (--help to show usage).\n", argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Transcode string hexadecinmal value into binary value */
|
||||
if ((*c <= '9') && (*c >= '0'))
|
||||
stackpointer |= (*c - '0') << 28-(i*4);
|
||||
else if ((*c <= 'F') && (*c >= 'A'))
|
||||
stackpointer |= ((*c - 'A') + 10) << 28-(i*4);
|
||||
else if ((*c <= 'f') && (*c >= 'a'))
|
||||
stackpointer |= ((*c - 'a') + 10) << 28-(i*4);
|
||||
}
|
||||
|
||||
/* Open firmware file in READ_ONLY mode. */
|
||||
filename = p_str_fwn;
|
||||
if (filename == NULL) {
|
||||
fprintf(stderr, "%s %d: No filename specified\n", __FILE__, __LINE__);
|
||||
exit(-1);
|
||||
}
|
||||
p_elfimage = fopen(filename, READ_FILE_MODE);
|
||||
|
||||
if (p_elfimage == NULL) {
|
||||
fprintf(stderr, "Error : could not open file <%s> in %s mode.\n", filename, READ_FILE_MODE);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (verboselevel >= VERBOSE_LEVEL_ACCESS_FILES)
|
||||
printf("Info: using file <%s> (successfully opened in %s mode).\n", filename, READ_FILE_MODE);
|
||||
|
||||
/* Read elf binary image file */
|
||||
/* Get informations from header file */
|
||||
if (!(get_elf_header(&elf_Ehdr, p_elfimage))) {
|
||||
fprintf(stderr, "Error : file doesn't match expected format.\n");
|
||||
fclose(p_elfimage);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (verboselevel >= VERBOSE_LEVEL_ACCESS_FILES)
|
||||
printf("Info: ok, file matches expected format.\n");
|
||||
|
||||
/* record the position of the section header table in the file */
|
||||
fseek(p_elfimage, (long)(elf_Ehdr.e_shoff), 0);
|
||||
Shdr_pos = ftell(p_elfimage);
|
||||
/* record the position of the section name string table */
|
||||
get_elf_section_header(&elf_Shdr, p_elfimage, elf_Ehdr.e_shstrndx);
|
||||
fseek(p_elfimage, (long)(elf_Shdr.sh_offset), 0);
|
||||
StringSec_pos = ftell(p_elfimage);
|
||||
StringSec_size = elf_Shdr.sh_size;
|
||||
|
||||
/* copy the string table into global variable */
|
||||
if (StringSec_size > MAX_SIZE_STRING_TABLE) {
|
||||
fprintf(stderr, "Error: section name string table too big (%ld > %d);"
|
||||
" increase max. allowed value in source code and recompile\n",
|
||||
StringSec_size, MAX_SIZE_STRING_TABLE);
|
||||
fclose(p_elfimage);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fread(SecNameStnTable, 1, StringSec_size, p_elfimage);
|
||||
|
||||
/* Action 1: force reboot (if option was specified) */
|
||||
if (verboselevel >= VERBOSE_LEVEL_MAIN_STEPS) {
|
||||
if (rebootflag == SWITCH_IS_ON)
|
||||
printf("Info: entering action #1 (forcing reboot of Leon).\n");
|
||||
else
|
||||
printf("Info: squeezed action #1 (forcing reboot of Leon).\n");
|
||||
}
|
||||
|
||||
if ((rebootflag == SWITCH_IS_ON) && (!pflag)) {
|
||||
ifile = open(DEVICE_NAME, ACCESS_MODE, 0);
|
||||
|
||||
if (ifile<0) {
|
||||
fprintf(stderr, "Error: could not open %s (open() returned %d, errno=%u).\n", DEVICE_NAME, ifile, errno);
|
||||
fclose(p_elfimage);
|
||||
exit(-1);
|
||||
} else if (verboselevel >= VERBOSE_LEVEL_IOCTL) {
|
||||
printf("Info: ok, successfully opened %s.\n", DEVICE_NAME);
|
||||
}
|
||||
|
||||
ioctl_params[0] = UPDATE_FIRMWARE_FORCE_REBOOT;
|
||||
/* Call ioctl driver */
|
||||
ioctlretval = ioctl(ifile, openair_UPDATE_FIRMWARE, ioctl_params);
|
||||
|
||||
if (ioctlretval) {
|
||||
fprintf(stderr, "Error: ioctl on %s failed.\n", DEVICE_NAME);
|
||||
close(ifile);
|
||||
fclose(p_elfimage);
|
||||
exit(-1);
|
||||
} else if (verboselevel >= VERBOSE_LEVEL_IOCTL) {
|
||||
printf("Info: ok, successful ioctl on %s to force reboot.\n", DEVICE_NAME);
|
||||
}
|
||||
|
||||
/* If the card received the boot order, then
|
||||
1) The firmware who handled the order must have cleared the BOOT_GOK bit
|
||||
before rebooting ;
|
||||
2) Boot-strap should once again set it back upon its init operations.
|
||||
So we wait for this bit to be set again before issuing the rest of the
|
||||
update-firmware operations (transfer loadable sections and so on...).
|
||||
Note: putting the polling loop here is better than to have it in the
|
||||
openair driver, because it avoids hanging the kernel if the card was
|
||||
ever not to reboot cleanly. If the loop was to not end, user can simply
|
||||
gives up the update-firmware operation by issuing a Ctrl-C. */
|
||||
ioctl_params[0] = UPDATE_FIRMWARE_TEST_GOK;
|
||||
|
||||
/* Call ioctl driver */
|
||||
if (verboselevel >= VERBOSE_LEVEL_MAIN_STEPS)
|
||||
printf("Info: waiting for GOK bit (as acknowledge of reboot command) - May take a few seconds...\n");
|
||||
|
||||
ioctl_test_gok = 0;
|
||||
|
||||
do {
|
||||
ioctlretval = ioctl(ifile, openair_UPDATE_FIRMWARE, ioctl_params);
|
||||
ioctl_test_gok++;
|
||||
sleep(1); /* sleep 1 second */
|
||||
|
||||
if (!(ioctl_test_gok % 10))
|
||||
printf("Warning: card does not seem to have rebooted cleanly (no GOK bit). Still trying ([Ctrl-C] to abort).\n");
|
||||
} while (ioctlretval);
|
||||
|
||||
if (verboselevel >= VERBOSE_LEVEL_IOCTL)
|
||||
printf("Info: ok, card set again GOK bit (after %u seconds).\n", ioctl_test_gok);
|
||||
|
||||
close(ifile);
|
||||
} /* rebootflag && pflag */
|
||||
|
||||
if ((verboselevel >= VERBOSE_LEVEL_MAIN_STEPS) && (rebootflag == SWITCH_IS_ON))
|
||||
printf("Info: action #1 done.\n");
|
||||
|
||||
/* Action 2: Find the .text section */
|
||||
if (verboselevel >= VERBOSE_LEVEL_MAIN_STEPS) printf("Info: entering action #2 (Transfer .text section).\n");
|
||||
|
||||
find_and_transfer_section(".text", verboselevel);
|
||||
sleep(1);
|
||||
|
||||
if (verboselevel >= VERBOSE_LEVEL_MAIN_STEPS) printf("Info: action #2 done.\n");
|
||||
|
||||
/* Action 3 : Find the .data section */
|
||||
if (verboselevel >= VERBOSE_LEVEL_MAIN_STEPS) printf("Info: entering action #3 (Transfer .data section).\n");
|
||||
|
||||
find_and_transfer_section(".data", verboselevel);
|
||||
sleep(1);
|
||||
|
||||
if (verboselevel >= VERBOSE_LEVEL_MAIN_STEPS) printf("Info: action #3 done.\n");
|
||||
|
||||
/* Action 4 : Find the .bss section */
|
||||
if (verboselevel >= VERBOSE_LEVEL_MAIN_STEPS) printf("Info: entering action #4 (Clear .bss section).\n");
|
||||
|
||||
find_and_clear_section_bss(verboselevel);
|
||||
sleep(1);
|
||||
|
||||
if (verboselevel >= VERBOSE_LEVEL_MAIN_STEPS) printf("Info: action #4 done.\n");
|
||||
|
||||
/* Action 5 : Find the entry address */
|
||||
if (verboselevel >= VERBOSE_LEVEL_MAIN_STEPS) printf("Info: entering action #5 (Jump to firmware/set stack-pointer).\n");
|
||||
|
||||
if (verboselevel >= VERBOSE_LEVEL_SECTION_DETAILS)
|
||||
printf("Info: Firmware entry point = 0x%08x, setting stack pointer = 0x%08x.\n", (unsigned int)elf_Ehdr.e_entry, stackpointer);
|
||||
|
||||
/* Open the special device file. */
|
||||
if (!pflag) {
|
||||
ifile = open(DEVICE_NAME, ACCESS_MODE, 0);
|
||||
|
||||
if (ifile<0) {
|
||||
fprintf(stderr, "Error: could not open %s (open() returned %d, errno=%u).\n", DEVICE_NAME, ifile, errno);
|
||||
fclose(p_elfimage);
|
||||
exit(-1);
|
||||
} else if (verboselevel >= VERBOSE_LEVEL_IOCTL) {
|
||||
printf("Info: ok, successfully opened %s.\n", DEVICE_NAME);
|
||||
}
|
||||
|
||||
/* Collect control data for ioctl. */
|
||||
ioctl_params[0] = UPDATE_FIRMWARE_START_EXECUTION;
|
||||
ioctl_params[1] = elf_Ehdr.e_entry;
|
||||
ioctl_params[2] = stackpointer;
|
||||
|
||||
//invert4(ioctl_params[1]);
|
||||
//invert4(ioctl_params[2]);
|
||||
/* Call ioctl driver */
|
||||
if ( noexecflag == SWITCH_IS_OFF ) {
|
||||
ioctlretval = ioctl(ifile, openair_UPDATE_FIRMWARE, ioctl_params);
|
||||
|
||||
if (ioctlretval) {
|
||||
fprintf(stderr, "Error: ioctl on %s failed.\n", DEVICE_NAME);
|
||||
close(ifile);
|
||||
fclose(p_elfimage);
|
||||
exit(-1);
|
||||
} else if (verboselevel >= VERBOSE_LEVEL_IOCTL) {
|
||||
printf("Info: ok, successful ioctl on %s for stack-pointer setting/firmware-execution.\n", DEVICE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
close(ifile);
|
||||
} /* pflag */
|
||||
|
||||
if (verboselevel >= VERBOSE_LEVEL_MAIN_STEPS) printf("Info: action #5 done.\n");
|
||||
|
||||
fclose(p_elfimage);
|
||||
|
||||
/* Did we pretend ? */
|
||||
if (pflag) printf("Nothing done.\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*
|
||||
C Header file <updatefw.h> for updatefw tool.
|
||||
|
||||
K. Khalfallah, Aug, 2007
|
||||
kkhalfallah@free.fr
|
||||
*/
|
||||
|
||||
#ifndef UPDATEFW_H
|
||||
#define UPDATEFW_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#define _testsyscall(x, y, z) {if (x==-1) { \
|
||||
fprintf(stderr, "Error : %s() returned "z" (errno=%d)\n", y, x, errno); \
|
||||
fprintf(stderr, "Warning : not leaving normally. Remove ipc ressources by hand !"); \
|
||||
fprintf(stderr, " (use shell commands ipcs & ipcrm)\n"); \
|
||||
exit(-1); \
|
||||
}}
|
||||
// else { \
|
||||
// printf("Info : successfully called %s, returned "z"\n", y, x);}}
|
||||
|
||||
/* Intel is little-endian, sparc is big */
|
||||
unsigned long ltmp;
|
||||
#define invert4(x) {ltmp=x; x=((ltmp & 0xff)<<24) | ((ltmp & 0xff00)<<8) | \
|
||||
((ltmp & 0xff0000)>>8) | ((ltmp & 0xff000000)>>24); }
|
||||
unsigned short stmp;
|
||||
#define invert2(x) {stmp=x; x=((stmp & 0xff)<< 8) | ((stmp & 0xff00)>>8);}
|
||||
|
||||
|
||||
/* static variables, global */
|
||||
char* virt_addr;
|
||||
unsigned int packet_ndx = 0;
|
||||
|
||||
#define FSEEK_ORIGIN 0
|
||||
#define FSEEK_CURRENT 1
|
||||
#define READ_FILE_MODE "r"
|
||||
/* Verbose levels */
|
||||
#define VERBOSE_LEVEL_MAIN_STEPS 1
|
||||
#define VERBOSE_LEVEL_ACCESS_FILES 2
|
||||
#define VERBOSE_LEVEL_SECTION_DETAILS 3
|
||||
#define VERBOSE_LEVEL_IOCTL 4
|
||||
|
||||
|
||||
#endif /* UPDATEFW_H */
|
||||
@@ -1,50 +0,0 @@
|
||||
CC = gcc
|
||||
CFLAGS = -DEXMIMO -g
|
||||
XTRA_CFLAGS = -msse -msse2 -mssse3 -fPIC
|
||||
|
||||
#ifndef OPENAIR0_DIR
|
||||
# $(error Environment variable OPENAIR0_DIR must be set!)
|
||||
#else
|
||||
# CFLAGS += -I$(OPENAIR0_DIR)/express-mimo/software/pcie
|
||||
#endif
|
||||
|
||||
|
||||
GCCVERSION = $(shell gcc --version | grep ^gcc | sed 's/^.* //g')
|
||||
ifeq "$(GCCVERSION)" "4.4.3"
|
||||
CFLAGS += -Wno-packed-bitfield-compat
|
||||
endif
|
||||
ifeq "$(GCCVERSION)" "4.5.2"
|
||||
CFLAGS += -Wno-packed-bitfield-compat
|
||||
endif
|
||||
ifeq "$(GCCVERSION)" "4.6.1"
|
||||
CFLAGS += -Wno-packed-bitfield-compat
|
||||
endif
|
||||
|
||||
|
||||
OPENAIRTARGETS_DIR ?=../../../..
|
||||
|
||||
OPENAIROBJS += $(OPENAIRTARGETS_DIR)/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.o
|
||||
CFLAGS += -I$(OPENAIRTARGETS_DIR)/ARCH/EXMIMO/USERSPACE/LIB -I$(OPENAIRTARGETS_DIR)/ARCH/EXMIMO/DEFS -I$(OPENAIRTARGETS_DIR)/ARCH/COMMON
|
||||
|
||||
#OPENAIROBJS = $(OPENAIR1_DIR)/PHY/CONFIG/openair_readconfigfile.o $(OPENAIR1_DIR)/PHY/CONFIG/openair_configure.o
|
||||
|
||||
OCTAVEOBJS = oarf_config_exmimo.oct oarf_get_frame.oct oarf_stop.oct oarf_send_frame.oct oarf_get_num_detected_cards.oct oarf_stop_without_reset.oct
|
||||
|
||||
all: $(OCTAVEOBJS) gpib_send.oct
|
||||
|
||||
oarf: $(OCTAVEOBJS)
|
||||
|
||||
$(OPENAIROBJS) : %.o : %.c
|
||||
gcc -c $(CFLAGS) $(XTRA_CFLAGS) -o $@ $<
|
||||
|
||||
test:
|
||||
echo $(OPENAIROBJS)
|
||||
|
||||
$(OCTAVEOBJS) : %.oct : %.cc $(OPENAIROBJS)
|
||||
mkoctfile -o $@ $(CFLAGS) -lm $(OPENAIROBJS) $<
|
||||
|
||||
gpib_send.oct: gpib_send.cc
|
||||
mkoctfile -I/usr/include/gpib -I/usr/local/include/gpib -lgpib gpib_send.cc
|
||||
|
||||
clean:
|
||||
rm -f gpib_send.oct $(OCTAVEOBJS) $(OPENAIROBJS) *.o octave-core
|
||||
@@ -1,19 +0,0 @@
|
||||
function [sig,sig_length] = OFDM_TX(num_carriers,num_zeros,prefix_length,input)
|
||||
|
||||
% OFDM Transmitter - DC removed
|
||||
% sig is the output signal
|
||||
% length is the length of the output signal
|
||||
% num_carriers - number of sub-carriers (power of 2)
|
||||
% num_zeros - number of zeros minus 1 (DC) in output spectrum (odd)
|
||||
% prefix_length - length of cyclic prefix
|
||||
% input - input dimensions (length = number_carriers - num_zeros - 1)
|
||||
|
||||
if (length(input) + num_zeros + 1 ~= num_carriers)
|
||||
fprintf('error in lengths\n');
|
||||
return;
|
||||
end
|
||||
|
||||
ext_input = [0 input(1:length(input)/2) zeros(1,num_zeros) input((1+length(input)/2) : length(input))];
|
||||
output_1 = ifft(ext_input);
|
||||
sig = [output_1((num_carriers - prefix_length + 1) : num_carriers) output_1];
|
||||
sig_length = length(sig);
|
||||
@@ -1,25 +0,0 @@
|
||||
function [sig, sig_f] = OFDM_TX_FRAME(num_carriers,num_zeros,prefix_length,num_symbols_frame,preamble_length)
|
||||
|
||||
% sig - output signal
|
||||
% sig_length - output signal length
|
||||
% num_carriers - number of sub-carriers
|
||||
% num_zeros - number of zero carriers minus 1 (DC)
|
||||
% prefix_length - length of cyclic prefix
|
||||
% num_symbols_frame - number of symbols per OFDM frame
|
||||
% preamble_length - length of 4-QAM preamble
|
||||
|
||||
num_useful_carriers = num_carriers - num_zeros -1;
|
||||
|
||||
sig = zeros(1,(num_carriers+prefix_length)*num_symbols_frame);
|
||||
sig_f = zeros(num_symbols_frame,num_useful_carriers);
|
||||
for k=1:preamble_length
|
||||
QAM4_preamble = QAM_MOD(4,floor(4*abs(rand(1,num_useful_carriers/4))));
|
||||
sig((k-1)*(num_carriers+prefix_length)+1:k*(num_carriers+prefix_length)) = OFDM_TX(num_carriers,num_zeros,prefix_length,QAM4_preamble);
|
||||
sig_f(k,:) = QAM4_preamble;
|
||||
end
|
||||
|
||||
for k=preamble_length+1:num_symbols_frame
|
||||
QAM_data = QAM_MOD(256,floor(256*abs(rand(1,num_useful_carriers/256))));
|
||||
sig((k-1)*(num_carriers+prefix_length)+1:k*(num_carriers+prefix_length)) = OFDM_TX(num_carriers,num_zeros,prefix_length,QAM_data);
|
||||
sig_f(k,:) = QAM_data;
|
||||
end
|
||||
@@ -1,29 +0,0 @@
|
||||
function [sig,sig_length] = QAM_MOD(size,input)
|
||||
|
||||
% sig - output symbols
|
||||
% size - modulation size (4,16,256)
|
||||
% input - vector of bytes to be modulated
|
||||
|
||||
AM2 = [-1 1];
|
||||
AM4 = [-3 -1 1 3]; AM4 = 2*AM4/sqrt(AM4*AM4');
|
||||
AM16 = [-15 -13 -11 -9 -7 -5 -3 -1 1 3 5 7 9 11 13 15]; AM16 = 4*AM16/sqrt(AM16*AM16');
|
||||
|
||||
sig = zeros(1,length(input)*8/log2(size));
|
||||
sig_length = length(input)*8/log2(size);
|
||||
|
||||
for l=1:length(input)
|
||||
if (size == 256)
|
||||
sig(l) = (AM16(1+ floor((input(l)/16))) +sqrt(-1)*AM16(1+rem(input(l),16)))/sqrt(2);
|
||||
|
||||
elseif (size == 16)
|
||||
sig(1 + 2*(l-1)) = (AM4(1+floor((input(l)/64))) + sqrt(-1)*AM4(1+rem(floor(input(l)/16) , 4)))/sqrt(2);
|
||||
sig(2 + 2*(l-1)) = (AM4(1+rem(floor(input(l)/4) , 4)) + sqrt(-1)*AM4(1+rem(input(l) , 4)))/sqrt(2);
|
||||
|
||||
elseif (size == 4)
|
||||
sig(1+ 4*(l-1)) = (AM2(1+(floor(input(l)/128))) + sqrt(-1)*AM2(1+rem(floor(input(l)/64) , 2)))/sqrt(2);
|
||||
sig(2+ 4*(l-1)) = (AM2(1+rem(floor(input(l)/32) ,2)) + sqrt(-1)*AM2(1+rem(floor(input(l)/16) , 2)))/sqrt(2);
|
||||
sig(3+ 4*(l-1)) = (AM2(1+rem(floor(input(l)/8) , 2)) + sqrt(-1)*AM2(1+rem(floor(input(l)/4) , 2)))/sqrt(2);
|
||||
sig(4+ 4*(l-1)) = (AM2(1+rem(floor(input(l)/2) , 2)) + sqrt(-1)*AM2(1+rem(input(l) , 2)))/sqrt(2);
|
||||
|
||||
end
|
||||
end
|
||||
@@ -1,19 +0,0 @@
|
||||
chan=1;
|
||||
hold off ;
|
||||
card=0;
|
||||
s=oarf_get_frame(card);
|
||||
|
||||
s2=zeros(76800*2,1);
|
||||
s2(1:2:end) = s(:,chan);
|
||||
s2(2:2:end) = s(:,chan);
|
||||
|
||||
plot(real(s2),'b',"markersize",1);
|
||||
hold on; plot(imag(s2),'r',"markersize",1);
|
||||
|
||||
bit11_I = rem(floor(real(2048+s(:,chan))/2048),2);
|
||||
bit11_Q = rem(floor(imag((2048*j)+s(:,chan))/2048),2);
|
||||
bit11_IQ = zeros(1,2*length(bit11_I));
|
||||
bit11_IQ(1:2:end) = bit11_I;
|
||||
bit11_IQ(2:2:end) = bit11_Q;
|
||||
plot(500*bit11_IQ,'k')
|
||||
axis([0 76800 -1000 1000])
|
||||
@@ -1,17 +0,0 @@
|
||||
vlen=76800
|
||||
chan=2
|
||||
|
||||
gainimb_rx = -0.0020; phaseimb_rx = -2.38; % ExMIMO1 / lime1, VGAgain2 = 0, 1.9 GHz
|
||||
gainimb_rx = 0.55; phaseimb_rx = 24.3; % ExMIMO1 / lime1, VGAgain2 = 0, 1.9 GHz
|
||||
|
||||
phaseimb_rx = phaseimb_rx/180*pi; % phaser imb in radians
|
||||
beta_rx = (1/2)*(1 + (1+ gainimb_rx) * exp(1i*phaseimb_rx));
|
||||
alpha_rx = (1/2)*(1 - (1+ gainimb_rx) * exp(-1i*phaseimb_rx));
|
||||
den=abs(beta_rx)^2-abs(alpha_rx)^2;
|
||||
beta_rx=beta_rx/den;
|
||||
alpha_rx=alpha_rx/den;
|
||||
|
||||
s2 = beta_rx.*s + alpha_rx.*conj(s);
|
||||
hold off ; plot(20*log10(abs(fftshift(fft(s2(:,chan)))))); grid on;
|
||||
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
dual_tx=0;
|
||||
eNBflag = 0;
|
||||
card=0;
|
||||
limeparms;
|
||||
|
||||
%% acquisition
|
||||
%rf_mode = ( RXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + RXOUTSW )*[1 1 0 0];
|
||||
rf_mode = ( RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM )*[1 1 1 1];
|
||||
|
||||
% internal loopback test
|
||||
%rf_mode = (RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAByp+RFBBLNA1)*[1 1 0 0];
|
||||
%rf_mode = (RXEN+ TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAByp+RFBBLNA1)*[1 1 1 1];
|
||||
%rf_mode = [0 0 0 0];
|
||||
|
||||
%% Select DMA directions
|
||||
rf_mode = rf_mode + (DMAMODE_RX + DMAMODE_TX)*[1 0 0 0];
|
||||
|
||||
freq_rx = (1907600000 - 0*9000)*[1 1 1 1];
|
||||
%rf_local= [rfl(56,56,31,31) rfl(16,12,31,31) rfl(36,48,31,31) rfl(32,20,31,31)]; % 1.9 GHz, Exmimo2-No1, lime_cal_exmimo
|
||||
%rf_local= [rfl(34,40,31,31) rfl(20,25,38,21) rfl(12,38,21,14) rfl(31,19,36, 6)]; % 1.9 GHz, Exmimo2-No1, LIME GUI
|
||||
rf_local= [rfl(32,36,26,25) rfl(20,25,37,21) rfl(12,38,21,14) rfl(31,19,36, 6)];
|
||||
rf_vcocal=(( 0xE)*(2^6)) + ( 0xE)*[1 1 1 1]; % 1.907 GHz, (OLD)
|
||||
freq_tx = freq_rx + 000000; % 1kHz offset: @30 MSPS: 2.5 sines, @15 MSPS: 5 sines, @7 MSPS: 10 sines
|
||||
rf_rxdc = rf_rxdc*[1 1 1 1];
|
||||
|
||||
|
||||
tx_gain = 13*[1 1 1 1]; rx_gain = 25*[1 1 1 1]; amp=32000;
|
||||
%tx_gain = 25*[1 1 1 1]; rx_gain = 0*[1 1 1 1]; amp=32000;
|
||||
oarf_config_exmimo(card,freq_rx,freq_tx,0,dual_tx,rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal);
|
||||
|
||||
sleep(1);
|
||||
% create_testvector
|
||||
vlen=76800
|
||||
chan=1
|
||||
|
||||
v=0000*exp(-i*(3*[0:vlen-1]/vlen)*2*pi); v=[v;v]'; oarf_send_frame(card,v,16); sleep(0.2);
|
||||
s = oarf_get_frame(card); figure ; plot(real(s(:,chan)),'b-.',"markersize",2) ; hold on ; plot(imag(s(:,chan)),'r-.',"markersize",2);
|
||||
s = s(:,chan) - mean(s(:,chan)); % remove DC
|
||||
e_s0 = sum( s' * s )
|
||||
v=amp*exp(-i*(10000*[0:vlen-1]/vlen)*2*pi); e_v=sum(v*v'); v=[v;v]'; oarf_send_frame(card,v,16); sleep(0.2);
|
||||
s = oarf_get_frame(card); figure ; plot(real(s(:,chan)),'b-.',"markersize",2) ; hold on ; plot(imag(s(:,chan)),'r-.',"markersize",2);
|
||||
s = s(:,chan) - mean(s(:,chan)); % remove DC
|
||||
figure; plot(20*log10(fftshift(abs(fft(s))))); grid on;
|
||||
e_v
|
||||
e_s = sum( s' * s )
|
||||
s_over_s0_db = 10*log10( e_s / e_s0 )
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
dual_tx=0;
|
||||
eNBflag = 0;
|
||||
card=0;
|
||||
limeparms;
|
||||
|
||||
%% acquisition
|
||||
%rf_mode = ( RXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + RXOUTSW )*[1 1 0 0];
|
||||
rf_mode = ( TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM )*[1 1 0 0];
|
||||
|
||||
% internal loopback test
|
||||
%rf_mode = (RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAByp+RFBBLNA1)*[1 1 0 0];
|
||||
%rf_mode = (RXEN+ TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAByp+RFBBLNA1)*[1 1 1 1];
|
||||
%rf_mode = [0 0 0 0];
|
||||
|
||||
%% Select DMA directions
|
||||
rf_mode = rf_mode + (DMAMODE_TX)*[0 1 0 0];
|
||||
|
||||
freq_rx = (1907600000 - 0*9000)*[1 1 1 1];
|
||||
%rf_local= [rfl(56,56,31,31) rfl(16,12,31,31) rfl(36,48,31,31) rfl(32,20,31,31)]; % 1.9 GHz, Exmimo2-No1, lime_cal_exmimo
|
||||
%rf_local= [rfl(34,40,31,31) rfl(20,25,38,21) rfl(12,38,21,14) rfl(31,19,36, 6)]; % 1.9 GHz, Exmimo2-No1, LIME GUI
|
||||
%rf_local= [rfl(32,36,26,25) rfl(20,25,37,21) rfl(12,38,21,14) rfl(31,19,36, 6)];
|
||||
rf_local= [rfl(33,36,26,25) rfl(20,24,37,21) rfl(12,38,21,14) rfl(31,19,36, 6)];
|
||||
rf_vcocal=(( 0xE)*(2^6)) + ( 0xE)*[1 1 1 1]; % 1.907 GHz, (OLD)
|
||||
freq_tx = freq_rx + 000000; % 1kHz offset: @30 MSPS: 2.5 sines, @15 MSPS: 5 sines, @7 MSPS: 10 sines
|
||||
rf_rxdc = rf_rxdc*[1 1 1 1];
|
||||
|
||||
|
||||
tx_gain = 20*[1 1 1 1]; rx_gain = 25*[1 1 1 1]; amp=10000;
|
||||
%tx_gain = 25*[1 1 1 1]; rx_gain = 0*[1 1 1 1]; amp=32000;
|
||||
oarf_config_exmimo(card, freq_rx,freq_tx,0,dual_tx,rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal);
|
||||
|
||||
sleep(1);
|
||||
% create_testvector
|
||||
vlen=76800
|
||||
chan=1
|
||||
|
||||
%v=0000*exp(-i*(3*[0:vlen-1]/vlen)*2*pi); v=[v;v]'; oarf_send_frame(card,v,16); sleep(0.2);
|
||||
%s = oarf_get_frame(card); figure ; plot(real(s(:,chan)),'b-.',"markersize",2) ; hold on ; plot(imag(s(:,chan)),'r-.',"markersize",2);
|
||||
% create_testvector
|
||||
vlen=76800
|
||||
chan=1
|
||||
amp=10000
|
||||
|
||||
%v=0000*exp(-i*(3*[0:vlen-1]/vlen)*2*pi); v=[v;v]'; oarf_send_frame(card,v,16); sleep(0.2);
|
||||
%s = oarf_get_frame(card); figure ; plot(real(s(:,chan)),'b-.',"markersize",2) ; hold on ; plot(imag(s(:,chan)),'r-.',"markersize",2);
|
||||
|
||||
v=amp*exp(-i*(10000*[0:vlen-1]/vlen)*2*pi); v=[v;v]';
|
||||
|
||||
|
||||
%for gainimb_tx = -0.05:0.01:0.05
|
||||
%for phaseimb_tx= -5:1:5
|
||||
|
||||
gainimb_tx = -0.028; % gain imabalance of modulator in linear scale
|
||||
phaseimb_tx = 3.0; % phase imbalance of modulator in degrees
|
||||
|
||||
gainimb_tx = -0.028; phaseimb_tx = 3.0; % for exmimo2-1 lime1
|
||||
|
||||
phaseimb_tx = phaseimb_tx/180*pi; % phaser imb in radians
|
||||
beta_tx = (1/2)*(1 + (1+ gainimb_tx) * exp(1i*phaseimb_tx));
|
||||
alpha_tx = (1/2)*(1 - (1+ gainimb_tx) * exp(-1i*phaseimb_tx));
|
||||
den=abs(beta_tx)^2-abs(alpha_tx)^2;
|
||||
beta_tx=beta_tx/den;
|
||||
alpha_tx=alpha_tx/den;
|
||||
|
||||
v = beta_tx.*v + alpha_tx.*conj(v);
|
||||
|
||||
sleep(0.5); oarf_send_frame(card,v,16);
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
% Basic configuration script for ExpressMIMO-1 and ExpressMIMO-2
|
||||
% Some functions are only available on ExpressMIMO-2!
|
||||
limeparms;
|
||||
|
||||
eNBflag = 0;
|
||||
card=0;
|
||||
|
||||
tdd_config = TXRXSWITCH_LSB;
|
||||
%tdd_config = TXRXSWITCH_TESTTX;
|
||||
syncmode = SYNCMODE_FREE;
|
||||
|
||||
%% acquisition
|
||||
%rf_mode = ( RXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + RXOUTSW )*[1 1 0 0];
|
||||
rf_mode = ( RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM )*[ 1 0 0 0 ];
|
||||
%rf_mode = rf_mode + (RXEN+TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM )*[ 0 1 0 0 ];
|
||||
|
||||
% internal loopback test
|
||||
%rf_mode = (RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAByp+RFBBLNA1)*[1 1 0 0];
|
||||
%rf_mode = (RXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA.1ON+LNAByp+RFBBLNA1)*[1 1 1 1];
|
||||
%rf_mode = [0 0 0 0];
|
||||
|
||||
%% Select DMA directions
|
||||
%rf_mode = rf_mode + (DMAMODE_RX)*[0 1 0 0];
|
||||
%rf_mode = rf_mode + (DMAMODE_RX)*[0 0 1 1];
|
||||
%rf_mode = rf_mode + (DMAMODE_TX)*[1 1 0 0];
|
||||
rf_mode = rf_mode + (DMAMODE_RX + DMAMODE_TX)*[ 1 0 0 0 ];
|
||||
%rf_mode = rf_mode + (DMAMODE_RX )*[0 1 0 0];
|
||||
%rf_mode = rf_mode + (DMAMODE_TX)*[1 0 0 0]; rf_mode = rf_mode + (DMAMODE_RX)*[0 1 0 0];
|
||||
|
||||
|
||||
%freq_rx = 749600000*[1 1 1 1];
|
||||
%rf_local= [8255004 8253440 8257340 8257340]; % 700 MHz
|
||||
%rf_vcocal=((0x24)*(2^6)) + (0x24)*[1 1 1 1]; % 700 MHz
|
||||
freq_rx = (1907600000 - 0*9000)*[1 1 1 1];
|
||||
%rf_local= [rfl( 0, 0,31,31) rfl(28,44,31,31) rfl(60,60,31,31) rfl(60,60,31,31)]; % 1.9 GHz, OLD
|
||||
%rf_local= [rfl(56,56,31,31) rfl(16,12,31,31) rfl(36,48,31,31) rfl(32,20,31,31)]; % 1.9 GHz, Exmimo2-No1, lime_cal_exmimo
|
||||
%rf_local= [rfl(34,40,31,31) rfl(20,25,38,21) rfl(12,38,21,14) rfl(31,19,36, 6)]; % 1.9 GHz, Exmimo2-No1, LIME GUI
|
||||
rf_local= [rfl(20,25,26,04) rfl(20,25,26,04) 0 0]; % 1.9 GHz & 860 MHz, VGA2Gain=0
|
||||
%rf_local= [0 rfl(20,25,38,21) 0 0 ]; % 1.9 GHz, VGA2Gain=30
|
||||
|
||||
rf_vcocal=(( 0xE)*(2^6)) + ( 0xE)*[1 1 1 1]; % 1.907 GHz, (OLD)
|
||||
%rf_vcocal=((0x14)*(2^6)) + (0x13)*[1 1 1 1]; % 1.907 GHz, RX(msbs)+ TX(lsbs), RX:0xC..0x14, TX:0xB..0x13 (ExMIMO2-No1)
|
||||
%rf_vcocal=((0x12)*(2^6)) + (0x10)*[1 1 1 1]; % 1.917 GHz, RX(msbs)+ TX(lsbs), RX:0xD..0x16, TX:0xC..0x14 (ExMIMO2-No1)
|
||||
|
||||
%freq_rx = ( 860000000 - 0*9000)*[1 1 1 1];
|
||||
%rf_vcocal=((0x1d)*(2^6)) + (0x1d)*[1 1 1 1]; % 860 MHz
|
||||
|
||||
freq_tx = freq_rx + 0000000; % 1kHz offset: @30 MSPS: 2.5 sines, @15 MSPS: 5 sines, @7 MSPS: 10 sines
|
||||
tx_gain = 13*[1 1 1 1];
|
||||
rx_gain = 20*[1 1 1 1];
|
||||
|
||||
rf_rxdc = rf_rxdc*[1 1 1 1];
|
||||
|
||||
rffe_rxg_low = 63*[1 1 1 1];
|
||||
rffe_rxg_final = 63*[1 1 1 1];
|
||||
rffe_band = TVWS_TDD*[1 1 1 1];
|
||||
autocal = [1 1 1 1];
|
||||
oarf_config_exmimo(card,freq_rx,freq_tx,tdd_config,syncmode,rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal)
|
||||
%sleep(0.2)
|
||||
|
||||
% stuff for I/Q imbalance correction on RX
|
||||
%gainimb_rx = -0.0020; phaseimb_rx = -2.38; % RX IQ imbal. ExMIMO1 / lime1, VGAgain2 = 0, 1.9 GHz
|
||||
gainimb_rx = -0.0030; phaseimb_rx = -2.38; % RX IQ imbal. ExMIMO1 / lime1, VGAgain2 = 30, 1.9 GHz
|
||||
|
||||
phaseimb_rx = phaseimb_rx/180*pi; % phaser imb in radians
|
||||
beta_rx = (1/2)*(1 + (1+ gainimb_rx) * exp(1i*phaseimb_rx));
|
||||
alpha_rx = (1/2)*(1 - (1+ gainimb_rx) * exp(-1i*phaseimb_rx));
|
||||
den=abs(beta_rx)^2-abs(alpha_rx)^2;
|
||||
beta_rx=beta_rx/den;
|
||||
alpha_rx=alpha_rx/den;
|
||||
|
||||
|
||||
% create_testvector
|
||||
vlen=76800
|
||||
%v=10000*exp(-i*2*pi*1/7.68*[0:vlen-1]); v=[v;v]'; oarf_send_frame(card,v,16);
|
||||
|
||||
%v=([2:1+vlen; 10002:10001+vlen] - i*[3:2+vlen; 10003:10002+vlen])';
|
||||
%v=32767*(1+i)*ones(vlen,2); oarf_send_frame(card,v,16);
|
||||
%v = floor(( [640:639+vlen ; 640:639+vlen] / 5 ))'; oarf_send_frame(card,v,16);
|
||||
%v = floor(( [75000:-1:75001-vlen ; 75000:-1:75001-vlen] / 5 ))'; oarf_send_frame(card,v,16);
|
||||
%v=i*2^11*ones(vlen,2)+2^11*ones(vlen,2); oarf_send_frame(card,v,16);
|
||||
%v=15000*exp(-i*2*pi*1/7.68*[0:vlen-1]); v=[v;v]'; oarf_send_frame(card,v,16);
|
||||
%v=10000*exp(-i*(3000*[0:vlen-1]/vlen)*2*pi); v=[v;v]'; oarf_send_frame(card,v,16);
|
||||
%v=20000*exp(-i*pi*(0:vlen-1)/2); v=[v;v]'; oarf_send_frame(card,v,16);
|
||||
|
||||
% Set LSB to RX (,1) or to TX(,0)
|
||||
%v=10000*m'.*exp(-i*(50*[0:vlen-1]/vlen)*2*pi); v=bitset(real(v),1,0) + i*bitset(imag(v),1,0); v=[v;v]'; oarf_send_frame(card,v,16);
|
||||
|
||||
|
||||
v2=15000*sin((1:vlen)/vlen*2*pi); v2=[v2;v2]';
|
||||
v=15000*exp(i*2*pi*1/7.68*[1:vlen]); v=[v;v]';
|
||||
%oarf_send_frame(card,v,16);
|
||||
|
||||
%len=1000;off=0; chan=2; s=oarf_get_frame(card); hold off ; plot(real(s(off+1:off+len,chan)),'-o',"markersize",2) ; hold on ; plot(imag(s(off+1:off+len,chan)),'r-o',"markersize",2)
|
||||
%chan=1; s = oarf_get_frame(card); hold off ; plot(real(s(:,chan)),'b-o',"markersize",2) ; hold on ; plot(imag(s(:,chan)),'r-o',"markersize",2)
|
||||
%while 1;len=5000;off=0; chan=1; s = oarf_get_frame(card); hold off ; plot(real(s(off+1:off+len,chan)),'-o',"markersize",2) ; hold on ; plot(imag(s(off+1:off+len,chan)),'r-o',"markersize",3); sleep(0.3);endwhile
|
||||
%chan=2; s=oarf_get_frame(card); s=s-0.99999*mean(s(:,chan)); s = beta_rx.*s + alpha_rx.*conj(s); hold off ; plot(20*log10(abs(fftshift(fft(s(:,chan)))))); grid on; min_r=min(real(s(:,chan))); min_i=min(imag(s(:,chan))); max_r=max(real(s(:,chan))); max_i=max(imag(s(:,chan))); disp("Min-I/Q Max-I/Q"); disp([min_r min_i max_r max_i]);
|
||||
%chan=2; s=oarf_get_frame(card); s=s-0.99999*mean(s(:,chan)); s = beta_rx.*s + alpha_rx.*conj(s); hold off ; plot(20*log10(abs(fftshift(fft(hamming(vlen).*s(:,chan)))))); grid on; min_r=min(real(s(:,chan))); min_i=min(imag(s(:,chan))); max_r=max(real(s(:,chan))); max_i=max(imag(s(:,chan))); disp("Min-I/Q Max-I/Q"); disp([min_r min_i max_r max_i]);
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
% Switch off limes
|
||||
limeparms;
|
||||
|
||||
eNBflag = 0;
|
||||
card=-1;
|
||||
|
||||
tdd_config = TXRXSWITCH_LSB;
|
||||
%tdd_config = TXRXSWITCH_TESTTX;
|
||||
syncmode = SYNCMODE_FREE;
|
||||
|
||||
|
||||
rf_mode = [0 0 0 0];
|
||||
|
||||
%% Select DMA directions
|
||||
rf_mode = rf_mode + (DMAMODE_RX + DMAMODE_TX)*[ 1 0 0 0 ];
|
||||
rf_mode = rf_mode + (DMAMODE_RX )*[0 1 0 0];
|
||||
|
||||
freq_rx = (1907593260)*[1 1 1 1];
|
||||
rf_local= [0 0 0 0 ];
|
||||
|
||||
rf_vcocal=(( 0xE)*(2^6)) + ( 0xE)*[1 1 1 1]; % 1.907 GHz, (OLD)
|
||||
|
||||
freq_tx = freq_rx + 0000000; % 1kHz offset: @30 MSPS: 2.5 sines, @15 MSPS: 5 sines, @7 MSPS: 10 sines
|
||||
tx_gain = 13*[1 1 1 1];
|
||||
rx_gain = 10*[1 1 1 1];
|
||||
|
||||
rf_rxdc = (1 + 1*(2^8))*[1 1 1 1]; % I:LSB, Q:MSB
|
||||
|
||||
oarf_config_exmimo(card,freq_rx,freq_tx,tdd_config,syncmode,rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal)
|
||||
|
||||
oarf_stop(-1);
|
||||
%sleep(0.2)
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
% Basic configuration script for ExpressMIMO-1 and ExpressMIMO-2
|
||||
% Some functions are only available on ExpressMIMO-2!
|
||||
limeparms;
|
||||
|
||||
eNBflag = 0;
|
||||
card=0;
|
||||
|
||||
tdd_config = TXRXSWITCH_LSB;
|
||||
%tdd_config = TXRXSWITCH_TESTTX;
|
||||
tdd_config += TEST_ADACLOOP_EN;
|
||||
syncmode = SYNCMODE_FREE;
|
||||
|
||||
%% acquisition
|
||||
%rf_mode = ( RXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + RXOUTSW )*[1 1 0 0];
|
||||
rf_mode = ( RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM )*[ 1 1 0 0 ];
|
||||
|
||||
%% Select DMA directions
|
||||
rf_mode = rf_mode + (DMAMODE_RX + DMAMODE_TX)*[ 1 0 0 0 ];
|
||||
rf_mode = rf_mode + (DMAMODE_TX )*[0 1 0 0];
|
||||
|
||||
freq_rx = (1907600000)*[1 1 1 1];
|
||||
rf_local= [rfl(20,25,26,04) rfl(20,25,26,04) 0 0]; % 1.9 GHz & 860 MHz, VGA2Gain=0
|
||||
rf_vcocal=(( 0xE)*(2^6)) + ( 0xE)*[1 1 1 1]; % 1.907 GHz, (OLD)
|
||||
freq_tx = freq_rx + 0000000; % 1kHz offset: @30 MSPS: 2.5 sines, @15 MSPS: 5 sines, @7 MSPS: 10 sines
|
||||
tx_gain = 13*[1 1 1 1];
|
||||
rx_gain = 20*[1 1 1 1];
|
||||
rf_rxdc = (1 + 1*(2^8))*[1 1 1 1]; % I:LSB, Q:MSB
|
||||
rffe_rxg_low = 61*[1 1 1 1];
|
||||
rffe_rxg_final = 61*[1 1 1 1];
|
||||
rffe_band = B19G_TDD*[1 1 1 1];
|
||||
|
||||
oarf_config_exmimo(card,freq_rx,freq_tx,tdd_config,syncmode,rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band)
|
||||
|
||||
|
||||
|
||||
% create_testvector
|
||||
vlen=76800
|
||||
v = floor(( [ (201:200+60000) - i*(101:100+60000) ] ))' - (30000+i*30000);
|
||||
v = [v; floor(( [ (201:200+vlen-60000) - i*(101:100+vlen-60000) ] ))' - (30000+i*30000) ];
|
||||
|
||||
%v=([11:10+vlen] - i*[101:100+vlen])'; % attention, doesn't wrap!
|
||||
%v=15000*exp(-i*2*pi*1/7.68*[0:vlen-1])';
|
||||
v2=30000*(1+i)*ones(vlen,2);
|
||||
|
||||
oarf_send_frame(card,[v v2],16);
|
||||
|
||||
sleep(2); % need this, otherwise, get_frame will return garbage sometimes
|
||||
|
||||
%len=1000;off=0; chan=2; hold off ; plot(real(s(off+1:off+len,chan)),'-o',"markersize",2) ; hold on ; plot(imag(s(off+1:off+len,chan)),'r-o',"markersize",2)
|
||||
chan=1; s = oarf_get_frame(card); hold off ; grid on; plot(real(s(:,chan)),'b-o',"markersize",2) ; hold on ; plot(imag(s(:,chan)),'r-o',"markersize",2)
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
% Try out multicard setup
|
||||
limeparms;
|
||||
|
||||
eNBflag = 0;
|
||||
|
||||
tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_LSB;
|
||||
rf_mode = ( RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM )*[1 0 0 0];
|
||||
rf_mode = rf_mode + (DMAMODE_RX + DMAMODE_TX)*[1 0 0 0];
|
||||
freq_rx = (1908600000 - 0*9000)*[1 1 1 1];
|
||||
freq_tx = freq_rx + 0000000; % 1kHz offset: @30 MSPS: 2.5 sines, @15 MSPS: 5 sines, @7 MSPS: 10 sines
|
||||
rf_local= [ rfl(20,25,26,04) 0 0 0 ]; % 1.9 GHz & 860 MHz, VGA2Gain=0
|
||||
rf_vcocal=(( 0xE)*(2^6)) + ( 0xE)*[1 1 1 1]; % 1.907 GHz, (OLD)
|
||||
tx_gain = 13*[1 1 1 1];
|
||||
rx_gain = 20*[1 1 1 1];
|
||||
rf_rxdc = rf_rxdc*[1 1 1 1];
|
||||
|
||||
|
||||
% set first card to slave mode
|
||||
card=1; % -1 for all cards
|
||||
syncmode = SYNCMODE_SLAVE;
|
||||
|
||||
oarf_config_exmimo(card,freq_rx,freq_tx,tdd_config,syncmode,rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal)
|
||||
sleep(1)
|
||||
|
||||
% set second card to master mode
|
||||
card=0; % -1 for all cards
|
||||
syncmode = SYNCMODE_MASTER;
|
||||
|
||||
oarf_config_exmimo(card,freq_rx,freq_tx,tdd_config,syncmode,rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal)
|
||||
sleep(1)
|
||||
|
||||
% create_testvector
|
||||
vlen=76800
|
||||
%v=5000*exp(-i*(300*[0:vlen-1]/vlen)*2*pi); v=[v;v;v;v]'; oarf_send_frame(0,v,16);
|
||||
%v=5000*exp(-i*( 30*[0:vlen-1]/vlen)*2*pi); v=[v;v;v;v]'; oarf_send_frame(1,v,16);
|
||||
|
||||
%len=1000;off=0; chan=2; s=oarf_get_frame(card); hold off ; plot(real(s(off+1:off+len,chan)),'-o',"markersize",2) ; hold on ; plot(imag(s(off+1:off+len,chan)),'r-o',"markersize",2)
|
||||
%while 1;len=5000;off=0; chan=1; s = oarf_get_frame(card); hold off ; plot(real(s(off+1:off+len,chan)),'-o',"markersize",2) ; hold on ; plot(imag(s(off+1:off+len,chan)),'r-o',"markersize",3); sleep(0.3);endwhile
|
||||
%while 1;len=vlen;off=0; chan=[1 5]; s = oarf_get_frame(-1); hold off ; plot(real(s(off+1:off+len,chan)),'-o',"markersize",2) ; hold on ; plot(imag(s(off+1:off+len,chan)),'r-o',"markersize",3); sleep(0.5);endwhile
|
||||
|
||||
v = 5000* [ zeros(1,1000) ones(1,500) zeros(1,500) ones(1,1) zeros(1,vlen-1000-1000-1)]; v=[v;v;v;v]'; oarf_send_frame(1,v,16);
|
||||
sleep(1)
|
||||
|
||||
len=2500;off=0; chan=[1 5]; s = oarf_get_frame(-1); hold off ; plot(real(s(off+1:off+len,chan)),'-o',"markersize",2) ; hold on ; plot(imag(s(off+1:off+len,chan)),'r-o',"markersize",2);
|
||||
@@ -1,44 +0,0 @@
|
||||
dual_tx=0;
|
||||
eNBflag = 0;
|
||||
card=0;
|
||||
limeparms;
|
||||
|
||||
% internal loopback test
|
||||
rf_mode = (RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF5+RXLPFNORM+RXLPFEN+RXLPF5+LNA1ON+LNAByp+RFBBLNA1)*[1 1 0 0];
|
||||
%rf_mode = [0 0 0 0];
|
||||
|
||||
%% Select DMA directions
|
||||
%rf_mode = rf_mode + (DMAMODE_RX)*[1 0 0 0 ];
|
||||
%rf_mode = rf_mode + (DMAMODE_RX)*[1 1 0 0];
|
||||
%rf_mode = rf_mode + (DMAMODE_TX)*[1 1 0 0];
|
||||
%rf_mode = rf_mode + (DMAMODE_RX + DMAMODE_TX)*[1 0 0 0];
|
||||
rf_mode = rf_mode + (DMAMODE_RX + DMAMODE_TX)*[1 0 0 0];
|
||||
|
||||
freq_rx = 1907600000*[1 1 1 1];
|
||||
rf_local= [8254744 8255063 8257340 8257340]; % 1.9 GHz
|
||||
rf_vcocal=((0xE)*(2^6)) + (0xE)*[1 1 1 1]; % 1.9 GHz
|
||||
|
||||
freq_tx = freq_rx + 1;
|
||||
tx_gain = 25*[1 1 1 1];
|
||||
rx_gain = 20*[1 1 1 1];
|
||||
|
||||
rf_rxdc = rf_rxdc*[1 1 1 1];
|
||||
|
||||
|
||||
oarf_config_exmimo(card, freq_rx,freq_tx,0,dual_tx,rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal)
|
||||
|
||||
% create_testvector
|
||||
vlen=76800
|
||||
%v=([2:1+vlen; 10002:10001+vlen] - i*[3:2+vlen; 10003:10002+vlen])'; % achtung, wrapped nicht!
|
||||
v = floor(( [640:639+vlen ; 640:639+vlen] / 5 ))';
|
||||
|
||||
break
|
||||
|
||||
sleep(5)
|
||||
|
||||
oarf_send_frame(card,v,16);
|
||||
|
||||
|
||||
%len=1000;off=0; chan=2; hold off ; plot(real(s(off+1:off+len,chan)),'-o',"markersize",2) ; hold on ; plot(imag(s(off+1:off+len,chan)),'r-o',"markersize",2)
|
||||
chan=1; s = oarf_get_frame(card); hold off ; plot(real(s(:,chan)),'b',"markersize",1) ; % hold on ; plot(imag(s(:,chan)),'r',"markersize",1)
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
close all
|
||||
clear all
|
||||
hold off
|
||||
card = 0;
|
||||
% Maxime Guillaud - created Wed May 10 18:08:04 CEST 2006
|
||||
|
||||
gpib_card=0; % first GPIB PCI card in the computer
|
||||
gpib_device=28; % this is configured in the signal generator Utilities->System->GPIB->Address menu
|
||||
|
||||
cables_loss_dB = 6; % we need to account for the power loss between the signal generator and the card input (splitter, cables)
|
||||
dual_tx = 0;
|
||||
tdd = 1;
|
||||
|
||||
fc = 1907600e3;
|
||||
%fc = 2.68e9;
|
||||
fs = 7680e3;
|
||||
%fs = 6500e3;
|
||||
fref = fc+fs/4;
|
||||
power_dBm=-70;
|
||||
f_off_min = 1e6;
|
||||
|
||||
limeparms;
|
||||
%rf_mode = (RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM)*[1 1 1 1];
|
||||
rf_mode = (RXEN+0+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM+DMAMODE_RX+0)*[1 0 0 0];
|
||||
freq_rx = fc*[1 0 0 0];
|
||||
freq_tx = freq_rx+1920000;
|
||||
rx_gain = 30*[1 1 1 1];
|
||||
tx_gain = 25*[1 1 1 1];
|
||||
%rf_local=rf_local*[1 1 1 1];
|
||||
rf_local = [8254813 8255016 8254813 8254813]; %exmimo2_2
|
||||
%rf_rxdc =rf_rxdc*[1 1 1 1];
|
||||
rf_rxdc = [37059 35459 36300 36999]; %exmimo2_2
|
||||
rf_vcocal=rf_vcocal_19G*[1 1 1 1];
|
||||
tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_LSB;
|
||||
syncmode = SYNCMODE_FREE;
|
||||
rffe_rxg_low = 63*[1 1 1 1];
|
||||
rffe_rxg_final = 31*[1 1 1 1];
|
||||
rffe_band = B19G_TDD*[1 1 1 1];
|
||||
autocal = [1 1 1 1];
|
||||
resampling = [2 2 2 2];
|
||||
|
||||
%gpib_send(gpib_card,gpib_device,'*RST;*CLS'); % reset and configure the signal generator
|
||||
%gpib_send(gpib_card,gpib_device,['POW ' int2str(power_dBm+cables_loss_dB) 'dBm']);
|
||||
%gpib_send(gpib_card,gpib_device,['FREQ 1.91860 Ghz']); % set the frequency
|
||||
%gpib_send(gpib_card,gpib_device,['FREQ ' int2str(fref/1e3) 'khz']); % set the frequency
|
||||
%gpib_send(gpib_card,gpib_device,'OUTP:STAT ON'); % activate output
|
||||
|
||||
%keyboard;
|
||||
|
||||
|
||||
|
||||
sleep(2)
|
||||
|
||||
step = 4096;
|
||||
i=0;
|
||||
do
|
||||
format long
|
||||
fc
|
||||
freq_rx = fc*[1 0 0 0];
|
||||
freq_tx = freq_rx+1920000;
|
||||
oarf_config_exmimo(card, freq_rx,freq_tx,tdd_config,syncmode,rx_gain,tx_gain,0,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling);
|
||||
|
||||
i=i+1;
|
||||
sleep(1);
|
||||
s=oarf_get_frame(card); %oarf_get_frame
|
||||
s(76801:end,:)=[];
|
||||
|
||||
nb_rx = 1; %size(s,2);
|
||||
|
||||
% find the DC component
|
||||
m = mean(s);
|
||||
|
||||
s_phase = unwrap(angle(s(10000:4:length(s),1).'));
|
||||
s_phase = s_phase - s_phase(1,1);
|
||||
f_off = mean(s_phase(2:length(s_phase))*fs/4./(1:(length(s_phase)-1))/2/pi)
|
||||
plot(1:length(s_phase),s_phase,'r');
|
||||
|
||||
if (nb_rx>1)
|
||||
s_phase2 = unwrap(angle(s(10000:4:length(s),2).'));
|
||||
s_phase2 = s_phase2 - s_phase2(1,1);
|
||||
f_off2 = mean(s_phase2(2:length(s_phase2))*fs/4./(1:(length(s_phase2)-1))/2/pi)
|
||||
hold on
|
||||
plot(1:length(s_phase2),s_phase2,'g');
|
||||
drawnow;
|
||||
hold off
|
||||
end
|
||||
|
||||
|
||||
if (abs(f_off) < f_off_min)
|
||||
f_off_min = abs((f_off));
|
||||
end
|
||||
|
||||
if ((f_off) > 0)
|
||||
fc = fc + step;
|
||||
else
|
||||
fc = fc - step;
|
||||
endif
|
||||
|
||||
step = step/2;
|
||||
until (step < 50)
|
||||
|
||||
|
||||
%gpib_send(gpib_card,gpib_device,'OUTP:STAT OFF'); % deactivate output
|
||||
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
// Maxime Guillaud - created Wed May 10 19:23:30 CEST 2006
|
||||
// see http://www.gnu.org/software/octave/doc/interpreter/Dynamically-Linked-Functions.html#Dynamically-Linked-Functions
|
||||
// and http://octave.sourceforge.net/coda/c58.html
|
||||
// compile with: mkoctfile -I/usr/local/include/gpib -lgpib gpib_send.cc
|
||||
|
||||
#include <octave/oct.h>
|
||||
#include <gpib/ib.h>
|
||||
|
||||
|
||||
|
||||
|
||||
static bool any_bad_argument(const octave_value_list &args)
|
||||
{
|
||||
if (args.length()!=3)
|
||||
{
|
||||
error("gpib_send: syntax: gpib_send(gpib_board,gpib_device,gpib_str).");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (!args(0).is_real_scalar())
|
||||
{
|
||||
error("gpib_send: GPIB board number must be a positive integer.");
|
||||
return true;
|
||||
}
|
||||
if (args(0).scalar_value() < 0.0)
|
||||
{
|
||||
error("gpib_send: GPIB board number must be a positive integer.");
|
||||
return true;
|
||||
}
|
||||
if (floor(args(0).scalar_value()) != args(0).scalar_value())
|
||||
{
|
||||
error("gpib_send: GPIB board number must be a positive integer.");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (!args(1).is_real_scalar())
|
||||
{
|
||||
error("gpib_send: GPIB device number must be a positive integer.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args(1).scalar_value() < 0.0)
|
||||
{
|
||||
error("gpib_send: GPIB device number must be a positive integer.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (floor(args(1).scalar_value()) != args(1).scalar_value())
|
||||
{
|
||||
error("gpib_send: GPIB device number must be a positive integer.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!args(2).is_string())
|
||||
{
|
||||
error("gpib_send: third parameter must be a char string.");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
DEFUN_DLD (gpib_send, args, nargout,"sends commands to the GPIB bus")
|
||||
{
|
||||
if (any_bad_argument(args))
|
||||
return octave_value_list();
|
||||
|
||||
|
||||
const int gpib_board = args(0).int_value();
|
||||
const int gpib_device = args(1).int_value();
|
||||
const std::string gpib_string = args(2).string_value();
|
||||
|
||||
unsigned short addlist[2] = {gpib_device, NOADDR};
|
||||
|
||||
SendIFC(gpib_board);
|
||||
|
||||
// ENABLE all on GPIB bus
|
||||
EnableRemote(gpib_board, addlist);
|
||||
// If error, Bye!
|
||||
if (ibsta & ERR)
|
||||
{
|
||||
error("gpib_send: Instrument enable failed!");
|
||||
return octave_value_list();
|
||||
}
|
||||
|
||||
Send(gpib_board, gpib_device, gpib_string.c_str(), strlen(gpib_string.c_str()), NLend);
|
||||
if (ibsta & ERR)
|
||||
{
|
||||
error("gpib_send: Send failed!");
|
||||
return octave_value_list();
|
||||
}
|
||||
|
||||
return octave_value_list();
|
||||
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
clear all
|
||||
close all
|
||||
|
||||
addpath([getenv('OPENAIR1_DIR') '/PHY/LTE_REFSIG/']);
|
||||
addpath([getenv('OPENAIR1_DIR') '/PHY/LTE_TRANSPORT/']);
|
||||
primary_synch; %loads the primary sync signal
|
||||
sss_gen; %loads the secondary sync signal
|
||||
|
||||
% grab a frame
|
||||
ch=1;
|
||||
rx_spec;
|
||||
|
||||
% load frame
|
||||
%addpath([getenv('OPENAIR_TARGETS') '/SIMU/USER/']);
|
||||
%eNBtxsig1
|
||||
%s = txs1;
|
||||
|
||||
figure(1)
|
||||
plot(real(s))
|
||||
|
||||
pss_t = upsample(primary_synch0_time,4);
|
||||
[corr,lag] = xcorr(s(:,ch).',pss_t);
|
||||
figure(2);
|
||||
plot(lag,abs(corr));
|
||||
|
||||
[pss_amp, pss_pos0] = max(abs(corr));
|
||||
pss_pos = lag(pss_pos0);
|
||||
%pss_pos = 8817;
|
||||
|
||||
%sss_pos = pss_pos - 548; %FDD normal CP
|
||||
%sss_pos = pss_pos - 640; %FDD extended CP
|
||||
sss_pos = pss_pos - 1648; %TDD normal CP
|
||||
%sss_pos = pss_pos - 1920; %TDD extended CP
|
||||
|
||||
psst = s([pss_pos:(pss_pos+511)],ch);
|
||||
pssf = fft(psst);
|
||||
ssst = s([sss_pos:(sss_pos+511)],ch);
|
||||
sssf = fft(ssst);
|
||||
|
||||
pssf_ext = pssf([(512-30):512 2:32]); % extract innter 62 subcarriers
|
||||
sssf_ext = sssf([(512-30):512 2:32]); % extract innter 62 subcarriers
|
||||
|
||||
%estimate channel from pss
|
||||
pss_ch = pssf_ext.*(primary_synch0(6:67)');
|
||||
pss_ch = pss_ch./mean(abs(pss_ch));
|
||||
|
||||
%compensate sssf_ext with channel
|
||||
sssf_comp = sssf_ext.*conj(pss_ch);
|
||||
|
||||
% frequency domain correlation (dot-wise product) of sssf_comp and d0 and d5
|
||||
% account for phase offset
|
||||
|
||||
Nid2=0;
|
||||
for Nid1=0:167
|
||||
for phase=0; %-4:4
|
||||
corr0(Nid1+1,phase+1) = d0(Nid2+Nid1*3+1,:)*conj(sssf_comp*exp(1j*pi*phase/8));
|
||||
corr5(Nid1+1,phase+1) = d5(Nid2+Nid1*3+1,:)*conj(sssf_comp*exp(1j*pi*phase/8));
|
||||
end
|
||||
end
|
||||
|
||||
figure(3)
|
||||
plot(abs(corr0))
|
||||
figure(4)
|
||||
plot(abs(corr5))
|
||||
|
||||
[m0,i0] = max(abs(corr0(:)));
|
||||
[m5,i5] = max(abs(corr5(:)));
|
||||
|
||||
if (m0>m5)
|
||||
frame_start = pss_pos - 8816
|
||||
phase = floor((i0-1)/168) %phase
|
||||
Nid1 = mod(i0-1,168) %Nid
|
||||
else
|
||||
frame_start = pss_pos - 47216
|
||||
phase = floor((i5-1)/168) %phase
|
||||
Nid1 = mod(i5-1,168) %Nid
|
||||
end
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
clear;
|
||||
card=0;
|
||||
|
||||
limeparms;
|
||||
TX_LO_LEAKAGE_MIN0 = 99999;
|
||||
TX_LO_LEAKAGE_MIN1 = 99999;
|
||||
freq_rx = 1907600000*[1 1 1 1];
|
||||
%freq_rx = 859500000*[1 1 1 1];
|
||||
freq_tx = freq_rx+1920000;
|
||||
rf_vcocal = rf_vcocal_19G*[1 1 1 1];
|
||||
rf_rxdc = rf_rxdc*[1 1 1 1];
|
||||
rxgain = 30*[1 1 1 1];
|
||||
txgain = 25*[1 1 1 1];
|
||||
tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_LSB;
|
||||
syncmode = SYNCMODE_FREE;
|
||||
rffe_rxg_low = 31*[1 1 1 1];
|
||||
rffe_rxg_final = 31*[1 1 1 1];
|
||||
rffe_band = TVWS_TDD*[1 1 1 1];
|
||||
|
||||
sleepafterconfig=0.2
|
||||
|
||||
% coarse calibration loop for both rx chains
|
||||
for txdc_I=0:4:63
|
||||
for txdc_Q=0:4:63
|
||||
rf_mode = (RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAByp+RFBBLNA1)*[1 1 0 0];
|
||||
rf_mode = rf_mode + (DMAMODE_RX+DMAMODE_TX)*[1 1 0 0];
|
||||
rf_local = (txdc_I + (txdc_Q)*(2^6) + 31*(2^12) + 31*(2^18))*[1 1 1 1];
|
||||
|
||||
oarf_config_exmimo(card, freq_rx,freq_tx,tdd_config,syncmode,rxgain,txgain,0,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band);
|
||||
sleep(sleepafterconfig)
|
||||
|
||||
s=oarf_get_frame(card);
|
||||
sF0 = 20*log10(abs(fftshift(fft(s(:,1)))));
|
||||
sF1 = 20*log10(abs(fftshift(fft(s(:,2)))));
|
||||
|
||||
f = (7.68*(0:length(s(:,1))-1)/(length(s(:,1))))-3.84;
|
||||
spec0 = sF0;
|
||||
spec1 = sF1;
|
||||
|
||||
RX_LO_LEAKAGE0 = sF0(1+(length(sF0)/2));
|
||||
TX_LO_LEAKAGE0 = sF0(1+(.75*length(sF0)));
|
||||
TX_SIG0 = sF0(1+((11/16)*length(sF0)));
|
||||
TX_IQ0 = sF0(1+((13/16)*length(sF0))) - TX_SIG0;
|
||||
RX_IQ0 = sF0(1+((5/16)*length(sF0))) - TX_SIG0;
|
||||
RX_LO_LEAKAGE1 = sF1(1+(length(sF0)/2));
|
||||
TX_LO_LEAKAGE1 = sF1(1+(.75*length(sF0)));
|
||||
TX_SIG1 = sF1(1+((11/16)*length(sF0)));
|
||||
TX_IQ1 = sF1(1+((13/16)*length(sF0))) - TX_SIG1;
|
||||
RX_IQ1 = sF1(1+((5/16)*length(sF0))) - TX_SIG1;
|
||||
% subplot(211)
|
||||
% plot(f',spec0,'r')
|
||||
% axis([-3.84,3.84,40,160])
|
||||
% subplot(212)
|
||||
% plot(f',spec1,'b')
|
||||
% axis([-3.84,3.84,40,160])
|
||||
% grid
|
||||
% drawnow
|
||||
if (TX_LO_LEAKAGE0 < TX_LO_LEAKAGE_MIN0)
|
||||
TX_LO_LEAKAGE_MIN0=TX_LO_LEAKAGE0;
|
||||
txdc_I_min0 = txdc_I;
|
||||
txdc_Q_min0 = txdc_Q;
|
||||
TX_LO_LEAKAGE0
|
||||
txdc_I_min0
|
||||
txdc_Q_min0
|
||||
fflush(stdout);
|
||||
end
|
||||
if (TX_LO_LEAKAGE1 < TX_LO_LEAKAGE_MIN1)
|
||||
TX_LO_LEAKAGE_MIN1=TX_LO_LEAKAGE1;
|
||||
txdc_I_min1 = txdc_I;
|
||||
txdc_Q_min1 = txdc_Q;
|
||||
TX_LO_LEAKAGE1
|
||||
txdc_I_min1
|
||||
txdc_Q_min1
|
||||
fflush(stdout);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
% fine calibration loop for RX1 (RX2 stays constant)
|
||||
txdc_I_min02 = txdc_I_min0;
|
||||
txdc_Q_min02 = txdc_Q_min0;
|
||||
for deltaI = -3:3,
|
||||
for deltaQ = -3:3,
|
||||
txdc_I = txdc_I_min0 + deltaI;
|
||||
txdc_Q = txdc_Q_min0 + deltaQ;
|
||||
|
||||
if (txdc_I>=0) && (txdc_Q>=0) && (txdc_I < 64) && (txdc_Q < 64)
|
||||
% printf("txdc_IQ => (%d,%d)\n",txdc_I,txdc_Q);
|
||||
% fflush(stdout);
|
||||
|
||||
|
||||
rf_local(1) = txdc_I + (txdc_Q)*(2^6) + 31*(2^12) + 31*(2^18);
|
||||
rf_local(2) = txdc_I_min1 + (txdc_Q_min1)*(2^6) + 31*(2^12) + 31*(2^18);
|
||||
|
||||
oarf_config_exmimo(card, freq_rx,freq_tx,tdd_config,syncmode,rxgain,txgain,0,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band);
|
||||
sleep(sleepafterconfig)
|
||||
|
||||
s=oarf_get_frame(card);
|
||||
sF0 = 20*log10(abs(fftshift(fft(s(:,1)))));
|
||||
spec0 = sF0;
|
||||
spec1 = sF1;
|
||||
|
||||
RX_LO_LEAKAGE = sF0(1+(length(sF0)/2));
|
||||
TX_LO_LEAKAGE = sF0(1+(.75*length(sF0)));
|
||||
TX_SIG = sF0(1+((11/16)*length(sF0)));
|
||||
TX_IQ = sF0(1+((13/16)*length(sF0))) - TX_SIG;
|
||||
RX_IQ = sF0(1+((5/16)*length(sF0))) - TX_SIG;
|
||||
% subplot(211)
|
||||
% plot(f',spec0,'r')
|
||||
% axis([-3.84,3.84,40,160])
|
||||
% grid
|
||||
% drawnow
|
||||
if (TX_LO_LEAKAGE < TX_LO_LEAKAGE_MIN0)
|
||||
TX_LO_LEAKAGE_MIN0=TX_LO_LEAKAGE;
|
||||
txdc_I_min02 = txdc_I;
|
||||
txdc_Q_min02 = txdc_Q;
|
||||
TX_LO_LEAKAGE
|
||||
txdc_I_min02
|
||||
txdc_Q_min02
|
||||
fflush(stdout);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
% fine calibration loop for RX2 (RX1 stays constant)
|
||||
txdc_I_min12 = txdc_I_min1;
|
||||
txdc_Q_min12 = txdc_Q_min1;
|
||||
for deltaI = -3:3,
|
||||
for deltaQ = -3:3,
|
||||
txdc_I = txdc_I_min1 + deltaI;
|
||||
txdc_Q = txdc_Q_min1 + deltaQ;
|
||||
|
||||
if (txdc_I>=0) && (txdc_Q>=0) && (txdc_I < 64) && (txdc_Q < 64)
|
||||
% printf("txdc_IQ => (%d,%d)\n",txdc_I,txdc_Q);
|
||||
% fflush(stdout);
|
||||
|
||||
% rf_local = txdc_I_min02 + (txdc_Q_min02)*(2^6) + (txdc_I)*(2^12) + (txdc_Q)*(2^18);
|
||||
rf_local(1) = txdc_I_min02 + (txdc_Q_min02)*(2^6) + 31*(2^12) + 31*(2^18);
|
||||
rf_local(2) = txdc_I + (txdc_Q)*(2^6) + 31*(2^12) + 31*(2^18);
|
||||
|
||||
oarf_config_exmimo(card, freq_rx,freq_tx,tdd_config,syncmode,rxgain,txgain,0,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band);
|
||||
sleep(sleepafterconfig)
|
||||
|
||||
s=oarf_get_frame(card);
|
||||
sF1 = 20*log10(abs(fftshift(fft(s(:,2)))));
|
||||
spec1 = sF1;
|
||||
|
||||
RX_LO_LEAKAGE = sF1(1+(length(sF0)/2));
|
||||
TX_LO_LEAKAGE = sF1(1+(.75*length(sF0)));
|
||||
TX_SIG = sF1(1+((11/16)*length(sF0)));
|
||||
TX_IQ = sF1(1+((13/16)*length(sF0))) - TX_SIG;
|
||||
RX_IQ = sF1(1+((5/16)*length(sF0))) - TX_SIG;
|
||||
% subplot(212)
|
||||
% plot(f',spec1,'b')
|
||||
% axis([-3.84,3.84,40,160])
|
||||
% grid
|
||||
% drawnow
|
||||
|
||||
if (TX_LO_LEAKAGE < TX_LO_LEAKAGE_MIN1)
|
||||
TX_LO_LEAKAGE_MIN1=TX_LO_LEAKAGE;
|
||||
txdc_I_min12 = txdc_I;
|
||||
txdc_Q_min12 = txdc_Q;
|
||||
TX_LO_LEAKAGE
|
||||
txdc_I_min12
|
||||
txdc_Q_min12
|
||||
fflush(stdout);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
TX_LO_LEAKAGE_MIN0
|
||||
txdc_I_min02
|
||||
txdc_Q_min02
|
||||
TX_LO_LEAKAGE_MIN1
|
||||
txdc_I_min12
|
||||
txdc_Q_min12
|
||||
|
||||
rf_local(1) = txdc_I_min02 + (txdc_Q_min02)*(2^6) + 31*(2^12) + 31*(2^18);
|
||||
rf_local(2) = txdc_I_min12 + (txdc_Q_min12)*(2^6) + 31*(2^12) + 31*(2^18);
|
||||
|
||||
|
||||
oarf_config_exmimo(card, freq_rx,freq_tx,tdd_config,syncmode,rxgain,txgain,0,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band);
|
||||
sleep(sleepafterconfig)
|
||||
|
||||
s=oarf_get_frame(card);
|
||||
sF0 = 20*log10(abs(fftshift(fft(s(:,1)))));
|
||||
sF1 = 20*log10(abs(fftshift(fft(s(:,2)))));
|
||||
spec0 = sF0;
|
||||
spec1 = sF1;
|
||||
|
||||
RX_LO_LEAKAGE = sF0(1+(length(sF0)/2))
|
||||
TX_LO_LEAKAGE = sF0(1+(.75*length(sF0)))
|
||||
TX_SIG = sF0(1+((11/16)*length(sF0)))
|
||||
TX_IQ = sF0(1+((13/16)*length(sF0))) - TX_SIG
|
||||
RX_IQ = sF0(1+((5/16)*length(sF0))) - TX_SIG
|
||||
|
||||
RX_LO_LEAKAGE = sF1(1+(length(sF0)/2))
|
||||
TX_LO_LEAKAGE = sF1(1+(.75*length(sF0)))
|
||||
TX_SIG = sF1(1+((11/16)*length(sF0)))
|
||||
TX_IQ = sF1(1+((13/16)*length(sF0))) - TX_SIG
|
||||
RX_IQ = sF1(1+((5/16)*length(sF0))) - TX_SIG
|
||||
|
||||
subplot(211)
|
||||
plot(f',spec0,'r')
|
||||
subplot(212)
|
||||
plot(f',spec1,'b')
|
||||
axis([-3.84,3.84,40,160])
|
||||
grid
|
||||
drawnow
|
||||
|
||||
%gpib_send(gpib_card,gpib_device,'OUTP:STAT OFF'); % activate output
|
||||
%legend('Antenna Port 0','Antenna Port 1');
|
||||
grid
|
||||
|
||||
rf_local
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
clear all
|
||||
close all
|
||||
card=0;
|
||||
|
||||
limeparms;
|
||||
freq_rx = 1907600000*[1 1 1 1];
|
||||
%freq_rx = 700600000*[1 1 1 1];
|
||||
%freq_rx = 748000000*[1 1 1 1];
|
||||
freq_tx = freq_rx+1920000;
|
||||
rxgain = 30*[1 1 1 1];
|
||||
txgain = 0*[1 1 1 1];
|
||||
tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_TESTRX;
|
||||
syncmode = SYNCMODE_FREE;
|
||||
autocal = [1 1 1 1];
|
||||
resampling = [2 2 2 2];
|
||||
|
||||
rf_mode = (RXEN+0+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM+DMAMODE_RX+0) * [1 1 1 1];
|
||||
rf_local = [8254813 8255016 8254813 8254813]; % from the tx calibration
|
||||
%rf_local = [8255842 8255064 8257340 8257340]; % 700MHz
|
||||
%rf_local = [8256776 8255788 8257340 8257340]; % 850MHz
|
||||
rf_rxdc = rf_rxdc*[1 1 1 1]; % initial value
|
||||
rf_vcocal= rf_vcocal_19G*[1 1 1 1];
|
||||
rffe_rxg_low = 31*[1 1 1 1];
|
||||
rffe_rxg_final = 31*[1 1 1 1];
|
||||
rffe_band = B19G_TDD*[1 1 1 1];
|
||||
|
||||
oarf_config_exmimo(card, freq_rx,freq_tx,tdd_config,syncmode,rxgain,txgain,0,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling);
|
||||
|
||||
autocal = [2 2 2 2];
|
||||
sleepafterconfig=0.2
|
||||
|
||||
% coarse calibration loop for both rx chains
|
||||
for ant=1:4
|
||||
%rf_mode = zeros(1,4);
|
||||
%rf_mode(ant) = (RXEN+0+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM+DMAMODE_RX+0);
|
||||
dc_off_re_min = 99999;
|
||||
dc_off_im_min = 99999;
|
||||
|
||||
stepsize = 64;
|
||||
rxdc_Q_s = 0;
|
||||
rxdc_I = 0;
|
||||
while (stepsize>=1)
|
||||
stepsize = stepsize/2;
|
||||
|
||||
if (rxdc_I<0)
|
||||
rxdc_I_s = 64+abs(rxdc_I);
|
||||
else
|
||||
rxdc_I_s = rxdc_I;
|
||||
end
|
||||
rf_rxdc(ant) = ((128+rxdc_I_s) + (128+rxdc_Q_s)*(2^8));
|
||||
|
||||
oarf_config_exmimo(card, freq_rx,freq_tx,tdd_config,syncmode,rxgain,txgain,0,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling);
|
||||
sleep(sleepafterconfig)
|
||||
|
||||
s=oarf_get_frame(card);
|
||||
figure(1)
|
||||
plot(real(s));
|
||||
ylim([-2048 2048]);
|
||||
drawnow;
|
||||
%sF0 = 20*log10(abs(fftshift(fft(s(:,1)))));
|
||||
%sF1 = 20*log10(abs(fftshift(fft(s(:,2)))));
|
||||
%f = (7.68*(0:length(s(:,1))-1)/(length(s(:,1))))-3.84;
|
||||
%spec0 = sF0;
|
||||
%spec1 = sF1;
|
||||
|
||||
rxdc_I
|
||||
rxdc_I_s
|
||||
dc_offset = mean(s(:,ant));
|
||||
fflush(stdout);
|
||||
|
||||
if (abs(real(dc_offset))<dc_off_re_min)
|
||||
dc_off_re_min = abs(real(dc_offset));
|
||||
rxdc_I_min(ant) = rxdc_I_s;
|
||||
end
|
||||
|
||||
if (real(dc_offset)>0)
|
||||
rxdc_I = rxdc_I+stepsize;
|
||||
else
|
||||
rxdc_I = rxdc_I-stepsize;
|
||||
end
|
||||
end
|
||||
|
||||
stepsize = 64;
|
||||
rxdc_Q = 0;
|
||||
while (stepsize>=1)
|
||||
stepsize = stepsize/2;
|
||||
|
||||
if (rxdc_Q<0)
|
||||
rxdc_Q_s = 64+abs(rxdc_Q);
|
||||
else
|
||||
rxdc_Q_s = rxdc_Q;
|
||||
end
|
||||
rf_rxdc(ant) = ((128+rxdc_I_s) + (128+rxdc_Q_s)*(2^8));
|
||||
|
||||
oarf_config_exmimo(card, freq_rx,freq_tx,tdd_config,syncmode,rxgain,txgain,0,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling);
|
||||
sleep(sleepafterconfig)
|
||||
|
||||
s=oarf_get_frame(card);
|
||||
figure(2)
|
||||
plot(imag(s));
|
||||
ylim([-2048 2048]);
|
||||
drawnow;
|
||||
%sF0 = 20*log10(abs(fftshift(fft(s(:,1)))));
|
||||
%sF1 = 20*log10(abs(fftshift(fft(s(:,2)))));
|
||||
%f = (7.68*(0:length(s(:,1))-1)/(length(s(:,1))))-3.84;
|
||||
%spec0 = sF0;
|
||||
%spec1 = sF1;
|
||||
|
||||
|
||||
rxdc_Q
|
||||
rxdc_Q_s
|
||||
dc_offset = mean(s(:,ant));
|
||||
fflush(stdout);
|
||||
|
||||
if (abs(imag(dc_offset))<dc_off_im_min)
|
||||
dc_off_im_min = abs(imag(dc_offset));
|
||||
rxdc_Q_min(ant) = rxdc_Q_s;
|
||||
end
|
||||
|
||||
if (imag(dc_offset)>0)
|
||||
rxdc_Q = rxdc_Q+stepsize;
|
||||
else
|
||||
rxdc_Q = rxdc_Q-stepsize;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
rxdc_I_min
|
||||
rxdc_Q_min
|
||||
|
||||
rf_rxdc_min = ((128+rxdc_I_min) + (128+rxdc_Q_min)*(2^8))
|
||||
@@ -1,122 +0,0 @@
|
||||
% Octave defines, according to pcie_interface.h
|
||||
|
||||
% Parameters for rf_mode in structure exmimo_rf_t
|
||||
|
||||
RXEN=1;
|
||||
TXEN=2;
|
||||
|
||||
TXLPFENMASK=4;
|
||||
TXLPFEN=4;
|
||||
|
||||
|
||||
TXLPFMASK =15*(2^3);
|
||||
TXLPF14 =0;
|
||||
TXLPF10 =1*(2^3);
|
||||
TXLPF7 =2*(2^3);
|
||||
TXLPF6 =3*(2^3);
|
||||
TXLPF5 =4*(2^3);
|
||||
TXLPF4375 =5*(2^3);
|
||||
TXLPF35 =6*(2^3);
|
||||
TXLPF3 =7*(2^3);
|
||||
TXLPF275 =8*(2^3);
|
||||
TXLPF25 =9*(2^3);
|
||||
TXLPF192 =10*(2^3);
|
||||
TXLPF15 =11*(2^3);
|
||||
TXLPF1375 =12*(2^3);
|
||||
TXLPF125 =13*(2^3);
|
||||
TXLPF0875 =14*(2^3);
|
||||
TXLPF075 =15*(2^3);
|
||||
RXLPFENMASK=1*(2^7);
|
||||
RXLPFEN =128;
|
||||
RXLPFMASK =15*(2^8);
|
||||
RXLPF14 =0;
|
||||
RXLPF10 =1*(2^8);
|
||||
RXLPF7 =2*(2^8);
|
||||
RXLPF6 =3*(2^8);
|
||||
RXLPF5 =4*(2^8);
|
||||
RXLPF4375 =5*(2^8);
|
||||
RXLPF35 =6*(2^8);
|
||||
RXLPF3 =7*(2^8);
|
||||
RXLPF275 =8*(2^8);
|
||||
RXLPF25 =9*(2^8);
|
||||
RXLPF192 =10*(2^8);
|
||||
RXLPF15 =11*(2^8);
|
||||
RXLPF1375 =12*(2^8);
|
||||
RXLPF125 =13*(2^8);
|
||||
RXLPF0875 =14*(2^8);
|
||||
RXLPF075 =15*(2^8);
|
||||
LNAMASK=3*(2^12);
|
||||
LNADIS =0;
|
||||
LNA1ON =1*(2^12);
|
||||
LNA2ON =2*(2^12) ;
|
||||
LNA3ON =3*(2^12);
|
||||
LNAGAINMASK=3*(2^14);
|
||||
LNAByp =1*(2^14);
|
||||
LNAMed =2*(2^14);
|
||||
LNAMax =3*(2^14);
|
||||
|
||||
RFBBMASK =7*(2^16);
|
||||
RFBBNORM =0;
|
||||
RFBBRXLPF =1*(2^16);
|
||||
RFBBRXVGA =2*(2^16);
|
||||
RFBBOUTPUT=3*(2^16);
|
||||
RFBBLNA1 =4*(2^16);
|
||||
RFBBLNA2 =5*(2^16);
|
||||
RFBBLNA3 =6*(2^16);
|
||||
|
||||
RXLPFMODEMASK=3*(2^19);
|
||||
RXLPFNORM =0;
|
||||
RXLPFBYP =1*(2^19);
|
||||
RXLPFBPY2 =3*(2^19);
|
||||
|
||||
TXLPFMODEMASK=1*(2^21);
|
||||
TXLPFNORM =0;
|
||||
TXLPFBYP =1*(2^21);
|
||||
|
||||
RXOUTSW =1*(2^22);
|
||||
|
||||
DMAMODE_TRXMASK =3*(2^23);
|
||||
DMAMODE_RX =1*(2^23);
|
||||
DMAMODE_TX =2*(2^23);
|
||||
|
||||
rf_local = 31 + 31*(2^6) + 31*(2^12) + 31*(2^18);
|
||||
rf_rxdc = 0 + 0*(2^8); % DC offset ( DCOFF_I_RXFE [6:0], DCOFF_Q_RXFE[14:8] )
|
||||
rf_vcocal_19G = ((0xE)*(2^6)) + (0xE); % VCO calibration values for 1.9 GHz
|
||||
rf_vcocal_700 = ((0x24)*(2^6)) + (0x24); % 700 MHz
|
||||
rf_vcocal_850 = ((0x1d)*(2^6)) + (0x1d); %850 MHz
|
||||
rf_vcocal_859 = ((31)*(2^6)) + (31); %859.5 MHz
|
||||
%rf_vcocal_26G_eNB = ((0x1f)*(2^6)) + (0x13);
|
||||
%rf_vcocal_26G_UE = ((0x13)*(2^6)) + (0x1f);
|
||||
rf_vcocal_26G_UE = ((0x3)*(2^6)) + (0x26);
|
||||
rf_vcocal_26G_eNB = ((0x26)*(2^6)) + (0x0);
|
||||
|
||||
% register values and masks for tdd_config
|
||||
DUPLEXMODE_MASK = 1*(2^0);
|
||||
DUPLEXMODE_FDD = 0;
|
||||
DUPLEXMODE_TDD = 2*(2^0);
|
||||
TXRXSWITCH_MASK = 3*(2^1);
|
||||
TXRXSWITCH_LSB = 0;
|
||||
TXRXSWITCH_FPGA = 1*(2^1);
|
||||
TXRXSWITCH_TESTRX = 2*(2^1);
|
||||
TXRXSWITCH_TESTTX = 3*(2^1);
|
||||
SWITCHSTATE_MASK = 1*(2^3);
|
||||
SWITCHSTATE_0 = 0;
|
||||
SWITCHSTATE_1 = 1*(2^3);
|
||||
TEST_ADACLOOP_MASK= 1*(2^4);
|
||||
TEST_ADACLOOP_EN = 1*(2^4);
|
||||
|
||||
% multicard synchronization mode (multicard_syncmode)
|
||||
SYNCMODE_FREE = 0;
|
||||
SYNCMODE_MASTER = 1;
|
||||
SYNCMODE_SLAVE = 2;
|
||||
|
||||
% external RF frontend
|
||||
TVWS_TDD = 0;
|
||||
DD_FDD = 1;
|
||||
DD_TDD = 2;
|
||||
B19G_TDD = 3;
|
||||
B24G_TDD = 4;
|
||||
B26G_TDD = 5;
|
||||
B26G_FDD = 6;
|
||||
B35G_TDD = 7;
|
||||
B50G_TDD = 8;
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
volatile int oai_exit=0;
|
||||
@@ -1,446 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
// Matthias Ihmig, based on code from Maxime Guillaud - created 28.01.2013
|
||||
// see http://www.gnu.org/software/octave/doc/interpreter/Dynamically-Linked-Functions.html#Dynamically-Linked-Functions
|
||||
// and http://wiki.octave.org/wiki.pl?CodaTutorial
|
||||
// and http://octave.sourceforge.net/coda/c58.html
|
||||
// compilation: see Makefile
|
||||
|
||||
#include <octave/oct.h>
|
||||
|
||||
#include "pcie_interface.h"
|
||||
#include "oarf.h"
|
||||
|
||||
extern "C" {
|
||||
#include "openair0_lib.h"
|
||||
}
|
||||
|
||||
#define FCNNAME "oarf_config_exmimo"
|
||||
|
||||
#define TRACE 1
|
||||
|
||||
static bool any_bad_argument(const octave_value_list &args)
|
||||
{
|
||||
octave_value v,w;
|
||||
int i;
|
||||
|
||||
if (args.length()!=17)
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("Wrong number of parameters! Did you add the card number as first parameter?");
|
||||
error("syntax: oarf_config_exmimo(card,freqrx,freq_tx,tdd_config,syncmode,rxgain,txgain,eNB_flag,rf_mode,rx_dc,rf_local,rf_vcolocal,rffe_rxg_low,rffe_rxg_final,autocal,resampling_factor)");
|
||||
return true;
|
||||
}
|
||||
|
||||
v=args(1);
|
||||
for (i=0;i<v.columns();i++) {
|
||||
if ((real(v.row_vector_value()(i)) < 0.0) ||
|
||||
(floor(real(v.row_vector_value()(i))) != real(v.row_vector_value()(i))) ||
|
||||
(real(v.row_vector_value()(i)) > 3.9e9))
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("rx freqband %d must be 0-3.9e9",i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
v=args(2);
|
||||
for (i=0;i<v.columns();i++) {
|
||||
if ((real(v.row_vector_value()(i)) < 0.0) ||
|
||||
(floor(real(v.row_vector_value()(i))) != real(v.row_vector_value()(i))) ||
|
||||
(real(v.row_vector_value()(i)) > 3.9e9))
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("tx freqband %d must be 0-3.9e9",i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!args(3).is_real_scalar()))
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("tdd_config must be an integer.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((!args(4).is_real_scalar()))
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("multicard_syncmode must be an integer.");
|
||||
return true;
|
||||
}
|
||||
|
||||
v=args(5);
|
||||
if (v.columns() == 4)
|
||||
{
|
||||
for (i=0;i<v.columns();i++)
|
||||
{
|
||||
if ((real(args(5).row_vector_value()(i))<0.0) || (real(args(5).row_vector_value()(i))>63.0))
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("rx gain must be between 0 and 63. (got %f).",args(5).row_vector_value()(i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(FCNNAME);
|
||||
error("number of columns for rxgain must be 4 (got %d)\n",v.columns());
|
||||
}
|
||||
|
||||
v=args(6);
|
||||
if (v.columns() == 4)
|
||||
{
|
||||
for (i=0;i<v.columns();i++)
|
||||
{
|
||||
if ((real(args(6).row_vector_value()(i))<0.0) || (real(args(6).row_vector_value()(i))>63.0))
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("tx gain must be between 0 and 63. (got %f).",args(6).row_vector_value()(i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(FCNNAME);
|
||||
error("number of columns for txgain must be 4 (got %d)\n",v.columns());
|
||||
}
|
||||
|
||||
|
||||
if ((!args(7).is_real_scalar()) || (args(7).scalar_value()<0.0) || (args(7).scalar_value()>1)) {
|
||||
error(FCNNAME);
|
||||
error("eNB_flag must be between 0 and 1 (got %f).",args(7).scalar_value());
|
||||
return true;
|
||||
}
|
||||
|
||||
v = args(8);
|
||||
if (v.columns() == 4)
|
||||
{
|
||||
for (i=0;i<v.columns();i++)
|
||||
{
|
||||
if ((v.row_vector_value()(i)<0.0) || (v.row_vector_value()(i)>(double)((uint32_t)(1<<31)))) {
|
||||
error(FCNNAME);
|
||||
error("rf_mode %d must be between 0 and 2^31 (got %f).",i,v.row_vector_value()(i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(FCNNAME);
|
||||
error("number of columns for rf_mode must be 4\n");
|
||||
}
|
||||
|
||||
v = args(9);
|
||||
if (v.columns() == 4)
|
||||
{
|
||||
for (i=0;i<v.columns();i++)
|
||||
{
|
||||
if ((v.row_vector_value()(i)<0.0) || (v.row_vector_value()(i)>(double)((uint32_t)(1<<16)))) {
|
||||
error(FCNNAME);
|
||||
error("rx_dc %d must be between 0 and 2^16 (got %f).",i,v.row_vector_value()(i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(FCNNAME);
|
||||
error("number of columns for rf_mode must be 4\n");
|
||||
}
|
||||
|
||||
v = args(10);
|
||||
if (v.columns() == 4)
|
||||
{
|
||||
for (i=0;i<v.columns();i++)
|
||||
{
|
||||
if ((v.row_vector_value()(i)<0.0) || (v.row_vector_value()(i)>(double)((uint32_t)(1<<24)))) {
|
||||
error(FCNNAME);
|
||||
error("rf_local %d must be between 0 and 2^24 (got %f).",i,v.row_vector_value()(i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(FCNNAME);
|
||||
error("number of columns for rf_local must be 4\n");
|
||||
}
|
||||
|
||||
v = args(11);
|
||||
if (v.columns() == 4)
|
||||
{
|
||||
for (i=0;i<v.columns();i++)
|
||||
{
|
||||
if ((v.row_vector_value()(i)<0.0) || (v.row_vector_value()(i)>(double)((uint32_t)(1<<12)))) {
|
||||
error(FCNNAME);
|
||||
error("rf_vcocal %d must be between 0 and 2^12 (got %f).",i,v.row_vector_value()(i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(FCNNAME);
|
||||
error("number of columns for rf_vcocal must be 4\n");
|
||||
}
|
||||
|
||||
v = args(12);
|
||||
if (v.columns() == 4)
|
||||
{
|
||||
for (i=0;i<v.columns();i++)
|
||||
{
|
||||
if ((v.row_vector_value()(i)<0.0) || (v.row_vector_value()(i)>63.0)) {
|
||||
error(FCNNAME);
|
||||
error("rffe_rxg_low %d must be between 0 and 63 (got %f).",i,v.row_vector_value()(i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(FCNNAME);
|
||||
error("number of columns for rffe_rxg_low must be 4\n");
|
||||
}
|
||||
|
||||
v = args(13);
|
||||
if (v.columns() == 4)
|
||||
{
|
||||
for (i=0;i<v.columns();i++)
|
||||
{
|
||||
if ((v.row_vector_value()(i)<0.0) || (v.row_vector_value()(i)>63.0)) {
|
||||
error(FCNNAME);
|
||||
error("rffe_rxg_final %d must be between 0 and 63 (got %f).",i,v.row_vector_value()(i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(FCNNAME);
|
||||
error("number of columns for rffe_rxg_final must be 4\n");
|
||||
}
|
||||
|
||||
v = args(14);
|
||||
if (v.columns() == 4)
|
||||
{
|
||||
for (i=0;i<v.columns();i++)
|
||||
{
|
||||
if ((v.row_vector_value()(i)<0.0) || (v.row_vector_value()(i)>8.0)) {
|
||||
error(FCNNAME);
|
||||
error("rffe_band %d must be between 0 and 8 (got %f).",i,v.row_vector_value()(i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(FCNNAME);
|
||||
error("number of columns for rffe_band must be 4\n");
|
||||
}
|
||||
|
||||
v = args(15);
|
||||
if (v.columns() == 4)
|
||||
{
|
||||
for (i=0;i<v.columns();i++)
|
||||
{
|
||||
if ((v.row_vector_value()(i)<0.0) || (v.row_vector_value()(i)>2.0)) {
|
||||
error(FCNNAME);
|
||||
error("autocal %d must be 0 or 2 (got %f).",i,v.row_vector_value()(i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(FCNNAME);
|
||||
error("number of columns for autocal must be 4\n");
|
||||
}
|
||||
|
||||
v = args(16);
|
||||
if (v.columns() == 4)
|
||||
{
|
||||
for (i=0;i<v.columns();i++)
|
||||
{
|
||||
if ((v.row_vector_value()(i)<0.0) || (v.row_vector_value()(i)>2.0)) {
|
||||
error(FCNNAME);
|
||||
error("resampling_factor %d must be 0, 1 or 2 (got %f).",i,v.row_vector_value()(i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(FCNNAME);
|
||||
error("number of columns for resampling_factor must be 4\n");
|
||||
}
|
||||
|
||||
|
||||
if ( !args(0).is_real_scalar() )
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("card_id must be scalar (count starting from 0).\nUse card_id = -1 to send command to all cards.\nUse card_id = -2 to update config in memory, but do not send DUMP_CONFIG ioctl.");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DEFUN_DLD (oarf_config_exmimo, args, nargout,"configure the openair interface - returns 0 if successful")
|
||||
{
|
||||
int ret;
|
||||
int ant;
|
||||
int a,b;
|
||||
int no_dump_config = 0;
|
||||
if (any_bad_argument(args))
|
||||
return octave_value_list();
|
||||
|
||||
int card = args(0).int_value();
|
||||
RowVector freqrx = args(1).row_vector_value();
|
||||
RowVector freqtx = args(2).row_vector_value();
|
||||
const int tdd_config = args(3).int_value();
|
||||
const int multicard_syncmode = args(4).int_value();
|
||||
RowVector rxgain = args(5).row_vector_value();
|
||||
RowVector txgain = args(6).row_vector_value();
|
||||
const int eNB_flag = args(7).int_value();
|
||||
RowVector rf_mode = args(8).row_vector_value();
|
||||
RowVector rf_dc = args(9).row_vector_value();
|
||||
RowVector rf_local = args(10).row_vector_value();
|
||||
RowVector rf_vcocal = args(11).row_vector_value();
|
||||
RowVector rffe_rxg_low = args(12).row_vector_value();
|
||||
RowVector rffe_rxg_final = args(13).row_vector_value();
|
||||
RowVector rffe_band = args(14).row_vector_value();
|
||||
RowVector autocal = args(15).row_vector_value();
|
||||
RowVector resampling_factor = args(16).row_vector_value();
|
||||
int rffe_band_int;
|
||||
|
||||
exmimo_config_t *p_exmimo_config;
|
||||
exmimo_id_t *p_exmimo_id;
|
||||
|
||||
octave_value returnvalue;
|
||||
|
||||
ret = openair0_open();
|
||||
if ( ret != 0 )
|
||||
{
|
||||
error(FCNNAME);
|
||||
if (ret == -1)
|
||||
error("Error opening /dev/openair0");
|
||||
if (ret == -2)
|
||||
error("Error mapping bigshm");
|
||||
if (ret == -3)
|
||||
error("Error mapping RX or TX buffer");
|
||||
if (ret == -5)
|
||||
error("Error Firmware/Software do not match");
|
||||
return octave_value(ret);
|
||||
}
|
||||
|
||||
if (card == -2) {
|
||||
no_dump_config = 1;
|
||||
card = -1;
|
||||
}
|
||||
|
||||
if (card <-1 || card >= openair0_num_detected_cards) {
|
||||
warning("Invalid card number %d! Must be between 0 and %d. Or -1 for all card. Will assume -1.", openair0_num_detected_cards-1);
|
||||
card = -1;
|
||||
}
|
||||
|
||||
if (card == -1) {
|
||||
a = 0;
|
||||
b = openair0_num_detected_cards;
|
||||
} else {
|
||||
a = card;
|
||||
b = card+1;
|
||||
}
|
||||
|
||||
//printf("Number of cards: %d\n", openair0_num_detected_cards);
|
||||
|
||||
for (card = a; card < b; card++)
|
||||
{
|
||||
p_exmimo_config = openair0_exmimo_pci[card].exmimo_config_ptr;
|
||||
p_exmimo_id = openair0_exmimo_pci[card].exmimo_id_ptr;
|
||||
|
||||
p_exmimo_config->framing.eNB_flag = eNB_flag;
|
||||
p_exmimo_config->framing.tdd_config = tdd_config;
|
||||
p_exmimo_config->framing.multicard_syncmode = multicard_syncmode;
|
||||
// p_exmimo_config->framing.resampling_factor = 2;
|
||||
|
||||
for (ant=0; ant<4; ant++)
|
||||
{
|
||||
p_exmimo_config->rf.do_autocal[ant] = autocal(ant);
|
||||
p_exmimo_config->rf.rf_freq_rx[ant] = freqrx(ant);
|
||||
p_exmimo_config->rf.rf_freq_tx[ant] = freqtx(ant);
|
||||
p_exmimo_config->rf.rx_gain[ant][0] = (uint32_t) rxgain(ant);
|
||||
p_exmimo_config->rf.tx_gain[ant][0] = (uint32_t) txgain(ant);
|
||||
p_exmimo_config->rf.rf_mode[ant] = rf_mode(ant);
|
||||
|
||||
p_exmimo_config->rf.rf_local[ant] = rf_local(ant);
|
||||
p_exmimo_config->rf.rf_rxdc[ant] = rf_dc(ant);
|
||||
p_exmimo_config->rf.rf_vcocal[ant] = rf_vcocal(ant);
|
||||
|
||||
p_exmimo_config->rf.rffe_gain_txlow[ant] = 31;
|
||||
p_exmimo_config->rf.rffe_gain_txhigh[ant] = 31;
|
||||
p_exmimo_config->rf.rffe_gain_rxfinal[ant] = rffe_rxg_final(ant);
|
||||
p_exmimo_config->rf.rffe_gain_rxlow[ant] = rffe_rxg_low(ant);
|
||||
p_exmimo_config->framing.resampling_factor[ant] = resampling_factor(ant);
|
||||
rffe_band_int = (int) rffe_band(ant);
|
||||
switch (rffe_band_int) {
|
||||
case 0:
|
||||
p_exmimo_config->rf.rffe_band_mode[ant] = TVWS_TDD;
|
||||
break;
|
||||
case 1:
|
||||
p_exmimo_config->rf.rffe_band_mode[ant] = DD_FDD;
|
||||
break;
|
||||
case 2:
|
||||
p_exmimo_config->rf.rffe_band_mode[ant] = DD_TDD;
|
||||
break;
|
||||
case 3:
|
||||
p_exmimo_config->rf.rffe_band_mode[ant] = B19G_TDD;
|
||||
break;
|
||||
case 4:
|
||||
p_exmimo_config->rf.rffe_band_mode[ant] = B24G_TDD;
|
||||
break;
|
||||
case 5:
|
||||
p_exmimo_config->rf.rffe_band_mode[ant] = B26G_TDD;
|
||||
break;
|
||||
case 6:
|
||||
p_exmimo_config->rf.rffe_band_mode[ant] = B26G_FDD;
|
||||
break;
|
||||
case 7:
|
||||
p_exmimo_config->rf.rffe_band_mode[ant] = B35G_TDD;
|
||||
break;
|
||||
case 8:
|
||||
p_exmimo_config->rf.rffe_band_mode[ant] = B50G_TDD;
|
||||
break;
|
||||
default:
|
||||
p_exmimo_config->rf.rffe_band_mode[ant] = TVWS_TDD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (no_dump_config == 0)
|
||||
returnvalue = openair0_dump_config( card );
|
||||
|
||||
if (0)
|
||||
printf("Card %d: ExpressMIMO %d, HW Rev. 0x%d, SW Rev 0x%d, SVN Rev %d, Builddate %d, %d antennas\n", card, p_exmimo_id->board_exmimoversion,
|
||||
p_exmimo_id->board_hwrev, p_exmimo_id->board_swrev,
|
||||
p_exmimo_id->system_id.bitstream_id, p_exmimo_id->system_id.bitstream_build_date,
|
||||
openair0_num_antennas[card]);
|
||||
}
|
||||
|
||||
openair0_close();
|
||||
|
||||
return octave_value(returnvalue);
|
||||
}
|
||||
|
||||
@@ -1,213 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
// Maxime Guillaud - created Fri May 12 16:20:04 CEST 2006
|
||||
// Matthias Ihmig, 2013
|
||||
// see http://www.gnu.org/software/octave/doc/interpreter/Dynamically-Linked-Functions.html#Dynamically-Linked-Functions
|
||||
// and http://wiki.octave.org/wiki.pl?CodaTutorial
|
||||
// and http://octave.sourceforge.net/coda/c58.html
|
||||
// compilation: see Makefile
|
||||
// Update: Wed May 23 17:25:39 CEST 2007, fifo acquisition of signal buffer (RK)
|
||||
// 29.01.2013: adopted to new kernel driver
|
||||
|
||||
|
||||
#include <octave/oct.h>
|
||||
|
||||
extern "C" {
|
||||
#include "openair0_lib.h"
|
||||
}
|
||||
#include "oarf.h"
|
||||
|
||||
#define FCNNAME "oarf_get_frame"
|
||||
|
||||
#define TRACE 1
|
||||
|
||||
#define FRAME_LENGTH_COMPLEX_SAMPLES 76800
|
||||
|
||||
static bool any_bad_argument(const octave_value_list &args)
|
||||
{
|
||||
octave_value v;
|
||||
if (args.length()!=1)
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("syntax: oarf_get_frame(card)");
|
||||
return true;
|
||||
}
|
||||
|
||||
v=args(0);
|
||||
if ((!v.is_real_scalar()) || (v.scalar_value() < -2) || (floor(v.scalar_value()) != v.scalar_value()) || (v.scalar_value() >= MAX_CARDS))
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("card must be 0-19 for a specific card, or -1 to get frame from all cards.\nSet framing.sync_mode =SYNCMODE_MASTER for one card and =SYNCMODE_SLAVE to obtain synchronized frames.\n");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int find_mastercard()
|
||||
{
|
||||
int card=0, found_master=0, i;
|
||||
const char *str[] = { "FREE", "MASTER", "SLAVE" };
|
||||
|
||||
printf("Card configuration: card");
|
||||
for (i=0; i<openair0_num_detected_cards; i++)
|
||||
printf(" [%i]=%s,", i, str[ openair0_exmimo_pci[i].exmimo_config_ptr->framing.multicard_syncmode ]);
|
||||
printf("\n");
|
||||
|
||||
for (i=0; i<openair0_num_detected_cards; i++)
|
||||
{
|
||||
if ( openair0_exmimo_pci[i].exmimo_config_ptr->framing.multicard_syncmode == SYNCMODE_MASTER )
|
||||
{
|
||||
if (found_master >= 1)
|
||||
{
|
||||
printf("Warning: There is more than one master active! Will put card[%i] back into SYNCMODE_FREE!\n", i);
|
||||
openair0_exmimo_pci[i].exmimo_config_ptr->framing.multicard_syncmode == SYNCMODE_FREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
card = i;
|
||||
found_master++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found_master == 0)
|
||||
printf("Warning: No master activated! Will trigger getframe on card 0\n");
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
DEFUN_DLD (oarf_get_frame, args, nargout,"Get frame")
|
||||
{
|
||||
int numant, no_getframe_ioctl=0;
|
||||
|
||||
if (any_bad_argument(args))
|
||||
return octave_value_list();
|
||||
|
||||
int card = args(0).int_value();
|
||||
|
||||
octave_value returnvalue;
|
||||
int i,aa,j;
|
||||
short *rx_sig[MAX_CARDS * MAX_ANTENNAS];
|
||||
int ret;
|
||||
int frame_length_samples[MAX_CARDS];
|
||||
|
||||
ret = openair0_open();
|
||||
if ( ret != 0 )
|
||||
{
|
||||
error(FCNNAME);
|
||||
if (ret == -1)
|
||||
error("Error opening /dev/openair0");
|
||||
if (ret == -2)
|
||||
error("Error mapping bigshm");
|
||||
if (ret == -3)
|
||||
error("Error mapping RX or TX buffer");
|
||||
return octave_value(ret);
|
||||
}
|
||||
|
||||
if (card == -2)
|
||||
{
|
||||
no_getframe_ioctl = 1;
|
||||
card = -1;
|
||||
}
|
||||
|
||||
if (card <-1 || card >= openair0_num_detected_cards) {
|
||||
error("card number must be between 0 and %d. Or -1 for all cards.", openair0_num_detected_cards-1);
|
||||
return octave_value(-4);
|
||||
}
|
||||
|
||||
if (card == -1) {
|
||||
numant = openair0_num_detected_cards * openair0_num_antennas[0];
|
||||
card = find_mastercard();
|
||||
}
|
||||
else
|
||||
numant = openair0_num_antennas[card];
|
||||
|
||||
if ( no_getframe_ioctl )
|
||||
{
|
||||
// print mbox counters
|
||||
for (i=0; i<numant; i++)
|
||||
{
|
||||
|
||||
if ( numant == openair0_num_antennas[card] )
|
||||
printf("rx_cnt[%d] = %d, tx_cnt[%d] = %d, ", i, *openair0_exmimo_pci[card].rxcnt_ptr[i],
|
||||
i, *openair0_exmimo_pci[card].txcnt_ptr[i]);
|
||||
else
|
||||
printf("rx_cnt[%d] = %d, tx_cnt[%d] = %d, ", i, *openair0_exmimo_pci[i / (int)openair0_num_antennas[0]].rxcnt_ptr[i % openair0_num_antennas[0]],
|
||||
i, *openair0_exmimo_pci[i / (int)openair0_num_antennas[0]].txcnt_ptr[i % openair0_num_antennas[0]]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
for (i=0; i<openair0_num_detected_cards; i++)
|
||||
{
|
||||
if (openair0_exmimo_pci[i].exmimo_config_ptr->framing.resampling_factor[0] == 2)
|
||||
frame_length_samples[i] = FRAME_LENGTH_COMPLEX_SAMPLES;
|
||||
else if (openair0_exmimo_pci[i].exmimo_config_ptr->framing.resampling_factor[0] == 1)
|
||||
frame_length_samples[i] = FRAME_LENGTH_COMPLEX_SAMPLES*2;
|
||||
else if (openair0_exmimo_pci[i].exmimo_config_ptr->framing.resampling_factor[0] == 0)
|
||||
frame_length_samples[i] = FRAME_LENGTH_COMPLEX_SAMPLES*4;
|
||||
else
|
||||
frame_length_samples[i] = FRAME_LENGTH_COMPLEX_SAMPLES;
|
||||
}
|
||||
printf("Info : Only resampling_factor of channel 0 is taken into account for copying received frame for all the other chains\n");
|
||||
|
||||
|
||||
ComplexMatrix dx (FRAME_LENGTH_COMPLEX_SAMPLES*4, MAX_ANTENNAS*openair0_num_detected_cards);
|
||||
/*
|
||||
// set the tx buffer to 0x00010001 to put switch in rx mode
|
||||
for (aa=0; aa<numant; aa++)
|
||||
for (i=0; i<FRAME_LENGTH_COMPLEX_SAMPLES; i++)
|
||||
((int*)(openair0_exmimo_pci[card].dac_head[aa]))[i] = 0x00010001;
|
||||
*/
|
||||
if ((openair0_exmimo_pci[card].exmimo_config_ptr->framing.tdd_config & TXRXSWITCH_MASK) != TXRXSWITCH_TESTRX)
|
||||
printf("Warning: tdd_config is not set to TXRXSWITCH_TESTRX! You better know what you are doing! :)\n");
|
||||
|
||||
// assign userspace pointers
|
||||
|
||||
for (j=0; j<openair0_num_detected_cards;j++)
|
||||
{
|
||||
for (i=0; i<MAX_ANTENNAS; i++)
|
||||
{
|
||||
//if ( numant == openair0_num_antennas[j] )
|
||||
rx_sig[i+(j*MAX_ANTENNAS)] = (short*) openair0_exmimo_pci[ j ].adc_head[ i ];
|
||||
//else
|
||||
// rx_sig[i+(j*MAX_ANTENNAS)] = (short*) openair0_exmimo_pci[ i / (int)openair0_num_antennas[0] ].adc_head[i % openair0_num_antennas[0]];
|
||||
|
||||
// printf("Card %i adc_head[%i] = %p \n",j, i, rx_sig[i+(j*MAX_ANTENNAS)]);
|
||||
}
|
||||
}
|
||||
|
||||
// msg("Getting buffer...\n");
|
||||
if ( no_getframe_ioctl == 0)
|
||||
openair0_get_frame(card);
|
||||
|
||||
for (j=0; j<openair0_num_detected_cards;j++)
|
||||
for (i=0; i<frame_length_samples[j]; i++)
|
||||
for (aa=0; aa<MAX_ANTENNAS; aa++)
|
||||
dx(i, aa+j*MAX_ANTENNAS) = Complex( rx_sig[aa+j*MAX_ANTENNAS][i*2], rx_sig[aa+j*MAX_ANTENNAS][i*2+1] );
|
||||
|
||||
openair0_close();
|
||||
|
||||
return octave_value (dx);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
// Matthias Ihmig, 2013
|
||||
// see http://www.gnu.org/software/octave/doc/interpreter/Dynamically-Linked-Functions.html#Dynamically-Linked-Functions
|
||||
// and http://wiki.octave.org/wiki.pl?CodaTutorial
|
||||
// and http://octave.sourceforge.net/coda/c58.html
|
||||
// compilation: see Makefile
|
||||
|
||||
|
||||
#include <octave/oct.h>
|
||||
|
||||
extern "C" {
|
||||
#include "openair0_lib.h"
|
||||
}
|
||||
#include "oarf.h"
|
||||
|
||||
#define FCNNAME "oarf_get_num_detected_cards"
|
||||
|
||||
#define TRACE 1
|
||||
|
||||
|
||||
static bool any_bad_argument(const octave_value_list &args)
|
||||
{
|
||||
octave_value v;
|
||||
if (args.length()!=0)
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("syntax: oarf_get_num_detected_cards");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
DEFUN_DLD (oarf_get_num_detected_cards, args, nargout,"Returns number of detected cards.")
|
||||
{
|
||||
|
||||
if (any_bad_argument(args))
|
||||
return octave_value_list();
|
||||
|
||||
int ret;
|
||||
|
||||
octave_value returnvalue;
|
||||
|
||||
ret = openair0_open();
|
||||
if ( ret != 0 )
|
||||
{
|
||||
error(FCNNAME);
|
||||
if (ret == -1)
|
||||
error("Error opening /dev/openair0");
|
||||
if (ret == -2)
|
||||
error("Error mapping bigshm");
|
||||
if (ret == -3)
|
||||
error("Error mapping RX or TX buffer");
|
||||
return octave_value(ret);
|
||||
}
|
||||
|
||||
returnvalue = openair0_num_detected_cards;
|
||||
|
||||
openair0_close( );
|
||||
|
||||
return octave_value(returnvalue);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
// Matthias Ihmig, 2013
|
||||
// Maxime Guillaud - created Fri May 12 16:20:04 CEST 2006
|
||||
// see http://www.gnu.org/software/octave/doc/interpreter/Dynamically-Linked-Functions.html#Dynamically-Linked-Functions
|
||||
// and http://wiki.octave.org/wiki.pl?CodaTutorial
|
||||
// and http://octave.sourceforge.net/coda/c58.html
|
||||
// compilation: see Makefile
|
||||
// Update: Wed May 23 17:25:39 CEST 2007, fifo acquisition of signal buffer (RK)
|
||||
|
||||
|
||||
#include <octave/oct.h>
|
||||
|
||||
extern "C" {
|
||||
#include "openair0_lib.h"
|
||||
}
|
||||
#include "oarf.h"
|
||||
|
||||
#define FCNNAME "oarf_send_frame"
|
||||
|
||||
#define TRACE 1
|
||||
|
||||
static bool any_bad_argument(const octave_value_list &args)
|
||||
{
|
||||
octave_value v;
|
||||
if (args.length()!=3)
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("syntax: oarf_send_frame(card,sig,nbits)\n card (starting from 0), sig is a 2D array (size depends on no. of antennas and resampling factor), nbits is number of bits to quantize the signal to.");
|
||||
return true;
|
||||
}
|
||||
|
||||
v=args(0);
|
||||
if ((!v.is_real_scalar()) || (v.scalar_value() < 0.0) || (floor(v.scalar_value()) != v.scalar_value()) || (v.scalar_value() >= MAX_CARDS))
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("card must be between 0 and MAX_CARDS.");
|
||||
return true;
|
||||
}
|
||||
|
||||
v=args(1);
|
||||
printf("signal: R %d, C %d\n",v.rows(),v.columns());
|
||||
|
||||
v=args(2);
|
||||
if ((!v.is_real_scalar()) && (v.scalar_value()!=8) && (v.scalar_value()!=16))
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("nbits must be either 8 (CBMIMO) or 16 (ExpressMIMO)bits.");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
DEFUN_DLD (oarf_send_frame, args, nargout,"Send frame")
|
||||
{
|
||||
if (any_bad_argument(args))
|
||||
return octave_value_list();
|
||||
|
||||
const int card = args(0).int_value();
|
||||
ComplexMatrix dx = args(1).complex_matrix_value();
|
||||
|
||||
octave_value returnvalue;
|
||||
int i, ret;
|
||||
unsigned int length,aa,nbits,numcols;
|
||||
unsigned int resampling_factor[4];
|
||||
|
||||
ret = openair0_open();
|
||||
if ( ret != 0 )
|
||||
{
|
||||
error(FCNNAME);
|
||||
if (ret == -1)
|
||||
error("Error opening /dev/openair0");
|
||||
if (ret == -2)
|
||||
error("Error mapping bigshm");
|
||||
if (ret == -3)
|
||||
error("Error mapping RX or TX buffer");
|
||||
return octave_value(ret);
|
||||
}
|
||||
|
||||
if (card <0 || card >= openair0_num_detected_cards) {
|
||||
error("Invalid card number!");
|
||||
return octave_value(-4);
|
||||
}
|
||||
|
||||
numcols = args(1).columns();
|
||||
|
||||
//printf("colums = %d, rows = %d\n\n\n", numcols, args(1).rows());
|
||||
|
||||
if ( numcols<1 || (numcols > openair0_num_antennas[card]))
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("input array must be of column size %d.", openair0_num_antennas[card]);
|
||||
return octave_value_list();
|
||||
}
|
||||
|
||||
for (i=0;i<4;i++) {
|
||||
resampling_factor[i] = (openair0_exmimo_pci[card].exmimo_config_ptr)->framing.resampling_factor[i];
|
||||
printf("card %d, ant %d, resampling %u\n",card,i,resampling_factor[i]);
|
||||
}
|
||||
|
||||
for (i=0;i<numcols;i++){
|
||||
if (args(1).rows()<(76800*(1 << (2-resampling_factor[i]))))
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("input array column number %d must be of size %d.",i,(76800*(1 << (2-resampling_factor[i]))));
|
||||
return octave_value_list();
|
||||
}
|
||||
}
|
||||
|
||||
if ((openair0_exmimo_pci[card].exmimo_config_ptr->framing.tdd_config & TXRXSWITCH_MASK) != TXRXSWITCH_TESTTX)
|
||||
printf("Warning: tdd_config is not set to TXRXSWITCH_TESTTX! You better know what you are doing! :)\n");
|
||||
|
||||
|
||||
nbits = args(2).scalar_value();
|
||||
|
||||
for (aa=0;aa<numcols;aa++)
|
||||
{
|
||||
if (nbits==16)
|
||||
{
|
||||
for (i=0;i<(76800*(1 << (2-resampling_factor[aa])));i++)
|
||||
{
|
||||
//if (i<64) printf("%d: %d,%d\n",i,(short)real(dx(i,aa)),(short)imag(dx(i,aa)));
|
||||
((short*) openair0_exmimo_pci[card].dac_head[aa])[2*i] = (short)(real(dx(i,aa)));
|
||||
((short*) openair0_exmimo_pci[card].dac_head[aa])[1+(2*i)] = (short)(imag(dx(i,aa)));
|
||||
}
|
||||
}
|
||||
else if (nbits==8)
|
||||
{
|
||||
for (i=0;i<(76800*(1 << (2-resampling_factor[aa])));i++)
|
||||
{
|
||||
//if (i<64) printf("%d: %d,%d\n",i,char(real(dx(i,aa))),char(imag(dx(i,aa))));
|
||||
((char*) openair0_exmimo_pci[card].dac_head[aa])[2*i] = char(real(dx(i,aa)));
|
||||
((char*) openair0_exmimo_pci[card].dac_head[aa])[1+(2*i)] = char(imag(dx(i,aa)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(FCNNAME);
|
||||
error("nbits has to be 8 or 16!");
|
||||
}
|
||||
}
|
||||
|
||||
openair0_start_rt_acquisition( card );
|
||||
|
||||
openair0_close();
|
||||
|
||||
return octave_value (dx);
|
||||
}
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
// Matthias Ihmig, 2013
|
||||
// Florian Kaltenberger - created 2010-01-22
|
||||
// see http://www.gnu.org/software/octave/doc/interpreter/Dynamically-Linked-Functions.html#Dynamically-Linked-Functions
|
||||
// and http://wiki.octave.org/wiki.pl?CodaTutorial
|
||||
// and http://octave.sourceforge.net/coda/c58.html
|
||||
// compilation: see Makefile
|
||||
|
||||
|
||||
#include <octave/oct.h>
|
||||
|
||||
extern "C" {
|
||||
#include "openair0_lib.h"
|
||||
}
|
||||
#include "oarf.h"
|
||||
|
||||
#define FCNNAME "oarf_stop"
|
||||
|
||||
#define TRACE 1
|
||||
|
||||
|
||||
static bool any_bad_argument(const octave_value_list &args)
|
||||
{
|
||||
octave_value v;
|
||||
if (args.length()!=1)
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("syntax: oarf_stop(card)");
|
||||
return true;
|
||||
}
|
||||
|
||||
v=args(0);
|
||||
if ((!v.is_real_scalar()) || (v.scalar_value() < -1) || (floor(v.scalar_value()) != v.scalar_value()) || (v.scalar_value() >= MAX_CARDS))
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("card must be 0..number of cards-1.\nUse card = -1 to stop all cards.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
DEFUN_DLD (oarf_stop, args, nargout,"Stop RT acquisition and write registers.")
|
||||
{
|
||||
int a,b;
|
||||
if (any_bad_argument(args))
|
||||
return octave_value_list();
|
||||
|
||||
int card = args(0).int_value();
|
||||
int ret;
|
||||
|
||||
octave_value returnvalue;
|
||||
|
||||
ret = openair0_open();
|
||||
if ( ret != 0 )
|
||||
{
|
||||
error(FCNNAME);
|
||||
if (ret == -1)
|
||||
error("Error opening /dev/openair0");
|
||||
if (ret == -2)
|
||||
error("Error mapping bigshm");
|
||||
if (ret == -3)
|
||||
error("Error mapping RX or TX buffer");
|
||||
return octave_value(ret);
|
||||
}
|
||||
|
||||
if (card <-1 || card >= openair0_num_detected_cards)
|
||||
error("Invalid card number (num detected cards: %d, card: %d)!", openair0_num_detected_cards, card);
|
||||
|
||||
if (card == -1) {
|
||||
for (card = 0; card < openair0_num_detected_cards; card++)
|
||||
returnvalue = openair0_stop( card );
|
||||
} else
|
||||
returnvalue = openair0_stop( card );
|
||||
|
||||
openair0_close( );
|
||||
|
||||
return octave_value(returnvalue);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
// Riadh Ghaddab - created 2013-10-24
|
||||
// see http://www.gnu.org/software/octave/doc/interpreter/Dynamically-Linked-Functions.html#Dynamically-Linked-Functions
|
||||
// and http://wiki.octave.org/wiki.pl?CodaTutorial
|
||||
// and http://octave.sourceforge.net/coda/c58.html
|
||||
// compilation: see Makefile
|
||||
|
||||
|
||||
#include <octave/oct.h>
|
||||
|
||||
extern "C" {
|
||||
#include "openair0_lib.h"
|
||||
}
|
||||
#include "oarf.h"
|
||||
|
||||
#define FCNNAME "oarf_stop_without_reset"
|
||||
|
||||
#define TRACE 1
|
||||
|
||||
|
||||
static bool any_bad_argument(const octave_value_list &args)
|
||||
{
|
||||
octave_value v;
|
||||
if (args.length()!=1)
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("syntax: oarf_stop(card)");
|
||||
return true;
|
||||
}
|
||||
|
||||
v=args(0);
|
||||
if ((!v.is_real_scalar()) || (v.scalar_value() < -1) || (floor(v.scalar_value()) != v.scalar_value()) || (v.scalar_value() >= MAX_CARDS))
|
||||
{
|
||||
error(FCNNAME);
|
||||
error("card must be 0..number of cards-1.\nUse card = -1 to stop all cards.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFUN_DLD (oarf_stop_without_reset, args, nargout,"Stop RT acquisition and write registers.")
|
||||
{
|
||||
int a,b;
|
||||
if (any_bad_argument(args))
|
||||
return octave_value_list();
|
||||
|
||||
int card = args(0).int_value();
|
||||
int ret;
|
||||
|
||||
octave_value returnvalue;
|
||||
|
||||
ret = openair0_open();
|
||||
if ( ret != 0 )
|
||||
{
|
||||
error(FCNNAME);
|
||||
if (ret == -1)
|
||||
error("Error opening /dev/openair0");
|
||||
if (ret == -2)
|
||||
error("Error mapping bigshm");
|
||||
if (ret == -3)
|
||||
error("Error mapping RX or TX buffer");
|
||||
return octave_value(ret);
|
||||
}
|
||||
|
||||
if (card <-1 || card >= openair0_num_detected_cards)
|
||||
error("Invalid card number (num detected cards: %d, card: %d)!", openair0_num_detected_cards, card);
|
||||
|
||||
if (card == -1) {
|
||||
for (card = 0; card < openair0_num_detected_cards; card++)
|
||||
returnvalue = openair0_stop( card );
|
||||
} else
|
||||
returnvalue = openair0_stop_without_reset( card );
|
||||
|
||||
openair0_close( );
|
||||
|
||||
return octave_value(returnvalue);
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
card=0;
|
||||
s = oarf_get_frame(card);
|
||||
%s=s-0.99999*mean(s(:,2));
|
||||
sig0 = s(:,1);
|
||||
sig1 = s(:,2);
|
||||
|
||||
#sig0 = s(5000:end,1); % first channel
|
||||
#sig1 = s(5000:end,2); % 2nd channel
|
||||
|
||||
|
||||
bw=7.68e6;
|
||||
|
||||
spec = abs(fft(sig1)).^2;
|
||||
%[a,b] = max(spec(2:end)); b=b+1;
|
||||
[a,b] = max(spec);
|
||||
freq = (b-1)*bw/length(sig0);
|
||||
|
||||
L= 1000;
|
||||
W = 1;
|
||||
|
||||
offset_vec = (0:L-1)*((2*W)+1);
|
||||
W2 = 1+(2*W);
|
||||
|
||||
window_vec = (-W : W);
|
||||
pn = zeros(1,(2*L) - 1);
|
||||
for i = 1:L,
|
||||
pn(i+L-1) = sum(spec(offset_vec(i) + b + window_vec));
|
||||
end
|
||||
|
||||
for i = 2:L,
|
||||
pn(L-i+1) = sum(spec(-offset_vec(i) + b + window_vec));
|
||||
end
|
||||
|
||||
pn_2 = 10*log10(pn / pn(L)) - 10*log10(W2*bw/length(sig0));
|
||||
|
||||
f = ((-L+1):(L-1))*W2*bw/length(sig0);
|
||||
|
||||
|
||||
ylabel('dBc/Hz')
|
||||
xlabel("f_offset (Hz)")
|
||||
title("Phase Noise @ IQ output for Fc = 1912.6 + Fs/4 MHz CW input at antenna")
|
||||
semilogx(f(L:(2*L - 1)),pn_2(L:(2*L -1)))
|
||||
grid on
|
||||
axis([1e2 100e3 -90 -30]);
|
||||
|
||||
sum(pn*(f(2)-f(1)))
|
||||
|
||||
signal_amp = 10*log10(pn(L))
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
## Composes rf_local values: rfl(txi, txq, rxi, rxq)
|
||||
|
||||
## Author: Matthias Ihmig <ihmig@solstice>
|
||||
## Created: 2012-12-05
|
||||
|
||||
function [ ret ] = rfl(txi, txq, rxi, rxq)
|
||||
ret = txi + txq*2^6 + rxi*2^12 + rxq*2^18;
|
||||
endfunction
|
||||
@@ -1,11 +0,0 @@
|
||||
## Decodes rf_local values: [ txi, txq, rxi, rxq ] = rfldec(rflocal)
|
||||
|
||||
## Author: Matthias Ihmig <ihmig@solstice>
|
||||
## Created: 2012-12-05
|
||||
|
||||
function [ txi, txq, rxi, rxq ] = rfldec(rflocal)
|
||||
txi = mod(floor( rflocal /1 ), 64)
|
||||
txq = mod(floor( rflocal /64), 64)
|
||||
rxi = mod(floor( rflocal /4096), 64)
|
||||
rxq = mod(floor( rflocal /262144), 64)
|
||||
endfunction
|
||||
@@ -1,194 +0,0 @@
|
||||
close all
|
||||
clear all
|
||||
hold off
|
||||
|
||||
%gpib_card=0; % first GPIB PCI card in the computer
|
||||
%gpib_device=28; % this is configured in the signal generator Utilities->System->GPIB->Address menu
|
||||
smbv_ip_addr = "192.168.12.201";
|
||||
command = [getenv("OPENAIR_TARGETS") "/TEST/ROHDE_SCHWARZ/EthernetRawCommand.out"];
|
||||
|
||||
%fc = 1907600e3;
|
||||
fc = 2.6e9;
|
||||
%fc=800e6;
|
||||
|
||||
fs = 7680e3;
|
||||
fref = fc+fs/4;
|
||||
|
||||
power_dBm = [-70 -80 -90]+20;
|
||||
cables_loss_dB = 12; % we need to account for the power loss between the signal generator and the card input (splitter, cables)
|
||||
|
||||
dual_tx = 0;
|
||||
tdd = 1;
|
||||
card = 0;
|
||||
limeparms;
|
||||
%rf_mode = (RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM+DMAMODE_RX+DMAMODE_TX)*[1 1 1 1];
|
||||
rf_mode = (RXEN+0+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM+DMAMODE_RX+0)*[1 1 1 1];
|
||||
freq_rx = fc*[1 1 1 1];
|
||||
freq_tx = freq_rx;
|
||||
tx_gain = 25*[1 1 1 1];
|
||||
rx_gain = 15*[1 1 1 1];
|
||||
%rf_local= [8254744 8255063 8257340 8257340]; %rf_local*[1 1 1 1];
|
||||
rf_local = [8254813 8255016 8254813 8254813]; %exmimo2_2
|
||||
%rf_rxdc = rf_rxdc*[1 1 1 1];
|
||||
%rf_rxdc = ((128+rxdc_I) + (128+rxdc_Q)*(2^8))*[1 1 1 1];
|
||||
rf_rxdc = [37059 35459 36300 36999]; %exmimo2_2
|
||||
rf_vcocal=rf_vcocal_19G*[1 1 1 1];
|
||||
eNBflag = 0;
|
||||
tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_TESTRX;
|
||||
%syncmode = SYNCMODE_FREE;
|
||||
syncmode = [SYNCMODE_MASTER SYNCMODE_SLAVE];
|
||||
rffe_rxg_low = 63*[1 1 1 1];
|
||||
rffe_rxg_final = 63*[1 1 1 1];
|
||||
rffe_band = B19G_TDD*[1 1 1 1];
|
||||
autocal = [1 1 1 1];
|
||||
resampling_factor = [2 2 2 2];
|
||||
|
||||
|
||||
system(sprintf('%s %s ''*RST;*CLS''',command, smbv_ip_addr)); % reset and configure the signal generator
|
||||
%gpib_send(gpib_card,gpib_device,sprintf("POW %ddBm",power_dBm+cables_loss_dB));
|
||||
%gpib_send(gpib_card,gpib_device,'POW -14dBm');
|
||||
%gpib_send(gpib_card,gpib_device,'FREQ 1.91860GHz');
|
||||
%gpib_send(gpib_card,gpib_device,'FREQ 1.919225GHz');
|
||||
%gpib_send(gpib_card,gpib_device,'FREQ 1.909225GHz');
|
||||
system(sprintf('%s %s ''FREQ %ldHz''',command,smbv_ip_addr,fref));
|
||||
|
||||
for card=1:oarf_get_num_detected_cards
|
||||
oarf_config_exmimo(card-1,freq_rx,freq_tx,tdd_config,syncmode(card),rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor);
|
||||
end
|
||||
autocal = [0 0 0 0];
|
||||
|
||||
ALL_rxrfmode = [LNAByp LNAMed LNAMax];
|
||||
ALL_gain = 0:5:30;
|
||||
|
||||
num_chains = 4*oarf_get_num_detected_cards;
|
||||
|
||||
SpN0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
%SpN1 = zeros(length(ALL_rxrfmode),length(ALL_gain));
|
||||
N0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
%N1 = zeros(length(ALL_rxrfmode),length(ALL_gain));
|
||||
S0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
S0_lin = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
%S1 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
G0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
%G1 = zeros(length(ALL_rxrfmode),length(ALL_gain));
|
||||
NF0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
%NF1 = zeros(length(ALL_rxrfmode),length(ALL_gain));
|
||||
SNR0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
%SNR1 = zeros(length(ALL_rxrfmode),length(ALL_gain));
|
||||
|
||||
%keyboard
|
||||
|
||||
idx_power = 1;
|
||||
for mode_idx = 1:3
|
||||
LNA=ALL_rxrfmode(mode_idx);
|
||||
|
||||
system(sprintf('%s %s ''POW %d dBm''',command,smbv_ip_addr,power_dBm(mode_idx)+cables_loss_dB));
|
||||
|
||||
idx_gain = 1;
|
||||
for rx_gain=ALL_gain
|
||||
|
||||
rf_mode = (RXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNA+RFBBNORM+DMAMODE_RX)*[1 1 1 1];
|
||||
rx_gain = rx_gain * [1 1 1 1];
|
||||
|
||||
for card=1:oarf_get_num_detected_cards
|
||||
oarf_config_exmimo(card-1,freq_rx,freq_tx,tdd_config,syncmode(card),rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor);
|
||||
end
|
||||
sleep(1);
|
||||
|
||||
% signal measurement
|
||||
system(sprintf('%s %s ''OUTP:STAT ON''',command,smbv_ip_addr)); % activate output
|
||||
sleep(.5);
|
||||
|
||||
s=oarf_get_frame(0);
|
||||
sleep(.5);
|
||||
|
||||
SpN0(idx_power,idx_gain,:) = mean(abs(s).^2,1) - abs(mean(s,1)).^2;
|
||||
%SpN1(idx_power,idx_gain) = mean(abs(s(:,2)).^2) - abs(mean(s(:,2))).^2;
|
||||
|
||||
figure(1);
|
||||
hold off
|
||||
plot(20*log10(abs(fft(s(:,end)))),'r'); %,20*log10(abs(fft(s(:,2)))),'b')
|
||||
title("Signal");
|
||||
ylim([0 200]);
|
||||
|
||||
% noise measurement
|
||||
system(sprintf('%s %s ''OUTP:STAT OFF''',command,smbv_ip_addr)); % deactivate output
|
||||
sleep(.5);
|
||||
|
||||
s=oarf_get_frame(0); %oarf_get_frame
|
||||
sleep(.5);
|
||||
|
||||
N0(idx_power,idx_gain,:) = mean(abs(s).^2,1) - abs(mean(s,1)).^2;
|
||||
%N1(idx_power,idx_gain) = mean(abs(s(:,2)).^2) - abs(mean(s(:,2))).^2;
|
||||
|
||||
figure(2);
|
||||
hold off
|
||||
plot(20*log10(abs(fft(s(:,end)))),'r'); %,20*log10(abs(fft(s(:,2)))),'b')
|
||||
title("Noise");
|
||||
ylim([0 200]);
|
||||
|
||||
% do some plausibility checks
|
||||
% if ((N0(idx_power,idx_gain) > SpN0(idx_power,idx_gain)) ||
|
||||
% (N1(idx_power,idx_gain) > SpN1(idx_power,idx_gain)))
|
||||
% error("something is wrong");
|
||||
% end
|
||||
|
||||
S0_lin(idx_power,idx_gain,:) = SpN0(idx_power,idx_gain,:)-N0(idx_power,idx_gain,:);
|
||||
S0_lin(idx_power,idx_gain,S0_lin(idx_power,idx_gain,:)<0) = 0;
|
||||
S0(idx_power,idx_gain,:) = 10*log10(S0_lin(idx_power,idx_gain,:));
|
||||
%S1(idx_power,idx_gain) = 10*log10(SpN1(idx_power,idx_gain)-N1(idx_power,idx_gain));
|
||||
G0(idx_power,idx_gain,:) = S0(idx_power,idx_gain,:) - power_dBm(mode_idx);
|
||||
%G1(idx_power,idx_gain) = S1(idx_power,idx_gain) - power_dBm;
|
||||
NF0(idx_power,idx_gain,:) = 10*log10(N0(idx_power,idx_gain,:)) - G0(idx_power,idx_gain,:) + 105; % 108 is the thermal noise
|
||||
%NF1(idx_power,idx_gain) = 10*log10(N1(idx_power,idx_gain)) - G1(idx_power,idx_gain) + 105;
|
||||
SNR0(idx_power,idx_gain,:) = S0(idx_power,idx_gain,:)-10*log10(N0(idx_power,idx_gain,:));
|
||||
%SNR1(idx_power,idx_gain) = S1(idx_power,idx_gain)-10*log10(N1(idx_power,idx_gain));
|
||||
|
||||
%printf(' %d: Signal strength (%f,%f), Gain (%f %f), N (%f %f) SNR (%f %f) NF (%f %f)\n',
|
||||
% rx_gain(1), S0(idx_power,idx_gain),S1(idx_power,idx_gain),
|
||||
% G0(idx_power,idx_gain),G1(idx_power,idx_gain),
|
||||
% 10*log10(N0(idx_power,idx_gain)),10*log10(N1(idx_power,idx_gain)),
|
||||
% SNR0(idx_power,idx_gain),SNR1(idx_power,idx_gain),
|
||||
% NF0(idx_power,idx_gain),NF1(idx_power,idx_gain));
|
||||
%fflush(stdout);
|
||||
%fprintf(fid,'%d, %d, %d, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n',
|
||||
%power_dBm,gain2391,gain9862, S0,S1,G0,G1,10*log10(N0),10*log10(N1),SNR0,SNR1,NF0,NF1);
|
||||
|
||||
|
||||
figure(3)
|
||||
hold off
|
||||
plot(ALL_gain,G0(:,:,1),'o-','markersize',10)
|
||||
hold on
|
||||
plot(ALL_gain,G0(:,:,2),'x-','markersize',10)
|
||||
plot(ALL_gain,G0(:,:,3),'s-','markersize',10)
|
||||
plot(ALL_gain,G0(:,:,4),'d-','markersize',10)
|
||||
legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1','Byp RX2','Med RX2','Max RX2','Byp RX3','Med RX3','Max RX3');
|
||||
title('Gains')
|
||||
|
||||
figure(4)
|
||||
hold off
|
||||
plot(ALL_gain,NF0(:,:,1),'o-','markersize',10)
|
||||
hold on
|
||||
plot(ALL_gain,NF0(:,:,2),'x-','markersize',10)
|
||||
plot(ALL_gain,NF0(:,:,3),'s-','markersize',10)
|
||||
plot(ALL_gain,NF0(:,:,4),'d-','markersize',10)
|
||||
legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1','Byp RX2','Med RX2','Max RX2','Byp RX3','Med RX3','Max RX3');
|
||||
title('Noise Figure')
|
||||
|
||||
idx_gain = idx_gain + 1;
|
||||
|
||||
end
|
||||
|
||||
idx_power = idx_power + 1;
|
||||
|
||||
end
|
||||
|
||||
%gpib_send(gpib_card,gpib_device,'OUTP:STAT OFF'); % deactivate output
|
||||
|
||||
%l0 = [ALL_gain2391; ones(size(ALL_gain2391))].'\G0;
|
||||
%l1 = [ALL_gain2391; ones(size(ALL_gain2391))].'\G1;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,276 +0,0 @@
|
||||
close all
|
||||
clear all
|
||||
hold off
|
||||
|
||||
%gpib_card=0; % first GPIB PCI card in the computer
|
||||
%gpib_device=28; % this is configured in the signal generator Utilities->System->GPIB->Address menu
|
||||
smbv_ip_addr = "192.168.12.201";
|
||||
command = [getenv("OPENAIR_TARGETS") "/TEST/ROHDE_SCHWARZ/EthernetRawCommand.out"];
|
||||
|
||||
fc = 1907600e3;
|
||||
%fc = 2.6e9;
|
||||
%fc=700e6;
|
||||
|
||||
fs = 7680e3;
|
||||
fref = fc+fs/4;
|
||||
|
||||
power_dBm = [-70 -80 -90]; %needs to be adjusted based on carrier freq
|
||||
cables_loss_dB = 11; % we need to account for the power loss between the signal generator and the card input (splitter, cables)
|
||||
nb_meas = 10;
|
||||
|
||||
dual_tx = 0;
|
||||
tdd = 1;
|
||||
card = 0;
|
||||
limeparms;
|
||||
%rf_mode = (RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM+DMAMODE_RX+DMAMODE_TX)*[1 1 1 1];
|
||||
rf_mode = (RXEN+0+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM+DMAMODE_RX+0)*[1 1 1 1];
|
||||
freq_rx = fc*[1 1 1 1];
|
||||
freq_tx = freq_rx;
|
||||
tx_gain = 25*[1 1 1 1];
|
||||
rx_gain = 15*[1 1 1 1];
|
||||
%rf_local= [8254744 8255063 8257340 8257340]; %rf_local*[1 1 1 1];
|
||||
rf_local = [8254813 8255016 8254813 8254813]; %exmimo2_2
|
||||
%rf_rxdc = rf_rxdc*[1 1 1 1];
|
||||
%rf_rxdc = ((128+rxdc_I) + (128+rxdc_Q)*(2^8))*[1 1 1 1];
|
||||
rf_rxdc = [37059 35459 36300 36999]; %exmimo2_2
|
||||
rf_vcocal=rf_vcocal_19G*[1 1 1 1];
|
||||
eNBflag = 0;
|
||||
tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_TESTRX;
|
||||
syncmode = SYNCMODE_FREE;
|
||||
%syncmode = [SYNCMODE_MASTER SYNCMODE_SLAVE];
|
||||
rffe_rxg_low = 63*[1 1 1 1];
|
||||
rffe_rxg_final = 63*[1 1 1 1];
|
||||
rffe_band = B19G_TDD*[1 1 1 1];
|
||||
autocal = [1 1 1 1];
|
||||
resampling_factor = [2 2 2 2];
|
||||
|
||||
|
||||
system(sprintf('%s %s ''*RST;*CLS''',command, smbv_ip_addr)); % reset and configure the signal generator
|
||||
%gpib_send(gpib_card,gpib_device,sprintf("POW %ddBm",power_dBm+cables_loss_dB));
|
||||
%gpib_send(gpib_card,gpib_device,'POW -14dBm');
|
||||
%gpib_send(gpib_card,gpib_device,'FREQ 1.91860GHz');
|
||||
%gpib_send(gpib_card,gpib_device,'FREQ 1.919225GHz');
|
||||
%gpib_send(gpib_card,gpib_device,'FREQ 1.909225GHz');
|
||||
system(sprintf('%s %s ''FREQ %ldHz''',command,smbv_ip_addr,fref));
|
||||
|
||||
%for card=1:oarf_get_num_detected_cards
|
||||
%oarf_config_exmimo(card-1,freq_rx,freq_tx,tdd_config,syncmode(card),rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor);
|
||||
%end
|
||||
|
||||
autocal = [0 0 0 0];
|
||||
|
||||
ALL_rxrfmode = [LNAByp LNAMed LNAMax];
|
||||
%ALL_rxrfmode = [LNAMax];
|
||||
ALL_gain = 0:10:30;
|
||||
|
||||
num_chains = 4*oarf_get_num_detected_cards;
|
||||
|
||||
SpN0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
%SpN1 = zeros(length(ALL_rxrfmode),length(ALL_gain));
|
||||
N0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
%N1 = zeros(length(ALL_rxrfmode),length(ALL_gain));
|
||||
S0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
S0_lin = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
%S1 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
G0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
G1 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
NF0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
NF1 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
NF2 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
SNR0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
|
||||
%SNR1 = zeros(length(ALL_rxrfmode),length(ALL_gain));
|
||||
|
||||
%keyboard
|
||||
|
||||
for mode_idx = 3
|
||||
LNA=ALL_rxrfmode(mode_idx);
|
||||
|
||||
system(sprintf('%s %s ''POW %d dBm''',command,smbv_ip_addr,power_dBm(mode_idx)+cables_loss_dB));
|
||||
|
||||
idx_gain = 1;
|
||||
for rx_gain=ALL_gain
|
||||
|
||||
rf_mode = (RXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNA+RFBBNORM+DMAMODE_RX)*[1 1 1 1];
|
||||
rx_gain = rx_gain * [1 1 1 1];
|
||||
|
||||
for card=1:oarf_get_num_detected_cards
|
||||
oarf_config_exmimo(card-1,freq_rx,freq_tx,tdd_config,syncmode(card),rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor);
|
||||
end
|
||||
sleep(1);
|
||||
|
||||
% signal measurement
|
||||
system(sprintf('%s %s ''OUTP:STAT ON''',command,smbv_ip_addr)); % activate output
|
||||
sleep(.5);
|
||||
%f1 = (7.68*(0:length(s(:,2))-1)/(length(s(:,2))))-3.84;
|
||||
f1 = (7.68*(0:307200-1)/307200)-3.84;
|
||||
%nidx = find(f1>=0.5 & f1<=1.5); %1MHz
|
||||
nidx = find(f1>=1.5 & f1<=2.5); %1MHz
|
||||
sidx = find(f1>=1.87 & f1<=1.97); %100kHz
|
||||
|
||||
SpN0_temp = 0;
|
||||
spn0_temp = 0;
|
||||
for k=1:nb_meas
|
||||
s=oarf_get_frame(0);
|
||||
sleep(.5);
|
||||
s = s - repmat(mean(s,1),size(s,1),1);
|
||||
|
||||
SpN0_temp = SpN0_temp + mean(abs(s).^2,1) - abs(mean(s,1)).^2;
|
||||
sf = fftshift(fft(s),1)/sqrt(length(s));
|
||||
%np = 10*log10(sum(abs(sf(nidx,:)).^2));
|
||||
%sp_temp = sp_temp + 10*log10(sum(abs(sf(sidx,:)).^2));
|
||||
spn0_temp = spn0_temp + sum(abs(sf).^2);
|
||||
end
|
||||
%SpN0(mode_idx,idx_gain,:) = mean(abs(s).^2,1) - abs(mean(s,1)).^2;
|
||||
%SpN1(mode_idx,idx_gain) = mean(abs(s(:,2)).^2) - abs(mean(s(:,2))).^2;
|
||||
SpN0(mode_idx,idx_gain,:) = SpN0_temp/nb_meas;
|
||||
spn0 = spn0_temp/nb_meas;
|
||||
|
||||
%keyboard;
|
||||
|
||||
sf = fftshift(fft(s),1)/sqrt(length(s));
|
||||
figure(1);
|
||||
hold off
|
||||
plot(f1,20*log10(abs((sf(:,3)))),'r');
|
||||
hold on
|
||||
plot(f1(nidx),20*log10(abs(sf(nidx,3))),'b');
|
||||
plot(f1(sidx),20*log10(abs(sf(sidx,3))),'g');
|
||||
|
||||
title("Signal");
|
||||
ylim([0 200]);
|
||||
|
||||
% noise measurement
|
||||
system(sprintf('%s %s ''OUTP:STAT OFF''',command,smbv_ip_addr)); % deactivate output
|
||||
sleep(.5);
|
||||
|
||||
N0_temp = 0;
|
||||
np_temp = 0;
|
||||
np_temp_unit = 0;
|
||||
for k=1:nb_meas
|
||||
s=oarf_get_frame(0); %oarf_get_frame
|
||||
sleep(.5);
|
||||
s = s - repmat(mean(s,1),size(s,1),1);
|
||||
|
||||
N0_temp = N0_temp + mean(abs(s).^2,1) - abs(mean(s,1)).^2;
|
||||
%N1(idx_power,idx_gain) = mean(abs(s(:,2)).^2) - abs(mean(s(:,2))).^2;
|
||||
sf = fftshift(fft(s),1)/sqrt(length(s));
|
||||
np_temp = np_temp + sum(abs(sf).^2);
|
||||
np_temp_unit = np_temp_unit + sum(abs(sf(nidx,:)).^2);
|
||||
end
|
||||
N0(mode_idx,idx_gain,:) = N0_temp/nb_meas;
|
||||
%N0(mode_idx,idx_gain,:) = mean(abs(s).^2,1) - abs(mean(s,1)).^2;
|
||||
%N1(mode_idx,idx_gain) = mean(abs(s(:,2)).^2) - abs(mean(s(:,2))).^2;
|
||||
%G1(mode_idx,idx_gain,:) = sp - power_dBm(mode_idx);
|
||||
np = np_temp/nb_meas;
|
||||
snr = 10*log10((spn0-np)./np); %measured snr
|
||||
snr_real = power_dBm(mode_idx) - (-174 + 10*log10(7.68e6)); %signal over thermal noise
|
||||
|
||||
np_unit = np_temp_unit/nb_meas;
|
||||
snr_output_unit = 10*log10((spn0-np_unit)./np_unit); %measured snr
|
||||
snr_input_unit = power_dBm(mode_idx) - (-174 + 10*log10(1e6)); %signal over thermal noise
|
||||
|
||||
NF1(mode_idx,idx_gain,:) = snr_real - snr;
|
||||
NF2(mode_idx,idx_gain,:) = snr_input_unit - snr_output_unit;
|
||||
|
||||
sf = fftshift(fft(s),1)/sqrt(length(s));
|
||||
figure(2);
|
||||
hold off
|
||||
plot(f1,20*log10(abs((sf(:,3)))),'r');
|
||||
title("Noise");
|
||||
ylim([0 200]);
|
||||
|
||||
% do some plausibility checks
|
||||
% if ((N0(mode_idx,idx_gain) > SpN0(mode_idx,idx_gain)) ||
|
||||
% (N1(mode_idx,idx_gain) > SpN1(mode_idx,idx_gain)))
|
||||
% error("something is wrong");
|
||||
% end
|
||||
|
||||
S0_lin(mode_idx,idx_gain,:) = SpN0(mode_idx,idx_gain,:)-N0(mode_idx,idx_gain,:);
|
||||
S0_lin(mode_idx,idx_gain,S0_lin(mode_idx,idx_gain,:)<0) = 0;
|
||||
S0(mode_idx,idx_gain,:) = 10*log10(S0_lin(mode_idx,idx_gain,:));
|
||||
%S1(mode_idx,idx_gain) = 10*log10(SpN1(mode_idx,idx_gain)-N1(mode_idx,idx_gain));
|
||||
G0(mode_idx,idx_gain,:) = S0(mode_idx,idx_gain,:) - power_dBm(mode_idx);
|
||||
%G1(mode_idx,idx_gain) = S1(mode_idx,idx_gain) - power_dBm;
|
||||
NF0(mode_idx,idx_gain,:) = 10*log10(N0(mode_idx,idx_gain,:)) - G0(mode_idx,idx_gain,:) + 105; % 108 is the thermal noise
|
||||
%NF1(mode_idx,idx_gain) = 10*log10(N1(mode_idx,idx_gain)) - G1(mode_idx,idx_gain) + 105;
|
||||
SNR0(mode_idx,idx_gain,:) = S0(mode_idx,idx_gain,:)-10*log10(N0(mode_idx,idx_gain,:));
|
||||
%SNR1(mode_idx,idx_gain) = S1(mode_idx,idx_gain)-10*log10(N1(mode_idx,idx_gain));
|
||||
|
||||
%printf(' %d: Signal strength (%f,%f), Gain (%f %f), N (%f %f) SNR (%f %f) NF (%f %f)\n',
|
||||
% rx_gain(1), S0(mode_idx,idx_gain),S1(mode_idx,idx_gain),
|
||||
% G0(mode_idx,idx_gain),G1(mode_idx,idx_gain),
|
||||
% 10*log10(N0(mode_idx,idx_gain)),10*log10(N1(mode_idx,idx_gain)),
|
||||
% SNR0(mode_idx,idx_gain),SNR1(mode_idx,idx_gain),
|
||||
% NF0(mode_idx,idx_gain),NF1(mode_idx,idx_gain));
|
||||
%fflush(stdout);
|
||||
%fprintf(fid,'%d, %d, %d, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n',
|
||||
%power_dBm,gain2391,gain9862, S0,S1,G0,G1,10*log10(N0),10*log10(N1),SNR0,SNR1,NF0,NF1);
|
||||
%keyboard
|
||||
|
||||
figure(3)
|
||||
hold off
|
||||
plot(ALL_gain,G0(:,:,1),'o-','markersize',10)
|
||||
hold on
|
||||
plot(ALL_gain,G0(:,:,2),'x-','markersize',10)
|
||||
plot(ALL_gain,G0(:,:,3),'s-','markersize',10)
|
||||
plot(ALL_gain,G0(:,:,4),'d-','markersize',10)
|
||||
%legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1');
|
||||
legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1','Byp RX2','Med RX2','Max RX2','Byp RX3','Med RX3','Max RX3');
|
||||
title('Gains')
|
||||
xlabel('rx gains (dB)')
|
||||
ylabel('NF (dB)')
|
||||
|
||||
figure(4)
|
||||
hold off
|
||||
plot(ALL_gain,NF0(:,:,1),'o-','markersize',10)
|
||||
hold on
|
||||
plot(ALL_gain,NF0(:,:,2),'x-','markersize',10)
|
||||
plot(ALL_gain,NF0(:,:,3),'s-','markersize',10)
|
||||
plot(ALL_gain,NF0(:,:,4),'d-','markersize',10)
|
||||
%legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1');
|
||||
legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1','Byp RX2','Med RX2','Max RX2','Byp RX3','Med RX3','Max RX3');
|
||||
title('Averaged Noise Figure measured in time domain')
|
||||
xlabel('rx gains (dB)')
|
||||
ylabel('NF (dB)')
|
||||
|
||||
figure(5)
|
||||
hold off
|
||||
plot(ALL_gain,NF1(:,:,1),'o-','markersize',10)
|
||||
hold on
|
||||
plot(ALL_gain,NF1(:,:,2),'x-','markersize',10)
|
||||
plot(ALL_gain,NF1(:,:,3),'s-','markersize',10)
|
||||
plot(ALL_gain,NF1(:,:,4),'d-','markersize',10)
|
||||
%legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1');
|
||||
legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1','Byp RX2','Med RX2','Max RX2','Byp RX3','Med RX3','Max RX3');
|
||||
title('Averaged Noise Figure measured in frequency domain')
|
||||
xlabel('rx gains (dB)')
|
||||
ylabel('NF (dB)')
|
||||
|
||||
|
||||
figure(6)
|
||||
hold off
|
||||
plot(ALL_gain,NF2(:,:,1),'o-','markersize',10)
|
||||
hold on
|
||||
plot(ALL_gain,NF2(:,:,2),'x-','markersize',10)
|
||||
plot(ALL_gain,NF2(:,:,3),'s-','markersize',10)
|
||||
plot(ALL_gain,NF2(:,:,4),'d-','markersize',10)
|
||||
%legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1');
|
||||
legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1','Byp RX2','Med RX2','Max RX2','Byp RX3','Med RX3','Max RX3');
|
||||
title('Unit Bandwidth Noise Figure measured in frequency domain')
|
||||
xlabel('rx gains (dB)')
|
||||
ylabel('NF (dB)')
|
||||
|
||||
idx_gain = idx_gain + 1;
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
%gpib_send(gpib_card,gpib_device,'OUTP:STAT OFF'); % deactivate output
|
||||
|
||||
%l0 = [ALL_gain2391; ones(size(ALL_gain2391))].'\G0;
|
||||
%l1 = [ALL_gain2391; ones(size(ALL_gain2391))].'\G1;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
close all
|
||||
clear all
|
||||
hold off
|
||||
|
||||
gpib_card=0; % first GPIB PCI card in the computer
|
||||
gpib_device=28; % this is configured in the signal generator Utilities->System->GPIB->Address menu
|
||||
|
||||
fc = 1907600e3;
|
||||
|
||||
fs = 7680e3;
|
||||
fref = fc+fs/4;
|
||||
|
||||
power_dBm = -70;
|
||||
cables_loss_dB = 6; % we need to account for the power loss between the signal generator and the card input (splitter, cables)
|
||||
|
||||
dual_tx = 0;
|
||||
tdd = 1;
|
||||
card = 0;
|
||||
limeparms;
|
||||
%rf_mode = (RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM+DMAMODE_RX+DMAMODE_TX)*[1 1 1 1];
|
||||
rf_mode1 = (RXEN+0+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM+DMAMODE_RX+0);
|
||||
rf_mode2 = (RXEN+0+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA2ON+LNAMax+RFBBNORM+DMAMODE_RX+0);
|
||||
rf_mode = [rf_mode1 rf_mode2 0 0];
|
||||
freq_rx = 1907600000*[1 1 1 1];
|
||||
freq_tx = freq_rx;
|
||||
tx_gain = 25*[1 1 1 1];
|
||||
rx_gain = 15*[1 1 1 1];
|
||||
%rf_local= [8254744 8255063 8257340 8257340]; %rf_local*[1 1 1 1];
|
||||
rf_local = [8254813 8255016 8254813 8254813]; %exmimo2_2
|
||||
%rf_rxdc = rf_rxdc*[1 1 1 1];
|
||||
%rf_rxdc = ((128+rxdc_I) + (128+rxdc_Q)*(2^8))*[1 1 1 1];
|
||||
rf_rxdc = [37059 35459 36300 36999]; %exmimo2_2
|
||||
rf_rxdc = [34689 34756 36300 36999]; %exmimo2_2 with external RF
|
||||
rf_vcocal=rf_vcocal_19G*[1 1 1 1];
|
||||
eNBflag = 0;
|
||||
tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_TESTRX;
|
||||
syncmode = SYNCMODE_FREE;
|
||||
rffe_rxg_low = 31*[1 1 1 1];
|
||||
rffe_rxg_final = 31*[1 1 1 1];
|
||||
rffe_band = B19G_TDD*[1 1 1 1];
|
||||
autocal = [1 1 1 1];
|
||||
|
||||
gpib_send(gpib_card,gpib_device,'*RST;*CLS'); % reset and configure the signal generator
|
||||
%gpib_send(gpib_card,gpib_device,sprintf("POW %ddBm",power_dBm+cables_loss_dB));
|
||||
gpib_send(gpib_card,gpib_device,sprintf("POW %ddBm",0));
|
||||
%gpib_send(gpib_card,gpib_device,'FREQ 1.91860GHz');
|
||||
%gpib_send(gpib_card,gpib_device,'FREQ 1.919225GHz');
|
||||
%gpib_send(gpib_card,gpib_device,'FREQ 1.909225GHz');
|
||||
gpib_send(gpib_card,gpib_device,sprintf("FREQ %dHz",fref));
|
||||
|
||||
oarf_config_exmimo(card,freq_rx,freq_tx,tdd_config,syncmode,rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal);
|
||||
autocal = [0 0 0 0];
|
||||
|
||||
%ALL_rxrfmode = [LNAByp LNAMed LNAMax];
|
||||
%ALL_gain = 0:10:30;
|
||||
ALL_rxrfmode = LNAMax;
|
||||
ALL_gain = 30;
|
||||
ALL_rffe_rxg_low = [0 7:8:64];
|
||||
ALL_rffe_rxg_final = [0 7:8:64];
|
||||
|
||||
|
||||
SpN0 = zeros(length(ALL_rffe_rxg_low),length(ALL_rffe_rxg_final));
|
||||
SpN1 = zeros(length(ALL_rffe_rxg_low),length(ALL_rffe_rxg_final));
|
||||
N0 = zeros(length(ALL_rffe_rxg_low),length(ALL_rffe_rxg_final));
|
||||
N1 = zeros(length(ALL_rffe_rxg_low),length(ALL_rffe_rxg_final));
|
||||
S0 = zeros(length(ALL_rffe_rxg_low),length(ALL_rffe_rxg_final));
|
||||
S1 = zeros(length(ALL_rffe_rxg_low),length(ALL_rffe_rxg_final));
|
||||
G0 = zeros(length(ALL_rffe_rxg_low),length(ALL_rffe_rxg_final));
|
||||
G1 = zeros(length(ALL_rffe_rxg_low),length(ALL_rffe_rxg_final));
|
||||
NF0 = zeros(length(ALL_rffe_rxg_low),length(ALL_rffe_rxg_final));
|
||||
NF1 = zeros(length(ALL_rffe_rxg_low),length(ALL_rffe_rxg_final));
|
||||
SNR0 = zeros(length(ALL_rffe_rxg_low),length(ALL_rffe_rxg_final));
|
||||
SNR1 = zeros(length(ALL_rffe_rxg_low),length(ALL_rffe_rxg_final));
|
||||
|
||||
%keyboard
|
||||
|
||||
idx_power = 1;
|
||||
for LNA=ALL_rxrfmode
|
||||
rf_mode = (RXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNA+RFBBNORM+DMAMODE_RX)*[1 1 0 0];
|
||||
|
||||
for rffe_rxg_low=ALL_rffe_rxg_low
|
||||
rffe_rxg_low = rffe_rxg_low*[1 1 1 1];
|
||||
|
||||
idx_gain = 1;
|
||||
for rx_gain=ALL_gain
|
||||
rx_gain = rx_gain * [1 1 1 1];
|
||||
|
||||
for rffe_rxg_final=ALL_rffe_rxg_final
|
||||
rffe_rxg_final = rffe_rxg_final*[1 1 1 1];
|
||||
|
||||
oarf_config_exmimo(card,freq_rx,freq_tx,tdd_config,syncmode,rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal);
|
||||
sleep(1);
|
||||
|
||||
% signal measurement
|
||||
gpib_send(gpib_card,gpib_device,'OUTP:STAT ON'); % activate output
|
||||
sleep(.5);
|
||||
|
||||
s=oarf_get_frame(card);
|
||||
sleep(.5);
|
||||
|
||||
SpN0(idx_power,idx_gain) = mean(abs(s(:,1)).^2) - abs(mean(s(:,1))).^2;
|
||||
SpN1(idx_power,idx_gain) = mean(abs(s(:,2)).^2) - abs(mean(s(:,2))).^2;
|
||||
|
||||
figure(1);
|
||||
hold off
|
||||
plot(20*log10(abs(fft(s(:,1)))),'r',20*log10(abs(fft(s(:,2)))),'b')
|
||||
title("Signal");
|
||||
ylim([0 200]);
|
||||
|
||||
% noise measurement
|
||||
gpib_send(gpib_card,gpib_device,'OUTP:STAT OFF'); % deactivate output
|
||||
sleep(.5);
|
||||
|
||||
s=oarf_get_frame(card); %oarf_get_frame
|
||||
sleep(.5);
|
||||
|
||||
N0(idx_power,idx_gain) = mean(abs(s(:,1)).^2) - abs(mean(s(:,1))).^2;
|
||||
N1(idx_power,idx_gain) = mean(abs(s(:,2)).^2) - abs(mean(s(:,2))).^2;
|
||||
|
||||
figure(2);
|
||||
hold off
|
||||
plot(20*log10(abs(fft(s(:,1)))),'r',20*log10(abs(fft(s(:,2)))),'b')
|
||||
title("Noise");
|
||||
ylim([0 200]);
|
||||
|
||||
% do some plausibility checks
|
||||
% if ((N0(idx_power,idx_gain) > SpN0(idx_power,idx_gain)) ||
|
||||
% (N1(idx_power,idx_gain) > SpN1(idx_power,idx_gain)))
|
||||
% error("something is wrong");
|
||||
% end
|
||||
|
||||
S0(idx_power,idx_gain) = 10*log10(SpN0(idx_power,idx_gain)-N0(idx_power,idx_gain));
|
||||
S1(idx_power,idx_gain) = 10*log10(SpN1(idx_power,idx_gain)-N1(idx_power,idx_gain));
|
||||
G0(idx_power,idx_gain) = S0(idx_power,idx_gain) - power_dBm;
|
||||
G1(idx_power,idx_gain) = S1(idx_power,idx_gain) - power_dBm;
|
||||
NF0(idx_power,idx_gain) = 10*log10(N0(idx_power,idx_gain)) - G0(idx_power,idx_gain) + 105; % 108 is the thermal noise
|
||||
NF1(idx_power,idx_gain) = 10*log10(N1(idx_power,idx_gain)) - G1(idx_power,idx_gain) + 105;
|
||||
SNR0(idx_power,idx_gain) = S0(idx_power,idx_gain)-10*log10(N0(idx_power,idx_gain));
|
||||
SNR1(idx_power,idx_gain) = S1(idx_power,idx_gain)-10*log10(N1(idx_power,idx_gain));
|
||||
|
||||
printf(' %d: Signal strength (%f,%f), Gain (%f %f), N (%f %f) SNR (%f %f) NF (%f %f)\n',
|
||||
rx_gain(1), S0(idx_power,idx_gain),S1(idx_power,idx_gain),
|
||||
G0(idx_power,idx_gain),G1(idx_power,idx_gain),
|
||||
10*log10(N0(idx_power,idx_gain)),10*log10(N1(idx_power,idx_gain)),
|
||||
SNR0(idx_power,idx_gain),SNR1(idx_power,idx_gain),
|
||||
NF0(idx_power,idx_gain),NF1(idx_power,idx_gain));
|
||||
fflush(stdout);
|
||||
%fprintf(fid,'%d, %d, %d, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n',
|
||||
%power_dBm,gain2391,gain9862, S0,S1,G0,G1,10*log10(N0),10*log10(N1),SNR0,SNR1,NF0,NF1);
|
||||
|
||||
|
||||
idx_gain = idx_gain + 1;
|
||||
|
||||
figure(3)
|
||||
hold off
|
||||
plot(ALL_rffe_rxg_final,G0,'o-','markersize',10)
|
||||
hold on
|
||||
plot(ALL_rffe_rxg_final,G1,'x-','markersize',10)
|
||||
legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1');
|
||||
title('Gains')
|
||||
|
||||
figure(4)
|
||||
hold off
|
||||
plot(ALL_rffe_rxg_final,NF0,'o-','markersize',10)
|
||||
hold on
|
||||
plot(ALL_rffe_rxg_final,NF1,'x-','markersize',10)
|
||||
legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1');
|
||||
title('Noise Figure')
|
||||
end
|
||||
end
|
||||
idx_power = idx_power + 1;
|
||||
end
|
||||
end
|
||||
|
||||
%gpib_send(gpib_card,gpib_device,'OUTP:STAT OFF'); % deactivate output
|
||||
|
||||
%l0 = [ALL_gain2391; ones(size(ALL_gain2391))].'\G0;
|
||||
%l1 = [ALL_gain2391; ones(size(ALL_gain2391))].'\G1;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
dual_tx=0;
|
||||
card=0;
|
||||
limeparms;
|
||||
active_rf = zeros(1,4);
|
||||
active_rf = [1 1 1 1];
|
||||
autocal = [1 1 1 1];
|
||||
resampling_factor = [2 2 2 2];
|
||||
|
||||
%rf_mode = (RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM)*[1 1 1 1];
|
||||
rf_mode = (RXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM)*active_rf;
|
||||
rf_mode = rf_mode+((DMAMODE_RX+DMAMODE_TX)*active_rf);
|
||||
%freq_rx = 2540000000*[1 1 1 1];
|
||||
freq_rx = 747000000*active_rf;
|
||||
%freq_rx = 2680000000*active_rf; %+ 2540000000*[0 1 0 0]; % + 859500000*[0 0 1 0];
|
||||
%freq_rx = 1912600000*[1 1 1 1];
|
||||
%freq_rx = 859500000*[1 1 1 1];
|
||||
freq_tx = freq_rx-120000000*active_rf;
|
||||
tx_gain = 0*active_rf; %[1 1 1 1];
|
||||
rx_gain = 0*active_rf; %1 1 1 1];
|
||||
rf_local= rf_local*active_rf; %[1 1 1 1];
|
||||
rf_rxdc = rf_rxdc*active_rf; %[1 1 1 1];
|
||||
%rf_vcocal=rf_vcocal_859*[1 1 1 1];
|
||||
rf_vcocal=rf_vcocal_19G*active_rf; %1 1 1 1];
|
||||
eNBflag = 0;
|
||||
tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_TESTRX;
|
||||
%tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_LSB;
|
||||
syncmode = SYNCMODE_FREE;
|
||||
rffe_rxg_low = 31*active_rf; %[1 1 1 1];
|
||||
rffe_rxg_final = 63*active_rf; %[1 1 1 1];
|
||||
rffe_band = B19G_TDD*active_rf; %[1 1 1 1];
|
||||
oarf_config_exmimo(card,freq_rx,freq_tx,tdd_config,syncmode,rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor)
|
||||
|
||||
|
||||
gpib_card=0; % first GPIB PCI card in the computer
|
||||
gpib_device=28; % this is configured in the signal generator Utilities->System
|
||||
cables_loss_dB = 6; % we need to account for the power loss between the signa
|
||||
power_dBm = -95;
|
||||
|
||||
%gpib_send(gpib_card,gpib_device,['POW ' int2str(power_dBm+cables_loss_dB) 'dBm']);
|
||||
%gpib_send(gpib_card,gpib_device,'OUTP:STAT ON'); % activate output
|
||||
|
||||
|
||||
s=oarf_get_frame(card);
|
||||
if (resampling_factor(1)== 2)
|
||||
f0 = (7.68*(0:length(s(:,1))-1)/(length(s(:,1))))-3.84;
|
||||
axis([-3.84,3.84,40,200]);
|
||||
elseif (resampling_factor(1) == 1)
|
||||
f0 = (15.36*(0:length(s(:,1))-1)/(length(s(:,1))))-7.68;
|
||||
axis([-7.68,7.68,40,200]);
|
||||
else
|
||||
f0 = (30.72*(0:length(s(:,1))-1)/(length(s(:,1))))-15.36;
|
||||
axis([-15.36,15.36,40,200]);
|
||||
endif
|
||||
|
||||
|
||||
if (resampling_factor(2)== 2)
|
||||
f1 = (7.68*(0:length(s(:,2))-1)/(length(s(:,2))))-3.84;
|
||||
axis([-3.84,3.84,40,200]);
|
||||
elseif (resampling_factor(2) == 1)
|
||||
f1 = (15.36*(0:length(s(:,2))-1)/(length(s(:,2))))-7.68;
|
||||
axis([-7.68,7.68,40,200]);
|
||||
else
|
||||
f1 = (30.72*(0:length(s(:,2))-1)/(length(s(:,2))))-15.36;
|
||||
axis([-15.36,15.36,40,200]);
|
||||
endif
|
||||
|
||||
if (resampling_factor(3)== 2)
|
||||
f2 = (7.68*(0:length(s(:,3))-1)/(length(s(:,3))))-3.84;
|
||||
axis([-3.84,3.84,40,200]);
|
||||
elseif (resampling_factor(3) == 1)
|
||||
f2 = (15.36*(0:length(s(:,3))-1)/(length(s(:,3))))-7.68;
|
||||
axis([-7.68,7.68,40,200]);
|
||||
else
|
||||
f2 = (30.72*(0:length(s(:,3))-1)/(length(s(:,3))))-15.36;
|
||||
axis([-15.36,15.36,40,200]);
|
||||
endif
|
||||
|
||||
if (resampling_factor(4)== 2)
|
||||
f3 = (7.68*(0:length(s(:,4))-1)/(length(s(:,4))))-3.84;
|
||||
axis([-3.84,3.84,40,200]);
|
||||
elseif (resampling_factor(4) == 1)
|
||||
f3 = (15.36*(0:length(s(:,4))-1)/(length(s(:,4))))-7.68;
|
||||
axis([-7.68,7.68,40,200]);
|
||||
else
|
||||
f3 = (30.72*(0:length(s(:,4))-1)/(length(s(:,4))))-15.36;
|
||||
axis([-15.36,15.36,40,200]);
|
||||
endif
|
||||
|
||||
|
||||
spec0 = 20*log10(abs(fftshift(fft(s(:,1)))));
|
||||
spec1 = 20*log10(abs(fftshift(fft(s(:,2)))));
|
||||
spec2 = 20*log10(abs(fftshift(fft(s(:,3)))));
|
||||
spec3 = 20*log10(abs(fftshift(fft(s(:,4)))));
|
||||
|
||||
clf
|
||||
if (active_rf(1) == 1)
|
||||
hold off;
|
||||
plot(f0',spec0,'r');
|
||||
endif
|
||||
%hold on
|
||||
if (active_rf(2) == 1)
|
||||
hold off;
|
||||
figure;
|
||||
plot(f1',spec1,'b');
|
||||
endif
|
||||
%hold on
|
||||
if (active_rf(3) == 1)
|
||||
hold off;
|
||||
figure;
|
||||
plot(f2',spec2,'g');
|
||||
endif
|
||||
%hold on
|
||||
if (active_rf(4) == 1)
|
||||
hold off;
|
||||
figure;
|
||||
plot(f3',spec3,'m');
|
||||
endif
|
||||
%hold on
|
||||
|
||||
%hold off
|
||||
%axis([-3.84,3.84,40,160]);
|
||||
%gpib_send(gpib_card,gpib_device,'OUTP:STAT OFF'); % activate output
|
||||
%legend('Antenna Port 0','Antenna Port 1','Antenna Port 2','Antenna Port 3');
|
||||
grid
|
||||
@@ -1,170 +0,0 @@
|
||||
dual_tx=0;
|
||||
card0=0;
|
||||
card1=1;
|
||||
limeparms;
|
||||
active_rf = zeros(1,4);
|
||||
active_rf = [1 1 1 1];
|
||||
autocal = [1 1 1 1];
|
||||
resampling_factor = [2 2 2 2];
|
||||
|
||||
%rf_mode = (RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM)*[1 1 1 1];
|
||||
rf_mode = (RXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM)*active_rf;
|
||||
rf_mode = rf_mode+((DMAMODE_RX)*active_rf);
|
||||
%freq_rx = 2540000000*[1 1 1 1];
|
||||
freq_rx = 2600000000*active_rf;
|
||||
%freq_rx = 2680000000*active_rf; %+ 2540000000*[0 1 0 0]; % + 859500000*[0 0 1 0];
|
||||
%freq_rx = 1912600000*[1 1 1 1];
|
||||
%freq_rx = 859500000*[1 1 1 1];
|
||||
freq_tx = freq_rx;
|
||||
tx_gain = 0*active_rf; %[1 1 1 1];
|
||||
rx_gain = 0*active_rf; %1 1 1 1];
|
||||
rf_local= rf_local*active_rf; %[1 1 1 1];
|
||||
rf_rxdc = rf_rxdc*active_rf; %[1 1 1 1];
|
||||
%rf_vcocal=rf_vcocal_859*[1 1 1 1];
|
||||
rf_vcocal=rf_vcocal_19G*active_rf; %1 1 1 1];
|
||||
eNBflag = 0;
|
||||
tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_TESTRX;
|
||||
%tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_LSB;
|
||||
syncmode0 = SYNCMODE_MASTER;
|
||||
syncmode1 = SYNCMODE_SLAVE;
|
||||
rffe_rxg_low = 31*active_rf; %[1 1 1 1];
|
||||
rffe_rxg_final = 63*active_rf; %[1 1 1 1];
|
||||
rffe_band = B19G_TDD*active_rf; %[1 1 1 1];
|
||||
printf('Configuring Card 0\n');
|
||||
oarf_config_exmimo(card0,freq_rx,freq_tx,tdd_config,syncmode0,rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor)
|
||||
sleep(1);
|
||||
printf('Configuring Card 1\n');
|
||||
oarf_config_exmimo(card1,freq_rx,freq_tx,tdd_config,syncmode1,rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor)
|
||||
|
||||
gpib_card=0; % first GPIB PCI card in the computer
|
||||
gpib_device=28; % this is configured in the signal generator Utilities->System
|
||||
cables_loss_dB = 6; % we need to account for the power loss between the signa
|
||||
power_dBm = -95;
|
||||
|
||||
%gpib_send(gpib_card,gpib_device,['POW ' int2str(power_dBm+cables_loss_dB) 'dBm']);
|
||||
%gpib_send(gpib_card,gpib_device,'OUTP:STAT ON'); % activate output
|
||||
%vlen=76800;
|
||||
%v = 5000* [ zeros(1,1000) ones(1,500) zeros(1,500) ones(1,1) zeros(1,vlen-1000-1000-1)]; v=[v;v;v;v]'; oarf_send_frame(1,v,16);
|
||||
%sleep(1)
|
||||
|
||||
s=oarf_get_frame(0);
|
||||
%s1=oarf_get_frame(1);
|
||||
|
||||
%s = [s s1];
|
||||
|
||||
if (resampling_factor(1)== 2)
|
||||
length1 = 76800;
|
||||
f0 = (7.68*(0:length(s(:,1))/4-1)/(length(s(:,1))/4))-3.84;
|
||||
axis([-3.84,3.84,40,200]);
|
||||
elseif (resampling_factor(1) == 1)
|
||||
length1 = 153600;
|
||||
f0 = (15.36*(0:length(s(:,1))/2-1)/(length(s(:,1))/2))-7.68;
|
||||
axis([-7.68,7.68,40,200]);
|
||||
else
|
||||
length1 = 307200;
|
||||
f0 = (30.72*(0:length(s(:,1))-1)/(length(s(:,1))))-15.36;
|
||||
axis([-15.36,15.36,40,200]);
|
||||
endif
|
||||
|
||||
|
||||
if (resampling_factor(2)== 2)
|
||||
length2 = 76800;
|
||||
f1 = (7.68*(0:length(s(:,2))/4-1)/(length(s(:,2))/4))-3.84;
|
||||
axis([-3.84,3.84,40,200]);
|
||||
elseif (resampling_factor(2) == 1)
|
||||
length2 = 153600;
|
||||
f1 = (15.36*(0:length(s(:,2))/2-1)/(length(s(:,2))/2))-7.68;
|
||||
axis([-7.68,7.68,40,200]);
|
||||
else
|
||||
length2 = 307200;
|
||||
f1 = (30.72*(0:length(s(:,2))-1)/(length(s(:,2))))-15.36;
|
||||
axis([-15.36,15.36,40,200]);
|
||||
endif
|
||||
|
||||
if (resampling_factor(3)== 2)
|
||||
length3 = 76800;
|
||||
f2 = (7.68*(0:length(s(:,3))/4-1)/(length(s(:,3))/4))-3.84;
|
||||
axis([-3.84,3.84,40,200]);
|
||||
elseif (resampling_factor(3) == 1)
|
||||
length3 = 153600;
|
||||
f2 = (15.36*(0:length(s(:,3))/2-1)/(length(s(:,3))/2))-7.68;
|
||||
axis([-7.68,7.68,40,200]);
|
||||
else
|
||||
length3 = 307200;
|
||||
f2 = (30.72*(0:length(s(:,3))-1)/(length(s(:,3))))-15.36;
|
||||
axis([-15.36,15.36,40,200]);
|
||||
endif
|
||||
|
||||
if (resampling_factor(4)== 2)
|
||||
length4 = 76800;
|
||||
f3 = (7.68*(0:length(s(:,4))/4-1)/(length(s(:,4))/4))-3.84;
|
||||
axis([-3.84,3.84,40,200]);
|
||||
elseif (resampling_factor(4) == 1)
|
||||
length4 = 153600;
|
||||
f3 = (15.36*(0:length(s(:,4))/2-1)/(length(s(:,4))/2))-7.68;
|
||||
axis([-7.68,7.68,40,200]);
|
||||
else
|
||||
length4 = 307200;
|
||||
f3 = (30.72*(0:length(s(:,4))-1)/(length(s(:,4))))-15.36;
|
||||
axis([-15.36,15.36,40,200]);
|
||||
endif
|
||||
|
||||
length_slave = 76800;
|
||||
|
||||
spec0 = 20*log10(abs(fftshift(fft(s(1:length1,1)))));
|
||||
spec1 = 20*log10(abs(fftshift(fft(s(1:length2,2)))));
|
||||
spec2 = 20*log10(abs(fftshift(fft(s(1:length3,3)))));
|
||||
spec3 = 20*log10(abs(fftshift(fft(s(1:length4,4)))));
|
||||
spec4 = 20*log10(abs(fftshift(fft(s(1:length_slave,5)))));
|
||||
spec5 = 20*log10(abs(fftshift(fft(s(1:length_slave,6)))));
|
||||
spec6 = 20*log10(abs(fftshift(fft(s(1:length_slave,7)))));
|
||||
spec7 = 20*log10(abs(fftshift(fft(s(1:length_slave,8)))));
|
||||
|
||||
axis_time = [1:76800*4];
|
||||
|
||||
|
||||
clf
|
||||
if (active_rf(1) == 1)
|
||||
hold off;
|
||||
plot(f0',spec0,'r');
|
||||
figure
|
||||
plot(f0',spec4,'b');
|
||||
endif
|
||||
%hold on
|
||||
if (active_rf(2) == 1)
|
||||
hold off;
|
||||
figure;
|
||||
plot(f1',spec1,'b');
|
||||
endif
|
||||
%hold on
|
||||
if (active_rf(3) == 1)
|
||||
hold off;
|
||||
figure;
|
||||
plot(f2',spec2,'g');
|
||||
endif
|
||||
%hold on
|
||||
if (active_rf(4) == 1)
|
||||
hold off;
|
||||
figure;
|
||||
plot(f3',spec3,'m');
|
||||
endif
|
||||
%hold on
|
||||
hold off;
|
||||
figure;
|
||||
plot(real(s(1:length1,1)),'r');
|
||||
hold on
|
||||
plot(real(s(1:length_slave,5)),'b');
|
||||
hold off;
|
||||
figure;
|
||||
plot(imag(s(1:length1,1)),'r');
|
||||
hold on
|
||||
plot(imag(s(1:length_slave,5)),'b');
|
||||
|
||||
|
||||
%len=2500;off=0; chan=[1 5]; hold off ; figure; plot(real(s(off+1:off+len,chan)),'-o',"markersize",2) ; hold off ; figure; plot(imag(s(off+1:off+len,chan)),'r-o',"markersize",2);
|
||||
|
||||
%hold off
|
||||
%axis([-3.84,3.84,40,160]);
|
||||
%gpib_send(gpib_card,gpib_device,'OUTP:STAT OFF'); % activate output
|
||||
%legend('Antenna Port 0','Antenna Port 1','Antenna Port 2','Antenna Port 3');
|
||||
grid
|
||||
@@ -1,137 +0,0 @@
|
||||
fc = 2560000000
|
||||
%fc = 1907600000;
|
||||
%fc = 859.5e6;
|
||||
|
||||
rxgain=0;
|
||||
txgain=0;
|
||||
eNB_flag = 0;
|
||||
card = 0;
|
||||
active_rf = [1 0 0 0];
|
||||
autocal = [1 1 1 1];
|
||||
resampling_factor = [2 2 2 2];
|
||||
limeparms;
|
||||
rf_mode = (RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM) * active_rf;
|
||||
rf_mode = rf_mode + (DMAMODE_RX + DMAMODE_TX)*active_rf;
|
||||
%rf_mode = rf_mode + (DMAMODE_TX)*active_rf + DMAMODE_RX*active_rf;
|
||||
%rf_mode = RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAByp+RFBBLNA1;
|
||||
%rf_local= [8253704 8253704 8257340 8257340]; %eNB2tx %850MHz
|
||||
%rf_local= [8255004 8253440 8257340 8257340]; % ex2 700 MHz
|
||||
rf_local = [8254744 8255063 8257340 8257340]; %eNB2tx 1.9GHz
|
||||
%rf_local = [8257292 8257300 8257340 8257340]; %ex2 850 MHz
|
||||
%rf_local = rf_local * chan_sel;
|
||||
rf_rxdc = rf_rxdc * active_rf;
|
||||
%rf_vcocal = rf_vcocal_859 * chan_sel;
|
||||
rf_vcocal = rf_vcocal_19G * active_rf;
|
||||
%rf_vcocal = rf_vcocal_26G_eNB * chan_sel;
|
||||
rxgain = rxgain*active_rf;
|
||||
txgain = txgain*active_rf;
|
||||
freq_tx = fc.*active_rf;
|
||||
freq_rx = freq_tx;
|
||||
%freq_rx = freq_tx-120000000*chan_sel;
|
||||
%freq_tx = freq_rx+1920000;
|
||||
%tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_LSB;
|
||||
tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_TESTTX;
|
||||
syncmode = SYNCMODE_FREE;
|
||||
rffe_rxg_low = 61*[1 1 1 1];
|
||||
rffe_rxg_final = 61*[1 1 1 1];
|
||||
rffe_band = B19G_TDD*[1 1 1 1];
|
||||
|
||||
oarf_config_exmimo(card, freq_rx,freq_tx,tdd_config,syncmode,rxgain,txgain,eNB_flag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor);
|
||||
%oarf_config_exmimo(1, freq_rx,freq_tx,tdd_config,syncmode,rxgain,txgain,eNB_flag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor);
|
||||
amp = pow2(10)-1;
|
||||
n_bit = 16;
|
||||
|
||||
length = 307200/pow2(resampling_factor(1));
|
||||
|
||||
s = zeros(length,4);
|
||||
|
||||
select = 7;
|
||||
|
||||
switch(select)
|
||||
|
||||
case 0
|
||||
s(:,1) = amp * ones(1,length);
|
||||
s(:,2) = amp * ones(1,length);
|
||||
s(:,3) = amp * ones(1,length);
|
||||
s(:,4) = amp * ones(1,length);
|
||||
|
||||
case 1
|
||||
s(:,1) = floor(amp * (exp(1i*2*pi*(0:((length)-1))/4)));
|
||||
s(:,2) = floor(amp * (exp(1i*2*pi*(0:((length)-1))/4)));
|
||||
s(:,3) = floor(amp * (exp(1i*2*pi*(0:((length)-1))/4)));
|
||||
s(:,4) = floor(amp * (exp(1i*2*pi*(0:((length)-1))/4)));
|
||||
|
||||
case 2
|
||||
s(38400+128,1)= 80-1j*40;
|
||||
s(38400+138,1)= -80+1j*40;
|
||||
|
||||
case 3
|
||||
for i=0:(12*5-1)
|
||||
s((38401+640*i):(38400+640*(i+1)),1)=floor(linspace(-127,128,640)); %+1j*floor(linspace(128,-127,640));
|
||||
end
|
||||
|
||||
case 4
|
||||
pss0_f0=[0,0,0,0,0,0,0,0,0,0,32767,0,-26120,-19785,11971,-30502,-24020,-22288,32117,6492,31311,9658,-16384,-28378,25100,-21063,-7292,-31946,20429,25618,14948,29158,11971,-30502,31311,9658,25100,-21063,-16384,28377,-24020,22287,32117,6492,-7292,31945,20429,25618,-26120,-19785,-16384,-28378,-16384,28377,-26120,-19785,-32402,4883,31311,-9659,32117,6492,-7292,-31946,32767,-1,25100,-21063,-24020,22287,-32402,4883,-32402,4883,-24020,22287,25100,-21063,32767,-1,-7292,-31946,32117,6492,31311,-9659,-32402,4883,-26120,-19785,-16384,28377,-16384,-28378,-26120,-19785,20429,25618,-7292,31945,32117,6492,-24020,22287,-16384,28377,25100,-21063,31311,9658,11971,-30502,14948,29158,20429,25618,-7292,-31946,25100,-21063,-16384,-28378,31311,9658,32117,6492,-24020,-22288,11971,-30502,-26120,-19785,32767,0,0,0,0,0,0,0,0,0,0,0];
|
||||
|
||||
%pss0_f = pss0_f0(1:2:length(pss0_f0)) + sqrt(-1)*pss0_f0(2:2:length(pss0_f0));
|
||||
pss0_f = pss0_f0(1:2:size(pss0_f0,2)) + sqrt(-1)*pss0_f0(2:2:size(pss0_f0,2));
|
||||
|
||||
pss0_f = [0 pss0_f(37:72) zeros(1,512-73) pss0_f(1:36)];
|
||||
pss0_t = ifft(pss0_f);
|
||||
pss0_t = [pss0_t((512-127):512) pss0_t];
|
||||
pss0_t = [pss0_t zeros(1,512+36) pss0_t];
|
||||
pss0_max = max(max(abs(real(pss0_t))),max(abs(imag(pss0_t))));
|
||||
|
||||
pss0_t_fp_re = floor(real(8192*pss0_t/pss0_max));
|
||||
pss0_t_fp_im = floor(imag(8192*pss0_t/pss0_max));
|
||||
|
||||
%keyboard;
|
||||
s(38400+(1:length(pss0_t_fp_re)),1) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
|
||||
s(38400+(1:length(pss0_t_fp_re)),2) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
|
||||
s(38400+(1:length(pss0_t_fp_re)),3) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
|
||||
s(38400+(1:length(pss0_t_fp_re)),4) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
|
||||
%s(38400+(1:size(pss0_t_fp_re,2)),1) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
|
||||
%s(38400+(1:size(pss0_t_fp_re,2)),2) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
|
||||
%s(38400+(1:size(pss0_t_fp_re,2)),3) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
|
||||
%s(38400+(1:size(pss0_t_fp_re,2)),4) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
|
||||
|
||||
case 5
|
||||
x=1:length;
|
||||
|
||||
s(:,1) = 1i*8*(mod(x-1,4096)); % + 1i*(8*(mod(x-1,4096)));
|
||||
s(:,2) = 8*(mod(x-1,4096)) + 1i*(8*(mod(x-1,4096)));
|
||||
s(:,3) = 8*(mod(x-1,4096)) + 1i*(8*(mod(x-1,4096)));
|
||||
s(:,4) = 8*(mod(x-1,4096)) + 1i*(8*(mod(x-1,4096)));
|
||||
|
||||
case 6
|
||||
|
||||
nb_rb = 100; %this can be 25, 50, or 100
|
||||
num_carriers = 2048/100*nb_rb;
|
||||
num_zeros = num_carriers-(12*nb_rb+1);
|
||||
prefix_length = num_carriers/4; %this is extended CP
|
||||
num_symbols_frame = 120;
|
||||
preamble_length = 120;
|
||||
|
||||
s(:,1) = OFDM_TX_FRAME(num_carriers,num_zeros,prefix_length,num_symbols_frame,preamble_length);
|
||||
s(:,1) = floor(amp*(s(:,1)./max([real(s(:,1)); imag(s(:,1))])));
|
||||
|
||||
case 7
|
||||
s(:,1) = floor(txs0);
|
||||
|
||||
otherwise
|
||||
error('unknown case')
|
||||
|
||||
end %switch
|
||||
|
||||
s = s*2;
|
||||
|
||||
oarf_send_frame(card,s,n_bit);
|
||||
%oarf_send_frame(1,s,n_bit);
|
||||
%sleep (1)
|
||||
%r = oarf_get_frame(card);
|
||||
|
||||
figure(1)
|
||||
hold off
|
||||
plot(real(s(:,1)),'r')
|
||||
%hold on
|
||||
%plot(imag(s(:,2)),'b')
|
||||
@@ -1,121 +0,0 @@
|
||||
%fc = 2660000000;
|
||||
fc = 1907600000;
|
||||
%fc = 859.5e6;
|
||||
|
||||
rxgain=0;
|
||||
txgain=25;
|
||||
eNB_flag = 0;
|
||||
card = 0;
|
||||
active_rf = [1 1 0 0];
|
||||
autocal = [1 1 1 1];
|
||||
resampling_factor = [2 2 2 2];
|
||||
limeparms;
|
||||
rf_mode = (RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM) * active_rf;
|
||||
rf_mode = rf_mode + (DMAMODE_RX + DMAMODE_TX)*active_rf;
|
||||
%rf_mode = RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAByp+RFBBLNA1;
|
||||
%rf_local= [8253704 8253704 8257340 8257340]; %eNB2tx %850MHz
|
||||
%rf_local= [8255004 8253440 8257340 8257340]; % ex2 700 MHz
|
||||
rf_local = [8254744 8255063 8257340 8257340]; %eNB2tx 1.9GHz
|
||||
%rf_local = [8257292 8257300 8257340 8257340]; %ex2 850 MHz
|
||||
%rf_local = rf_local * chan_sel;
|
||||
rf_rxdc = rf_rxdc * active_rf;
|
||||
%rf_vcocal = rf_vcocal_859 * chan_sel;
|
||||
rf_vcocal = rf_vcocal_19G * active_rf;
|
||||
%rf_vcocal = rf_vcocal_26G_eNB * chan_sel;
|
||||
rxgain = rxgain*active_rf;
|
||||
txgain = txgain*active_rf;
|
||||
freq_tx = fc*active_rf;
|
||||
freq_rx = freq_tx;
|
||||
%freq_rx = freq_tx-120000000*chan_sel;
|
||||
%freq_tx = freq_rx+1920000;
|
||||
tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_TESTTX;
|
||||
syncmode0 = SYNCMODE_MASTER;
|
||||
syncmode1 = SYNCMODE_SLAVE;
|
||||
rffe_rxg_low = 61*[1 1 1 1];
|
||||
rffe_rxg_final = 61*[1 1 1 1];
|
||||
rffe_band = B19G_TDD*[1 1 1 1];
|
||||
|
||||
oarf_config_exmimo(0, freq_rx,freq_tx,tdd_config,syncmode0,rxgain,txgain,eNB_flag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor);
|
||||
sleep(1);
|
||||
oarf_config_exmimo(1, freq_rx,freq_tx,tdd_config,syncmode1,rxgain,txgain,eNB_flag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor);
|
||||
amp = pow2(14)-1;
|
||||
n_bit = 16;
|
||||
|
||||
s = zeros(76800*4,4);
|
||||
|
||||
select = 1;
|
||||
|
||||
switch(select)
|
||||
|
||||
case 1
|
||||
s(:,1) = floor(amp * (exp(1i*2*pi*(0:((76800*4)-1))/7680)));
|
||||
s(:,2) = floor(amp * (exp(1i*2*pi*(0:((76800*4)-1))/7680)));
|
||||
s(:,3) = floor(amp * (exp(1i*2*pi*(0:((76800*4)-1))/7680)));
|
||||
s(:,4) = floor(amp * (exp(1i*2*pi*(0:((76800*4)-1))/7680)));
|
||||
|
||||
case 2
|
||||
s(38400+128,1)= 80-1j*40;
|
||||
s(38400+138,1)= -80+1j*40;
|
||||
|
||||
case 3
|
||||
for i=0:(12*5-1)
|
||||
s((38401+640*i):(38400+640*(i+1)),1)=floor(linspace(-127,128,640)); %+1j*floor(linspace(128,-127,640));
|
||||
end
|
||||
|
||||
case 4
|
||||
pss0_f0=[0,0,0,0,0,0,0,0,0,0,32767,0,-26120,-19785,11971,-30502,-24020,-22288,32117,6492,31311,9658,-16384,-28378,25100,-21063,-7292,-31946,20429,25618,14948,29158,11971,-30502,31311,9658,25100,-21063,-16384,28377,-24020,22287,32117,6492,-7292,31945,20429,25618,-26120,-19785,-16384,-28378,-16384,28377,-26120,-19785,-32402,4883,31311,-9659,32117,6492,-7292,-31946,32767,-1,25100,-21063,-24020,22287,-32402,4883,-32402,4883,-24020,22287,25100,-21063,32767,-1,-7292,-31946,32117,6492,31311,-9659,-32402,4883,-26120,-19785,-16384,28377,-16384,-28378,-26120,-19785,20429,25618,-7292,31945,32117,6492,-24020,22287,-16384,28377,25100,-21063,31311,9658,11971,-30502,14948,29158,20429,25618,-7292,-31946,25100,-21063,-16384,-28378,31311,9658,32117,6492,-24020,-22288,11971,-30502,-26120,-19785,32767,0,0,0,0,0,0,0,0,0,0,0];
|
||||
|
||||
pss0_f = pss0_f0(1:2:length(pss0_f0)) + sqrt(-1)*pss0_f0(2:2:length(pss0_f0));
|
||||
|
||||
pss0_f = [0 pss0_f(37:72) zeros(1,512-73) pss0_f(1:36)];
|
||||
pss0_t = ifft(pss0_f);
|
||||
pss0_t = [pss0_t((512-127):512) pss0_t];
|
||||
pss0_t = [pss0_t zeros(1,512+36) pss0_t];
|
||||
pss0_max = max(max(abs(real(pss0_t))),max(abs(imag(pss0_t))));
|
||||
|
||||
pss0_t_fp_re = floor(real(8192*pss0_t/pss0_max));
|
||||
pss0_t_fp_im = floor(imag(8192*pss0_t/pss0_max));
|
||||
|
||||
s(38400+(1:length(pss0_t_fp_re)),1) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
|
||||
s(38400+(1:length(pss0_t_fp_re)),2) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
|
||||
s(38400+(1:length(pss0_t_fp_re)),3) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
|
||||
s(38400+(1:length(pss0_t_fp_re)),4) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
|
||||
case 5
|
||||
x=1:76800;
|
||||
|
||||
s(:,1) = 1i*8*(mod(x-1,4096)); % + 1i*(8*(mod(x-1,4096)));
|
||||
s(:,2) = 8*(mod(x-1,4096)) + 1i*(8*(mod(x-1,4096)));
|
||||
s(:,3) = 8*(mod(x-1,4096)) + 1i*(8*(mod(x-1,4096)));
|
||||
s(:,4) = 8*(mod(x-1,4096)) + 1i*(8*(mod(x-1,4096)));
|
||||
% s(:,4) = 8*(rem(x-1,2048))-2**15 + 1i*(8*(rem(x-1,2048))-2**15);
|
||||
|
||||
% s(:,4) = 8*(mod(x-1,4096)) + 1i*8*(mod(x-1,4096));
|
||||
|
||||
%s(:,1) = 8*floor(mod(x-1,76800)/75) + 1i*8*floor(mod(x-1,76800)/75);
|
||||
%s(:,2) = 8*floor(mod(x-1,76800)/75) + 1i*8*floor(mod(x-1,76800)/75);
|
||||
%s(:,3) = 8*floor(mod(x-1,76800)/75) + 1i*8*floor(mod(x-1,76800)/75);
|
||||
%s(:,4) = 8*floor(mod(x-1,76800)/75) + 1i*8*floor(mod(x-1,76800)/75);
|
||||
|
||||
otherwise
|
||||
error('unknown case')
|
||||
endswitch
|
||||
|
||||
%s = s*2 - 2**15 -1i*(2**15);
|
||||
s = s*2;
|
||||
|
||||
|
||||
%s(38400:end,1) = (1+1j);
|
||||
%s(38400:end,2) = (1+1j);
|
||||
|
||||
sleep (1)
|
||||
%keyboard
|
||||
|
||||
oarf_send_frame(0,s,n_bit);
|
||||
sleep(1);
|
||||
oarf_send_frame(1,s,n_bit);
|
||||
%r = oarf_get_frame(card);
|
||||
figure(1)
|
||||
hold off
|
||||
plot(real(s(:,1)),'r')
|
||||
%hold on
|
||||
%plot(imag(s(:,2)),'b')
|
||||
@@ -1,27 +0,0 @@
|
||||
dual_tx=1;
|
||||
cbmimo1=0;
|
||||
|
||||
if (cbmimo1)
|
||||
oarf_config(0,1,dual_tx,255);
|
||||
amp = pow2(7)-1;
|
||||
n_bit = 8;
|
||||
else
|
||||
oarf_config_exmimo(1902600000,1,dual_tx,30);
|
||||
amp = pow2(15)-1;
|
||||
n_bit = 16;
|
||||
end
|
||||
|
||||
s = zeros(76800,2);
|
||||
s(:,1) = 8*floor(amp*OFDM_TX_FRAME(512,211,128,120,8));
|
||||
s(:,2) = 8*floor(amp*OFDM_TX_FRAME(512,211,128,120,8));
|
||||
|
||||
|
||||
%s(:,1) = amp * (exp(sqrt(-1)*.5*pi*(0:((76800)-1))));
|
||||
%s(:,2) = amp * (exp(sqrt(-1)*.5*pi*(0:((76800)-1))));
|
||||
|
||||
if (cbmimo1)
|
||||
oarf_set_tx_gain(110,110,110,110);
|
||||
end
|
||||
oarf_send_frame(0,s,n_bit);
|
||||
|
||||
plot(20*log10(abs(fft(s(:,1)))))
|
||||
@@ -1,210 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include "common_lib.h"
|
||||
#include "ethernet_lib.h"
|
||||
|
||||
#include "mobipass.h"
|
||||
#include "queues.h"
|
||||
|
||||
struct mobipass_header {
|
||||
uint16_t flags;
|
||||
uint16_t fifo_status;
|
||||
unsigned char seqno;
|
||||
unsigned char ack;
|
||||
uint32_t word0;
|
||||
uint32_t timestamp;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
int mobipass_start(openair0_device *device) { init_mobipass(device->priv); return 0; }
|
||||
int mobipass_request(openair0_device *device, void *msg, ssize_t msg_len) { abort(); return 0; }
|
||||
int mobipass_reply(openair0_device *device, void *msg, ssize_t msg_len) { abort(); return 0; }
|
||||
int mobipass_get_stats(openair0_device* device) { return 0; }
|
||||
int mobipass_reset_stats(openair0_device* device) { return 0; }
|
||||
void mobipass_end(openair0_device *device) {}
|
||||
int mobipass_stop(openair0_device *device) { return 0; }
|
||||
int mobipass_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config) { return 0; }
|
||||
int mobipass_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) { return 0; }
|
||||
|
||||
int mobipass_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
|
||||
mobipass_state_t *mobi = device->priv;
|
||||
struct mobipass_header *mh = (struct mobipass_header *)(((char *)buff[0]) + 14);
|
||||
mobi->mobipass_write_last_timestamp += 640;
|
||||
mobi->mobipass_write_last_timestamp %= mobi->samples_per_1024_frames;
|
||||
mh->timestamp = htonl(ntohl(mh->timestamp) % mobi->samples_per_1024_frames);
|
||||
if (mobi->mobipass_write_last_timestamp != ntohl(mh->timestamp))
|
||||
{ printf("mobipass: ERROR: bad timestamp wanted %d got %d\n", mobi->mobipass_write_last_timestamp, ntohl(mh->timestamp)); exit(1); }
|
||||
//printf("__write nsamps %d timestamps %ld seqno %d (packet timestamp %d)\n", nsamps, timestamp, mh->seqno, ntohl(mh->timestamp));
|
||||
if (nsamps != 640) abort();
|
||||
enqueue_to_mobipass(mobi->qstate, buff[0]);
|
||||
return nsamps;
|
||||
}
|
||||
|
||||
int mobipass_read(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
|
||||
mobipass_state_t *mobi = device->priv;
|
||||
//printf("__read nsamps %d return timestamp %d\n", nsamps, ts);
|
||||
*timestamp = htonl(mobi->mobipass_read_ts);
|
||||
mobi->mobipass_read_ts += nsamps;
|
||||
mobi->mobipass_read_ts %= mobi->samples_per_1024_frames;
|
||||
if (nsamps != 640) { printf("mobipass: ERROR: bad nsamps %d, should be 640\n", nsamps); fflush(stdout); abort(); }
|
||||
|
||||
dequeue_from_mobipass(mobi->qstate, ntohl(*timestamp), buff[0]);
|
||||
|
||||
#if 1
|
||||
struct mobipass_header *mh = (struct mobipass_header *)(((char *)buff[0]) + 14);
|
||||
mh->flags = 0;
|
||||
mh->fifo_status = 0;
|
||||
mh->seqno = mobi->mobipass_read_seqno++;
|
||||
mh->ack = 0;
|
||||
mh->word0 = 0;
|
||||
mh->timestamp = htonl(mobi->mobipass_read_ts);
|
||||
#endif
|
||||
|
||||
return nsamps;
|
||||
}
|
||||
|
||||
/* this is the only function in the library that is visible from outside
|
||||
* because in CMakeLists.txt we use -fvisibility=hidden
|
||||
*/
|
||||
__attribute__((__visibility__("default")))
|
||||
int transport_init(openair0_device *device, openair0_config_t *openair0_cfg,
|
||||
eth_params_t * eth_params )
|
||||
{
|
||||
//init_mobipass();
|
||||
|
||||
mobipass_state_t *mobi = (mobipass_state_t*)malloc(sizeof(mobipass_state_t));
|
||||
memset(mobi, 0, sizeof(mobipass_state_t));
|
||||
|
||||
if (eth_params->transp_preference != 4) goto err;
|
||||
if (eth_params->if_compress != 0) goto err;
|
||||
|
||||
/* only 50 PRBs handled for the moment */
|
||||
if (openair0_cfg[0].sample_rate != 15360000) {
|
||||
printf("mobipass: ERROR: only 50 PRBs supported\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mobi->eth.flags = ETH_RAW_IF5_MOBIPASS;
|
||||
mobi->eth.compression = NO_COMPRESS;
|
||||
device->Mod_id = 0;//num_devices_eth++;
|
||||
device->transp_type = ETHERNET_TP;
|
||||
|
||||
device->trx_start_func = mobipass_start;
|
||||
device->trx_request_func = mobipass_request;
|
||||
device->trx_reply_func = mobipass_reply;
|
||||
device->trx_get_stats_func = mobipass_get_stats;
|
||||
device->trx_reset_stats_func = mobipass_reset_stats;
|
||||
device->trx_end_func = mobipass_end;
|
||||
device->trx_stop_func = mobipass_stop;
|
||||
device->trx_set_freq_func = mobipass_set_freq;
|
||||
device->trx_set_gains_func = mobipass_set_gains;
|
||||
device->trx_write_func = mobipass_write;
|
||||
device->trx_read_func = mobipass_read;
|
||||
|
||||
device->priv = mobi;
|
||||
|
||||
mobi->eth.if_name = strdup(eth_params->local_if_name);
|
||||
if (mobi->eth.if_name == NULL) abort();
|
||||
|
||||
if (sscanf(eth_params->my_addr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
||||
&mobi->eth_local[0],
|
||||
&mobi->eth_local[1],
|
||||
&mobi->eth_local[2],
|
||||
&mobi->eth_local[3],
|
||||
&mobi->eth_local[4],
|
||||
&mobi->eth_local[5]) != 6) {
|
||||
printf("mobipass: ERROR: bad local ethernet address '%s', check configuration file\n",
|
||||
eth_params->my_addr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sscanf(eth_params->remote_addr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
||||
&mobi->eth_remote[0],
|
||||
&mobi->eth_remote[1],
|
||||
&mobi->eth_remote[2],
|
||||
&mobi->eth_remote[3],
|
||||
&mobi->eth_remote[4],
|
||||
&mobi->eth_remote[5]) != 6) {
|
||||
printf("mobipass: ERROR: bad remote ethernet address '%s', check configuration file\n",
|
||||
eth_params->remote_addr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* note: this only works for 50 PRBs */
|
||||
mobi->samples_per_1024_frames = 7680*2*10*1024;
|
||||
|
||||
/* TX starts at subframe 4, let's pretend we are at the right position */
|
||||
/* note: this only works for 50 PRBs */
|
||||
mobi->mobipass_write_last_timestamp = 4*7680*2-640;
|
||||
|
||||
/* device specific */
|
||||
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
|
||||
openair0_cfg[0].iq_txshift = eth_params->iq_txshift;// shift
|
||||
openair0_cfg[0].tx_sample_advance = eth_params->tx_sample_advance;
|
||||
|
||||
/* this is useless, I think */
|
||||
if (device->host_type == BBU_HOST) {
|
||||
/*Note scheduling advance values valid only for case 7680000 */
|
||||
switch ((int)openair0_cfg[0].sample_rate) {
|
||||
case 30720000:
|
||||
openair0_cfg[0].samples_per_packet = 3840;
|
||||
break;
|
||||
case 23040000:
|
||||
openair0_cfg[0].samples_per_packet = 2880;
|
||||
break;
|
||||
case 15360000:
|
||||
openair0_cfg[0].samples_per_packet = 1920;
|
||||
break;
|
||||
case 7680000:
|
||||
openair0_cfg[0].samples_per_packet = 960;
|
||||
break;
|
||||
case 1920000:
|
||||
openair0_cfg[0].samples_per_packet = 240;
|
||||
break;
|
||||
default:
|
||||
printf("mobipass: ERROR: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
|
||||
exit(-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
device->openair0_cfg=&openair0_cfg[0];
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
printf("mobipass: ERROR: bad configuration file?\n");
|
||||
exit(1);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user