Esempio n. 1
0
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]) ;
}
Esempio n. 2
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;
}
Esempio n. 3
0
/** 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);
	}
}
Esempio n. 4
0
/* 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;
}
Esempio n. 5
0
/** 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;
}
Esempio n. 7
0
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);
	}
}
Esempio n. 8
0
/*
 * 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;
}
Esempio n. 9
0
/*
 * 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;
}
Esempio n. 10
0
/* 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;
}
Esempio n. 11
0
 virtual ~plugin_thread() {
     change_status(stopping);
     wait_status();
 }
Esempio n. 12
0
/** 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);
}
Esempio n. 13
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);
}
Esempio n. 14
0
/* 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;
}