void el_execsequence (char const *const *argv1, char const *const *argv2, char const *const *envp) { if (!argv2[0]) { pathexec0_run(argv1, envp) ; strerr_dieexec(111, argv1[0]) ; } else { int wstat ; unsigned int j = 2 ; #ifdef EXECLINE_OLD_VARNAMES char fmt[UINT_FMT * 2 + 15] = "?=" ; #else char fmt[UINT_FMT + 1] = "?=" ; #endif pid_t pid = el_spawn0(argv1[0], argv1, envp) ; if (!pid) strerr_warnwu2sys("spawn ", argv1[0]) ; if (wait_pid(pid, &wstat) < 0) strerr_diefu2sys(111, "wait for ", argv1[0]) ; j += uint_fmt(fmt + j, wait_status(wstat)) ; fmt[j++] = 0 ; #ifdef EXECLINE_OLD_VARNAMES byte_copy(fmt + j, 13, "LASTEXITCODE=") ; j += 13 ; j += uint_fmt(fmt + j, wait_status(wstat)) ; fmt[j++] = 0 ; #endif pathexec_r(argv2, envp, env_len(envp), fmt, j) ; } strerr_dieexec(111, argv2[0]) ; }
/* * Set the slave address. The controller must be disabled when * changing the address. * * This operation does not issue anything to the I2C bus but sets * the target address for when the controller later issues a START. */ static void set_slave_addr(ig4iic_softc_t *sc, uint8_t slave, int trans_op) { uint32_t tar; uint32_t ctl; int use_10bit; use_10bit = sc->use_10bit; if (trans_op & SMB_TRANS_7BIT) use_10bit = 0; if (trans_op & SMB_TRANS_10BIT) use_10bit = 1; if (sc->slave_valid && sc->last_slave == slave && sc->use_10bit == use_10bit) { return; } sc->use_10bit = use_10bit; /* * Wait for TXFIFO to drain before disabling the controller. * * If a write message has not been completed it's really a * programming error, but for now in that case issue an extra * byte + STOP. * * If a read message has not been completed it's also a programming * error, for now just ignore it. */ wait_status(sc, IG4_STATUS_TX_NOTFULL); if (sc->write_started) { reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_STOP); sc->write_started = 0; } if (sc->read_started) sc->read_started = 0; wait_status(sc, IG4_STATUS_TX_EMPTY); set_controller(sc, 0); ctl = reg_read(sc, IG4_REG_CTL); ctl &= ~IG4_CTL_10BIT; ctl |= IG4_CTL_RESTARTEN; tar = slave; if (sc->use_10bit) { tar |= IG4_TAR_10BIT; ctl |= IG4_CTL_10BIT; } reg_write(sc, IG4_REG_CTL, ctl); reg_write(sc, IG4_REG_TAR_ADD, tar); set_controller(sc, IG4_I2C_ENABLE); sc->slave_valid = 1; sc->last_slave = slave; }
/** run_command(Command* cmd) ** Take a filled-out Command struct and run the command as specified. */ void run_command (Command* cmd) { //Fork cmd->pid = fork(); if(cmd->pid) { //Parent - add to background process list or wait if (cmd->background) { //Add to running background processes list add_background(cmd->pid); } else { wait_status(cmd->pid, 0); } } else { //Child //Input redirection (file or dev/null for background) if (cmd->background && !cmd->redirectIn) { dup2(open("/dev/null", O_RDONLY), 0); } else if (cmd->redirectIn) { dup2(fileno(cmd->redirectIn), STDIN_FILENO); fclose(cmd->redirectIn); } //Output redirection if (cmd->redirectOut) { dup2(fileno(cmd->redirectOut), STDOUT_FILENO); fclose(cmd->redirectOut); } //Reset normal signal handling signal(SIGINT, SIG_DFL); //Exec the child exec_child(cmd); } }
/* Receiver function */ static int receivedata(const struct spi_slave *slave, u8 *buffer, u32 size) { u32 read_data, base; int ret; struct img_spi_slave *img_slave = get_img_slave(slave); base = img_slave->base; /* * Do 32bit reads first. Clear status GDEX32BIT here so that the first * status reg. read gets the actual bit state */ write32_x(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX32BIT_MASK); while (size >= sizeof(u32)) { ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET, SPFI_GDEX32BIT_SHIFT); if (ret) return ret; read_data = read32_x(base + SPFI_GET_LONG_REG_OFFSET); memcpy(buffer, &read_data, sizeof(u32)); buffer += sizeof(u32); size -= sizeof(u32); /* Clear interrupt status on GDEX32BITL */ write32_x(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX32BIT_MASK); } /* * Do the remaining 8bit reads. Clear status GDEX8BIT here so that * the first status reg. read gets the actual bit state */ write32_x(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX8BIT_MASK); while (size) { ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET, SPFI_GDEX8BIT_SHIFT); if (ret) return ret; *buffer = read32_x(base + SPFI_GET_BYTE_REG_OFFSET); buffer++; size--; /* Clear interrupt status on SPFI_GDEX8BIT */ write32_x(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX8BIT_MASK); } return SPIM_OK; }
/** background_handler(int sig) ** Handler for SIGCHLD. Find the newly closed process, ** and remove it to the background process list. */ void background_handler(int sig) { int status; //Loop over background process list to find the closed process for (int i = 0; i < numBackground; i++) { //Use waitpid with nohang to determine if process has closed if (background[i].running) { status = wait_status(background[i].pid, WNOHANG); if (status != 2) { background[i].running = 0; } } } }
static int master_start(int port, int slave_addr) { int rv; /* Change to master send mode, reset stop bit, send start bit */ STM32_I2C_CR1(port) = (STM32_I2C_CR1(port) & ~(1 << 9)) | (1 << 8); /* Wait for start bit sent event */ rv = wait_status(port, SR1_SB, WAIT_MASTER_START); if (rv) return rv; /* Send address */ STM32_I2C_DR(port) = slave_addr; /* Wait for addr ready */ rv = wait_status(port, SR1_ADDR, WAIT_ADDR_READY); if (rv) return rv; read_clear_status(port); return EC_SUCCESS; }
static int do_umount() { pid_t pid; if((pid = fork()) == -1) { fprintf(stderr, "fork() failed\n"); exit(EXIT_FAILURE); } if(pid == 0) { exec_umount(); return -1; } else { return wait_status(pid); } }
/* * Incremental receive byte without stop (?). It is unclear why the slave * address is specified if this presumably is used in combination with * ig4iic_smb_quick(). */ int ig4iic_smb_recvb(device_t dev, u_char slave, char *byte) { ig4iic_softc_t *sc = device_get_softc(dev); int error; mtx_lock(&sc->mtx); set_slave_addr(sc, slave, 0); reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_COMMAND_RD); if (wait_status(sc, IG4_STATUS_RX_NOTEMPTY) == 0) { *byte = data_read(sc); error = 0; } else { *byte = 0; error = SMB_ETIMEOUT; } mtx_unlock(&sc->mtx); return error; }
/* * Incremental send byte without stop (?). It is unclear why the slave * address is specified if this presumably is used in combination with * ig4iic_smb_quick(). * * (Also, how would this work anyway? Issue the last byte with writeb()?) */ int ig4iic_smb_sendb(device_t dev, u_char slave, char byte) { ig4iic_softc_t *sc = device_get_softc(dev); uint32_t cmd; int error; mtx_lock(&sc->mtx); set_slave_addr(sc, slave, 0); cmd = byte; if (wait_status(sc, IG4_STATUS_TX_NOTFULL) == 0) { reg_write(sc, IG4_REG_DATA_CMD, cmd); error = 0; } else { error = SMB_ETIMEOUT; } mtx_unlock(&sc->mtx); return error; }
/* Transmitter function. Fills TX FIFO with data before enabling SPIM */ static int transmitdata(const struct spi_slave *slave, u8 *buffer, u32 size) { u32 blocksize, base, write_data; int ret; struct img_spi_slave *img_slave = get_img_slave(slave); base = img_slave->base; while (size) { /* Wait until FIFO empty */ write32_x(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_SDE_MASK); ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET, SPFI_SDE_SHIFT); if (ret) return ret; /* * Write to FIFO in blocks of 16 words (64 bytes) * Do 32bit writes first. */ blocksize = SPIM_MAX_BLOCK_BYTES; while ((size >= sizeof(u32)) && blocksize) { memcpy(&write_data, buffer, sizeof(u32)); write32_x(base + SPFI_SEND_LONG_REG_OFFSET, write_data); buffer += sizeof(u32); size -= sizeof(u32); blocksize -= sizeof(u32); } while (size && blocksize) { write32_x(base + SPFI_SEND_BYTE_REG_OFFSET, *buffer); buffer++; size--; blocksize--; } } return SPIM_OK; }
virtual ~plugin_thread() { change_status(stopping); wait_status(); }
/** run_pipe_commands (Command* cmd1, Command* cmd2) ** Take two commands and run them, piped together. */ void run_pipe_commands (Command* cmd1, Command* cmd2) { int fds[2]; //Make pipe between commands - 0 is read end, 1 is write end pipe(fds); //Fork first command cmd1->pid = fork(); if(!cmd1->pid) { //Child //Do input redirection if (cmd1->redirectIn) { dup2(fileno(cmd1->redirectIn), STDIN_FILENO); fclose(cmd2->redirectIn); } //Set stdout to write end of pipe dup2(fds[1] , 1); //Close files close(fds[0]); close(fds[1]); //Exec exec_child(cmd1); } //Fork second command cmd2->pid = fork(); if(!cmd2->pid) { //Child //Do output redirection if (cmd2->redirectOut) { dup2(fileno(cmd2->redirectOut), STDOUT_FILENO); fclose(cmd2->redirectOut); } //Set stdin to read end of pipe dup2(fds[0], 0); close(fds[0]); close(fds[1]); //Exec exec_child(cmd2); } //Close files close(fds[0]); close(fds[1]); int status[2]; //Wait on first process - if it fails, terminate the second if (wait_status(cmd1->pid, 0) == 1) { //Error occured - terminate kill(cmd2->pid, SIGINT); //Not a background command so we need to reap cmd2. //Don't want to display a message so don't use that command. waitpid(cmd2->pid, NULL, 0); } //Wait on second process waitpid(cmd2->pid, &status[1], 0); }
/* * Issue START with byte command, possible count, and a variable length * read or write buffer, then possible turn-around read. The read also * has a possible count received. * * For SMBUS - * * Quick: START+ADDR+RD/WR STOP * * Normal: START+ADDR+WR CMD DATA..DATA STOP * * START+ADDR+RD CMD * RESTART+ADDR RDATA..RDATA STOP * (can also be used for I2C transactions) * * Process Call: START+ADDR+WR CMD DATAL DATAH * RESTART+ADDR+RD RDATAL RDATAH STOP * * Block: START+ADDR+RD CMD * RESTART+ADDR+RD RCOUNT DATA... STOP * * START+ADDR+WR CMD * RESTART+ADDR+WR WCOUNT DATA... STOP * * For I2C - basically, no *COUNT fields, possibly no *CMD field. If the * sender needs to issue a 2-byte command it will incorporate it * into the write buffer and also set NOCMD. * * Generally speaking, the START+ADDR / RESTART+ADDR is handled automatically * by the controller at the beginning of a command sequence or on a data * direction turn-around, and we only need to tell it when to issue the STOP. */ static int smb_transaction(ig4iic_softc_t *sc, char cmd, int op, char *wbuf, int wcount, char *rbuf, int rcount, int *actualp) { int error; int unit; uint32_t last; /* * Debugging - dump registers */ if (ig4_dump) { unit = device_get_unit(sc->dev); if (ig4_dump & (1 << unit)) { ig4_dump &= ~(1 << unit); ig4iic_dump(sc); } } /* * Issue START or RESTART with next data byte, clear any previous * abort condition that may have been holding the txfifo in reset. */ last = IG4_DATA_RESTART; reg_read(sc, IG4_REG_CLR_TX_ABORT); if (actualp) *actualp = 0; /* * Issue command if not told otherwise (smbus). */ if ((op & SMB_TRANS_NOCMD) == 0) { error = wait_status(sc, IG4_STATUS_TX_NOTFULL); if (error) goto done; last |= (u_char)cmd; if (wcount == 0 && rcount == 0 && (op & SMB_TRANS_NOSTOP) == 0) last |= IG4_DATA_STOP; reg_write(sc, IG4_REG_DATA_CMD, last); last = 0; } /* * Clean out any previously received data. */ if (sc->rpos != sc->rnext && (op & SMB_TRANS_NOREPORT) == 0) { device_printf(sc->dev, "discarding %d bytes of spurious data\n", sc->rnext - sc->rpos); } sc->rpos = 0; sc->rnext = 0; /* * If writing and not told otherwise, issue the write count (smbus). */ if (wcount && (op & SMB_TRANS_NOCNT) == 0) { error = wait_status(sc, IG4_STATUS_TX_NOTFULL); if (error) goto done; last |= (u_char)cmd; reg_write(sc, IG4_REG_DATA_CMD, last); last = 0; } /* * Bulk write (i2c) */ while (wcount) { error = wait_status(sc, IG4_STATUS_TX_NOTFULL); if (error) goto done; last |= (u_char)*wbuf; if (wcount == 1 && rcount == 0 && (op & SMB_TRANS_NOSTOP) == 0) last |= IG4_DATA_STOP; reg_write(sc, IG4_REG_DATA_CMD, last); --wcount; ++wbuf; last = 0; } /* * Issue reads to xmit FIFO (strange, I know) to tell the controller * to clock in data. At the moment just issue one read ahead to * pipeline the incoming data. * * NOTE: In the case of NOCMD and wcount == 0 we still issue a * RESTART here, even if the data direction has not changed * from the previous CHAINing call. This we force the RESTART. * (A new START is issued automatically by the controller in * the other nominal cases such as a data direction change or * a previous STOP was issued). * * If this will be the last byte read we must also issue the STOP * at the end of the read. */ if (rcount) { last = IG4_DATA_RESTART | IG4_DATA_COMMAND_RD; if (rcount == 1 && (op & (SMB_TRANS_NOSTOP | SMB_TRANS_NOCNT)) == SMB_TRANS_NOCNT) { last |= IG4_DATA_STOP; } reg_write(sc, IG4_REG_DATA_CMD, last); last = IG4_DATA_COMMAND_RD; } /* * Bulk read (i2c) and count field handling (smbus) */ while (rcount) { /* * Maintain a pipeline by queueing the allowance for the next * read before waiting for the current read. */ if (rcount > 1) { if (op & SMB_TRANS_NOCNT) last = (rcount == 2) ? IG4_DATA_STOP : 0; else last = 0; reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_COMMAND_RD | last); } error = wait_status(sc, IG4_STATUS_RX_NOTEMPTY); if (error) { if ((op & SMB_TRANS_NOREPORT) == 0) { device_printf(sc->dev, "rx timeout addr 0x%02x\n", sc->last_slave); } goto done; } last = data_read(sc); if (op & SMB_TRANS_NOCNT) { *rbuf = (u_char)last; ++rbuf; --rcount; if (actualp) ++*actualp; } else { /* * Handle count field (smbus), which is not part of * the rcount'ed buffer. The first read data in a * bulk transfer is the count. * * XXX if rcount is loaded as 0 how do I generate a * STOP now without issuing another RD or WR? */ if (rcount > (u_char)last) rcount = (u_char)last; op |= SMB_TRANS_NOCNT; } } error = 0; done: /* XXX wait for xmit buffer to become empty */ last = reg_read(sc, IG4_REG_TX_ABRT_SOURCE); return (error); }
/* Function that carries out read/write operations */ static int spim_io(const struct spi_slave *slave, struct spim_buffer *first, struct spim_buffer *second) { u32 reg, base; int i, trans_count, ret; struct spim_buffer *transaction[2]; struct img_spi_slave *img_slave = get_img_slave(slave); base = img_slave->base; ret = check_buffers(slave, first, second); if (ret) return ret; /* * Soft reset peripheral internals, this will terminate any * pending transactions */ write32_x(base + SPFI_CONTROL_REG_OFFSET, SPIM_SOFT_RESET_MASK); write32_x(base + SPFI_CONTROL_REG_OFFSET, 0); /* Port state register */ reg = read32_x(base + SPFI_PORT_STATE_REG_OFFSET); reg = spi_write_reg_field(reg, SPFI_PORT_SELECT, slave->cs); write32_x(base + SPFI_PORT_STATE_REG_OFFSET, reg); /* Set transaction register */ reg = transaction_reg_setup(first, second); write32_x(base + SPFI_TRANSACTION_REG_OFFSET, reg); /* Clear status */ write32_x(base + SPFI_INT_CLEAR_REG_OFFSET, 0xffffffff); /* Set control register */ reg = control_reg_setup(first, second); write32_x(base + SPFI_CONTROL_REG_OFFSET, reg); /* First transaction always exists */ transaction[0] = first; trans_count = 1; /* Is there a second transaction? */ if (second) { transaction[1] = second; trans_count++; } /* Now write/read FIFO's */ for (i = 0; i < trans_count; i++) /* Which transaction to execute, "Send" or "Get"? */ if (transaction[i]->isread) { /* Get */ ret = receivedata(slave, transaction[i]->buffer, transaction[i]->size); if (ret) { printk(BIOS_ERR, "%s: Error: receive data failed.\n", __func__); return ret; } } else { /* Send */ ret = transmitdata(slave, transaction[i]->buffer, transaction[i]->size); if (ret) { printk(BIOS_ERR, "%s: Error: transmit data failed.\n", __func__); return ret; } } /* Wait for end of the transaction */ ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET, SPFI_ALLDONE_SHIFT); if (ret) return ret; /* * Soft reset peripheral internals, this will terminate any * pending transactions */ write32_x(base + SPFI_CONTROL_REG_OFFSET, SPIM_SOFT_RESET_MASK); write32_x(base + SPFI_CONTROL_REG_OFFSET, 0); return SPIM_OK; }