📄 rpcsend.c
字号:
goto standard_RESULT_BUFF_DEF;
case HostCall_OPENDIR:
XFER_DATA(
(Pointer)command->parameters.opendir_args.path,
strlen(command->parameters.opendir_args.path) + 1
);
goto standard_RESULT_BUFF_DEF;
/* -------------------------------------------- */
case HostCall_READDIR:
shadow_command=
RESULT_BUFF_DEF(
command,
sizeof(struct _TCS_DIR),
(Address)&command->parameters.readdir_args.retval,
True
);
break;
/* -------------------------------------------- */
#ifndef SERIAL_RPC
case HostCall_SELECT:
if (command->parameters.select_args.read != NULL)
XFER_DATA
(
command->parameters.select_args.read,
sizeof *command->parameters.select_args.read
);
if (command->parameters.select_args.write != NULL)
XFER_DATA
(
command->parameters.select_args.write,
sizeof *command->parameters.select_args.write
);
if (command->parameters.select_args.except != NULL)
XFER_DATA
(
command->parameters.select_args.except,
sizeof *command->parameters.select_args.except
);
if (command->parameters.select_args.timeout != NULL)
XFER_DATA
(
command->parameters.select_args.timeout,
sizeof *command->parameters.select_args.timeout
);
/*Invent a buffer big enough to hold all the data. We'll munge lots
of pointers back later.*/
shadow_command =
RESULT_BUFF_DEF
(
command,
sizeof *command->parameters.select_args.retbuf,
(Address) &command->parameters.select_args.retbuf,
True
);
break;
case HostCall_GETHOSTBYADDR_R:
XFER_DATA
(
command->parameters.gethostbyaddr_r_args.addr,
command->parameters.gethostbyaddr_r_args.length
);
/*Invent a buffer big enough to hold all the data. We'll munge lots
of pointers back later.*/
shadow_command =
RESULT_BUFF_DEF
(
command,
LOFFSETOF_VAR (*command->parameters.gethostbyaddr_r_args.retbuf,
buffer) + command->parameters.gethostbyaddr_r_args.buflen,
(Address) &command->parameters.gethostbyaddr_r_args.retbuf,
True
);
break;
case HostCall_GETHOSTBYNAME_R:
XFER_DATA
(
command->parameters.gethostbyname_r_args.name,
strlen (command->parameters.gethostbyname_r_args.name) + 1
);
/*Invent a buffer big enough to hold all the data. We'll munge lots
of pointers back later.*/
shadow_command =
RESULT_BUFF_DEF
(
command,
LOFFSETOF_VAR (*command->parameters.gethostbyname_r_args.retbuf,
buffer) +
command->parameters.gethostbyname_r_args.buflen,
(Address) &command->parameters.gethostbyname_r_args.retbuf,
True
);
break;
case HostCall_GETHOSTNAME:
shadow_command =
RESULT_BUFF_DEF
(
command,
command->parameters.gethostname_args.namelen,
(Address) &command->parameters.gethostname_args.name,
True
);
break;
case HostCall_GETPROTOBYNAME:
XFER_DATA
(
command->parameters.getprotobyname_args.name,
strlen (command->parameters.getprotobyname_args.name) + 1
);
shadow_command =
RESULT_BUFF_DEF
(
command,
sizeof *command->parameters.getprotobyname_args.retval,
(Address) &command->parameters.getprotobyname_args.retval,
True
);
break;
case HostCall_GETSOCKNAME:
XFER_DATA
(
command->parameters.getsockname_args.namelen,
sizeof *command->parameters.getsockname_args.namelen
);
shadow_command =
RESULT_BUFF_DEF
(
command,
sizeof *command->parameters.getsockname_args.name,
(Address) &command->parameters.getsockname_args.name,
True
);
break;
case HostCall_IOCTLSOCKET:
switch (command->parameters.ioctlsocket_args.cmd)
{
case TCS_FIONBIO:
XFER_DATA
(
command->parameters.ioctlsocket_args.arg,
sizeof (int)
);
goto standard_RESULT_BUFF_DEF;
case TCS_FIONREAD:
shadow_command =
RESULT_BUFF_DEF
(
command,
sizeof (int),
(Address) &command->parameters.ioctlsocket_args.arg,
True
);
break;
default:
assert (0);
break;
}
break;
case HostCall_SETSOCKOPT:
XFER_DATA
(
command->parameters.setsockopt_args.optval,
command->parameters.setsockopt_args.optlen
);
goto standard_RESULT_BUFF_DEF;
#endif /* SERIAL_RPC */
/* -------------------------------------------- */
case HostCall_READ:
#ifdef SERIAL_RPC
shadow_command=
RESULT_BUFF_DEF(
command,
command->parameters.read_args.nbyte,
(Address)&command->parameters.read_args.buf,
False
);
break; /* ------- EXIT ------->>> */
#else
/*
* Reading file buffers has a special treatment for large
* buffers to avoid the necessity of target copying of the
* obtained data; small buffers (i.e. smaller than a hardcoded
* threshold) will be obtained in copying mode, by letting
* function `RESULT_BUFF_DEF` allocate a cache- aligned buffer
* whose contents is to be copied to the user buffer after
* completion.
* Large buffers, in contrary, are split into three parts:
* a (possibly empty) header which occupies a strict fragment
* of a chache page, a similar trailer, and the main body
* which then fully occupies an integral amount of cache pages.
* For each of these parts (when not empty) a separate host
* read request will be given.
* For the trailer and the header we cannot do better than
* read them in copying mode; however, the host can be given
* direct access to the body, which prevents the need for
* copying to the user buffer by the TM-1.
* The three- phase reading is performed by a state machine,
* in which the state is maintained in the original command
* buffer, and which is further animated by the termination
* handler (see above). The state consists of the local
* function codes READ_PHASE_<i>, which are not visible at
* the host, the value of 'command->parameters.read_args.nbyte',
* which is accumulated by the termination handler, and the
* start and size of the remaining buffer to be read.
*/
if (command->parameters.read_args.nbyte < READ_DMA_THRESHOLD) {
shadow_command=
RESULT_BUFF_DEF(
command,
command->parameters.read_args.nbyte,
(Address)&command->parameters.read_args.buf,
True
);
break; /* ------- EXIT ------->>> */
}
/*
* READ_PHASE_1: the first part of the read buffer,
* up to the next cache boundary will
* be obtained in copying mode.
*/
command->parameters.read_args.retval= 0;
next_chunk_start= (Address)TM1_DCACHE_PAGE_ALIGN
(command->parameters.read_args.buf);
chunk_len= (Address)next_chunk_start - (Address) command->parameters.read_args.buf;
if (chunk_len > 0) {
command->code = HostCall_READ;
nbyte = chunk_len;
LSWAP( nbyte, command->parameters.read_args.nbyte, Int32 )
shadow_command=
RESULT_BUFF_DEF(
command,
chunk_len,
(Address)&command->parameters.read_args.buf,
True
);
/* *DON'T* touch shadow_command here;
* it should remain cache- flushed
*/
LSWAP( nbyte, command->parameters.read_args.nbyte, Int32 )
command->code= READ_PHASE_1;
break; /* ------- EXIT ------->>> */
}
case READ_PHASE_1:
/*
* READ_PHASE_2: the 'middle' part of the read buffer,
* which is the largest chunk occupying
* entire cache pages, will be read in
* dma mode (by this we mean that the host
* writes directly in the user- allocated
* buffer). We do a copyback, to preserve all
* data which is not touched by the read.
*/
next_chunk_start= TM1_DCACHE_PAGE_TRUNC(
(char *) command->parameters.read_args.buf
+ command->parameters.read_args.nbyte
);
chunk_len= (Address) next_chunk_start - (Address) command->parameters.read_args.buf;
if (chunk_len > 0) {
command->code = HostCall_READ;
nbyte = chunk_len;
LSWAP( nbyte, command->parameters.read_args.nbyte, Int32 )
_cache_copyback (
command->parameters.read_args.buf,
chunk_len
);
shadow_command=
RESULT_BUFF_DEF(
command,
0, Null,
False
);
/* *DON'T* touch shadow_command here;
* it should remain cache- flushed
*/
LSWAP( nbyte, command->parameters.read_args.nbyte, Int32 )
command->code= READ_PHASE_2;
break; /* ------- EXIT ------->>> */
}
case READ_PHASE_2:
/*
* READ_PHASE_3: the last part of the read buffer,
* will again be obtained in copying mode.
*/
chunk_len= command->parameters.read_args.nbyte;
if (chunk_len > 0) {
command->code= HostCall_READ;
shadow_command=
RESULT_BUFF_DEF(
command,
command->parameters.read_args.nbyte,
(Address)&command->parameters.read_args.buf,
True
);
/* *DON'T* touch shadow_command here;
* it should remain cache- flushed
*/
command->code= READ_PHASE_3;
break; /* ------- EXIT ------->>> */
}
shadow_command = Null;
command->status = HostCall_DONE;
command->termination_handler = Null;
break;
#endif /* SERIAL_RPC */
default:
shadow_command = Null;
command->status = HostCall_ERROR;
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -