/******************************************************************************* OpenAirInterface Copyright(c) 1999 - 2014 Eurecom OpenAirInterface is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenAirInterface is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenAirInterface.The full GNU General Public License is included in this distribution in the file called "COPYING". If not, see . Contact Information OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE *******************************************************************************/ /** openair0_lib : API to interface with ExpressMIMO-1&2 kernel driver * * Authors: Matthias Ihmig , 2013 * Raymond Knopp * * Changelog: * 28.01.2013: Initial version */ #include #include #include #include #include #include #include #include "openair0_lib.h" #include "openair_device.h" #include "common_lib.h" #define max(a,b) ((a)>(b) ? (a) : (b)) exmimo_pci_interface_bot_virtual_t openair0_exmimo_pci[MAX_CARDS]; // contains userspace pointers for each card char *bigshm_top[MAX_CARDS] = INIT_ZEROS; int openair0_fd; int openair0_num_antennas[MAX_CARDS]; int openair0_num_detected_cards = 0; unsigned int PAGE_SHIFT; static uint32_t rf_local[4] = {8255000,8255000,8255000,8255000}; // UE zepto //{8254617, 8254617, 8254617, 8254617}; //eNB khalifa //{8255067,8254810,8257340,8257340}; // eNB PETRONAS static uint32_t rf_vcocal[4] = {910,910,910,910}; static uint32_t rf_vcocal_850[4] = {2015, 2015, 2015, 2015}; static uint32_t rf_rxdc[4] = {32896,32896,32896,32896}; unsigned int log2_int( unsigned int x ) { unsigned int ans = 0 ; while( x>>=1 ) ans++; return ans ; } int openair0_open(void) { exmimo_pci_interface_bot_virtual_t exmimo_pci_kvirt[MAX_CARDS]; void *bigshm_top_kvirtptr[MAX_CARDS]; int card; int ant; PAGE_SHIFT = log2_int( sysconf( _SC_PAGESIZE ) ); if ((openair0_fd = open("/dev/openair0", O_RDWR,0)) <0) { return -1; } ioctl(openair0_fd, openair_GET_NUM_DETECTED_CARDS, &openair0_num_detected_cards); if ( openair0_num_detected_cards == 0 ) { fprintf(stderr, "No cards detected!\n"); return -4; } ioctl(openair0_fd, openair_GET_BIGSHMTOPS_KVIRT, &bigshm_top_kvirtptr[0]); ioctl(openair0_fd, openair_GET_PCI_INTERFACE_BOTS_KVIRT, &exmimo_pci_kvirt[0]); //printf("bigshm_top_kvirtptr (MAX_CARDS %d): %p %p %p %p\n", MAX_CARDS,bigshm_top_kvirtptr[0], bigshm_top_kvirtptr[1], bigshm_top_kvirtptr[2], bigshm_top_kvirtptr[3]); for( card=0; card < openair0_num_detected_cards; card++) { bigshm_top[card] = (char *)mmap( NULL, BIGSHM_SIZE_PAGES<board_swrev != BOARD_SWREV_CNTL2) { error("Software revision %d and firmware revision %d do not match, Please update either Software or Firmware",BOARD_SWREV_CNTL2,openair0_exmimo_pci[card].exmimo_id_ptr->board_swrev); return -5; } */ if ( openair0_exmimo_pci[card].exmimo_id_ptr->board_exmimoversion == 1) openair0_num_antennas[card] = 2; if ( openair0_exmimo_pci[card].exmimo_id_ptr->board_exmimoversion == 2) openair0_num_antennas[card] = 4; for (ant=0; antboard_exmimoversion, openair0_exmimo_pci[card].exmimo_id_ptr->board_hwrev, openair0_exmimo_pci[card].exmimo_id_ptr->board_swrev, openair0_num_antennas[card]); } // end for(card) return 0; } int openair0_close(void) { int ant; int card; close(openair0_fd); for (card=0; cardMAX_CARDS) { printf ("Detected %d number of cards, but MAX_CARDS=%d\n", openair0_num_detected_cards, MAX_CARDS); } else { printf ("Detected %d number of cards, %d number of antennas.\n", openair0_num_detected_cards, openair0_num_antennas[0]); } // p_exmimo_config = openair0_exmimo_pci[0].exmimo_config_ptr; p_exmimo_id = openair0_exmimo_pci[0].exmimo_id_ptr; printf("Card %d: ExpressMIMO %d, HW Rev %d, SW Rev 0x%d\n", 0, p_exmimo_id->board_exmimoversion, p_exmimo_id->board_hwrev, p_exmimo_id->board_swrev); // check if the software matches firmware if (p_exmimo_id->board_swrev!=BOARD_SWREV_CNTL2) { printf("Software revision %d and firmware revision %d do not match. Please update either the firmware or the software!\n",BOARD_SWREV_CNTL2,p_exmimo_id->board_swrev); return(-1); } device->type = EXMIMO_DEV; return(0); } int openair0_config(openair0_config_t *openair0_cfg, int UE_flag) { int ret; int ant, card; int resampling_factor=2; int rx_filter=RXLPF25, tx_filter=TXLPF25; exmimo_config_t *p_exmimo_config; exmimo_id_t *p_exmimo_id; if (!openair0_cfg) { printf("Error, openair0_cfg is null!!\n"); return(-1); } for (card=0; cardboard_swrev>=9) p_exmimo_config->framing.eNB_flag = 0; else p_exmimo_config->framing.eNB_flag = !UE_flag; p_exmimo_config->framing.tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_LSB; if (openair0_num_detected_cards==1) p_exmimo_config->framing.multicard_syncmode=SYNCMODE_FREE; else if (card==0) p_exmimo_config->framing.multicard_syncmode=SYNCMODE_MASTER; else p_exmimo_config->framing.multicard_syncmode=SYNCMODE_SLAVE; if (openair0_cfg[card].sample_rate==30.72e6) { resampling_factor = 0; rx_filter = RXLPF10; tx_filter = TXLPF10; } else if (openair0_cfg[card].sample_rate==15.36e6) { resampling_factor = 1; rx_filter = RXLPF5; tx_filter = TXLPF5; } else if (openair0_cfg[card].sample_rate==7.68e6) { resampling_factor = 2; rx_filter = RXLPF25; tx_filter = TXLPF25; } else { printf("Sampling rate not supported, using default 7.68MHz"); resampling_factor = 2; rx_filter = RXLPF25; tx_filter = TXLPF25; } #if (BOARD_SWREV_CNTL2>=0x0A) for (ant=0; ant<4; ant++) p_exmimo_config->framing.resampling_factor[ant] = resampling_factor; #else p_exmimo_config->framing.resampling_factor = resampling_factor; #endif for (ant=0; ant<4; ant++) { if (openair0_cfg[card].rx_freq[ant] || openair0_cfg[card].tx_freq[ant]) { p_exmimo_config->rf.rf_mode[ant] = RF_MODE_BASE; p_exmimo_config->rf.do_autocal[ant] = 1;//openair0_cfg[card].autocal[ant]; printf("card %d, antenna %d, autocal %d\n",card,ant,openair0_cfg[card].autocal[ant]); } if (openair0_cfg[card].tx_freq[ant]) { p_exmimo_config->rf.rf_mode[ant] += (TXEN + DMAMODE_TX + TXLPFNORM + TXLPFEN + tx_filter); p_exmimo_config->rf.rf_freq_tx[ant] = (unsigned int)openair0_cfg[card].tx_freq[ant]; p_exmimo_config->rf.tx_gain[ant][0] = (unsigned int)openair0_cfg[card].tx_gain[ant]; } if (openair0_cfg[card].rx_freq[ant]) { p_exmimo_config->rf.rf_mode[ant] += (RXEN + DMAMODE_RX + RXLPFNORM + RXLPFEN + rx_filter); p_exmimo_config->rf.rf_freq_rx[ant] = (unsigned int)openair0_cfg[card].rx_freq[ant]; p_exmimo_config->rf.rx_gain[ant][0] = (unsigned int)openair0_cfg[card].rx_gain[ant]; printf("openair0 : programming card %d RX antenna %d (freq %u, gain %d)\n",card,ant,p_exmimo_config->rf.rf_freq_rx[ant],p_exmimo_config->rf.rx_gain[ant][0]); switch (openair0_cfg[card].rxg_mode[ant]) { default: case max_gain: p_exmimo_config->rf.rf_mode[ant] += LNAMax; break; case med_gain: p_exmimo_config->rf.rf_mode[ant] += LNAMed; break; case byp_gain: p_exmimo_config->rf.rf_mode[ant] += LNAByp; break; } } else { p_exmimo_config->rf.rf_mode[ant] = 0; p_exmimo_config->rf.do_autocal[ant] = 0; } p_exmimo_config->rf.rf_local[ant] = rf_local[ant]; p_exmimo_config->rf.rf_rxdc[ant] = rf_rxdc[ant]; if (( p_exmimo_config->rf.rf_freq_tx[ant] >= 850000000) && ( p_exmimo_config->rf.rf_freq_tx[ant] <= 865000000)) { p_exmimo_config->rf.rf_vcocal[ant] = rf_vcocal_850[ant]; p_exmimo_config->rf.rffe_band_mode[ant] = DD_TDD; } else if (( p_exmimo_config->rf.rf_freq_tx[ant] >= 1900000000) && ( p_exmimo_config->rf.rf_freq_tx[ant] <= 2000000000)) { p_exmimo_config->rf.rf_vcocal[ant] = rf_vcocal[ant]; p_exmimo_config->rf.rffe_band_mode[ant] = B19G_TDD; } else { p_exmimo_config->rf.rf_vcocal[ant] = rf_vcocal[ant]; p_exmimo_config->rf.rffe_band_mode[ant] = 0; } } ret = ioctl(openair0_fd, openair_DUMP_CONFIG, card); if (ret!=0) return(-1); } return(0); } int openair0_reconfig(openair0_config_t *openair0_cfg) { int ant, card; exmimo_config_t *p_exmimo_config; // exmimo_id_t *p_exmimo_id; if (!openair0_cfg) { printf("Error, openair0_cfg is null!!\n"); return(-1); } for (card=0; cardrf.rf_freq_tx[ant] = (unsigned int)openair0_cfg[card].tx_freq[ant]; p_exmimo_config->rf.tx_gain[ant][0] = (unsigned int)openair0_cfg[card].tx_gain[ant]; //printf("openair0 : programming TX antenna %d (freq %u, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]); } if (openair0_cfg[card].rx_freq[ant]) { p_exmimo_config->rf.rf_freq_rx[ant] = (unsigned int)openair0_cfg[card].rx_freq[ant]; p_exmimo_config->rf.rx_gain[ant][0] = (unsigned int)openair0_cfg[card].rx_gain[ant]; //printf("openair0 : programming RX antenna %d (freq %u, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_rx[ant],p_exmimo_config->rf.rx_gain[ant][0]); switch (openair0_cfg[card].rxg_mode[ant]) { default: case max_gain: p_exmimo_config->rf.rf_mode[ant] = (p_exmimo_config->rf.rf_mode[ant]&(~LNAGAINMASK))|LNAMax; break; case med_gain: p_exmimo_config->rf.rf_mode[ant] = (p_exmimo_config->rf.rf_mode[ant]&(~LNAGAINMASK))|LNAMed; break; case byp_gain: p_exmimo_config->rf.rf_mode[ant] = (p_exmimo_config->rf.rf_mode[ant]&(~LNAGAINMASK))|LNAByp; break; } } } } return(0); } int openair0_set_frequencies(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config) { if (exmimo_dump_config > 0) { // do a full configuration openair0_config(openair0_cfg,0); } else { // just change the frequencies in pci descriptor openair0_reconfig(openair0_cfg); } return(0); } int openair0_set_gains(openair0_device* device, openair0_config_t *openair0_cfg){ return(0); } unsigned int *openair0_daq_cnt(void) { return((unsigned int *)openair0_exmimo_pci[0].rxcnt_ptr[0]); }