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

📄 serial.c

📁 In the ffuart.tar.gz it has one file. The serial.c is the source codes of the FFUART as a console
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  linux/drivers/char/serial.c * *  Copyright (C) 1991, 1992  Linus Torvalds *  Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997,  * 		1998, 1999  Theodore Ts'o * *  Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92.  Now *  much more extensible to support other serial cards based on the *  16450/16550A UART's.  Added support for the AST FourPort and the *  Accent Async board.   * *  set_serial_info fixed to set the flags, custom divisor, and uart * 	type fields.  Fix suggested by Michael K. Johnson 12/12/92. * *  11/95: TIOCMIWAIT, TIOCGICOUNT by Angelo Haritsis <ah@doc.ic.ac.uk> * *  03/96: Modularised by Angelo Haritsis <ah@doc.ic.ac.uk> * *  rs_set_termios fixed to look also for changes of the input *      flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK. *                                            Bernd Anh鋟pl 05/17/96. * *  1/97:  Extended dumb serial ports are a config option now.   *         Saves 4k.   Michael A. Griffith <grif@acm.org> *  *  8/97: Fix bug in rs_set_termios with RTS *        Stanislav V. Voronyi <stas@uanet.kharkov.ua> * *  3/98: Change the IRQ detection, use of probe_irq_o*(), *	  suppress TIOCSERGWILD and TIOCSERSWILD *	  Etienne Lorrain <etienne.lorrain@ibm.net> * *  4/98: Added changes to support the ARM architecture proposed by * 	  Russell King * *  5/99: Updated to include support for the XR16C850 and ST16C654 *        uarts.  Stuart MacDonald <stuartm@connecttech.com> * *  8/99: Generalized PCI support added.  Theodore Ts'o *  *  3/00: Rid circular buffer of redundant xmit_cnt.  Fix a *	  few races on freeing buffers too. *	  Alan Modra <alan@linuxcare.com> * *  5/00: Support for the RSA-DV II/S card added. *	  Kiyokazu SUTO <suto@ks-and-ks.ne.jp> *  *  6/00: Remove old-style timer, use timer_list *        Andrew Morton <andrewm@uow.edu.au> * *  7/00: Support Timedia/Sunix/Exsys PCI cards * *  7/00: fix some returns on failure not using MOD_DEC_USE_COUNT. *	  Arnaldo Carvalho de Melo <acme@conectiva.com.br> * * 10/00: add in optional software flow control for serial console. *	  Kanoj Sarcar <kanoj@sgi.com>  (Modified by Theodore Ts'o) * */static char *serial_version = "5.05c";static char *serial_revdate = "2001-07-08";/* * Serial driver configuration section.  Here are the various options: * * CONFIG_HUB6 *		Enables support for the venerable Bell Technologies *		HUB6 card. * * CONFIG_SERIAL_MANY_PORTS * 		Enables support for ports beyond the standard, stupid * 		COM 1/2/3/4. * * CONFIG_SERIAL_MULTIPORT * 		Enables support for special multiport board support. * * CONFIG_SERIAL_SHARE_IRQ * 		Enables support for multiple serial ports on one IRQ * * CONFIG_SERIAL_DETECT_IRQ *		Enable the autodetection of IRQ on standart ports * * SERIAL_PARANOIA_CHECK * 		Check the magic number for the async_structure where * 		ever possible. * * CONFIG_SERIAL_ACPI *		Enable support for serial console port and serial  *		debug port as defined by the SPCR and DBGP tables in  *		ACPI 2.0. */#include <linux/config.h>#include <linux/version.h>#undef SERIAL_PARANOIA_CHECK#define CONFIG_SERIAL_NOPAUSE_IO#define SERIAL_DO_RESTART#if 0/* These defines are normally controlled by the autoconf.h */#define CONFIG_SERIAL_MANY_PORTS#define CONFIG_SERIAL_SHARE_IRQ#define CONFIG_SERIAL_DETECT_IRQ#define CONFIG_SERIAL_MULTIPORT#define CONFIG_HUB6#endif#ifdef CONFIG_PCI#define ENABLE_SERIAL_PCI#ifndef CONFIG_SERIAL_SHARE_IRQ#define CONFIG_SERIAL_SHARE_IRQ#endif#ifndef CONFIG_SERIAL_MANY_PORTS#define CONFIG_SERIAL_MANY_PORTS#endif#endif#ifdef CONFIG_SERIAL_ACPI#define ENABLE_SERIAL_ACPI#endif#if defined(CONFIG_ISAPNP)|| (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE))#ifndef ENABLE_SERIAL_PNP#define ENABLE_SERIAL_PNP#endif#endif#ifdef CONFIG_ARCH_PXA#define pxa_port(x) ((x) == PORT_PXA)#define pxa_buggy_port(x) ({ \	int cpu_ver; asm("mrc%? p15, 0, %0, c0, c0" : "=r" (cpu_ver)); \	((x) == PORT_PXA && (cpu_ver & ~1) == 0x69052100); })#else#define pxa_port(x) (0)#define pxa_buggy_port(x) (0)#endif/* Set of debugging defines */#undef SERIAL_DEBUG_INTR#undef SERIAL_DEBUG_OPEN#undef SERIAL_DEBUG_FLOW#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT#undef SERIAL_DEBUG_PCI#undef SERIAL_DEBUG_AUTOCONF/* Sanity checks */#ifdef CONFIG_SERIAL_MULTIPORT#ifndef CONFIG_SERIAL_SHARE_IRQ#define CONFIG_SERIAL_SHARE_IRQ#endif#endif#ifdef CONFIG_HUB6#ifndef CONFIG_SERIAL_MANY_PORTS#define CONFIG_SERIAL_MANY_PORTS#endif#ifndef CONFIG_SERIAL_SHARE_IRQ#define CONFIG_SERIAL_SHARE_IRQ#endif#endif#ifdef MODULE#undef CONFIG_SERIAL_CONSOLE#endif#define CONFIG_SERIAL_RSA#define RS_STROBE_TIME (10*HZ)#define RS_ISR_PASS_LIMIT 256#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))#define SERIAL_INLINE#endif  /* * End of serial driver configuration section. */#include <linux/module.h>#include <linux/types.h>#ifdef LOCAL_HEADERS#include "serial_local.h"#else#include <linux/serial.h>#include <linux/serialP.h>#include <linux/serial_reg.h>#include <asm/serial.h>#define LOCAL_VERSTRING ""#endif#include <linux/errno.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/major.h>#include <linux/string.h>#include <linux/fcntl.h>#include <linux/ptrace.h>#include <linux/ioport.h>#include <linux/mm.h>#include <linux/slab.h>#if (LINUX_VERSION_CODE >= 131343)#include <linux/init.h>#endif#if (LINUX_VERSION_CODE >= 131336)#include <asm/uaccess.h>#endif#include <linux/delay.h>#ifdef CONFIG_SERIAL_CONSOLE#include <linux/console.h>#endif#ifdef ENABLE_SERIAL_PCI#include <linux/pci.h>#endif#ifdef ENABLE_SERIAL_PNP#include <linux/isapnp.h>#endif#ifdef CONFIG_MAGIC_SYSRQ#include <linux/sysrq.h>#endif/* * All of the compatibilty code so we can compile serial.c against * older kernels is hidden in serial_compat.h */#if defined(LOCAL_HEADERS) || (LINUX_VERSION_CODE < 0x020317) /* 2.3.23 */#include "serial_compat.h"#endif#include <asm/system.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/bitops.h>#if defined(CONFIG_MAC_SERIAL)#define SERIAL_DEV_OFFSET	((_machine == _MACH_prep || _machine == _MACH_chrp) ? 0 : 2)#else#define SERIAL_DEV_OFFSET	0#endif#ifdef SERIAL_INLINE#define _INLINE_ inline#else#define _INLINE_#endifstatic char *serial_name = "Serial driver";static DECLARE_TASK_QUEUE(tq_serial);static struct tty_driver serial_driver, callout_driver;static int serial_refcount;static struct timer_list serial_timer;/* serial subtype definitions */#ifndef SERIAL_TYPE_NORMAL#define SERIAL_TYPE_NORMAL	1#define SERIAL_TYPE_CALLOUT	2#endif/* number of characters left in xmit buffer before we ask for more */#define WAKEUP_CHARS 256/* * IRQ_timeout		- How long the timeout should be for each IRQ * 				should be after the IRQ has been active. */static struct async_struct *IRQ_ports[NR_IRQS];#ifdef CONFIG_SERIAL_MULTIPORTstatic struct rs_multiport_struct rs_multiport[NR_IRQS];#endifstatic int IRQ_timeout[NR_IRQS];#ifdef CONFIG_SERIAL_CONSOLEstatic struct console sercons;static int lsr_break_flag;#endif#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)static unsigned long break_pressed; /* break, really ... */#endifstatic unsigned detect_uart_irq (struct serial_state * state);static void autoconfig(struct serial_state * state);static void change_speed(struct async_struct *info, struct termios *old);static void rs_wait_until_sent(struct tty_struct *tty, int timeout);/* * Here we define the default xmit fifo size used for each type of * UART */static struct serial_uart_config uart_config[] = {	{ "unknown", 1, 0 }, 	{ "8250", 1, 0 }, 	{ "16450", 1, 0 }, 	{ "16550", 1, 0 }, 	{ "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, 	{ "cirrus", 1, 0 }, 	/* usurped by cyclades.c */	{ "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, 	{ "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO |		  UART_STARTECH }, 	{ "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO},	{ "Startech", 1, 0},	/* usurped by cyclades.c */	{ "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO},	{ "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO |		  UART_STARTECH }, 	{ "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO |		  UART_STARTECH },	{ "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }, 	{ "PXA UART", 32, UART_CLEAR_FIFO | UART_USE_FIFO },	{ 0, 0}};#if defined(CONFIG_SERIAL_RSA) && defined(MODULE)#define PORT_RSA_MAX 4static int probe_rsa[PORT_RSA_MAX];static int force_rsa[PORT_RSA_MAX];MODULE_PARM(probe_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");MODULE_PARM(force_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");MODULE_PARM_DESC(force_rsa, "Force I/O ports for RSA");#endif /* CONFIG_SERIAL_RSA  */static struct serial_state rs_table[RS_TABLE_SIZE] = {	SERIAL_PORT_DFNS	/* Defined in serial.h */};#define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))#if (defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP))#define NR_PCI_BOARDS	8static struct pci_board_inst	serial_pci_board[NR_PCI_BOARDS];#ifndef IS_PCI_REGION_IOPORT#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \				      IORESOURCE_IO)#endif#ifndef IS_PCI_REGION_IOMEM#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \				      IORESOURCE_MEM)#endif#ifndef PCI_IRQ_RESOURCE#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start)#endif#ifndef pci_get_subvendor#define pci_get_subvendor(dev) ((dev)->subsystem_vendor)#define pci_get_subdevice(dev)  ((dev)->subsystem_device)#endif#endif	/* ENABLE_SERIAL_PCI || ENABLE_SERIAL_PNP  */#ifndef PREPARE_FUNC#define PREPARE_FUNC(dev)  (dev->prepare)#define ACTIVATE_FUNC(dev)  (dev->activate)#define DEACTIVATE_FUNC(dev)  (dev->deactivate)#endif#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)static struct tty_struct *serial_table[NR_PORTS];static struct termios *serial_termios[NR_PORTS];static struct termios *serial_termios_locked[NR_PORTS];#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ kdevname(tty->device), (info->flags), serial_refcount,info->count,tty->count,s)#else#define DBG_CNT(s)#endif/* * tmp_buf is used as a temporary buffer by serial_write.  We need to * lock it in case the copy_from_user blocks while swapping in a page, * and some other program tries to do a serial write at the same time. * Since the lock will only come under contention when the system is * swapping and available memory is low, it makes sense to share one * buffer across all the serial ports, since it significantly saves * memory if large numbers of serial ports are open. */static unsigned char *tmp_buf;#ifdef DECLARE_MUTEXstatic DECLARE_MUTEX(tmp_buf_sem);#elsestatic struct semaphore tmp_buf_sem = MUTEX;#endifstatic inline int serial_paranoia_check(struct async_struct *info,					kdev_t device, const char *routine){#ifdef SERIAL_PARANOIA_CHECK	static const char *badmagic =		"Warning: bad magic number for serial struct (%s) in %s\n";	static const char *badinfo =		"Warning: null async_struct for (%s) in %s\n";	if (!info) {		printk(badinfo, kdevname(device), routine);		return 1;	}	if (info->magic != SERIAL_MAGIC) {		printk(badmagic, kdevname(device), routine);		return 1;	}#endif	return 0;}static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset){	switch (info->io_type) {#ifdef CONFIG_HUB6	case SERIAL_IO_HUB6:		outb(info->hub6 - 1 + offset, info->port);		return inb(info->port+1);#endif	case SERIAL_IO_MEM:		return readb((unsigned long) info->iomem_base +			     (offset<<info->iomem_reg_shift));	case SERIAL_IO_MEM32:		return readl((unsigned long) info->iomem_base +				(offset<<info->iomem_reg_shift));#ifdef CONFIG_SERIAL_GSC	case SERIAL_IO_GSC:		return gsc_readb(info->iomem_base + offset);#endif	default:		return inb(info->port + offset);	}}static _INLINE_ void serial_out(struct async_struct *info, int offset,				int value){	switch (info->io_type) {#ifdef CONFIG_HUB6	case SERIAL_IO_HUB6:		outb(info->hub6 - 1 + offset, info->port);		outb(value, info->port+1);		break;#endif	case SERIAL_IO_MEM:		writeb(value, (unsigned long) info->iomem_base +			      (offset<<info->iomem_reg_shift));		break;	case SERIAL_IO_MEM32:		writel(value, (unsigned long) info->iomem_base +				(offset<<info->iomem_reg_shift));		break;#ifdef CONFIG_SERIAL_GSC	case SERIAL_IO_GSC:		gsc_writeb(value, info->iomem_base + offset);		break;#endif	default:		outb(value, info->port+offset);	}}/* * We used to support using pause I/O for certain machines.  We * haven't supported this for a while, but just in case it's badly * needed for certain old 386 machines, I've left these #define's * in.... */#define serial_inp(info, offset)		serial_in(info, offset)#define serial_outp(info, offset, value)	serial_out(info, offset, value)/* * For the 16C950 */void serial_icr_write(struct async_struct *info, int offset, int  value){	serial_out(info, UART_SCR, offset);	serial_out(info, UART_ICR, value);}unsigned int serial_icr_read(struct async_struct *info, int offset){	int	value;

⌨️ 快捷键说明

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