/* 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); } }
/* * 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; }
/* 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; }
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); } }
/* 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; }