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

📄 synth_intr.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
        // 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 + -