|
Packit |
534379 |
// Copyright(c) 2017, Intel Corporation
|
|
Packit |
534379 |
//
|
|
Packit |
534379 |
// Redistribution and use in source and binary forms, with or without
|
|
Packit |
534379 |
// modification, are permitted provided that the following conditions are met:
|
|
Packit |
534379 |
//
|
|
Packit |
534379 |
// * Redistributions of source code must retain the above copyright notice,
|
|
Packit |
534379 |
// this list of conditions and the following disclaimer.
|
|
Packit |
534379 |
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
Packit |
534379 |
// this list of conditions and the following disclaimer in the documentation
|
|
Packit |
534379 |
// and/or other materials provided with the distribution.
|
|
Packit |
534379 |
// * Neither the name of Intel Corporation nor the names of its contributors
|
|
Packit |
534379 |
// may be used to endorse or promote products derived from this software
|
|
Packit |
534379 |
// without specific prior written permission.
|
|
Packit |
534379 |
//
|
|
Packit |
534379 |
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
534379 |
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
534379 |
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit |
534379 |
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
Packit |
534379 |
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
Packit |
534379 |
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
Packit |
534379 |
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
Packit |
534379 |
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
Packit |
534379 |
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
Packit |
534379 |
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
Packit |
534379 |
// POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
534379 |
//****************************************************************************
|
|
Packit |
534379 |
/// @file mml_debug_link_linux.cpp
|
|
Packit |
534379 |
/// @brief Basic AFU interaction.
|
|
Packit |
534379 |
/// @ingroup SigTap
|
|
Packit |
534379 |
/// @verbatim
|
|
Packit |
534379 |
//****************************************************************************
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#include <fcntl.h>
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#include <cerrno>
|
|
Packit |
534379 |
#include <cstdarg>
|
|
Packit |
534379 |
#include <cstdlib>
|
|
Packit |
534379 |
#include <cstring>
|
|
Packit |
534379 |
#include <string>
|
|
Packit |
534379 |
#include <iostream>
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#include <sys/ioctl.h>
|
|
Packit |
534379 |
#include <sys/stat.h>
|
|
Packit |
534379 |
#include <sys/types.h>
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#include <unistd.h>
|
|
Packit |
534379 |
#include <sys/mman.h>
|
|
Packit |
534379 |
#include "mm_debug_link_linux.h"
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#define DRIVER_PATH "/dev/mm_debug_link"
|
|
Packit |
534379 |
#define B2P_EOP 0x7B
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#define BASE_ADDR 4096
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#define MAP_SIZE 4096UL
|
|
Packit |
534379 |
#define MAP_MASK (MAP_SIZE - 1)
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#define MM_DEBUG_LINK_DATA_WRITE 0x100
|
|
Packit |
534379 |
#define MM_DEBUG_LINK_WRITE_CAPACITY 0x104
|
|
Packit |
534379 |
#define MM_DEBUG_LINK_DATA_READ 0x108
|
|
Packit |
534379 |
#define MM_DEBUG_LINK_READ_CAPACITY 0x10C
|
|
Packit |
534379 |
#define MM_DEBUG_LINK_FIFO_WRITE_COUNT 0x120
|
|
Packit |
534379 |
#define MM_DEBUG_LINK_FIFO_READ_COUNT 0x140
|
|
Packit |
534379 |
#define MM_DEBUG_LINK_ID_ROM 0x160
|
|
Packit |
534379 |
#define MM_DEBUG_LINK_SIGNATURE 0x170
|
|
Packit |
534379 |
#define MM_DEBUG_LINK_VERSION 0x174
|
|
Packit |
534379 |
#define MM_DEBUG_LINK_DEBUG_RESET 0x178
|
|
Packit |
534379 |
#define MM_DEBUG_LINK_MGMT_INTF 0x17C
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#define REMSTP_MMIO_RD_LEN 0x180
|
|
Packit |
534379 |
#define REMSTP_MMIO_WR_LEN 0x184
|
|
Packit |
534379 |
#define REMSTP_RESET 0x188
|
|
Packit |
534379 |
#define LEN_8B 0x2
|
|
Packit |
534379 |
#define LEN_4B 0x1
|
|
Packit |
534379 |
#define LEN_1B 0x0
|
|
Packit |
534379 |
|
|
Packit |
534379 |
//#define DEBUG_8B_4B_TRANSFERS 1 // Uncomment for 4B/8B DBG
|
|
Packit |
534379 |
//#define DEBUG_FLAG 1 //Uncomment to enable read/write information
|
|
Packit |
534379 |
|
|
Packit |
534379 |
using namespace std;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*
|
|
Packit |
534379 |
* The value to expect at offset MM_DEBUG_LINK_SIGNATURE, aka "SysC".
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
#define EXPECT_SIGNATURE 0x53797343
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*
|
|
Packit |
534379 |
* The maximum version this driver supports.
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
#define MAX_SUPPORTED_VERSION 1
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
mm_debug_link_interface *get_mm_debug_link(void)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
return new mm_debug_link_linux();
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
mm_debug_link_linux::mm_debug_link_linux() {
|
|
Packit |
534379 |
m_fd = -1;
|
|
Packit |
534379 |
m_buf_end = 0;
|
|
Packit |
534379 |
m_write_fifo_capacity = 0;
|
|
Packit |
534379 |
m_write_before_any_read_rfifo_level = false;
|
|
Packit |
534379 |
m_last_read_rfifo_level_empty_time = 0;
|
|
Packit |
534379 |
m_read_rfifo_level_empty_interval = 1;
|
|
Packit |
534379 |
map_base = NULL;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
int mm_debug_link_linux::open(unsigned char* stpAddr)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
unsigned int sign, version;
|
|
Packit |
534379 |
m_fd = -1;
|
|
Packit |
534379 |
map_base = stpAddr;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
cout << "Remote STP : Assert Reset" << endl << flush;
|
|
Packit |
534379 |
write_mmr(REMSTP_RESET, 'w', 0x1);
|
|
Packit |
534379 |
cout << "Remote STP : De-Assert Reset" << endl << flush;
|
|
Packit |
534379 |
write_mmr(REMSTP_RESET, 'w', 0x0);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
sign = read_mmr<unsigned int>(MM_DEBUG_LINK_SIGNATURE);
|
|
Packit |
534379 |
cout << "Read signature value " << std::hex << sign << " to hw\n" << flush;
|
|
Packit |
534379 |
if ( sign != EXPECT_SIGNATURE)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
cerr << "Unverified Signature\n";
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
version = read_mmr<unsigned int>(MM_DEBUG_LINK_VERSION);
|
|
Packit |
534379 |
cout << "Read version value " << version << " to hw\n";
|
|
Packit |
534379 |
if ( version > MAX_SUPPORTED_VERSION )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
cerr << "Unsupported Version\n";
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
this->m_write_fifo_capacity = read_mmr<int>(MM_DEBUG_LINK_WRITE_CAPACITY);
|
|
Packit |
534379 |
cout << "Read write fifo capacity value " << std::dec << this->m_write_fifo_capacity << " to hw\n";
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return 0;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
void mm_debug_link_linux::write_mmr(off_t target,
|
|
Packit |
534379 |
int access_type,
|
|
Packit |
534379 |
uint64_t write_val)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
#ifdef DEBUG_8B_4B_TRANSFERS
|
|
Packit |
534379 |
cout << hex <<"WRITING : "<< write_val << dec << endl;
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
void *virt_addr;
|
|
Packit |
534379 |
/* Map one page */
|
|
Packit |
534379 |
|
|
Packit |
534379 |
virt_addr = (void *) (map_base + target);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
switch(access_type) {
|
|
Packit |
534379 |
case 'b':
|
|
Packit |
534379 |
*((uint8_t *) virt_addr) = write_val;
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
case 'h':
|
|
Packit |
534379 |
*((uint16_t *) virt_addr) = write_val;
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
case 'w':
|
|
Packit |
534379 |
*((uint32_t *) virt_addr) = write_val;
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
case 'q':
|
|
Packit |
534379 |
*((uint64_t *) virt_addr) = write_val;
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
default:
|
|
Packit |
534379 |
cerr << "Illegal data type '" << access_type << "'.\n";
|
|
Packit |
534379 |
exit(2);
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
bool mm_debug_link_linux::can_read_data()
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
bool ret = this->m_write_before_any_read_rfifo_level;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if ( !ret )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
clock_t cur_time = ::clock();
|
|
Packit |
534379 |
clock_t duration = cur_time - this->m_last_read_rfifo_level_empty_time;
|
|
Packit |
534379 |
if ( duration < 0 )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
duration = -duration;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
if ( duration >= this->m_read_rfifo_level_empty_interval )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
ret = true;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return ret;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
ssize_t mm_debug_link_linux::read()
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
uint8_t num_bytes;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
num_bytes = read_mmr<uint8_t>(MM_DEBUG_LINK_FIFO_READ_COUNT);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
// Reset the timer record
|
|
Packit |
534379 |
if ( (this->m_write_before_any_read_rfifo_level || // when this is the first read after write
|
|
Packit |
534379 |
num_bytes > 0) ) // when something is available to read
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
this->m_write_before_any_read_rfifo_level = false;
|
|
Packit |
534379 |
this->m_read_rfifo_level_empty_interval = 1; // Increase the read fifo level polling freq. in anticipation of more read data availability.
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (num_bytes > 0 )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
if ( num_bytes > (mm_debug_link_linux::BUFSIZE - m_buf_end) )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
num_bytes = mm_debug_link_linux::BUFSIZE - m_buf_end;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#ifdef DEBUG_FLAG
|
|
Packit |
534379 |
cout << "Read " << num_bytes << " bytes\n";
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*
|
|
Packit |
534379 |
==========================================================================================================================
|
|
Packit |
534379 |
At this point, num_bytes has the No. of bytes available to read from the FPGA
|
|
Packit |
534379 |
Default implementation: Tries to pull 1B at a time.
|
|
Packit |
534379 |
|
|
Packit |
534379 |
The Objective is to increase link utilization (1/8) to (8/8):
|
|
Packit |
534379 |
-------------------------------------------------------------
|
|
Packit |
534379 |
The interface on HW to SLD HUB Controller system still supports 1B reads/ writes only
|
|
Packit |
534379 |
The solution is to avoid 1B ping-pong and communicate to remote STP soft logic on HW with No. of bytes to read (say N)
|
|
Packit |
534379 |
The HW should read so many bytes (N) from the SLD HUB Cont Sys and return a packed read response. (little endian 64b max payload)
|
|
Packit |
534379 |
A register (REMSTP_MMIO_RD_LEN) is defined @ PORT DFH offset 0x4180 - Default value is 0. Possible values are 0/1/2.
|
|
Packit |
534379 |
Only SW can modify this register. SW should always retain the last value written to this register
|
|
Packit |
534379 |
SW always does 8B/4B/1B MMIO reads to MM_DEBUG_LINK_DATA_READ register (depending on the current value of N)
|
|
Packit |
534379 |
RemoteSTP logic on HW translates this to REMSTP_MMIO_RD_LEN (N) number of 1B reads from SLD HUB Cont sys endpoint
|
|
Packit |
534379 |
HW returns a 1B/4B/8B read value. Only lower REMSTP_MMIO_RD_LEN bytes are valid
|
|
Packit |
534379 |
SW should drop the remaining upper bytes of the returned response and update the mem-mapped pointer.
|
|
Packit |
534379 |
SW is responsible for credit control on the HW read FIFO
|
|
Packit |
534379 |
i.e. SW should update REMSTP_MMIO_RD_LEN register based on num_bytes available to read
|
|
Packit |
534379 |
Leaving back entries in the FIFO/ popping an empty FIFO is FATAL
|
|
Packit |
534379 |
|
|
Packit |
534379 |
Similarly, on the Write Path number of bytes to be written to HW write FIFO is packed into 4B/8B writes whenever possible
|
|
Packit |
534379 |
A register (REMSTP_MMIO_WR_LEN) is defined @ PORT DFH offset 0x4184 - Default value is 0. Possible values are 0/1/2. (M say)
|
|
Packit |
534379 |
RemoteSTP logic on HW will replay 1B writes M times into SLD HUB controller system w/o SLD endpoint.
|
|
Packit |
534379 |
|
|
Packit |
534379 |
Encodings for REMSTP_MMIO_WR_LEN & REMSTP_MMIO_RD_LEN
|
|
Packit |
534379 |
-----------------------------------------------------
|
|
Packit |
534379 |
|
|
Packit |
534379 |
-------------------------
|
|
Packit |
534379 |
| Encoding | Rd/Wr Len |
|
|
Packit |
534379 |
-------------------------
|
|
Packit |
534379 |
| 2'b00 | 1 |
|
|
Packit |
534379 |
| 2'b01 | 4 |
|
|
Packit |
534379 |
| 2'b10 | 8 |
|
|
Packit |
534379 |
| 2'b11 | Rsvd |
|
|
Packit |
534379 |
-------------------------
|
|
Packit |
534379 |
|
|
Packit |
534379 |
Performance impact:
|
|
Packit |
534379 |
-------------------
|
|
Packit |
534379 |
1)
|
|
Packit |
534379 |
OLD - Time to read 8bytes = 8 * 1 MMIO Read latency from device
|
|
Packit |
534379 |
NEW - Time to read 8bytes (best case) = 1 MMIO Read latency from device
|
|
Packit |
534379 |
NEW - Time to read 8bytes (worst case) = 1 MMIO Write latency to device + 1 MMIO Read latency from device
|
|
Packit |
534379 |
|
|
Packit |
534379 |
2) Through efficient utilization of MMIO data width, the amount of degradation seen on available AFU BW when using remoteSTP could be lowered
|
|
Packit |
534379 |
|
|
Packit |
534379 |
NOTE:
|
|
Packit |
534379 |
-----
|
|
Packit |
534379 |
MMIO reads to REMSTP_MMIO_RD_LEN or REMSTP_MMIO_WR_LEN is NOT supported
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
|
|
Packit |
534379 |
uint8_t num_8B_reads, num_4B_reads, num_1B_reads, remaining_bytes;
|
|
Packit |
534379 |
num_8B_reads = num_bytes/8;
|
|
Packit |
534379 |
remaining_bytes = num_bytes%8;
|
|
Packit |
534379 |
num_4B_reads = remaining_bytes/4;
|
|
Packit |
534379 |
remaining_bytes = remaining_bytes%4;
|
|
Packit |
534379 |
num_1B_reads = remaining_bytes;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#ifdef DEBUG_8B_4B_TRANSFERS
|
|
Packit |
534379 |
cout << dec;
|
|
Packit |
534379 |
cout << "DBG_READ : Total_Bytes = " << (unsigned) num_bytes << " ; 8_bytes = "
|
|
Packit |
534379 |
<< (unsigned) num_8B_reads << " ; 4_bytes = " << (unsigned) num_4B_reads << " ; 1_bytes = " << (unsigned) num_1B_reads << endl << flush;
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
|
|
Packit |
534379 |
// SW should update HW control (REMSTP_MMIO_RD_LEN) and use only REMSTP_MMIO_RD_LEN bytes returned
|
|
Packit |
534379 |
if (num_8B_reads > 0)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
// Change REMSTP_MMIO_RD_LEN to 8B
|
|
Packit |
534379 |
write_mmr( REMSTP_MMIO_RD_LEN, 'w', LEN_8B);
|
|
Packit |
534379 |
for ( unsigned char i = 0; i < num_8B_reads; ++i )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
volatile uint64_t *p = reinterpret_cast<volatile uint64_t *>(this->m_buf +
|
|
Packit |
534379 |
this->m_buf_end +
|
|
Packit |
534379 |
(i*8));
|
|
Packit |
534379 |
*p = read_mmr<uint64_t>(MM_DEBUG_LINK_DATA_READ);
|
|
Packit |
534379 |
#ifdef DEBUG_8B_4B_TRANSFERS
|
|
Packit |
534379 |
cout << "DBG_READ_8B : Iteration "<< (unsigned) i << "; READ VALUE : " << hex;
|
|
Packit |
534379 |
for (unsigned char j=0; j<8; j++)
|
|
Packit |
534379 |
cout << (int) *( this->m_buf + this->m_buf_end + (i*8) + j ) << flush;
|
|
Packit |
534379 |
cout << dec << endl << flush;
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (num_4B_reads > 0)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
// Change REMSTP_MMIO_RD_LEN to 4B
|
|
Packit |
534379 |
write_mmr( REMSTP_MMIO_RD_LEN, 'w', LEN_4B);
|
|
Packit |
534379 |
for ( unsigned char i = 0; i < num_4B_reads; ++i )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
volatile uint32_t *p = reinterpret_cast<volatile uint32_t *>(this->m_buf +
|
|
Packit |
534379 |
this->m_buf_end +
|
|
Packit |
534379 |
(num_8B_reads*8) +
|
|
Packit |
534379 |
(i*4));
|
|
Packit |
534379 |
*p = read_mmr<uint32_t>(MM_DEBUG_LINK_DATA_READ);
|
|
Packit |
534379 |
#ifdef DEBUG_8B_4B_TRANSFERS
|
|
Packit |
534379 |
cout << "DBG_READ_4B : Iteration "<< (int) i << "; READ VALUE : " << hex;
|
|
Packit |
534379 |
for (unsigned char j=0; j<4; j++)
|
|
Packit |
534379 |
cout << (int) *( this->m_buf + this->m_buf_end + ( (num_8B_reads*8) + (i*4) + j)) << flush;
|
|
Packit |
534379 |
cout << dec << endl << flush;
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (num_1B_reads > 0)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
// Change REMSTP_MMIO_RD_LEN to 1B
|
|
Packit |
534379 |
write_mmr( REMSTP_MMIO_RD_LEN, 'w', LEN_1B);
|
|
Packit |
534379 |
for ( unsigned char i = 0; i < num_1B_reads; ++i )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
volatile uint8_t *p = reinterpret_cast<volatile uint8_t *>(this->m_buf + this->m_buf_end +
|
|
Packit |
534379 |
(num_8B_reads*8) +
|
|
Packit |
534379 |
(num_4B_reads*4) +
|
|
Packit |
534379 |
i);
|
|
Packit |
534379 |
*p = read_mmr<uint8_t>(MM_DEBUG_LINK_DATA_READ);
|
|
Packit |
534379 |
#ifdef DEBUG_8B_4B_TRANSFERS
|
|
Packit |
534379 |
cout << "DBG_READ_1B : Iteration "<< (int) i << "; READ VALUE : "
|
|
Packit |
534379 |
<< hex << (int) *( this->m_buf + this->m_buf_end + ( (num_8B_reads*8) + (num_4B_reads*4) +i)) << endl << flush << dec;
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
// ==========================================================================================================================
|
|
Packit |
534379 |
|
|
Packit |
534379 |
unsigned int x;
|
|
Packit |
534379 |
for ( unsigned char i = 0; i < num_bytes; ++i )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
x = this->m_buf[this->m_buf_end + i];
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#ifdef DEBUG_FLAG
|
|
Packit |
534379 |
cout << setfill('0') << setw(2) << std::hex << x << " ";
|
|
Packit |
534379 |
#else
|
|
Packit |
534379 |
UNUSED_PARAM(x);
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
#ifdef DEBUG_FLAG
|
|
Packit |
534379 |
cout << std::dec << "\n";
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
|
|
Packit |
534379 |
this->m_buf_end += num_bytes;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
else
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
//printf( "%s %s(): error read hw read buffer level\n", __FILE__, __FUNCTION__ );
|
|
Packit |
534379 |
num_bytes = 0;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
this->m_last_read_rfifo_level_empty_time = ::clock();
|
|
Packit |
534379 |
|
|
Packit |
534379 |
//Throttle the read rfifo level polling freq. up to 10 sec.
|
|
Packit |
534379 |
this->m_read_rfifo_level_empty_interval *= 2;
|
|
Packit |
534379 |
if ( this->m_read_rfifo_level_empty_interval >= 10 * CLOCKS_PER_SEC )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
this->m_read_rfifo_level_empty_interval = 10 * CLOCKS_PER_SEC;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return num_bytes;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
ssize_t mm_debug_link_linux::write(const void *buf, size_t count)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
uint8_t num_bytes;
|
|
Packit |
534379 |
unsigned int x;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
num_bytes = read_mmr<uint8_t>(MM_DEBUG_LINK_FIFO_WRITE_COUNT);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
this->m_write_before_any_read_rfifo_level = true; // Set this to kick off any possible read activity even if write FIFO is full to avoid potential deadlock.
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if ( num_bytes < this->m_write_fifo_capacity )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
num_bytes = this->m_write_fifo_capacity - num_bytes;
|
|
Packit |
534379 |
if ( count < num_bytes )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
num_bytes = count;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
count = 0;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
// ==========================================================================================================================
|
|
Packit |
534379 |
uint8_t num_8B_writes, num_4B_writes, num_1B_writes, remaining_bytes;
|
|
Packit |
534379 |
num_8B_writes = num_bytes/8;
|
|
Packit |
534379 |
remaining_bytes = num_bytes%8;
|
|
Packit |
534379 |
num_4B_writes = remaining_bytes/4;
|
|
Packit |
534379 |
remaining_bytes = remaining_bytes%4;
|
|
Packit |
534379 |
num_1B_writes = remaining_bytes;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#ifdef DEBUG_8B_4B_TRANSFERS
|
|
Packit |
534379 |
cout << dec << endl;
|
|
Packit |
534379 |
cout << "DBG_WRITE : Total_Bytes = " << (unsigned) num_bytes << " ; 8_bytes = " << (unsigned) num_8B_writes
|
|
Packit |
534379 |
<< " ; 4_bytes = " << (unsigned) num_4B_writes << " ; 1_bytes = " << (unsigned) num_1B_writes << endl << flush;
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
|
|
Packit |
534379 |
// SW should update HW control (REMSTP_MMIO_WR_LEN) and use only REMSTP_MMIO_WR_LEN bytes returned
|
|
Packit |
534379 |
if (num_8B_writes > 0)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
// Change REMSTP_MMIO_WR_LEN to 8B
|
|
Packit |
534379 |
write_mmr( REMSTP_MMIO_WR_LEN, 'w', LEN_8B);
|
|
Packit |
534379 |
for ( size_t i = 0; i < num_8B_writes; ++i )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
#ifdef DEBUG_8B_4B_TRANSFERS
|
|
Packit |
534379 |
cout << "DBG_WRITE_8B : Iteration "<< i << "; ";
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
write_mmr( MM_DEBUG_LINK_DATA_WRITE, 'q', *( (uint64_t *)buf + i ) );
|
|
Packit |
534379 |
count+=8;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (num_4B_writes > 0)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
// Change REMSTP_MMIO_WR_LEN to 4B
|
|
Packit |
534379 |
write_mmr( REMSTP_MMIO_WR_LEN, 'w', LEN_4B);
|
|
Packit |
534379 |
for ( size_t i = 0; i < num_4B_writes; ++i )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
#ifdef DEBUG_8B_4B_TRANSFERS
|
|
Packit |
534379 |
cout << "DBG_WRITE_4B : Iteration "<< i << "; ";
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
write_mmr( MM_DEBUG_LINK_DATA_WRITE, 'w', *( (uint32_t *)buf + ( (num_8B_writes*2) + i ) ) );
|
|
Packit |
534379 |
count+=4;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (num_1B_writes > 0)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
// Change REMSTP_MMIO_WR_LEN to 1B
|
|
Packit |
534379 |
write_mmr( REMSTP_MMIO_WR_LEN, 'w', LEN_1B);
|
|
Packit |
534379 |
for ( size_t i = 0; i < num_1B_writes; ++i )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
#ifdef DEBUG_8B_4B_TRANSFERS
|
|
Packit |
534379 |
cout << "DBG_WRITE_1B : Iteration "<< i << "; ";
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
write_mmr( MM_DEBUG_LINK_DATA_WRITE, 'b', *( (unsigned char *)buf + ( (num_8B_writes*8) + (num_4B_writes*4) + (i) ) ) );
|
|
Packit |
534379 |
++count;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
// ==========================================================================================================================
|
|
Packit |
534379 |
|
|
Packit |
534379 |
num_bytes = count;
|
|
Packit |
534379 |
#ifdef DEBUG_FLAG
|
|
Packit |
534379 |
cout << "Wrote " << num_bytes << " bytes\n";
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
for ( int i = 0; i < num_bytes; ++i )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
x = *((unsigned char *)buf + i);
|
|
Packit |
534379 |
#ifdef DEBUG_FLAG
|
|
Packit |
534379 |
cout << setfill('0') << setw(2) << std::hex << x << " ";
|
|
Packit |
534379 |
#else
|
|
Packit |
534379 |
UNUSED_PARAM(x);
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
#ifdef DEBUG_FLAG
|
|
Packit |
534379 |
cout << std::dec << "\n" ;
|
|
Packit |
534379 |
#endif
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
else
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
//cerr << "Error write hw write buffer level\n";
|
|
Packit |
534379 |
num_bytes = 0;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return num_bytes;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
void mm_debug_link_linux::close(void)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if(munmap((void *) map_base, MAP_SIZE) == -1){
|
|
Packit |
534379 |
cerr << "Unmap error\n";
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (m_fd != -1){
|
|
Packit |
534379 |
::close(m_fd);
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
m_fd = -1;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
void mm_debug_link_linux::write_ident(int val)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
write_mmr(MM_DEBUG_LINK_ID_ROM, 'b', val);
|
|
Packit |
534379 |
cout << "Write mixer value " << val << " to hw\n";
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
void mm_debug_link_linux::reset(bool val)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
unsigned int reset_val = val ? 1 : 0;
|
|
Packit |
534379 |
write_mmr(MM_DEBUG_LINK_DEBUG_RESET, 'w', val);
|
|
Packit |
534379 |
cout << "Write reset value " << reset_val << " to hw\n";
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
void mm_debug_link_linux::ident(int id[4])
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
for ( int i = 0; i < 4; i++ )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
id[i] = read_mmr<int>(MM_DEBUG_LINK_ID_ROM + i * 4);
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
void mm_debug_link_linux::enable(int channel, bool state)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
int encoded_cmd = (channel << 8) | (state ? 1 : 0);
|
|
Packit |
534379 |
write_mmr(MM_DEBUG_LINK_MGMT_INTF, 'w', encoded_cmd);
|
|
Packit |
534379 |
cout << "Enable channel " << encoded_cmd << " to hw\n";
|
|
Packit |
534379 |
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
bool mm_debug_link_linux::flush_request(void)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
bool should_flush = false;
|
|
Packit |
534379 |
if (m_buf_end == BUFSIZE)
|
|
Packit |
534379 |
// Full buffer? Send.
|
|
Packit |
534379 |
should_flush = true;
|
|
Packit |
534379 |
else if (memchr(m_buf, B2P_EOP, m_buf_end - 1))
|
|
Packit |
534379 |
// Buffer contains eop? Send.
|
|
Packit |
534379 |
// If the eop character occurs in the very last buffer byte, there's no packet here -
|
|
Packit |
534379 |
// we need at least one more byte.
|
|
Packit |
534379 |
// Interesting corner case: it's not strictly true that one more byte after EOP indicates
|
|
Packit |
534379 |
// the end of a packet - that byte after EOP might be the escape character. In this case,
|
|
Packit |
534379 |
// we flush even though it's not necessarily a complete packet. This probably has negligible
|
|
Packit |
534379 |
// impact on performance.
|
|
Packit |
534379 |
should_flush = true;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if ( m_buf_end > 0 )
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
should_flush = true;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
return should_flush;
|
|
Packit |
534379 |
}
|