Ejemplo n.º 1
0
/* XXXKW locking? */
static void duart_stop(struct tty_struct *tty)
{
	uart_state_t *us = (uart_state_t *) tty->driver_data;

#ifdef DUART_SPEW
	printk("duart_stop called\n");
#endif

	if (us->outp_count && (us->flags & TX_INTEN)) {
		us->flags &= ~TX_INTEN;
		duart_mask_ints(us->line, M_DUART_IMR_TX);
	}
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
/* Set up the driver and register it, register the 2 1250 UART interrupts.  This
   is called from tty_init, or as a part of the module init */
static int __init sb1250_duart_init(void) 
{
	int i;

	sb1250_duart_driver = alloc_tty_driver(DUART_MAX_LINE);
	if (!sb1250_duart_driver)
		return -ENOMEM;

	sb1250_duart_driver->owner = THIS_MODULE;
	sb1250_duart_driver->name = "duart";
	sb1250_duart_driver->devfs_name = "duart/";
	sb1250_duart_driver->major = TTY_MAJOR;
	sb1250_duart_driver->minor_start = SB1250_DUART_MINOR_BASE;
	sb1250_duart_driver->type            = TTY_DRIVER_TYPE_SERIAL;
	sb1250_duart_driver->subtype         = SERIAL_TYPE_NORMAL;
	sb1250_duart_driver->init_termios    = tty_std_termios;
	sb1250_duart_driver->flags           = TTY_DRIVER_REAL_RAW;
	tty_set_operations(sb1250_duart_driver, &duart_ops);

	for (i=0; i<DUART_MAX_LINE; i++) {
		uart_state_t *port = uart_states + i;

		if (!sb1250_duart_present[i])
			continue;

		init_duart_port(port, i);
		spin_lock_init(&port->outp_lock);
		duart_mask_ints(i, M_DUART_IMR_ALL);
		if (request_irq(K_INT_UART_0+i, duart_int, 0, "uart", port)) {
			panic("Couldn't get uart0 interrupt line");
		}
		__raw_writeq(M_DUART_RX_EN|M_DUART_TX_EN,
			     (u8 *) IOADDR(A_DUART_CHANREG(i, R_DUART_CMD)));
		duart_set_cflag(i, DEFAULT_CFLAGS);
	}

	/* Interrupts are now active, our ISR can be called. */

	if (tty_register_driver(sb1250_duart_driver)) {
		printk(KERN_ERR "Couldn't register sb1250 duart serial driver\n");
		put_tty_driver(sb1250_duart_driver);
		return 1;
	}
	return 0;
}
Ejemplo n.º 4
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);
	}
}
Ejemplo n.º 5
0
/* Set up the driver and register it, register the 2 1250 UART interrupts.  This
   is called from tty_init, or as a part of the module init */
static int __init sb1250_duart_init(void) 
{
	int i;

	sb1250_duart_driver.magic            = TTY_DRIVER_MAGIC;
	sb1250_duart_driver.driver_name      = "serial";
#ifdef CONFIG_DEVFS_FS
	sb1250_duart_driver.name             = "tts/%d";
#else
	sb1250_duart_driver.name             = "ttyS";
#endif
	sb1250_duart_driver.major            = TTY_MAJOR;
	sb1250_duart_driver.minor_start      = SB1250_DUART_MINOR_BASE;
	sb1250_duart_driver.num              = DUART_MAX_LINE;
	sb1250_duart_driver.type             = TTY_DRIVER_TYPE_SERIAL;
	sb1250_duart_driver.subtype          = SERIAL_TYPE_NORMAL;
	sb1250_duart_driver.init_termios     = tty_std_termios;
	sb1250_duart_driver.flags            = TTY_DRIVER_REAL_RAW;
	sb1250_duart_driver.refcount         = &duart_refcount;
	sb1250_duart_driver.table            = duart_table;
	sb1250_duart_driver.termios          = duart_termios;
	sb1250_duart_driver.termios_locked   = duart_termios_locked;

	sb1250_duart_driver.open             = duart_open;
	sb1250_duart_driver.close            = duart_close;
	sb1250_duart_driver.write            = duart_write;
	sb1250_duart_driver.put_char         = duart_put_char;
	sb1250_duart_driver.write_room       = duart_write_room;
	sb1250_duart_driver.flush_chars      = duart_flush_chars;
	sb1250_duart_driver.chars_in_buffer  = duart_chars_in_buffer;
	sb1250_duart_driver.flush_buffer     = duart_flush_buffer;
	sb1250_duart_driver.ioctl            = duart_ioctl;
	sb1250_duart_driver.set_termios      = duart_set_termios;
	sb1250_duart_driver.stop             = duart_stop;
	sb1250_duart_driver.start            = duart_start;
	sb1250_duart_driver.hangup           = duart_hangup;
	sb1250_duart_driver.wait_until_sent  = duart_wait_until_sent;

	sb1250_duart_callout_driver          = sb1250_duart_driver;
#ifdef CONFIG_DEVFS_FS
	sb1250_duart_callout_driver.name     = "cua/%d";
#else
	sb1250_duart_callout_driver.name     = "cua";
#endif
	sb1250_duart_callout_driver.major    = TTYAUX_MAJOR;
	sb1250_duart_callout_driver.subtype  = SERIAL_TYPE_CALLOUT;

	for (i=0; i<DUART_MAX_LINE; i++) {
		uart_state_t *port = uart_states + i;

		if (!sb1250_duart_present[i])
			continue;

		init_duart_port(port, i);
		spin_lock_init(&port->outp_lock);
		duart_mask_ints(i, M_DUART_IMR_ALL);
		if (request_irq(K_INT_UART_0+i, duart_int, 0, "uart", port)) {
			panic("Couldn't get uart0 interrupt line");
		}
		out64(M_DUART_RX_EN|M_DUART_TX_EN,
		      IO_SPACE_BASE | A_DUART_CHANREG(i, R_DUART_CMD));
		duart_set_cflag(i, DEFAULT_CFLAGS);
	}

	/* Interrupts are now active, our ISR can be called. */

	if (tty_register_driver(&sb1250_duart_driver)) {
		printk(KERN_ERR "Couldn't register sb1250 duart serial driver\n");
	}
	if (tty_register_driver(&sb1250_duart_callout_driver)) {
		printk(KERN_ERR "Couldn't register sb1250 duart callout driver\n");
	}
	return 0;
}