Exemplo n.º 1
0
void serial_outc(unsigned char c, int line)
{
	uart_state_t *port = uart_states + line;
	while (!(READ_SERCSR(port->status, line) & M_DUART_TX_RDY)) ;
	WRITE_SERCSR(c, port->tx_hold, line);
	while (!(READ_SERCSR(port->status, port->line) & M_DUART_TX_EMT)) ;
}
Exemplo n.º 2
0
static irqreturn_t duart_int(int irq, void *dev_id, struct pt_regs *regs)
{
	uart_state_t *us = (uart_state_t *)dev_id;
	struct tty_struct *tty = us->tty;
	unsigned int status = READ_SERCSR(us->status, us->line);

#ifdef DUART_SPEW
	printk("DUART INT\n");
#endif

	if (status & M_DUART_RX_RDY) {
		int counter = 2048;
		unsigned int ch;

		if (status & M_DUART_OVRUN_ERR)
			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
		if (status & M_DUART_PARITY_ERR) {
			printk("Parity error!\n");
		} else if (status & M_DUART_FRM_ERR) {
			printk("Frame error!\n");
		}

		while (counter > 0) {
			if (!(READ_SERCSR(us->status, us->line) & M_DUART_RX_RDY))
				break;
			ch = READ_SERCSR(us->rx_hold, us->line);
			if (tty->flip.count < TTY_FLIPBUF_SIZE) {
				*tty->flip.char_buf_ptr++ = ch;
				*tty->flip.flag_buf_ptr++ = 0;
				tty->flip.count++;
			}
			udelay(1);
			counter--;
		}
		tty_flip_buffer_push(tty);
	}

	if (status & M_DUART_TX_RDY) {
		transmit_char_pio(us);
	}

	return IRQ_HANDLED;
}
Exemplo n.º 3
0
static void ser_console_write(struct console *cons, const char *s,
	unsigned int count)
{
	int line = cons->index;
	uart_state_t *port = uart_states + line;
	u32 imr;

	imr = READ_SERCSR(port->imr, line);
	WRITE_SERCSR(0, port->imr, line);
	while (count--) {
		if (*s == '\n')
			serial_outc('\r', line);
		serial_outc(*s++, line);
    	}
	WRITE_SERCSR(imr, port->imr, line);
}
Exemplo n.º 4
0
/*
 * Close a reference count out.  If reference count hits zero, null the
 * tty, kill the interrupts.  The tty_io driver is responsible for making
 * sure we've cleared out our internal buffers before calling close()
 */
static void duart_close(struct tty_struct *tty, struct file *filp)
{
	uart_state_t *us = (uart_state_t *) tty->driver_data;
	unsigned long flags;

#ifdef DUART_SPEW
	printk("duart_close called by %i (%s)\n", current->pid, current->comm);
#endif

	if (!us || !us->open)
		return;

	spin_lock_irqsave(&open_lock, flags);
	if (tty_hung_up_p(filp)) {
		MOD_DEC_USE_COUNT;
		spin_unlock_irqrestore(&open_lock, flags);
		return;
	}

	if (--us->open < 0) {
		us->open = 0;
		printk(KERN_ERR "duart: bad open count: %d\n", us->open);
	}
	if (us->open) {
		spin_unlock_irqrestore(&open_lock, flags);
		return;
	}

	spin_unlock_irqrestore(&open_lock, flags);

	tty->closing = 1;

	/* Stop accepting input */
	duart_mask_ints(us->line, M_DUART_IMR_RX);
	/* Wait for FIFO to drain */
	while (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_EMT))
		;

	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
		tty->ldisc.flush_buffer(tty);
	tty->closing = 0;

	MOD_DEC_USE_COUNT;
}
Exemplo n.º 5
0
static inline void transmit_char_pio(uart_state_t *us)
{
	struct tty_struct *tty = us->tty;
	int blocked = 0;

	if (spin_trylock(&us->outp_lock)) {
		for (;;) {
			if (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_RDY))
				break;
			if (us->outp_count <= 0 || tty->stopped || tty->hw_stopped) {
				break;
			} else {
				WRITE_SERCSR(us->outp_buf[us->outp_head],
					     us->tx_hold, us->line);
				us->outp_head = (us->outp_head + 1) & (SERIAL_XMIT_SIZE-1);
				if (--us->outp_count <= 0)
					break;
			}
			udelay(10);
		}
		spin_unlock(&us->outp_lock);
	} else {
		blocked = 1;
	}

	if (!us->outp_count || tty->stopped ||
	    tty->hw_stopped || blocked) {
		us->flags &= ~TX_INTEN;
		duart_mask_ints(us->line, M_DUART_IMR_TX);
	}

      	if (us->open &&
	    (us->outp_count < (SERIAL_XMIT_SIZE/2))) {
		/*
		 * We told the discipline at one point that we had no
		 * space, so it went to sleep.  Wake it up when we hit
		 * half empty
		 */
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		    tty->ldisc.write_wakeup)
			tty->ldisc.write_wakeup(tty);
		wake_up_interruptible(&tty->write_wait);
	}
}
Exemplo n.º 6
0
static void duart_wait_until_sent(struct tty_struct *tty, int timeout)
{
	uart_state_t *us = (uart_state_t *) tty->driver_data;
	unsigned long orig_jiffies;

	orig_jiffies = jiffies;
#ifdef DUART_SPEW
	printk("duart_wait_until_sent(%d)+\n", timeout);
#endif
	while (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_EMT)) {
		set_current_state(TASK_INTERRUPTIBLE);
	 	schedule_timeout(1);
		if (signal_pending(current))
			break;
		if (timeout && time_after(jiffies, orig_jiffies + timeout))
			break;
	}
#ifdef DUART_SPEW
	printk("duart_wait_until_sent()-\n");
#endif
}
Exemplo n.º 7
0
/* Unmask the passed interrupt lines at the duart level */
static inline void duart_unmask_ints(unsigned int line, unsigned int mask)
{
	uart_state_t *port = uart_states + line;
	u64 tmp = READ_SERCSR(port->imr, line);
	WRITE_SERCSR(tmp | mask, port->imr, line);
}