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

📄 sclp_con.c

📁 linux-2.6.15.6
💻 C
字号:
/* *  drivers/s390/char/sclp_con.c *    SCLP line mode console driver * *  S390 version *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation *    Author(s): Martin Peschke <mpeschke@de.ibm.com> *		 Martin Schwidefsky <schwidefsky@de.ibm.com> */#include <linux/config.h>#include <linux/kmod.h>#include <linux/console.h>#include <linux/init.h>#include <linux/timer.h>#include <linux/jiffies.h>#include <linux/bootmem.h>#include <linux/err.h>#include "sclp.h"#include "sclp_rw.h"#include "sclp_tty.h"#define SCLP_CON_PRINT_HEADER "sclp console driver: "#define sclp_console_major 4		/* TTYAUX_MAJOR */#define sclp_console_minor 64#define sclp_console_name  "ttyS"/* Lock to guard over changes to global variables */static spinlock_t sclp_con_lock;/* List of free pages that can be used for console output buffering */static struct list_head sclp_con_pages;/* List of full struct sclp_buffer structures ready for output */static struct list_head sclp_con_outqueue;/* Counter how many buffers are emitted (max 1) and how many *//* are on the output queue. */static int sclp_con_buffer_count;/* Pointer to current console buffer */static struct sclp_buffer *sclp_conbuf;/* Timer for delayed output of console messages */static struct timer_list sclp_con_timer;/* Output format for console messages */static unsigned short sclp_con_columns;static unsigned short sclp_con_width_htab;static voidsclp_conbuf_callback(struct sclp_buffer *buffer, int rc){	unsigned long flags;	void *page;	do {		page = sclp_unmake_buffer(buffer);		spin_lock_irqsave(&sclp_con_lock, flags);		/* Remove buffer from outqueue */		list_del(&buffer->list);		sclp_con_buffer_count--;		list_add_tail((struct list_head *) page, &sclp_con_pages);		/* Check if there is a pending buffer on the out queue. */		buffer = NULL;		if (!list_empty(&sclp_con_outqueue))			buffer = list_entry(sclp_con_outqueue.next,					    struct sclp_buffer, list);		spin_unlock_irqrestore(&sclp_con_lock, flags);	} while (buffer && sclp_emit_buffer(buffer, sclp_conbuf_callback));}static inline voidsclp_conbuf_emit(void){	struct sclp_buffer* buffer;	unsigned long flags;	int count;	int rc;	spin_lock_irqsave(&sclp_con_lock, flags);	buffer = sclp_conbuf;	sclp_conbuf = NULL;	if (buffer == NULL) {		spin_unlock_irqrestore(&sclp_con_lock, flags);		return;	}	list_add_tail(&buffer->list, &sclp_con_outqueue);	count = sclp_con_buffer_count++;	spin_unlock_irqrestore(&sclp_con_lock, flags);	if (count)		return;	rc = sclp_emit_buffer(buffer, sclp_conbuf_callback);	if (rc)		sclp_conbuf_callback(buffer, rc);}/* * When this routine is called from the timer then we flush the * temporary write buffer without further waiting on a final new line. */static voidsclp_console_timeout(unsigned long data){	sclp_conbuf_emit();}/* * Writes the given message to S390 system console */static voidsclp_console_write(struct console *console, const char *message,		   unsigned int count){	unsigned long flags;	void *page;	int written;	if (count == 0)		return;	spin_lock_irqsave(&sclp_con_lock, flags);	/*	 * process escape characters, write message into buffer,	 * send buffer to SCLP	 */	do {		/* make sure we have a console output buffer */		if (sclp_conbuf == NULL) {			while (list_empty(&sclp_con_pages)) {				spin_unlock_irqrestore(&sclp_con_lock, flags);				sclp_sync_wait();				spin_lock_irqsave(&sclp_con_lock, flags);			}			page = sclp_con_pages.next;			list_del((struct list_head *) page);			sclp_conbuf = sclp_make_buffer(page, sclp_con_columns,						       sclp_con_width_htab);		}		/* try to write the string to the current output buffer */		written = sclp_write(sclp_conbuf, (const unsigned char *)				     message, count);		if (written == count)			break;		/*		 * Not all characters could be written to the current		 * output buffer. Emit the buffer, create a new buffer		 * and then output the rest of the string.		 */		spin_unlock_irqrestore(&sclp_con_lock, flags);		sclp_conbuf_emit();		spin_lock_irqsave(&sclp_con_lock, flags);		message += written;		count -= written;	} while (count > 0);	/* Setup timer to output current console buffer after 1/10 second */	if (sclp_conbuf != NULL && sclp_chars_in_buffer(sclp_conbuf) != 0 &&	    !timer_pending(&sclp_con_timer)) {		init_timer(&sclp_con_timer);		sclp_con_timer.function = sclp_console_timeout;		sclp_con_timer.data = 0UL;		sclp_con_timer.expires = jiffies + HZ/10;		add_timer(&sclp_con_timer);	}	spin_unlock_irqrestore(&sclp_con_lock, flags);}static struct tty_driver *sclp_console_device(struct console *c, int *index){	*index = c->index;	return sclp_tty_driver;}/* * This routine is called from panic when the kernel * is going to give up. We have to make sure that all buffers * will be flushed to the SCLP. */static voidsclp_console_unblank(void){	unsigned long flags;	sclp_conbuf_emit();	spin_lock_irqsave(&sclp_con_lock, flags);	if (timer_pending(&sclp_con_timer))		del_timer(&sclp_con_timer);	while (sclp_con_buffer_count > 0) {		spin_unlock_irqrestore(&sclp_con_lock, flags);		sclp_sync_wait();		spin_lock_irqsave(&sclp_con_lock, flags);	}	spin_unlock_irqrestore(&sclp_con_lock, flags);}/* * used to register the SCLP console to the kernel and to * give printk necessary information */static struct console sclp_console ={	.name = sclp_console_name,	.write = sclp_console_write,	.device = sclp_console_device,	.unblank = sclp_console_unblank,	.flags = CON_PRINTBUFFER,	.index = 0 /* ttyS0 */};/* * called by console_init() in drivers/char/tty_io.c at boot-time. */static int __initsclp_console_init(void){	void *page;	int i;	int rc;	if (!CONSOLE_IS_SCLP)		return 0;	rc = sclp_rw_init();	if (rc)		return rc;	/* Allocate pages for output buffering */	INIT_LIST_HEAD(&sclp_con_pages);	for (i = 0; i < MAX_CONSOLE_PAGES; i++) {		page = alloc_bootmem_low_pages(PAGE_SIZE);		if (page == NULL)			return -ENOMEM;		list_add_tail((struct list_head *) page, &sclp_con_pages);	}	INIT_LIST_HEAD(&sclp_con_outqueue);	spin_lock_init(&sclp_con_lock);	sclp_con_buffer_count = 0;	sclp_conbuf = NULL;	init_timer(&sclp_con_timer);	/* Set output format */	if (MACHINE_IS_VM)		/*		 * save 4 characters for the CPU number		 * written at start of each line by VM/CP		 */		sclp_con_columns = 76;	else		sclp_con_columns = 80;	sclp_con_width_htab = 8;	/* enable printk-access to this driver */	register_console(&sclp_console);	return 0;}console_initcall(sclp_console_init);

⌨️ 快捷键说明

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