📄 synth_intr.c
字号:
// that the eCos application was run from some process other than a shell
// and hence that file descriptors 3 and 4 are already in use, but that is not
// supported. One possible workaround would be to close all file descriptors
// >= 3, another would be to munge the argument vector passing the file
// descriptors actually being used.
unexpected_error |= (0 != cyg_hal_sys_close(to_aux_pipe[1]));
unexpected_error |= (0 != cyg_hal_sys_close(from_aux_pipe[0]));
if (3 != to_aux_pipe[0]) {
if (3 == from_aux_pipe[1]) {
// Because to_aux_pipe[] was set up first it should have received file descriptors 3 and 4.
diag_printf("Internal error: file descriptors have been allocated in an unusual order.\n");
cyg_hal_sys_exit(1);
} else {
unexpected_error |= (3 != cyg_hal_sys_dup2(to_aux_pipe[0], 3));
unexpected_error |= (0 != cyg_hal_sys_close(to_aux_pipe[0]));
}
}
if (4 != from_aux_pipe[1]) {
unexpected_error |= (4 != cyg_hal_sys_dup2(from_aux_pipe[1], 4));
unexpected_error |= (0 != cyg_hal_sys_close(from_aux_pipe[1]));
}
if (unexpected_error) {
diag_printf("Error: internal error in auxiliary process, failed to manipulate pipes.\n");
cyg_hal_sys_exit(1);
}
// The arguments passed to the auxiliary are mostly those for
// the synthetic target application, except for argv[0] which
// is replaced with the auxiliary's pathname. The latter
// currently holds at least one ../, and cleaning this up is
// useful.
//
// If the argument vector contains -- then that and subsequent
// arguments are not passed to the auxiliary. Instead such
// arguments are reserved for use by the application.
do {
int len;
for (len = 0; '\0' != filename[len]; len++)
;
found_dotdot = false;
for (i = 0; i < (len - 4); i++) {
if (('/' == filename[i]) && ('.' == filename[i+1]) && ('.' == filename[i+2]) && ('/' == filename[i+3])) {
j = i + 3;
for ( --i; (i >= 0) && ('/' != filename[i]); i--) {
CYG_EMPTY_STATEMENT;
}
if (i >= 0) {
found_dotdot = true;
do {
i++; j++;
filename[i] = filename[j];
} while ('\0' != filename[i]);
}
}
}
} while(found_dotdot);
cyg_hal_sys_argv[0] = filename;
for (i = 1; i < cyg_hal_sys_argc; i++) {
const char* tmp = cyg_hal_sys_argv[i];
if (('-' == tmp[0]) && ('-' == tmp[1]) && ('\0' == tmp[2])) {
cyg_hal_sys_argv[i] = (const char*) 0;
break;
}
}
cyg_hal_sys_execve(filename, cyg_hal_sys_argv, cyg_hal_sys_environ);
// An execute error has occurred. Report this here, then exit. The
// parent will detect a close on the pipe without having received
// any data, and it will assume that a suitable diagnostic will have
// been displayed already.
diag_printf("Error: failed to execute the I/O auxiliary.\n");
cyg_hal_sys_exit(1);
} else {
int rc;
char buf[1];
// Still executing the eCos application.
// Do some cleaning-up.
to_aux = to_aux_pipe[1];
from_aux = from_aux_pipe[0];
if ((0 != cyg_hal_sys_close(to_aux_pipe[0])) ||
(0 != cyg_hal_sys_close(from_aux_pipe[1]))) {
diag_printf("Error: internal error in main process, failed to manipulate pipes.\n");
cyg_hal_sys_exit(1);
}
// It is now a good idea to block until the auxiliary is
// ready, i.e. give it a chance to read in its configuration
// files, load appropriate scripts, pop up windows, ... This
// may take a couple of seconds or so. Once the auxiliary is
// ready it will write a single byte down the pipe. This is
// the only time that the auxiliary will write other than when
// responding to a request.
do {
rc = cyg_hal_sys_read(from_aux, buf, 1);
} while (-CYG_HAL_SYS_EINTR == rc);
if (1 != rc) {
// The auxiliary has not started up successfully, so exit
// immediately. It should have generated appropriate
// diagnostics.
cyg_hal_sys_exit(1);
}
}
// At this point the auxiliary is up and running. It should not
// generate any interrupts just yet since none of the devices have
// been initialized. Remember that the auxiliary is now running,
// so that the initialization routines for those devices can
// figure out that they should interact with the auxiliary rather
// than attempt anything manually.
synth_auxiliary_running = true;
// Make sure that the auxiliary is the right version.
synth_auxiliary_xchgmsg(SYNTH_DEV_AUXILIARY, SYNTH_AUXREQ_GET_VERSION, 0, 0,
(const unsigned char*) 0, 0,
&aux_version, (unsigned char*) 0, (int*) 0, 0);
if (SYNTH_AUXILIARY_PROTOCOL_VERSION != aux_version) {
synth_auxiliary_running = false;
diag_printf("Error: an incorrect version of the I/O auxiliary is installed\n"
" Expected version %d, actual version %d\n"
" Installed binary is %s\n",
SYNTH_AUXILIARY_PROTOCOL_VERSION, aux_version, filename);
cyg_hal_sys_exit(1);
}
}
// Write a request to the I/O auxiliary, and optionally get back a
// reply. The dev_id is 0 for messages intended for the auxiliary
// itself, for example a device instantiation or a request for the
// current interrupt sate. Otherwise it identifies a specific device.
// The request code is specific to the device, and the two optional
// arguments are specific to the request.
void
synth_auxiliary_xchgmsg(int devid, int reqcode, int arg1, int arg2,
const unsigned char* txdata, int txlen,
int* result,
unsigned char* rxdata, int* actual_rxlen, int rxlen)
{
unsigned char request[SYNTH_REQUEST_LENGTH];
unsigned char reply[SYNTH_REPLY_LENGTH];
int rc;
int reply_rxlen;
cyg_bool_t old_isrstate;
CYG_ASSERT(devid >= 0, "A valid device id should be supplied");
CYG_ASSERT((0 == txlen) || ((const unsigned char*)0 != txdata), "Data transmits require a transmit buffer");
CYG_ASSERT((0 == rxlen) || ((unsigned char*)0 != rxdata), "Data receives require a receive buffer");
CYG_ASSERT((0 == rxlen) || ((int*)0 != result), "If a reply is expected then space must be allocated");
// I/O interactions with the auxiliary must be atomic: a context switch in
// between sending the header and the actual data would be bad.
HAL_DISABLE_INTERRUPTS(old_isrstate);
// The auxiliary should be running for the duration of this
// exchange. However the auxiliary can disappear asynchronously,
// so it is not possible for higher-level code to be sure that the
// auxiliary is still running.
//
// If the auxiliary disappears during this call then usually this
// will cause a SIGCHILD or SIGPIPE, both of which result in
// termination. The exception is when the auxiliary decides to
// shut down stdout for some reason without exiting - that has to
// be detected in the read loop.
if (synth_auxiliary_running) {
request[SYNTH_REQUEST_DEVID_OFFSET + 0] = (devid >> 0) & 0x0FF;
request[SYNTH_REQUEST_DEVID_OFFSET + 1] = (devid >> 8) & 0x0FF;
request[SYNTH_REQUEST_DEVID_OFFSET + 2] = (devid >> 16) & 0x0FF;
request[SYNTH_REQUEST_DEVID_OFFSET + 3] = (devid >> 24) & 0x0FF;
request[SYNTH_REQUEST_REQUEST_OFFSET + 0] = (reqcode >> 0) & 0x0FF;
request[SYNTH_REQUEST_REQUEST_OFFSET + 1] = (reqcode >> 8) & 0x0FF;
request[SYNTH_REQUEST_REQUEST_OFFSET + 2] = (reqcode >> 16) & 0x0FF;
request[SYNTH_REQUEST_REQUEST_OFFSET + 3] = (reqcode >> 24) & 0x0FF;
request[SYNTH_REQUEST_ARG1_OFFSET + 0] = (arg1 >> 0) & 0x0FF;
request[SYNTH_REQUEST_ARG1_OFFSET + 1] = (arg1 >> 8) & 0x0FF;
request[SYNTH_REQUEST_ARG1_OFFSET + 2] = (arg1 >> 16) & 0x0FF;
request[SYNTH_REQUEST_ARG1_OFFSET + 3] = (arg1 >> 24) & 0x0FF;
request[SYNTH_REQUEST_ARG2_OFFSET + 0] = (arg2 >> 0) & 0x0FF;
request[SYNTH_REQUEST_ARG2_OFFSET + 1] = (arg2 >> 8) & 0x0FF;
request[SYNTH_REQUEST_ARG2_OFFSET + 2] = (arg2 >> 16) & 0x0FF;
request[SYNTH_REQUEST_ARG2_OFFSET + 3] = (arg2 >> 24) & 0x0FF;
request[SYNTH_REQUEST_TXLEN_OFFSET + 0] = (txlen >> 0) & 0x0FF;
request[SYNTH_REQUEST_TXLEN_OFFSET + 1] = (txlen >> 8) & 0x0FF;
request[SYNTH_REQUEST_TXLEN_OFFSET + 2] = (txlen >> 16) & 0x0FF;
request[SYNTH_REQUEST_TXLEN_OFFSET + 3] = (txlen >> 24) & 0x0FF;
request[SYNTH_REQUEST_RXLEN_OFFSET + 0] = (rxlen >> 0) & 0x0FF;
request[SYNTH_REQUEST_RXLEN_OFFSET + 1] = (rxlen >> 8) & 0x0FF;
request[SYNTH_REQUEST_RXLEN_OFFSET + 2] = (rxlen >> 16) & 0x0FF;
request[SYNTH_REQUEST_RXLEN_OFFSET + 3] = ((rxlen >> 24) & 0x0FF) | (((int*)0 != result) ? 0x080 : 0);
// sizeof(synth_auxiliary_request) < PIPE_BUF (4096) so a single write should be atomic,
// subject only to incoming clock or SIGIO or child-related signals.
do {
rc = cyg_hal_sys_write(to_aux, (const void*) &request, SYNTH_REQUEST_LENGTH);
} while (-CYG_HAL_SYS_EINTR == rc);
// Is there any more data to be sent?
if (0 < txlen) {
int sent = 0;
CYG_LOOP_INVARIANT(synth_auxiliary_running, "The auxiliary cannot just disappear");
while (sent < txlen) {
rc = cyg_hal_sys_write(to_aux, (const void*) &(txdata[sent]), txlen - sent);
if (-CYG_HAL_SYS_EINTR == rc) {
continue;
} else if (rc < 0) {
diag_printf("Internal error: unexpected result %d when sending buffer to auxiliary.\n", rc);
diag_printf(" : this application is exiting immediately.\n");
cyg_hal_sys_exit(1);
} else {
sent += rc;
}
}
CYG_ASSERT(sent <= txlen, "Amount of data sent should not exceed requested size");
}
// The auxiliary can now process this entire request. Is a reply expected?
if ((int*)0 != result) {
// The basic reply is also only a small number of bytes, so should be atomic.
do {
rc = cyg_hal_sys_read(from_aux, (void*) &reply, SYNTH_REPLY_LENGTH);
} while (-CYG_HAL_SYS_EINTR == rc);
if (rc <= 0) {
if (rc < 0) {
diag_printf("Internal error: unexpected result %d when receiving data from auxiliary.\n", rc);
} else {
diag_printf("Internal error: EOF detected on pipe from auxiliary.\n");
}
diag_printf(" : this application is exiting immediately.\n");
cyg_hal_sys_exit(1);
}
CYG_ASSERT(SYNTH_REPLY_LENGTH == rc, "The correct amount of data should have been read");
// Replies are packed in Tcl and assumed to be two 32-bit
// little-endian integers.
*result = (reply[SYNTH_REPLY_RESULT_OFFSET + 3] << 24) |
(reply[SYNTH_REPLY_RESULT_OFFSET + 2] << 16) |
(reply[SYNTH_REPLY_RESULT_OFFSET + 1] << 8) |
(reply[SYNTH_REPLY_RESULT_OFFSET + 0] << 0);
reply_rxlen = (reply[SYNTH_REPLY_RXLEN_OFFSET + 3] << 24) |
(reply[SYNTH_REPLY_RXLEN_OFFSET + 2] << 16) |
(reply[SYNTH_REPLY_RXLEN_OFFSET + 1] << 8) |
(reply[SYNTH_REPLY_RXLEN_OFFSET + 0] << 0);
CYG_ASSERT(reply_rxlen <= rxlen, "The auxiliary should not be sending more data than was requested.");
if ((int*)0 != actual_rxlen) {
*actual_rxlen = reply_rxlen;
}
if (reply_rxlen) {
int received = 0;
while (received < reply_rxlen) {
rc = cyg_hal_sys_read(from_aux, (void*) &(rxdata[received]), reply_rxlen - received);
if (-CYG_HAL_SYS_EINTR == rc) {
continue;
} else if (rc <= 0) {
if (rc < 0) {
diag_printf("Internal error: unexpected result %d when receiving data from auxiliary.\n", rc);
} else {
diag_printf("Internal error: EOF detected on pipe from auxiliary.\n");
}
diag_printf(" : this application is exiting immediately.\n");
} else {
received += rc;
}
}
CYG_ASSERT(received == reply_rxlen, "Amount received should be exact");
}
}
}
HAL_RESTORE_INTERRUPTS(old_isrstate);
}
// Instantiate a device. This takes arguments such as
// devs/eth/synth/ecosynth, current, ethernet, eth0, and 200x100 If
// the package and version are NULL strings then the device being
// initialized is application-specific and does not belong to any
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -