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

📄 con3215.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
		raw->count++;	}	if (!(raw->flags & RAW3215_WORKING)) {		raw3215_mk_write_req(raw);		/* start or queue request */		raw3215_try_io(raw);	}	spin_unlock_irqrestore(raw->lock, flags);}/* * Flush routine, it simply sets the flush flag and tries to start * pending IO. */static voidraw3215_flush_buffer(struct raw3215_info *raw){	unsigned long flags;	spin_lock_irqsave(raw->lock, flags);	if (raw->count > 0) {		raw->flags |= RAW3215_FLUSHING;		raw3215_try_io(raw);		raw->flags &= ~RAW3215_FLUSHING;	}	spin_unlock_irqrestore(raw->lock, flags);}/* * Fire up a 3215 device. */static intraw3215_startup(struct raw3215_info *raw){	unsigned long flags;	if (raw->flags & RAW3215_ACTIVE)		return 0;	raw->line_pos = 0;	raw->flags |= RAW3215_ACTIVE;	spin_lock_irqsave(raw->lock, flags);	raw3215_try_io(raw);	spin_unlock_irqrestore(raw->lock, flags);	return 0;}/* * Shutdown a 3215 device. */static voidraw3215_shutdown(struct raw3215_info *raw){	DECLARE_WAITQUEUE(wait, current);	unsigned long flags;	if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FIXED))		return;	/* Wait for outstanding requests, then free irq */	spin_lock_irqsave(raw->lock, flags);	if ((raw->flags & RAW3215_WORKING) ||	    raw->queued_write != NULL ||	    raw->queued_read != NULL) {		raw->flags |= RAW3215_CLOSING;		add_wait_queue(&raw->empty_wait, &wait);		set_current_state(TASK_INTERRUPTIBLE);		spin_unlock_irqrestore(raw->lock, flags);		schedule();		spin_lock_irqsave(raw->lock, flags);		remove_wait_queue(&raw->empty_wait, &wait);		set_current_state(TASK_RUNNING);		raw->flags &= ~(RAW3215_ACTIVE | RAW3215_CLOSING);	}	spin_unlock_irqrestore(raw->lock, flags);}static intraw3215_probe (struct ccw_device *cdev){	struct raw3215_info *raw;	int line;	raw = kmalloc(sizeof(struct raw3215_info) +		      RAW3215_INBUF_SIZE, GFP_KERNEL|GFP_DMA);	if (raw == NULL)		return -ENOMEM;	spin_lock(&raw3215_device_lock);	for (line = 0; line < NR_3215; line++) {		if (!raw3215[line]) {			raw3215[line] = raw;			break;		}	}	spin_unlock(&raw3215_device_lock);	if (line == NR_3215) {		kfree(raw);		return -ENODEV;	}	raw->cdev = cdev;	raw->lock = get_ccwdev_lock(cdev);	raw->inbuf = (char *) raw + sizeof(struct raw3215_info);	memset(raw, 0, sizeof(struct raw3215_info));	raw->buffer = (char *) kmalloc(RAW3215_BUFFER_SIZE,				       GFP_KERNEL|GFP_DMA);	if (raw->buffer == NULL) {		spin_lock(&raw3215_device_lock);		raw3215[line] = 0;		spin_unlock(&raw3215_device_lock);		kfree(raw);		return -ENOMEM;	}	tasklet_init(&raw->tasklet,		     (void (*)(unsigned long)) raw3215_tasklet,		     (unsigned long) raw);	init_waitqueue_head(&raw->empty_wait);	cdev->dev.driver_data = raw;	cdev->handler = raw3215_irq;	return 0;}static voidraw3215_remove (struct ccw_device *cdev){	struct raw3215_info *raw;	ccw_device_set_offline(cdev);	raw = cdev->dev.driver_data;	if (raw) {		cdev->dev.driver_data = NULL;		kfree(raw->buffer);		kfree(raw);	}}static intraw3215_set_online (struct ccw_device *cdev){	struct raw3215_info *raw;	raw = cdev->dev.driver_data;	if (!raw)		return -ENODEV;	return raw3215_startup(raw);}static intraw3215_set_offline (struct ccw_device *cdev){	struct raw3215_info *raw;	raw = cdev->dev.driver_data;	if (!raw)		return -ENODEV;	raw3215_shutdown(raw);	return 0;}static struct ccw_device_id raw3215_id[] = {	{ CCW_DEVICE(0x3215, 0) },	{ /* end of list */ },};static struct ccw_driver raw3215_ccw_driver = {	.name		= "3215",	.owner		= THIS_MODULE,	.ids		= raw3215_id,	.probe		= &raw3215_probe,	.remove		= &raw3215_remove,	.set_online	= &raw3215_set_online,	.set_offline	= &raw3215_set_offline,};#ifdef CONFIG_TN3215_CONSOLE/* * Write a string to the 3215 console */static voidcon3215_write(struct console *co, const char *str, unsigned int count){	struct raw3215_info *raw;	int i;	if (count <= 0)		return;	raw = raw3215[0];	/* console 3215 is the first one */	while (count > 0) {		for (i = 0; i < count; i++)			if (str[i] == '\t' || str[i] == '\n')				break;		raw3215_write(raw, str, i);		count -= i;		str += i;		if (count > 0) {			raw3215_putchar(raw, *str);			count--;			str++;		}	}}static struct tty_driver *con3215_device(struct console *c, int *index){	*index = c->index;	return tty3215_driver;}/* * panic() calls console_unblank before the system enters a * disabled, endless loop. */static voidcon3215_unblank(void){	struct raw3215_info *raw;	unsigned long flags;	raw = raw3215[0];  /* console 3215 is the first one */	spin_lock_irqsave(raw->lock, flags);	raw3215_make_room(raw, RAW3215_BUFFER_SIZE);	spin_unlock_irqrestore(raw->lock, flags);}static int __init con3215_consetup(struct console *co, char *options){	return 0;}/* *  The console structure for the 3215 console */static struct console con3215 = {	.name	 = "ttyS",	.write	 = con3215_write,	.device	 = con3215_device,	.unblank = con3215_unblank,	.setup	 = con3215_consetup,	.flags	 = CON_PRINTBUFFER,};/* * 3215 console initialization code called from console_init(). * NOTE: This is called before kmalloc is available. */static int __initcon3215_init(void){	struct ccw_device *cdev;	struct raw3215_info *raw;	struct raw3215_req *req;	int i;	/* Check if 3215 is to be the console */	if (!CONSOLE_IS_3215)		return -ENODEV;	/* Set the console mode for VM */	if (MACHINE_IS_VM) {		cpcmd("TERM CONMODE 3215", NULL, 0, NULL);		cpcmd("TERM AUTOCR OFF", NULL, 0, NULL);	}	/* allocate 3215 request structures */	raw3215_freelist = NULL;	spin_lock_init(&raw3215_freelist_lock);	for (i = 0; i < NR_3215_REQ; i++) {		req = (struct raw3215_req *) alloc_bootmem_low(sizeof(struct raw3215_req));		req->next = raw3215_freelist;		raw3215_freelist = req;	}	cdev = ccw_device_probe_console();	if (!cdev)		return -ENODEV;	raw3215[0] = raw = (struct raw3215_info *)		alloc_bootmem_low(sizeof(struct raw3215_info));	memset(raw, 0, sizeof(struct raw3215_info));	raw->buffer = (char *) alloc_bootmem_low(RAW3215_BUFFER_SIZE);	raw->inbuf = (char *) alloc_bootmem_low(RAW3215_INBUF_SIZE);	raw->cdev = cdev;	raw->lock = get_ccwdev_lock(cdev);	cdev->dev.driver_data = raw;	cdev->handler = raw3215_irq;	raw->flags |= RAW3215_FIXED;	tasklet_init(&raw->tasklet,		     (void (*)(unsigned long)) raw3215_tasklet,		     (unsigned long) raw);	init_waitqueue_head(&raw->empty_wait);	/* Request the console irq */	if (raw3215_startup(raw) != 0) {		free_bootmem((unsigned long) raw->inbuf, RAW3215_INBUF_SIZE);		free_bootmem((unsigned long) raw->buffer, RAW3215_BUFFER_SIZE);		free_bootmem((unsigned long) raw, sizeof(struct raw3215_info));		raw3215[0] = NULL;		printk("Couldn't find a 3215 console device\n");		return -ENODEV;	}	register_console(&con3215);	return 0;}console_initcall(con3215_init);#endif/* * tty3215_open * * This routine is called whenever a 3215 tty is opened. */static inttty3215_open(struct tty_struct *tty, struct file * filp){	struct raw3215_info *raw;	int retval, line;	line = tty->index;	if ((line < 0) || (line >= NR_3215))		return -ENODEV;	raw = raw3215[line];	if (raw == NULL)		return -ENODEV;	tty->driver_data = raw;	raw->tty = tty;	tty->low_latency = 0;  /* don't use bottom half for pushing chars */	/*	 * Start up 3215 device	 */	retval = raw3215_startup(raw);	if (retval)		return retval;	return 0;}/* * tty3215_close() * * This routine is called when the 3215 tty is closed. We wait * for the remaining request to be completed. Then we clean up. */static voidtty3215_close(struct tty_struct *tty, struct file * filp){	struct raw3215_info *raw;	raw = (struct raw3215_info *) tty->driver_data;	if (raw == NULL || tty->count > 1)		return;	tty->closing = 1;	/* Shutdown the terminal */	raw3215_shutdown(raw);	tty->closing = 0;	raw->tty = NULL;}/* * Returns the amount of free space in the output buffer. */static inttty3215_write_room(struct tty_struct *tty){	struct raw3215_info *raw;	raw = (struct raw3215_info *) tty->driver_data;	/* Subtract TAB_STOP_SIZE to allow for a tab, 8 <<< 64K */	if ((RAW3215_BUFFER_SIZE - raw->count - TAB_STOP_SIZE) >= 0)		return RAW3215_BUFFER_SIZE - raw->count - TAB_STOP_SIZE;	else		return 0;}/* * String write routine for 3215 ttys */static inttty3215_write(struct tty_struct * tty,	      const unsigned char *buf, int count){	struct raw3215_info *raw;	if (!tty)		return 0;	raw = (struct raw3215_info *) tty->driver_data;	raw3215_write(raw, buf, count);	return count;}/* * Put character routine for 3215 ttys */static voidtty3215_put_char(struct tty_struct *tty, unsigned char ch){	struct raw3215_info *raw;	if (!tty)		return;	raw = (struct raw3215_info *) tty->driver_data;	raw3215_putchar(raw, ch);}static voidtty3215_flush_chars(struct tty_struct *tty){}/* * Returns the number of characters in the output buffer */static inttty3215_chars_in_buffer(struct tty_struct *tty){	struct raw3215_info *raw;	raw = (struct raw3215_info *) tty->driver_data;	return raw->count;}static voidtty3215_flush_buffer(struct tty_struct *tty){	struct raw3215_info *raw;	raw = (struct raw3215_info *) tty->driver_data;	raw3215_flush_buffer(raw);	tty_wakeup(tty);}/* * Currently we don't have any io controls for 3215 ttys */static inttty3215_ioctl(struct tty_struct *tty, struct file * file,	      unsigned int cmd, unsigned long arg){	if (tty->flags & (1 << TTY_IO_ERROR))		return -EIO;	switch (cmd) {	default:		return -ENOIOCTLCMD;	}	return 0;}/* * Disable reading from a 3215 tty */static voidtty3215_throttle(struct tty_struct * tty){	struct raw3215_info *raw;	raw = (struct raw3215_info *) tty->driver_data;	raw->flags |= RAW3215_THROTTLED;}/* * Enable reading from a 3215 tty */static voidtty3215_unthrottle(struct tty_struct * tty){	struct raw3215_info *raw;	unsigned long flags;	raw = (struct raw3215_info *) tty->driver_data;	if (raw->flags & RAW3215_THROTTLED) {		spin_lock_irqsave(raw->lock, flags);		raw->flags &= ~RAW3215_THROTTLED;		raw3215_try_io(raw);		spin_unlock_irqrestore(raw->lock, flags);	}}/* * Disable writing to a 3215 tty */static voidtty3215_stop(struct tty_struct *tty){	struct raw3215_info *raw;	raw = (struct raw3215_info *) tty->driver_data;	raw->flags |= RAW3215_STOPPED;}/* * Enable writing to a 3215 tty */static voidtty3215_start(struct tty_struct *tty){	struct raw3215_info *raw;	unsigned long flags;	raw = (struct raw3215_info *) tty->driver_data;	if (raw->flags & RAW3215_STOPPED) {		spin_lock_irqsave(raw->lock, flags);		raw->flags &= ~RAW3215_STOPPED;		raw3215_try_io(raw);		spin_unlock_irqrestore(raw->lock, flags);	}}static struct tty_operations tty3215_ops = {	.open = tty3215_open,	.close = tty3215_close,	.write = tty3215_write,	.put_char = tty3215_put_char,	.flush_chars = tty3215_flush_chars,	.write_room = tty3215_write_room,	.chars_in_buffer = tty3215_chars_in_buffer,	.flush_buffer = tty3215_flush_buffer,	.ioctl = tty3215_ioctl,	.throttle = tty3215_throttle,	.unthrottle = tty3215_unthrottle,	.stop = tty3215_stop,	.start = tty3215_start,};/* * 3215 tty registration code called from tty_init(). * Most kernel services (incl. kmalloc) are available at this poimt. */int __inittty3215_init(void){	struct tty_driver *driver;	int ret;	if (!CONSOLE_IS_3215)		return 0;	driver = alloc_tty_driver(NR_3215);	if (!driver)		return -ENOMEM;	ret = ccw_driver_register(&raw3215_ccw_driver);	if (ret) {		put_tty_driver(driver);		return ret;	}	/*	 * Initialize the tty_driver structure	 * Entries in tty3215_driver that are NOT initialized:	 * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc	 */	driver->owner = THIS_MODULE;	driver->driver_name = "tty3215";	driver->name = "ttyS";	driver->major = TTY_MAJOR;	driver->minor_start = 64;	driver->type = TTY_DRIVER_TYPE_SYSTEM;	driver->subtype = SYSTEM_TYPE_TTY;	driver->init_termios = tty_std_termios;	driver->init_termios.c_iflag = IGNBRK | IGNPAR;	driver->init_termios.c_oflag = ONLCR | XTABS;	driver->init_termios.c_lflag = ISIG;	driver->flags = TTY_DRIVER_REAL_RAW;	tty_set_operations(driver, &tty3215_ops);	ret = tty_register_driver(driver);	if (ret) {		printk("Couldn't register tty3215 driver\n");		put_tty_driver(driver);		return ret;	}	tty3215_driver = driver;	return 0;}static void __exittty3215_exit(void){	tty_unregister_driver(tty3215_driver);	put_tty_driver(tty3215_driver);	ccw_driver_unregister(&raw3215_ccw_driver);}module_init(tty3215_init);module_exit(tty3215_exit);

⌨️ 快捷键说明

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