📄 rpcclient.c
字号:
/*
* +-------------------------------------------------------------------+
* | Copyright (c) 1995,1996,1997 by Philips Semiconductors. |
* | |
* | This software is furnished under a license and may only be used |
* | and copied in accordance with the terms and conditions of such a |
* | license and with the inclusion of this copyright notice. This |
* | software or any other copies of this software may not be provided |
* | or otherwise made available to any other person. The ownership |
* | and title of this software is not transferred. |
* | |
* | The information in this software is subject to change without |
* | any prior notice and should not be construed as a commitment by |
* | Philips Semiconductors. |
* | |
* | This code and information is provided "as is" without any |
* | warranty of any kind, either expressed or implied, including but |
* | not limited to the implied warranties of merchantability and/or |
* | fitness for any particular purpose. |
* +-------------------------------------------------------------------+
*
* Module name : RPCClient.c 1.42
*
* Title : Implementation of HostCall interface
*
* Last update : 12:23:28 - 99/12/10
*
* Description :
*
* This module is part of an implementation of the HostCall interface.
* HostCall is the software component which is required by
* the TCS toolset to adapt the programs generated by this toolset
* to a specific host (see file HostCall.h in the TCS include dir).
*
* RPCClient is one of two modules which form an implementation of
* the HostCall interface (the other one is HostIF); RPCClient is
* still entirely host independent, and solves nasty datacache related
* issues, and selects efficient ways of transferring data over the
* PCI bus. More specific, the problems addressed in this module are
* as follows:
*
* 1) In reading and writing large amounts of data (e.g. by
* file IO functions 'read' and 'write'), data copying by
* the TM-1 CPU side should be avoided as much as possible.
*
* 2) In reading and writing large amounts of data, occupying the
* memory buses should be avoided as much as possible.
*
* 3) This interface provides- and gets data to the host via
* shared memory, by sending and receiving pointers to data
* via HostIF.
* The HostCall interface does not have any control over the
* alignment of the provided command buffers and provided
* data- or return buffers. Since reading/writing by the host
* into TM-1 visible memory is not synchronised with the TM-1
* data cache, the TM-1 has to do a cache copyback of data provided
* to the host, and cache invalidates on memory buffers filled
* by the host. Especially in multitasking environments, these
* operations are extremely dangerous when applied to memory
* which occupies cache pages which are not completely owned
* by the calling thread.
*
* RPCClient solves problem 3 by copying all relevant data
* (like the command buffer) into cache aligned memory, and
* using these copies in the actual communication. RPCClient
* solves problem 1 by providing write buffers for direct reading
* to the host, and by providing the large bodies of read buffers
* to the host in order to give the host direct access to these buffers.
* This is referred to in the sequel as 'dma' (lower case).
* RPCClient does not yet solve problem 2; but a modification using
* hardware DMA will soon be provided.
*
* The implementation of HostCall is partitioned between RPCClient
* and HostIF as follows:
*
* - _HostCall_notify is provided in HostIF
* - _HostCall_host_send is provided in RPCClient.
* - _HostCall_init and -terminate are provided in RPCClient.
* - Module RPCClient provides the general implementation strategy
* and solves all cache problems.
* - HostIF provides a simple communication interface for sending
* pointers hence and forth.
* - RPCClient communicates with a RPCServer on the host.
*/
/*---------------------------- Includes --------------------------------------*/
#define NDEBUG
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "Lib_Local.h"
#include <ops/custom_defs.h>
#include <tmtypes.h>
#include <HostCall.h>
#include "HostIF.h"
#include "RPC_Common.h"
#include <tmlib/tmlibc.h>
/*---------------------------- Module State ----------------------------------*/
/*
#include <tmlib/tmtypes.h>
#include <tmlib/HostCall.h>
*/
/*
* Threshold after which the read command will
* try to avoid unnecessary copying at the
* target site by letting the host do dma
* in the user- provided buffer.
*/
#define READ_DMA_THRESHOLD 320 /* bytes */
/*
* DCache page size and alignment:
*/
#define TM1_DCACHE_PAGE_SIZE 64
#define TM1_DCACHE_PAGE_TRUNC(address) \
((Address) LROUND_DOWN ((UInt32) (address), (UInt32) TM1_DCACHE_PAGE_SIZE))
#define TM1_DCACHE_PAGE_ALIGN(address) \
((Address) LROUND_UP ((UInt32) (address), (UInt32) TM1_DCACHE_PAGE_SIZE))
/* forward declaration */
static void termination_handler( HostCall_command *command );
/*----------------------------- Data Block To Host ---------------------------*/
/*
* Declaration of the data which is to be allocated
* for one host call. It will be allocated in one unit,
* and contains a cache aligned copy of the command,
* a cache aligned copy of the result buffer and tempotary
* working space:
*/
typedef struct ShadowBlockHeader {
HostCall_command command;
Int32 result_buf_offset;
Int32 result_buf_len;
} ShadowBlockHeader;
typedef struct ShadowBlock {
ShadowBlockHeader header;
/* copy of result buffer to be filled */
/* by host follows after this header. */
} ShadowBlock;
/*--------------------------------- Cache Issues -----------------------------*/
/*
* Make a copy of a command buffer, which is to be fully
* within 'private' cache pages; that is, prevent the
* possibility that parts of the cache pages which are
* occupied by the result are used by other processes
* during the host service request. Optionally, the
* address of a field in a command buffer which contains
* the address of a result buffer can be specified,
* with the length of this buffer. When present,
* a copy of the buffer will be allocated with (that is,
* after) the copy of the command, together with some
* administration.
* The result is linked into the user- provided command
* buffer, and will be sent to the host instead of the
* user- provided command- and result buffer; the termination
* handler (see below) will contain some termination
* handling after the service request has completed;
* this termination handling mainly consists of copying back
* the results from the host into the user- provided space,
* and of deallocation of the shadow command.
* The result is properly cache- flushed such that the
* host can expect it in memory, and cache- invalidated
* such that the host- written results are visible
* upon return of the host request.
* Parameter 'preserve' causes the contents of the user
* provided command buffer in which no results are returned
* to be preserved (simply by copying the contents into the
* command buffer copy before the transaction).
*/
static HostCall_command*
make_shadow(
HostCall_command *command,
Int32 result_buf_len,
Address result_buf,
Bool preserve
)
{
Int32 shadow_block_size;
ShadowBlock *shadow_block;
shadow_block_size = sizeof(ShadowBlock) + result_buf_len;
shadow_block = (Pointer)_cache_malloc(shadow_block_size, -1);
if (shadow_block == Null) {
return Null;
}
memcpy((Pointer)&shadow_block->header.command, (Pointer)command, sizeof(*command));
shadow_block->header.result_buf_len = result_buf_len;
shadow_block->header.command.target_link = command;
command->target_link = (HostCall_command *)shadow_block;
command->termination_handler = (HostCall_Termination_Handler)termination_handler;
if (result_buf_len == 0) {
_cache_copyback ( shadow_block, sizeof(ShadowBlockHeader) );
} else {
Int32 result_buf_offset = result_buf - (Address)command;
Address *pp_shadow_result_buf = (Pointer)(((Address)&shadow_block->header.command)+result_buf_offset);
Address p_shadow_result_buf = (Address)(shadow_block+1);
*pp_shadow_result_buf = p_shadow_result_buf;
shadow_block->header.result_buf_offset = result_buf_offset;
if (preserve) {
memcpy ( (Pointer)p_shadow_result_buf, *(Pointer*)result_buf, result_buf_len );
}
_cache_copyback ( shadow_block, sizeof(ShadowBlockHeader) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -