Newer
Older
/*******************************************************************************
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 <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@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 <matthias.ihmig@mytum.de>, 2013
* Raymond Knopp <raymond.knopp@eurecom.fr>
*
* Changelog:
* 28.01.2013: Initial version
*/
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include "openair0_lib.h"
#include "openair_device.h"
winckel
committed
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];
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 )
{
winckel
committed
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<<PAGE_SHIFT,
PROT_READ|PROT_WRITE,
MAP_SHARED, //|MAP_FIXED,//MAP_SHARED,
openair0_fd,
( openair_mmap_BIGSHM | openair_mmap_Card(card) )<<PAGE_SHIFT);
if (bigshm_top[card] == MAP_FAILED) {
openair0_close();
return -2;
}
// calculate userspace addresses
#if __x86_64
openair0_exmimo_pci[card].firmware_block_ptr = (bigshm_top[card] + (int64_t)exmimo_pci_kvirt[0].firmware_block_ptr - (int64_t)bigshm_top_kvirtptr[0]);
openair0_exmimo_pci[card].printk_buffer_ptr = (bigshm_top[card] + (int64_t)exmimo_pci_kvirt[0].printk_buffer_ptr - (int64_t)bigshm_top_kvirtptr[0]);
openair0_exmimo_pci[card].exmimo_config_ptr = (exmimo_config_t*) (bigshm_top[card] + (int64_t)exmimo_pci_kvirt[0].exmimo_config_ptr - (int64_t)bigshm_top_kvirtptr[0]);
openair0_exmimo_pci[card].exmimo_id_ptr = (exmimo_id_t*) (bigshm_top[card] + (int64_t)exmimo_pci_kvirt[0].exmimo_id_ptr - (int64_t)bigshm_top_kvirtptr[0]);
#else
openair0_exmimo_pci[card].firmware_block_ptr = (bigshm_top[card] + (int32_t)exmimo_pci_kvirt[0].firmware_block_ptr - (int32_t)bigshm_top_kvirtptr[0]);
openair0_exmimo_pci[card].printk_buffer_ptr = (bigshm_top[card] + (int32_t)exmimo_pci_kvirt[0].printk_buffer_ptr - (int32_t)bigshm_top_kvirtptr[0]);
openair0_exmimo_pci[card].exmimo_config_ptr = (exmimo_config_t*) (bigshm_top[card] + (int32_t)exmimo_pci_kvirt[0].exmimo_config_ptr - (int32_t)bigshm_top_kvirtptr[0]);
openair0_exmimo_pci[card].exmimo_id_ptr = (exmimo_id_t*) (bigshm_top[card] + (int32_t)exmimo_pci_kvirt[0].exmimo_id_ptr - (int32_t)bigshm_top_kvirtptr[0]);
#endif
printf("openair0_exmimo_pci.firmware_block_ptr (%p) = bigshm_top(%p) + exmimo_pci_kvirt.firmware_block_ptr(%p) - bigshm_top_kvirtptr(%p)\n",
openair0_exmimo_pci[card].firmware_block_ptr, bigshm_top, exmimo_pci_kvirt[card].firmware_block_ptr, bigshm_top_kvirtptr[card]);
printf("card%d, openair0_exmimo_pci.exmimo_id_ptr (%p) = bigshm_top(%p) + exmimo_pci_kvirt.exmimo_id_ptr (%p) - bigshm_top_kvirtptr(%p)\n",
card, openair0_exmimo_pci[card].exmimo_id_ptr, bigshm_top[card], exmimo_pci_kvirt[card].exmimo_id_ptr, bigshm_top_kvirtptr[card]);
//if (openair0_exmimo_pci[card].exmimo_id_ptr->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; ant<openair0_num_antennas[card]; ant++)
{
#if __x86_64__
openair0_exmimo_pci[card].rxcnt_ptr[ant] = (unsigned int *) (bigshm_top[card] + (int64_t)exmimo_pci_kvirt[card].rxcnt_ptr[ant] - (int64_t)bigshm_top_kvirtptr[card]);
openair0_exmimo_pci[card].txcnt_ptr[ant] = (unsigned int *) (bigshm_top[card] + (int64_t)exmimo_pci_kvirt[card].txcnt_ptr[ant] - (int64_t)bigshm_top_kvirtptr[card]);
#else
openair0_exmimo_pci[card].rxcnt_ptr[ant] = (unsigned int *) (bigshm_top[card] + (int32_t)exmimo_pci_kvirt[card].rxcnt_ptr[ant] - (int32_t)bigshm_top_kvirtptr[card]);
openair0_exmimo_pci[card].txcnt_ptr[ant] = (unsigned int *) (bigshm_top[card] + (int32_t)exmimo_pci_kvirt[card].txcnt_ptr[ant] - (int32_t)bigshm_top_kvirtptr[card]);
#endif
}
for (ant=0; ant<openair0_num_antennas[card]; ant++)
{
openair0_exmimo_pci[card].adc_head[ant] = mmap( NULL,
ADAC_BUFFERSZ_PERCHAN_B,
PROT_READ|PROT_WRITE,
MAP_SHARED, //|MAP_FIXED,//MAP_SHARED,
openair0_fd,
( openair_mmap_RX(ant) | openair_mmap_Card(card) )<<PAGE_SHIFT );
openair0_exmimo_pci[card].dac_head[ant] = mmap( NULL,
ADAC_BUFFERSZ_PERCHAN_B,
PROT_READ|PROT_WRITE,
MAP_SHARED, //|MAP_FIXED,//MAP_SHARED,
openair0_fd,
( openair_mmap_TX(ant) | openair_mmap_Card(card) )<<PAGE_SHIFT );
if (openair0_exmimo_pci[card].adc_head[ant] == MAP_FAILED || openair0_exmimo_pci[card].dac_head[ant] == MAP_FAILED) {
openair0_close();
return -3;
}
}
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
//printf("p_exmimo_config = %p, p_exmimo_id = %p\n", openair0_exmimo_pci.exmimo_config_ptr, openair0_exmimo_pci.exmimo_id_ptr);
printf("card %d: ExpressMIMO %d, HW Rev %d, SW Rev 0x%d, %d antennas\n", card, openair0_exmimo_pci[card].exmimo_id_ptr->board_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; card<openair0_num_detected_cards; card++)
{
if (bigshm_top[card] != NULL && bigshm_top[card] != MAP_FAILED)
munmap(bigshm_top[card], BIGSHM_SIZE_PAGES<<PAGE_SHIFT);
for (ant=0; ant<openair0_num_antennas[card]; ant++)
{
if (openair0_exmimo_pci[card].adc_head[ant] != NULL && openair0_exmimo_pci[card].adc_head[ant] != MAP_FAILED)
munmap(openair0_exmimo_pci[card].adc_head[ant], ADAC_BUFFERSZ_PERCHAN_B);
if (openair0_exmimo_pci[card].dac_head[ant] != NULL && openair0_exmimo_pci[card].dac_head[ant] != MAP_FAILED)
munmap(openair0_exmimo_pci[card].dac_head[ant], ADAC_BUFFERSZ_PERCHAN_B);
}
}
return 0;
}
int openair0_dump_config(int card)
{
return ioctl(openair0_fd, openair_DUMP_CONFIG, card);
}
int openair0_get_frame(int card)
{
return ioctl(openair0_fd, openair_GET_FRAME, card);
}
int openair0_start_rt_acquisition(int card)
{
return ioctl(openair0_fd, openair_START_RT_ACQUISITION, card);
}
int openair0_stop(int card)
{
return ioctl(openair0_fd, openair_STOP, card);
}
int openair0_stop_without_reset(int card)
{
return ioctl(openair0_fd, openair_STOP_WITHOUT_RESET, card);
}
static exmimo_config_t *p_exmimo_config;
static exmimo_id_t *p_exmimo_id;
#define MY_RF_MODE (RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + DMAMODE_RX + DMAMODE_TX)
#define RF_MODE_BASE (TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM)
int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
// Initialize card
int ret;
int ant;
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(ret);
}
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);
exit(-1);
}
if (p_exmimo_id->board_swrev>=9)
p_exmimo_config->framing.eNB_flag = 0;
else
p_exmimo_config->framing.eNB_flag = 1;//!UE_flag;
p_exmimo_config->framing.tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_LSB;
#if (BOARD_SWREV_CNTL2>=0x0A)
for (ant=0; ant<4; ant++)
p_exmimo_config->framing.resampling_factor[ant] = 2;
#else
p_exmimo_config->framing.resampling_factor = 2;
#endif
if (!openair0_cfg) {
printf("Error, openair0_cfg is null!!\n");
return(-1);
}
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
for (ant=0;ant<max(openair0_cfg->tx_num_channels,openair0_cfg->rx_num_channels);ant++)
p_exmimo_config->rf.rf_mode[ant] = RF_MODE_BASE;
for (ant=0;ant<openair0_cfg->tx_num_channels;ant++)
p_exmimo_config->rf.rf_mode[ant] += (TXEN + DMAMODE_TX);
for (ant=0;ant<openair0_cfg->rx_num_channels;ant++) {
p_exmimo_config->rf.rf_mode[ant] += (RXEN + DMAMODE_RX);
switch (openair0_cfg->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;
}
}
for (ant=max(openair0_cfg->tx_num_channels,openair0_cfg->rx_num_channels);ant<4;ant++) {
p_exmimo_config->rf.rf_mode[ant] = 0;
}
for (ant = 0; ant<openair0_cfg->rx_num_channels; ant++) {
p_exmimo_config->rf.do_autocal[ant] = 1;
p_exmimo_config->rf.rf_freq_rx[ant] = (unsigned int)openair0_cfg->rx_freq[ant];
p_exmimo_config->rf.rx_gain[ant][0] = (unsigned int)openair0_cfg->rx_gain[ant];
printf("openair0 : programming RX antenna %d (freq %d, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_rx[ant],p_exmimo_config->rf.rx_gain[ant][0]);
}
for (ant = 0; ant<openair0_cfg->tx_num_channels; ant++) {
p_exmimo_config->rf.rf_freq_tx[ant] = (unsigned int)openair0_cfg->tx_freq[ant];
p_exmimo_config->rf.tx_gain[ant][0] = (unsigned int)openair0_cfg->tx_gain[ant];
printf("openair0 : programming TX antenna %d (freq %d, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]);
p_exmimo_config->rf.rf_local[ant] = rf_local[ant];
p_exmimo_config->rf.rf_rxdc[ant] = rf_rxdc[ant];
for (ant=0;ant<4;ant++) {
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;
}
}
return(0);