lib/sw_apps/libmetal_echo_demo/src/system/generic/zynqmp_r5/zynqmp_amp_demo/ipi_shmem_demod.c
static int ipi_shmem_echod(struct metal_io_region *ipi_io,
		struct metal_io_region *shm_io)
{
	int ret = 0;
	uint32_t rx_count, rx_avail;
	unsigned long tx_avail_offset, rx_avail_offset;
	unsigned long rx_used_offset;
	unsigned long tx_addr_offset, rx_addr_offset;
	unsigned long tx_data_offset, rx_data_offset;
	void *lbuf = NULL;
	struct msg_hdr_s *msg_hdr;
	uint32_t ipi_mask = IPI_MASK;

	lbuf = metal_allocate_memory(BUF_SIZE_MAX);
	if (!lbuf) {
		LPERROR("Failed to allocate local buffer for msg.\n");
		ret = -ENOMEM;
		goto out;
	}

	/* Set tx/rx buffer address offset */
	tx_avail_offset = SHM_DESC_OFFSET_TX + SHM_DESC_AVAIL_OFFSET;
	rx_avail_offset = SHM_DESC_OFFSET_RX + SHM_DESC_AVAIL_OFFSET;
	rx_used_offset = SHM_DESC_OFFSET_RX + SHM_DESC_USED_OFFSET;
	tx_addr_offset = SHM_DESC_OFFSET_TX + SHM_DESC_ADDR_ARRAY_OFFSET;
	rx_addr_offset = SHM_DESC_OFFSET_RX + SHM_DESC_ADDR_ARRAY_OFFSET;
	tx_data_offset = SHM_DESC_OFFSET_TX + SHM_BUFF_OFFSET_TX;
	rx_data_offset = SHM_DESC_OFFSET_RX + SHM_BUFF_OFFSET_RX;

	LPRINTF("Wait for echo test to start.\n");
	rx_count = 0;
	while (1) {
		wait_for_notified(&remote_nkicked);
		rx_avail = metal_io_read32(shm_io, rx_avail_offset);
		while(rx_count != rx_avail) {
			uint32_t buf_phy_addr_32;

			/* Received ping from the other side */

			/* Get the buffer location from the shared memory
			 * rx address array.
			 */
			buf_phy_addr_32 = metal_io_read32(shm_io,
					rx_addr_offset);
			rx_data_offset = metal_io_phys_to_offset(shm_io,
					(metal_phys_addr_t)buf_phy_addr_32);
			if (rx_data_offset == METAL_BAD_OFFSET) {
				LPERROR("[%u]failed to get rx offset: 0x%x, 0x%lx.\n",
					rx_count, buf_phy_addr_32,
					metal_io_phys(shm_io, rx_addr_offset));
				ret = -EINVAL;
				goto out;
			}
			rx_addr_offset += sizeof(buf_phy_addr_32);

			/* Read message header from shared memory */
			metal_io_block_read(shm_io, rx_data_offset, lbuf,
				sizeof(struct msg_hdr_s));
			msg_hdr = (struct msg_hdr_s *)lbuf;

			/* Check if the message header is valid */
			if (msg_hdr->len > (BUF_SIZE_MAX - sizeof(*msg_hdr))) {
				LPERROR("wrong msg: length invalid: %u, %u.\n",
					BUF_SIZE_MAX - sizeof(*msg_hdr),
					msg_hdr->len);
				ret = -EINVAL;
				goto out;
			}
			rx_data_offset += sizeof(*msg_hdr);
			/* Read message */
			metal_io_block_read(shm_io,
					rx_data_offset,
					lbuf + sizeof(*msg_hdr), msg_hdr->len);
			rx_data_offset += msg_hdr->len;
			rx_count++;
			/* increase rx used count to indicate it has consumed
			 * the received data */
			metal_io_write32(shm_io, rx_used_offset, rx_count);

			/* Check if the it is the shutdown message */
			if (msg_hdr->len == strlen(SHUTDOWN) &&
				!strncmp(SHUTDOWN,
					(lbuf + sizeof(struct msg_hdr_s)),
					strlen(SHUTDOWN))) {
					LPRINTF("Received shutdown message\n");
					goto out;
			}
			/* Copy the message back to the other end */
			metal_io_block_write(shm_io, tx_data_offset, msg_hdr,
				sizeof(struct msg_hdr_s) + msg_hdr->len);

			/* Write to the address array to tell the other end
			 * the buffer address.
			 */
			buf_phy_addr_32 = (uint32_t)metal_io_phys(shm_io,
						tx_data_offset);
			metal_io_write32(shm_io, tx_addr_offset,
					buf_phy_addr_32);
			tx_data_offset += sizeof(struct msg_hdr_s) +
				msg_hdr->len;
			tx_addr_offset += sizeof(uint32_t);

			/* Increase number of available buffers */
			metal_io_write32(shm_io, tx_avail_offset, rx_count);
			/* Kick IPI to notify data is in shared buffer */
			metal_io_write32(ipi_io, IPI_TRIG_OFFSET,
					ipi_mask);
		}

	}

out:
	LPRINTF("IPI with shared memory demo finished with exit code: %i.\n",
		ret);

	if (lbuf)
		metal_free_memory(lbuf);
	return ret;
}
/**
 * @brief   ipi_shmem_echod() - shared memory IPI demo
 *          This task will:
 *          * Wait for IPI interrupt from the remote
 *          * Once it received the interrupt, copy the content from
 *            the ping buffer to the pong buffer.
 *          * Update the shared memory descriptor for the new available
 *            pong buffer.
 *          * Trigger IPI to notifty the remote.
 * @param[in] ipi_io - IPI metal i/o region
 * @param[in] shm_io - shared memory metal i/o region
 * @return - return 0 on success, otherwise return error number indicating
 *		 type of error.
 */
@brief   ipi_shmem_echod() - shared memory IPI demo
This task will:
Wait for IPI interrupt from the remote
Once it received the interrupt, copy the content from
the ping buffer to the pong buffer.
Update the shared memory descriptor for the new available
pong buffer.
Trigger IPI to notifty the remote.
@param[in] ipi_io - IPI metal i/o region
@param[in] shm_io - shared memory metal i/o region
@return - return 0 on success, otherwise return error number indicating
type of error.
@brief ipi_shmem_echod () - shared memory IPI demo This task will : Wait for IPI interrupt from the remote Once it received the interrupt copy the content from the ping buffer to the pong buffer . Update the shared memory descriptor for the new available pong buffer . Trigger IPI to notifty the remote . @param [ in ] ipi_io - IPI metal i / o region @param [ in ] shm_io - shared memory metal i / o region @return - return 0 on success otherwise return error number indicating type of error .
static int ipi_shmem_echod(struct metal_io_region *ipi_io,
		struct metal_io_region *shm_io)
{
	int ret = 0;
	uint32_t rx_count, rx_avail;
	unsigned long tx_avail_offset, rx_avail_offset;
	unsigned long rx_used_offset;
	unsigned long tx_addr_offset, rx_addr_offset;
	unsigned long tx_data_offset, rx_data_offset;
	void *lbuf = NULL;
	struct msg_hdr_s *msg_hdr;
	uint32_t ipi_mask = IPI_MASK;
	lbuf = metal_allocate_memory(BUF_SIZE_MAX);
	if (!lbuf) {
		LPERROR("Failed to allocate local buffer for msg.\n");
		ret = -ENOMEM;
		goto out;
	}
	tx_avail_offset = SHM_DESC_OFFSET_TX + SHM_DESC_AVAIL_OFFSET;
	rx_avail_offset = SHM_DESC_OFFSET_RX + SHM_DESC_AVAIL_OFFSET;
	rx_used_offset = SHM_DESC_OFFSET_RX + SHM_DESC_USED_OFFSET;
	tx_addr_offset = SHM_DESC_OFFSET_TX + SHM_DESC_ADDR_ARRAY_OFFSET;
	rx_addr_offset = SHM_DESC_OFFSET_RX + SHM_DESC_ADDR_ARRAY_OFFSET;
	tx_data_offset = SHM_DESC_OFFSET_TX + SHM_BUFF_OFFSET_TX;
	rx_data_offset = SHM_DESC_OFFSET_RX + SHM_BUFF_OFFSET_RX;
	LPRINTF("Wait for echo test to start.\n");
	rx_count = 0;
	while (1) {
		wait_for_notified(&remote_nkicked);
		rx_avail = metal_io_read32(shm_io, rx_avail_offset);
		while(rx_count != rx_avail) {
			uint32_t buf_phy_addr_32;
			buf_phy_addr_32 = metal_io_read32(shm_io,
					rx_addr_offset);
			rx_data_offset = metal_io_phys_to_offset(shm_io,
					(metal_phys_addr_t)buf_phy_addr_32);
			if (rx_data_offset == METAL_BAD_OFFSET) {
				LPERROR("[%u]failed to get rx offset: 0x%x, 0x%lx.\n",
					rx_count, buf_phy_addr_32,
					metal_io_phys(shm_io, rx_addr_offset));
				ret = -EINVAL;
				goto out;
			}
			rx_addr_offset += sizeof(buf_phy_addr_32);
			metal_io_block_read(shm_io, rx_data_offset, lbuf,
				sizeof(struct msg_hdr_s));
			msg_hdr = (struct msg_hdr_s *)lbuf;
			if (msg_hdr->len > (BUF_SIZE_MAX - sizeof(*msg_hdr))) {
				LPERROR("wrong msg: length invalid: %u, %u.\n",
					BUF_SIZE_MAX - sizeof(*msg_hdr),
					msg_hdr->len);
				ret = -EINVAL;
				goto out;
			}
			rx_data_offset += sizeof(*msg_hdr);
			metal_io_block_read(shm_io,
					rx_data_offset,
					lbuf + sizeof(*msg_hdr), msg_hdr->len);
			rx_data_offset += msg_hdr->len;
			rx_count++;
			metal_io_write32(shm_io, rx_used_offset, rx_count);
			if (msg_hdr->len == strlen(SHUTDOWN) &&
				!strncmp(SHUTDOWN,
					(lbuf + sizeof(struct msg_hdr_s)),
					strlen(SHUTDOWN))) {
					LPRINTF("Received shutdown message\n");
					goto out;
			}
			metal_io_block_write(shm_io, tx_data_offset, msg_hdr,
				sizeof(struct msg_hdr_s) + msg_hdr->len);
			buf_phy_addr_32 = (uint32_t)metal_io_phys(shm_io,
						tx_data_offset);
			metal_io_write32(shm_io, tx_addr_offset,
					buf_phy_addr_32);
			tx_data_offset += sizeof(struct msg_hdr_s) +
				msg_hdr->len;
			tx_addr_offset += sizeof(uint32_t);
			metal_io_write32(shm_io, tx_avail_offset, rx_count);
			metal_io_write32(ipi_io, IPI_TRIG_OFFSET,
					ipi_mask);
		}
	}
out:
	LPRINTF("IPI with shared memory demo finished with exit code: %i.\n",
		ret);
	if (lbuf)
		metal_free_memory(lbuf);
	return ret;
}
static int ipi_shmem_echod ( struct metal_io_region * ipi_io , struct metal_io_region * shm_io ) { int ret = 0 ; uint32_t rx_count , rx_avail ; unsigned long tx_avail_offset , rx_avail_offset ; unsigned long rx_used_offset ; unsigned long tx_addr_offset , rx_addr_offset ; unsigned long tx_data_offset , rx_data_offset ; void * lbuf = NULL ; struct msg_hdr_s * msg_hdr ; uint32_t ipi_mask = IPI_MASK ; lbuf = metal_allocate_memory ( BUF_SIZE_MAX ) ; if ( ! lbuf ) { LPERROR ( " \n " ) ; ret = - ENOMEM ; goto out ; } tx_avail_offset = SHM_DESC_OFFSET_TX + SHM_DESC_AVAIL_OFFSET ; rx_avail_offset = SHM_DESC_OFFSET_RX + SHM_DESC_AVAIL_OFFSET ; rx_used_offset = SHM_DESC_OFFSET_RX + SHM_DESC_USED_OFFSET ; tx_addr_offset = SHM_DESC_OFFSET_TX + SHM_DESC_ADDR_ARRAY_OFFSET ; rx_addr_offset = SHM_DESC_OFFSET_RX + SHM_DESC_ADDR_ARRAY_OFFSET ; tx_data_offset = SHM_DESC_OFFSET_TX + SHM_BUFF_OFFSET_TX ; rx_data_offset = SHM_DESC_OFFSET_RX + SHM_BUFF_OFFSET_RX ; LPRINTF ( " \n " ) ; rx_count = 0 ; while ( 1 ) { wait_for_notified ( & remote_nkicked ) ; rx_avail = metal_io_read32 ( shm_io , rx_avail_offset ) ; while ( rx_count != rx_avail ) { uint32_t buf_phy_addr_32 ; buf_phy_addr_32 = metal_io_read32 ( shm_io , rx_addr_offset ) ; rx_data_offset = metal_io_phys_to_offset ( shm_io , ( metal_phys_addr_t ) buf_phy_addr_32 ) ; if ( rx_data_offset == METAL_BAD_OFFSET ) { LPERROR ( " \n " , rx_count , buf_phy_addr_32 , metal_io_phys ( shm_io , rx_addr_offset ) ) ; ret = - EINVAL ; goto out ; } rx_addr_offset += sizeof ( buf_phy_addr_32 ) ; metal_io_block_read ( shm_io , rx_data_offset , lbuf , sizeof ( struct msg_hdr_s ) ) ; msg_hdr = ( struct msg_hdr_s * ) lbuf ; if ( msg_hdr -> len > ( BUF_SIZE_MAX - sizeof ( * msg_hdr ) ) ) { LPERROR ( " \n " , BUF_SIZE_MAX - sizeof ( * msg_hdr ) , msg_hdr -> len ) ; ret = - EINVAL ; goto out ; } rx_data_offset += sizeof ( * msg_hdr ) ; metal_io_block_read ( shm_io , rx_data_offset , lbuf + sizeof ( * msg_hdr ) , msg_hdr -> len ) ; rx_data_offset += msg_hdr -> len ; rx_count ++ ; metal_io_write32 ( shm_io , rx_used_offset , rx_count ) ; if ( msg_hdr -> len == strlen ( SHUTDOWN ) && ! strncmp ( SHUTDOWN , ( lbuf + sizeof ( struct msg_hdr_s ) ) , strlen ( SHUTDOWN ) ) ) { LPRINTF ( " \n " ) ; goto out ; } metal_io_block_write ( shm_io , tx_data_offset , msg_hdr , sizeof ( struct msg_hdr_s ) + msg_hdr -> len ) ; buf_phy_addr_32 = ( uint32_t ) metal_io_phys ( shm_io , tx_data_offset ) ; metal_io_write32 ( shm_io , tx_addr_offset , buf_phy_addr_32 ) ; tx_data_offset += sizeof ( struct msg_hdr_s ) + msg_hdr -> len ; tx_addr_offset += sizeof ( uint32_t ) ; metal_io_write32 ( shm_io , tx_avail_offset , rx_count ) ; metal_io_write32 ( ipi_io , IPI_TRIG_OFFSET , ipi_mask ) ; } } out : LPRINTF ( " \n " , ret ) ; if ( lbuf ) metal_free_memory ( lbuf ) ; return ret ; }
@brief   ipi_shmem_echod() - shared memory IPI demo
          This task will:
          * Wait for IPI interrupt from the remote
          * Once it received the interrupt, copy the content from
            the ping buffer to the pong buffer.
@brief ipi_shmem_echod () - shared memory IPI demo This task will : * Wait for IPI interrupt from the remote * Once it received the interrupt copy the content from the ping buffer to the pong buffer .
/* Set tx/rx buffer address offset */ /* Received ping from the other side */ /* Get the buffer location from the shared memory
			 * rx address array.
			 */ /* Read message header from shared memory */ /* Check if the message header is valid */ /* Read message */ /* increase rx used count to indicate it has consumed
			 * the received data */ /* Check if the it is the shutdown message */ /* Copy the message back to the other end */ /* Write to the address array to tell the other end
			 * the buffer address.
			 */ /* Increase number of available buffers */ /* Kick IPI to notify data is in shared buffer */