⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 console.c

📁 linux 内核源代码
💻 C
字号:
/* * arch/xtensa/platform-iss/console.c * * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 2001-2005 Tensilica Inc. *   Authors	Christian Zankel, Joe Taylor */#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/console.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/mm.h>#include <linux/major.h>#include <linux/param.h>#include <linux/serial.h>#include <linux/serialP.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/platform/simcall.h>#include <linux/tty.h>#include <linux/tty_flip.h>#ifdef SERIAL_INLINE#define _INLINE_ inline#endif#define SERIAL_MAX_NUM_LINES 1#define SERIAL_TIMER_VALUE (20 * HZ)static struct tty_driver *serial_driver;static struct timer_list serial_timer;static DEFINE_SPINLOCK(timer_lock);int errno;static int __simc (int a, int b, int c, int d, int e, int f){	int ret;	__asm__ __volatile__ ("simcall\n"			"mov %0, a2\n"			"mov %1, a3\n" : "=a" (ret), "=a" (errno)			: : "a2", "a3");	return ret;}static char *serial_version = "0.1";static char *serial_name = "ISS serial driver";/* * This routine is called whenever a serial port is opened.  It * enables interrupts for a serial port, linking in its async structure into * the IRQ chain.   It also performs the serial-specific * initialization for the tty structure. */static void rs_poll(unsigned long);static int rs_open(struct tty_struct *tty, struct file * filp){	int line = tty->index;	if ((line < 0) || (line >= SERIAL_MAX_NUM_LINES))		return -ENODEV;	spin_lock(&timer_lock);	if (tty->count == 1) {		init_timer(&serial_timer);		serial_timer.data = (unsigned long) tty;		serial_timer.function = rs_poll;		mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);	}	spin_unlock(&timer_lock);	return 0;}/* * ------------------------------------------------------------ * iss_serial_close() * * This routine is called when the serial port gets closed.  First, we * wait for the last remaining data to be sent.  Then, we unlink its * async structure from the interrupt chain if necessary, and we free * that IRQ if nothing is left in the chain. * ------------------------------------------------------------ */static void rs_close(struct tty_struct *tty, struct file * filp){	spin_lock(&timer_lock);	if (tty->count == 1)		del_timer_sync(&serial_timer);	spin_unlock(&timer_lock);}static int rs_write(struct tty_struct * tty,		    const unsigned char *buf, int count){	/* see drivers/char/serialX.c to reference original version */	__simc (SYS_write, 1, (unsigned long)buf, count, 0, 0);	return count;}static void rs_poll(unsigned long priv){	struct tty_struct* tty = (struct tty_struct*) priv;	struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };	int i = 0;	unsigned char c;	spin_lock(&timer_lock);	while (__simc(SYS_select_one, 0, XTISS_SELECT_ONE_READ, (int)&tv,0,0)){		__simc (SYS_read, 0, (unsigned long)&c, 1, 0, 0);		tty_insert_flip_char(tty, c, TTY_NORMAL);		i++;	}	if (i)		tty_flip_buffer_push(tty);	mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);	spin_unlock(&timer_lock);}static void rs_put_char(struct tty_struct *tty, unsigned char ch){	char buf[2];	if (!tty)		return;	buf[0] = ch;	buf[1] = '\0';		/* Is this NULL necessary? */	__simc (SYS_write, 1, (unsigned long) buf, 1, 0, 0);}static void rs_flush_chars(struct tty_struct *tty){}static int rs_write_room(struct tty_struct *tty){	/* Let's say iss can always accept 2K characters.. */	return 2 * 1024;}static int rs_chars_in_buffer(struct tty_struct *tty){	/* the iss doesn't buffer characters */	return 0;}static void rs_hangup(struct tty_struct *tty){	/* Stub, once again.. */}static void rs_wait_until_sent(struct tty_struct *tty, int timeout){	/* Stub, once again.. */}static int rs_read_proc(char *page, char **start, off_t off, int count,			int *eof, void *data){	int len = 0;	off_t begin = 0;	len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);	*eof = 1;	if (off >= len + begin)		return 0;	*start = page + (off - begin);	return ((count < begin + len - off) ? count : begin + len - off);}static struct tty_operations serial_ops = {	.open = rs_open,	.close = rs_close,	.write = rs_write,	.put_char = rs_put_char,	.flush_chars = rs_flush_chars,	.write_room = rs_write_room,	.chars_in_buffer = rs_chars_in_buffer,	.hangup = rs_hangup,	.wait_until_sent = rs_wait_until_sent,	.read_proc = rs_read_proc};int __init rs_init(void){	serial_driver = alloc_tty_driver(1);	printk ("%s %s\n", serial_name, serial_version);	/* Initialize the tty_driver structure */	serial_driver->owner = THIS_MODULE;	serial_driver->driver_name = "iss_serial";	serial_driver->name = "ttyS";	serial_driver->major = TTY_MAJOR;	serial_driver->minor_start = 64;	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;	serial_driver->subtype = SERIAL_TYPE_NORMAL;	serial_driver->init_termios = tty_std_termios;	serial_driver->init_termios.c_cflag =		B9600 | CS8 | CREAD | HUPCL | CLOCAL;	serial_driver->flags = TTY_DRIVER_REAL_RAW;	tty_set_operations(serial_driver, &serial_ops);	if (tty_register_driver(serial_driver))		panic("Couldn't register serial driver\n");	return 0;}static __exit void rs_exit(void){	int error;	if ((error = tty_unregister_driver(serial_driver)))		printk("ISS_SERIAL: failed to unregister serial driver (%d)\n",		       error);	put_tty_driver(serial_driver);}/* We use `late_initcall' instead of just `__initcall' as a workaround for * the fact that (1) simcons_tty_init can't be called before tty_init, * (2) tty_init is called via `module_init', (3) if statically linked, * module_init == device_init, and (4) there's no ordering of init lists. * We can do this easily because simcons is always statically linked, but * other tty drivers that depend on tty_init and which must use * `module_init' to declare their init routines are likely to be broken. */late_initcall(rs_init);#ifdef CONFIG_SERIAL_CONSOLEstatic void iss_console_write(struct console *co, const char *s, unsigned count){	int len = strlen(s);	if (s != 0 && *s != 0)		__simc (SYS_write, 1, (unsigned long)s,			count < len ? count : len,0,0);}static struct tty_driver* iss_console_device(struct console *c, int *index){	*index = c->index;	return serial_driver;}static struct console sercons = {	.name = "ttyS",	.write = iss_console_write,	.device = iss_console_device,	.flags = CON_PRINTBUFFER,	.index = -1};static int __init iss_console_init(void){	register_console(&sercons);	return 0;}console_initcall(iss_console_init);#endif /* CONFIG_SERIAL_CONSOLE */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -