Пример #1
0
static int poll_wait_key(char *obuf, struct uart_cpm_port *pinfo)
{
	u_char		c, *cp;
	volatile cbd_t	*bdp;
	int		i;

	/* Get the address of the host memory buffer.
	 */
	bdp = pinfo->rx_cur;
	while (bdp->cbd_sc & BD_SC_EMPTY)
		;

	/* If the buffer address is in the CPM DPRAM, don't
	 * convert it.
	 */
	cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);

	if (obuf) {
		i = c = bdp->cbd_datlen;
		while (i-- > 0)
			*obuf++ = *cp++;
	} else
		c = *cp;
	bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
	bdp->cbd_sc |= BD_SC_EMPTY;

	if (bdp->cbd_sc & BD_SC_WRAP)
		bdp = pinfo->rx_bd_base;
	else
		bdp++;
	pinfo->rx_cur = (cbd_t *)bdp;

	return (int)c;
}
Пример #2
0
/*
 * Receive character from the serial port.  This only works well
 * before the port is initialize for real use.
 */
static int kgdb_wait_key(char *obuf)
{
	struct uart_cpm_port *pinfo;
	u_char		c, *cp;
	volatile cbd_t	*bdp;
	int		i;

	pinfo = &cpm_uart_ports[KGDB_PINFO_INDEX];

	/* Get the address of the host memory buffer.
	 */
	bdp = pinfo->rx_cur;
	while (bdp->cbd_sc & BD_SC_EMPTY);

	/* If the buffer address is in the CPM DPRAM, don't
	 * convert it.
	 */
	cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);

	if (obuf) {
		i = c = bdp->cbd_datlen;
		while (i-- > 0)
			*obuf++ = *cp++;
	} else
		c = *cp;
	bdp->cbd_sc |= BD_SC_EMPTY;

	if (bdp->cbd_sc & BD_SC_WRAP)
		bdp = pinfo->rx_bd_base;
	else
		bdp++;
	pinfo->rx_cur = (cbd_t *)bdp;

	return (int)c;
}
Пример #3
0
/*
 * Transmit characters, refill buffer descriptor, if possible
 */
static int cpm_uart_tx_pump(struct uart_port *port)
{
	volatile cbd_t *bdp;
	unsigned char *p;
	int count;
	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
	struct circ_buf *xmit = &port->info->xmit;

	/* Handle xon/xoff */
	if (port->x_char) {
		/* Pick next descriptor and fill from buffer */
		bdp = pinfo->tx_cur;

		p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);

		*p++ = port->x_char;
		bdp->cbd_datlen = 1;
		bdp->cbd_sc |= BD_SC_READY;
		/* Get next BD. */
		if (bdp->cbd_sc & BD_SC_WRAP)
			bdp = pinfo->tx_bd_base;
		else
			bdp++;
		pinfo->tx_cur = bdp;

		port->icount.tx++;
		port->x_char = 0;
		return 1;
	}

	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
		cpm_uart_stop_tx(port);
		return 0;
	}

	/* Pick next descriptor and fill from buffer */
	bdp = pinfo->tx_cur;

	while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
		count = 0;
		p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
		while (count < pinfo->tx_fifosize) {
			*p++ = xmit->buf[xmit->tail];
			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
			port->icount.tx++;
			count++;
			if (xmit->head == xmit->tail)
				break;
		}
		bdp->cbd_datlen = count;
		bdp->cbd_sc |= BD_SC_READY;
		__asm__("eieio");
		/* Get next BD. */
		if (bdp->cbd_sc & BD_SC_WRAP)
			bdp = pinfo->tx_bd_base;
		else
			bdp++;
	}
	pinfo->tx_cur = bdp;

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);

	if (uart_circ_empty(xmit)) {
		cpm_uart_stop_tx(port);
		return 0;
	}

	return 1;
}
Пример #4
0
/*
 * Receive characters
 */
static void cpm_uart_int_rx(struct uart_port *port)
{
	int i;
	unsigned char ch, *cp;
	struct tty_struct *tty = port->info->tty;
	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
	volatile cbd_t *bdp;
	u16 status;
	unsigned int flg;

	pr_debug("CPM uart[%d]:RX INT\n", port->line);

	/* Just loop through the closed BDs and copy the characters into
	 * the buffer.
	 */
	bdp = pinfo->rx_cur;
	for (;;) {
		/* get status */
		status = bdp->cbd_sc;
		/* If this one is empty, return happy */
		if (status & BD_SC_EMPTY)
			break;

		/* get number of characters, and check spce in flip-buffer */
		i = bdp->cbd_datlen;

		/* If we have not enough room in tty flip buffer, then we try
		 * later, which will be the next rx-interrupt or a timeout
		 */
		if(tty_buffer_request_room(tty, i) < i) {
			printk(KERN_WARNING "No room in flip buffer\n");
			return;
		}

		/* get pointer */
		cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);

		/* loop through the buffer */
		while (i-- > 0) {
			ch = *cp++;
			port->icount.rx++;
			flg = TTY_NORMAL;

			if (status &
			    (BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV))
				goto handle_error;
			if (uart_handle_sysrq_char(port, ch))
				continue;

		      error_return:
			tty_insert_flip_char(tty, ch, flg);

		}		/* End while (i--) */

		/* This BD is ready to be used again. Clear status. get next */
		bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
		bdp->cbd_sc |= BD_SC_EMPTY;

		if (bdp->cbd_sc & BD_SC_WRAP)
			bdp = pinfo->rx_bd_base;
		else
			bdp++;

	} /* End for (;;) */

	/* Write back buffer pointer */
	pinfo->rx_cur = (volatile cbd_t *) bdp;

	/* activate BH processing */
	tty_flip_buffer_push(tty);

	return;

	/* Error processing */

      handle_error:
	/* Statistics */
	if (status & BD_SC_BR)
		port->icount.brk++;
	if (status & BD_SC_PR)
		port->icount.parity++;
	if (status & BD_SC_FR)
		port->icount.frame++;
	if (status & BD_SC_OV)
		port->icount.overrun++;

	/* Mask out ignored conditions */
	status &= port->read_status_mask;

	/* Handle the remaining ones */
	if (status & BD_SC_BR)
		flg = TTY_BREAK;
	else if (status & BD_SC_PR)
		flg = TTY_PARITY;
	else if (status & BD_SC_FR)
		flg = TTY_FRAME;

	/* overrun does not affect the current character ! */
	if (status & BD_SC_OV) {
		ch = 0;
		flg = TTY_OVERRUN;
		/* We skip this buffer */
		/* CHECK: Is really nothing senseful there */
		/* ASSUMPTION: it contains nothing valid */
		i = 0;
	}
#ifdef SUPPORT_SYSRQ
	port->sysrq = 0;
#endif
	goto error_return;
}
Пример #5
0
/*
 *	Print a string to the serial port trying not to disturb
 *	any possible real use of the port...
 *
 *	Note that this is called with interrupts already disabled
 */
static void cpm_uart_console_write(struct console *co, const char *s,
				   u_int count)
{
	struct uart_cpm_port *pinfo =
	    &cpm_uart_ports[cpm_uart_port_map[co->index]];
	unsigned int i;
	volatile cbd_t *bdp, *bdbase;
	volatile unsigned char *cp;

	/* Get the address of the host memory buffer.
	 */
	bdp = pinfo->tx_cur;
	bdbase = pinfo->tx_bd_base;

	/*
	 * Now, do each character.  This is not as bad as it looks
	 * since this is a holding FIFO and not a transmitting FIFO.
	 * We could add the complexity of filling the entire transmit
	 * buffer, but we would just wait longer between accesses......
	 */
	for (i = 0; i < count; i++, s++) {
		/* Wait for transmitter fifo to empty.
		 * Ready indicates output is ready, and xmt is doing
		 * that, not that it is ready for us to send.
		 */
		while ((bdp->cbd_sc & BD_SC_READY) != 0)
			;

		/* Send the character out.
		 * If the buffer address is in the CPM DPRAM, don't
		 * convert it.
		 */
		cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);

		*cp = *s;

		bdp->cbd_datlen = 1;
		bdp->cbd_sc |= BD_SC_READY;

		if (bdp->cbd_sc & BD_SC_WRAP)
			bdp = bdbase;
		else
			bdp++;

		/* if a LF, also do CR... */
		if (*s == 10) {
			while ((bdp->cbd_sc & BD_SC_READY) != 0)
				;

			cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);

			*cp = 13;
			bdp->cbd_datlen = 1;
			bdp->cbd_sc |= BD_SC_READY;

			if (bdp->cbd_sc & BD_SC_WRAP)
				bdp = bdbase;
			else
				bdp++;
		}
	}

	/*
	 * Finally, Wait for transmitter & holding register to empty
	 *  and restore the IER
	 */
	while ((bdp->cbd_sc & BD_SC_READY) != 0)
		;

	pinfo->tx_cur = (volatile cbd_t *) bdp;
}
Пример #6
0
/*
 * Transmit characters, refill buffer descriptor, if possible
 */
static int cpm_uart_tx_pump(struct uart_port *port)
{
	cbd_t __iomem *bdp;
	u8 *p;
	int count;
	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
	struct circ_buf *xmit = &port->info->xmit;

	/* Handle xon/xoff */
	if (port->x_char) {
		/* Pick next descriptor and fill from buffer */
		bdp = pinfo->tx_cur;

		p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);

		*p++ = port->x_char;

		out_be16(&bdp->cbd_datlen, 1);
		setbits16(&bdp->cbd_sc, BD_SC_READY);
		/* Get next BD. */
		if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
			bdp = pinfo->tx_bd_base;
		else
			bdp++;
		pinfo->tx_cur = bdp;

		port->icount.tx++;
		port->x_char = 0;
		return 1;
	}

	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
		cpm_uart_stop_tx(port);
		return 0;
	}

	/* Pick next descriptor and fill from buffer */
	bdp = pinfo->tx_cur;

	while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) &&
	       xmit->tail != xmit->head) {
		count = 0;
		p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
		while (count < pinfo->tx_fifosize) {
			*p++ = xmit->buf[xmit->tail];
			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
			port->icount.tx++;
			count++;
			if (xmit->head == xmit->tail)
				break;
		}
		out_be16(&bdp->cbd_datlen, count);
		setbits16(&bdp->cbd_sc, BD_SC_READY);
		/* Get next BD. */
		if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
			bdp = pinfo->tx_bd_base;
		else
			bdp++;
	}
	pinfo->tx_cur = bdp;

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);

	if (uart_circ_empty(xmit)) {
		cpm_uart_stop_tx(port);
		return 0;
	}

	return 1;
}
Пример #7
0
/*
 *	Print a string to the serial port trying not to disturb
 *	any possible real use of the port...
 *
 *	Note that this is called with interrupts already disabled
 */
static void cpm_uart_console_write(struct console *co, const char *s,
				   u_int count)
{
	struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];
	unsigned int i;
	cbd_t __iomem *bdp, *bdbase;
	unsigned char *cp;
	unsigned long flags;
	int nolock = oops_in_progress;

	if (unlikely(nolock)) {
		local_irq_save(flags);
	} else {
		spin_lock_irqsave(&pinfo->port.lock, flags);
	}

	/* Get the address of the host memory buffer.
	 */
	bdp = pinfo->tx_cur;
	bdbase = pinfo->tx_bd_base;

	/*
	 * Now, do each character.  This is not as bad as it looks
	 * since this is a holding FIFO and not a transmitting FIFO.
	 * We could add the complexity of filling the entire transmit
	 * buffer, but we would just wait longer between accesses......
	 */
	for (i = 0; i < count; i++, s++) {
		/* Wait for transmitter fifo to empty.
		 * Ready indicates output is ready, and xmt is doing
		 * that, not that it is ready for us to send.
		 */
		while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
			;

		/* Send the character out.
		 * If the buffer address is in the CPM DPRAM, don't
		 * convert it.
		 */
		cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
		*cp = *s;

		out_be16(&bdp->cbd_datlen, 1);
		setbits16(&bdp->cbd_sc, BD_SC_READY);

		if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
			bdp = bdbase;
		else
			bdp++;

		/* if a LF, also do CR... */
		if (*s == 10) {
			while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
				;

			cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
			*cp = 13;

			out_be16(&bdp->cbd_datlen, 1);
			setbits16(&bdp->cbd_sc, BD_SC_READY);

			if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
				bdp = bdbase;
			else
				bdp++;
		}
	}

	/*
	 * Finally, Wait for transmitter & holding register to empty
	 *  and restore the IER
	 */
	while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
		;

	pinfo->tx_cur = bdp;

	if (unlikely(nolock)) {
		local_irq_restore(flags);
	} else {
		spin_unlock_irqrestore(&pinfo->port.lock, flags);
	}
}
Пример #8
0
/*
 * Write a string to the serial port
 * Note that this is called with interrupts already disabled
 */
static void cpm_uart_early_write(struct uart_cpm_port *pinfo,
		const char *string, u_int count)
{
	unsigned int i;
	cbd_t __iomem *bdp, *bdbase;
	unsigned char *cpm_outp_addr;

	/* Get the address of the host memory buffer.
	 */
	bdp = pinfo->tx_cur;
	bdbase = pinfo->tx_bd_base;

	/*
	 * Now, do each character.  This is not as bad as it looks
	 * since this is a holding FIFO and not a transmitting FIFO.
	 * We could add the complexity of filling the entire transmit
	 * buffer, but we would just wait longer between accesses......
	 */
	for (i = 0; i < count; i++, string++) {
		/* Wait for transmitter fifo to empty.
		 * Ready indicates output is ready, and xmt is doing
		 * that, not that it is ready for us to send.
		 */
		while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
			;

		/* Send the character out.
		 * If the buffer address is in the CPM DPRAM, don't
		 * convert it.
		 */
		cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
					pinfo);
		*cpm_outp_addr = *string;

		out_be16(&bdp->cbd_datlen, 1);
		setbits16(&bdp->cbd_sc, BD_SC_READY);

		if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
			bdp = bdbase;
		else
			bdp++;

		/* if a LF, also do CR... */
		if (*string == 10) {
			while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
				;

			cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
						pinfo);
			*cpm_outp_addr = 13;

			out_be16(&bdp->cbd_datlen, 1);
			setbits16(&bdp->cbd_sc, BD_SC_READY);

			if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
				bdp = bdbase;
			else
				bdp++;
		}
	}

	/*
	 * Finally, Wait for transmitter & holding register to empty
	 *  and restore the IER
	 */
	while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
		;

	pinfo->tx_cur = bdp;
}