⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rpcclient.c

📁 PNX系列设备驱动 PNX系列设备驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
        _cache_copyback ( p_shadow_result_buf, result_buf_len      );
    }

    return &shadow_block->header.command;
}





/*--------------------------- The Screwd Protocol Stuff ----------------------*/


/*
 * Termination handler, which will be called by the sender
 * of a host request after this request has completed.
 * it contains some postprocessing, plus follow- up code
 * for the three- stage read engine.
 * The cache invalidation of the command buffer already
 * has been done in the notification routine; invalidation
 * of a result buffer, when present, must still be done.
 */

static void termination_handler( HostCall_command  *command )
{
    ShadowBlock       *shadow_block           = (ShadowBlock*)command->target_link;
    HostCall_command  *shadow_command         = &shadow_block->header.command;
    Int32              result_buf_len         =  shadow_block->header.result_buf_len;
    Int32              result_buf_offset      =  shadow_block->header.result_buf_offset;

    Address           *pp_shadow_result_buf   = (Pointer)(((Address)shadow_command)+result_buf_offset);
    Address           *pp_command_result_buf  = (Pointer)(((Address)command       )+result_buf_offset);
    Address            p_shadow_result_buf    = *pp_shadow_result_buf;
    Address            p_command_result_buf;

    Bool               has_result_buffer       = result_buf_len > 0;
    Int32              readsize, reqsize;

   /*
    * Check if there is a result buffer to be copied
    * back to the original command. In principle,
    * this can be concluded from the result buffer size (!=0)
    * However, some commands (getenv) may return Null,
    * in which case the original buffer pointer is cleared:
    */
    if (p_shadow_result_buf == Null) has_result_buffer= Null;

    if ( has_result_buffer ) {
       p_command_result_buf = *pp_command_result_buf;
       _cache_invalidate( p_shadow_result_buf, result_buf_len );
       memcpy( p_command_result_buf, p_shadow_result_buf, result_buf_len );
    }



   /*
    * Accumulate the data which has been read in case
    * of a read command, and flag premature termination
    * when not all requested data could be returned:
    */
    switch (command->code) {
    case READ_PHASE_2:
        _cache_invalidate(
             shadow_command->parameters.read_args.buf,
             shadow_command->parameters.read_args.retval
        );
    /*FALLTHROUGH*/

    case READ_PHASE_1:
    case READ_PHASE_3:
        if (shadow_command->notification_status == HostCall_ERROR) {
            readsize= 0;
        } else {
            readsize= shadow_command->parameters.read_args.retval;
        }
        reqsize= shadow_command->parameters.read_args.nbyte;

        shadow_command->code= command->code;
        shadow_command->parameters.read_args.retval = command->parameters.read_args.retval + readsize;
        shadow_command->parameters.read_args.nbyte  = command->parameters.read_args.nbyte  - readsize;

        if (has_result_buffer) {
           /*
            * Adapted read buffer start, to be patched
            * into original command buffer after this switch:
            */
            p_command_result_buf += readsize;
        } else {
           /*
            * Adapted read buffer start, to be copied with
            * rest of shadow command into original command
            * buffer after this switch:
            */
            shadow_command->parameters.read_args.buf = (Pointer)((Address)command->parameters.read_args.buf + readsize);
        }
    }

   /*
    * Copy the contents of the returned command buffer
    * (returned results, original function code, and unmodified
    * original contents) back to the command buffer.
    * However, do not destroy the result buffer pointer.
    * Afterwards: free up all allocated memory.
    * NB: note that the buffer pointer is also implicitly
    * incremented for read commands (see code in above switch):
    */
   memcpy(command, shadow_command, sizeof(HostCall_command));

    if (has_result_buffer) {
       *pp_command_result_buf= p_command_result_buf;
    }

   _cache_free( shadow_block );



   /*
    * In case of read command, do the
    * next read in recursion:
    */
    switch (command->code) {

    case READ_PHASE_2:
    case READ_PHASE_1:
            if (readsize < reqsize) {
                command->code= HostCall_READ;
            } else {
                _HostCall_send(command);
            }
            break;

    case READ_PHASE_3:
            command->code= HostCall_READ;
            break;
    }
}




/*--------------------------- Interface Functions-----------------------------*/


/*
 * Service request routine to host:
 */
void _HostCall_host_send( HostCall_command *command )
{
        HostCall_command *shadow_command;

        Address     next_chunk_start;
        Int32   chunk_len;
        Int32   nbyte;

#define RESULT_BUFF_DEF(command,result_buf_len,result_buf,preserve) \
            make_shadow(command,result_buf_len,result_buf,preserve)
      
#define XFER_DATA(addr,len) \
           _cache_copyback(addr,len)

#define XFER_DATA2(addr,len) \
           _cache_copyback(addr,len)

#undef SERIAL_RPC
#include "RPCSend.c"

        if (command->status != HostCall_DONE)
        {
           if (shadow_command == Null)
           {
              command->status = HostCall_ERROR;
           }
           else
           {
              if (_HostIF_send (shadow_command))
              {
                 if (shadow_command->status == HostCall_DONE)
                 {
                    command->status = HostCall_DONE;
                    _cache_invalidate
                    (
                       shadow_command,
                       sizeof (ShadowBlockHeader)
                    );
                 }
              }
              else
              {
                 _cache_free (command->target_link);
                 command->status = HostCall_ERROR;
              }
           }
        }
}



/*
 * Reply routine which handles messages from host;
 * such messages always are notifications of served
 * commands; invalidate the cache pages in which the
 * result buffer plus attached administration is mapped.
 * This allows inspection for further  processing without
 * reading stale data; invalidation of any result buffer
 * attached to the command is done in the termination
 * handler.
 */

void _RPCClient_notify ( HostCall_command *command )
{
        _cache_invalidate( command, sizeof( ShadowBlockHeader ) );

        command->notification_handler( command );
}



/*--------------------------- Initialisation / Termination -------------------*/


Bool    _HostCall_init( void )
{
   return _HostIF_init();
}



void _HostCall_term( void )
{
        _HostIF_term();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -