Blame tools/extra/mmlink/mm_debug_link_linux.cpp

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
}