📄 sh-sci.c
字号:
sercons.cflag = 0; sci_set_real_termios(port); }#endif sci_enable_rx_interrupts(port); port->gs.session = current->session; port->gs.pgrp = current->pgrp; return 0;failed_3: sci_free_irq(port);failed_2: MOD_DEC_USE_COUNT;failed_1: port->gs.count--; return retval;}static void sci_hungup(void *ptr){ MOD_DEC_USE_COUNT;}static void sci_close(void *ptr){ MOD_DEC_USE_COUNT;}static int sci_ioctl(struct tty_struct * tty, struct file * filp, unsigned int cmd, unsigned long arg){ int rc; struct sci_port *port = tty->driver_data; int ival; rc = 0; switch (cmd) { case TIOCGSOFTCAR: rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), (unsigned int *) arg); break; case TIOCSSOFTCAR: if ((rc = get_user(ival, (unsigned int *) arg)) == 0) tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0); break; case TIOCGSERIAL: if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct serial_struct))) == 0) rc = gs_getserial(&port->gs, (struct serial_struct *) arg); break; case TIOCSSERIAL: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(struct serial_struct))) == 0) rc = gs_setserial(&port->gs, (struct serial_struct *) arg); break; case TIOCMGET: ival = sci_getsignals(port); rc = put_user(ival, (unsigned int *) arg); break; case TIOCMBIS: if ((rc = get_user(ival, (unsigned int *) arg)) == 0) sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1), ((ival & TIOCM_RTS) ? 1 : -1)); break; case TIOCMBIC: if ((rc = get_user(ival, (unsigned int *) arg)) == 0) sci_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1), ((ival & TIOCM_RTS) ? 0 : -1)); break; case TIOCMSET: if ((rc = get_user(ival, (unsigned int *)arg)) == 0) sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0), ((ival & TIOCM_RTS) ? 1 : 0)); break; default: rc = -ENOIOCTLCMD; break; } return rc;}static void sci_throttle(struct tty_struct * tty){ struct sci_port *port = (struct sci_port *)tty->driver_data; /* If the port is using any type of input flow * control then throttle the port. */ if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty)) ) port->gs.flags |= SCI_RX_THROTTLE;}static void sci_unthrottle(struct tty_struct * tty){ struct sci_port *port = (struct sci_port *)tty->driver_data; /* Always unthrottle even if flow control is not enabled on * this port in case we disabled flow control while the port * was throttled */ port->gs.flags &= ~SCI_RX_THROTTLE; return;}#ifdef CONFIG_PROC_FSstatic int sci_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ int i; struct sci_port *port; int len = 0; len += sprintf(page, "sciinfo:0.1\n"); for (i = 0; i < SCI_NPORTS && len < 4000; i++) { port = &sci_ports[i]; len += sprintf(page+len, "%d: uart:%s address: %08x", i, (port->type == PORT_SCI) ? "SCI" : "SCIF", port->base); len += sprintf(page+len, " baud:%d", port->gs.baud); len += sprintf(page+len, " tx:%d rx:%d", port->icount.tx, port->icount.rx); if (port->icount.frame) len += sprintf(page+len, " fe:%d", port->icount.frame); if (port->icount.parity) len += sprintf(page+len, " pe:%d", port->icount.parity); if (port->icount.brk) len += sprintf(page+len, " brk:%d", port->icount.brk); if (port->icount.overrun) len += sprintf(page+len, " oe:%d", port->icount.overrun); len += sprintf(page+len, "\n"); } return len;}#endif/* ********************************************************************** * * Here are the initialization routines. * * ********************************************************************** */static int sci_init_drivers(void){ int error; struct sci_port *port; memset(&sci_driver, 0, sizeof(sci_driver)); sci_driver.magic = TTY_DRIVER_MAGIC; sci_driver.driver_name = "sci";#ifdef CONFIG_DEVFS_FS sci_driver.name = "ttsc/%d";#else sci_driver.name = "ttySC";#endif sci_driver.major = SCI_MAJOR; sci_driver.minor_start = SCI_MINOR_START; sci_driver.num = SCI_NPORTS; sci_driver.type = TTY_DRIVER_TYPE_SERIAL; sci_driver.subtype = SERIAL_TYPE_NORMAL; sci_driver.init_termios = tty_std_termios; sci_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL | CRTSCTS; sci_driver.flags = TTY_DRIVER_REAL_RAW; sci_driver.refcount = &sci_refcount; sci_driver.table = sci_table; sci_driver.termios = sci_termios; sci_driver.termios_locked = sci_termios_locked; sci_driver.open = sci_open; sci_driver.close = gs_close; sci_driver.write = gs_write; sci_driver.put_char = gs_put_char; sci_driver.flush_chars = gs_flush_chars; sci_driver.write_room = gs_write_room; sci_driver.chars_in_buffer = gs_chars_in_buffer; sci_driver.flush_buffer = gs_flush_buffer; sci_driver.ioctl = sci_ioctl; sci_driver.throttle = sci_throttle; sci_driver.unthrottle = sci_unthrottle; sci_driver.set_termios = gs_set_termios; sci_driver.stop = gs_stop; sci_driver.start = gs_start; sci_driver.hangup = gs_hangup;#ifdef CONFIG_PROC_FS sci_driver.read_proc = sci_read_proc;#endif sci_callout_driver = sci_driver;#ifdef CONFIG_DEVFS_FS sci_callout_driver.name = "cusc/%d";#else sci_callout_driver.name = "cusc";#endif sci_callout_driver.major = SCI_MAJOR+1; sci_callout_driver.subtype = SERIAL_TYPE_CALLOUT; sci_callout_driver.read_proc = NULL; if ((error = tty_register_driver(&sci_driver))) { printk(KERN_ERR "sci: Couldn't register SCI driver, error = %d\n", error); return 1; } if ((error = tty_register_driver(&sci_callout_driver))) { tty_unregister_driver(&sci_driver); printk(KERN_ERR "sci: Couldn't register SCI callout driver, error = %d\n", error); return 1; } for (port = &sci_ports[0]; port < &sci_ports[SCI_NPORTS]; port++) { port->gs.callout_termios = sci_callout_driver.init_termios; port->gs.normal_termios = sci_driver.init_termios; port->gs.magic = SCI_MAGIC; port->gs.close_delay = HZ/2; port->gs.closing_wait = 30 * HZ; port->gs.rd = &sci_real_driver; init_waitqueue_head(&port->gs.open_wait); init_waitqueue_head(&port->gs.close_wait); port->old_cflag = 0; port->icount.cts = port->icount.dsr = port->icount.rng = port->icount.dcd = 0; port->icount.rx = port->icount.tx = 0; port->icount.frame = port->icount.parity = 0; port->icount.overrun = port->icount.brk = 0; } return 0;}static int sci_request_irq(struct sci_port *port){ int i; void (*handlers[4])(int irq, void *ptr, struct pt_regs *regs) = { sci_er_interrupt, sci_rx_interrupt, sci_tx_interrupt, sci_br_interrupt, }; for (i=0; i<4; i++) { if (!port->irqs[i]) continue; if (request_irq(port->irqs[i], handlers[i], SA_INTERRUPT, "sci", port)) { printk(KERN_ERR "sci: Cannot allocate irq.\n"); return -ENODEV; } } return 0;}static void sci_free_irq(struct sci_port *port){ int i; for (i=0; i<4; i++) { if (!port->irqs[i]) continue; free_irq(port->irqs[i], port); }}static char banner[] __initdata = KERN_INFO "SuperH SCI(F) driver initialized\n";int __init sci_init(void){ struct sci_port *port; int j; printk("%s", banner); for (j=0; j<SCI_NPORTS; j++) { port = &sci_ports[j]; printk(KERN_INFO "ttySC%d at 0x%08x is a %s\n", j, port->base, (port->type == PORT_SCI) ? "SCI" : "SCIF"); } sci_init_drivers();#ifdef CONFIG_SH_STANDARD_BIOS sh_bios_gdb_detach();#endif return 0; /* Return -EIO when not detected */}module_init(sci_init);#ifdef MODULE#undef func_enter#undef func_exitvoid cleanup_module(void){ tty_unregister_driver(&sci_driver); tty_unregister_driver(&sci_callout_driver);}#include "generic_serial.c"#endif#ifdef CONFIG_SERIAL_CONSOLE/* * Print a string to the serial port trying not to disturb * any possible real use of the port... */static void serial_console_write(struct console *co, const char *s, unsigned count){ put_string(sercons_port, s, count);}/* * Receive character from the serial port */static int serial_console_wait_key(struct console *co){ /* Not implemented yet */ return 0;}static kdev_t serial_console_device(struct console *c){ return MKDEV(SCI_MAJOR, SCI_MINOR_START + c->index);}/* * Setup initial baud/bits/parity. We do two things here: * - construct a cflag setting for the first rs_open() * - initialize the serial port * Return non-zero if we didn't find a serial port. */static int __init serial_console_setup(struct console *co, char *options){ int baud = 9600; int bits = 8; int parity = 'n'; int cflag = CREAD | HUPCL | CLOCAL; char *s; sercons_port = &sci_ports[co->index]; if (options) { baud = simple_strtoul(options, NULL, 10); s = options; while(*s >= '0' && *s <= '9') s++; if (*s) parity = *s++; if (*s) bits = *s - '0'; } /* * Now construct a cflag setting. */ switch (baud) { case 19200: cflag |= B19200; break; case 38400: cflag |= B38400; break; case 57600: cflag |= B57600; break; case 115200: cflag |= B115200; break; case 9600: default: cflag |= B9600; baud = 9600; break; } switch (bits) { case 7: cflag |= CS7; break; default: case 8: cflag |= CS8; break; } switch (parity) { case 'o': case 'O': cflag |= PARODD; break; case 'e': case 'E': cflag |= PARENB; break; } co->cflag = cflag; sercons_baud = baud; sci_set_termios_cflag(sercons_port, cflag, baud); sercons_port->old_cflag = cflag; return 0;}static struct console sercons = { name: "ttySC", write: serial_console_write, device: serial_console_device, wait_key: serial_console_wait_key, setup: serial_console_setup, flags: CON_PRINTBUFFER, index: -1,};/* * Register console. */#ifdef CONFIG_SH_EARLY_PRINTKextern void sh_console_unregister (void);#endifvoid __init sci_console_init(void){ register_console(&sercons);#ifdef CONFIG_SH_EARLY_PRINTK /* Now that the real console is available, unregister the one we * used while first booting. */ sh_console_unregister();#endif}#endif /* CONFIG_SERIAL_CONSOLE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -