/* * Gets values of serial signals. */ static int mcfrs_getsignals(struct mcf_serial *info) { volatile unsigned char *uartp; unsigned long flags; int sigs; #if defined(CONFIG_NETtel) && defined(CONFIG_M5307) unsigned short ppdata; #endif #if 0 printk("%s(%d): mcfrs_getsignals(info=%x)\n", __FILE__, __LINE__); #endif local_irq_save(flags); uartp = info->addr; sigs = (uartp[MCFUART_UIPR] & MCFUART_UIPR_CTS) ? 0 : TIOCM_CTS; sigs |= (info->sigs & TIOCM_RTS); #ifdef MCFPP_DCD0 { unsigned int ppdata; ppdata = mcf_getppdata(); if (info->line == 0) { sigs |= (ppdata & MCFPP_DCD0) ? 0 : TIOCM_CD; sigs |= (ppdata & MCFPP_DTR0) ? 0 : TIOCM_DTR; } else if (info->line == 1) { sigs |= (ppdata & MCFPP_DCD1) ? 0 : TIOCM_CD; sigs |= (ppdata & MCFPP_DTR1) ? 0 : TIOCM_DTR; } } #endif local_irq_restore(flags); return(sigs); }
/* * This subroutine is called when the RS_TIMER goes off. It is used * to monitor the state of the DCD lines - since they have no edge * sensors and interrupt generators. */ static void mcfrs_timer(void) { unsigned int ppstatus, dcdval, i; ppstatus = mcf_getppdata() & (MCFPP_DCD0 | MCFPP_DCD1); if (ppstatus != mcfrs_ppstatus) { for (i = 0; (i < 2); i++) { dcdval = (i ? MCFPP_DCD1 : MCFPP_DCD0); if ((ppstatus & dcdval) != (mcfrs_ppstatus & dcdval)) { mcfrs_modem_change(&mcfrs_table[i], ((ppstatus & dcdval) ? 0 : 1)); } } } mcfrs_ppstatus = ppstatus; /* Re-arm timer */ mcfrs_timer_struct.expires = jiffies + HZ/25; add_timer(&mcfrs_timer_struct); }
/* mcfrs_init inits the driver */ static int __init mcfrs_init(void) { struct mcf_serial *info; unsigned long flags; int i; /* Setup base handler, and timer table. */ #ifdef MCFPP_DCD0 init_timer(&mcfrs_timer_struct); mcfrs_timer_struct.function = mcfrs_timer; mcfrs_timer_struct.data = 0; mcfrs_timer_struct.expires = jiffies + HZ/25; add_timer(&mcfrs_timer_struct); mcfrs_ppstatus = mcf_getppdata() & (MCFPP_DCD0 | MCFPP_DCD1); #endif mcfrs_serial_driver = alloc_tty_driver(NR_PORTS); if (!mcfrs_serial_driver) return -ENOMEM; show_serial_version(); /* Initialize the tty_driver structure */ mcfrs_serial_driver->owner = THIS_MODULE; mcfrs_serial_driver->name = "ttyS"; mcfrs_serial_driver->driver_name = "mcfserial"; mcfrs_serial_driver->major = TTY_MAJOR; mcfrs_serial_driver->minor_start = 64; mcfrs_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; mcfrs_serial_driver->subtype = SERIAL_TYPE_NORMAL; mcfrs_serial_driver->init_termios = tty_std_termios; mcfrs_serial_driver->init_termios.c_cflag = mcfrs_console_cbaud | CS8 | CREAD | HUPCL | CLOCAL; mcfrs_serial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(mcfrs_serial_driver, &mcfrs_ops); if (tty_register_driver(mcfrs_serial_driver)) { printk("MCFRS: Couldn't register serial driver\n"); put_tty_driver(mcfrs_serial_driver); return(-EBUSY); } local_irq_save(flags); /* * Configure all the attached serial ports. */ for (i = 0, info = mcfrs_table; (i < NR_PORTS); i++, info++) { info->magic = SERIAL_MAGIC; info->line = i; info->port.tty = NULL; info->custom_divisor = 16; info->close_delay = 50; info->closing_wait = 3000; info->x_char = 0; info->event = 0; info->count = 0; info->blocked_open = 0; INIT_WORK(&info->tqueue, mcfrs_offintr); INIT_WORK(&info->tqueue_hangup, do_serial_hangup); init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); info->imr = 0; mcfrs_setsignals(info, 0, 0); mcfrs_irqinit(info); printk("ttyS%d at 0x%04x (irq = %d)", info->line, (unsigned int) info->addr, info->irq); printk(" is a builtin ColdFire UART\n"); } local_irq_restore(flags); return 0; }