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

📄 serial.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 * fifo. This is used when flashing the IRMA chip. Disabled by default. * * Revision 1.26  2000/03/29 15:32:02  bjornw * 2.0.34 updates * * Revision 1.25  2000/02/16 16:59:36  bjornw * * Receive DMA directly into the flip-buffer, eliminating an intermediary *   receive buffer and a memcpy. Will avoid some overruns. * * Error message on debug port if an overrun or flip buffer overrun occurs. * * Just use the first byte in the flag flip buffer for errors. * * Check for timeout on the serial ports only each 5/100 s, not 1/100. * * Revision 1.24  2000/02/09 18:02:28  bjornw * * Clear serial errors (overrun, framing, parity) correctly. Before, the *   receiver would get stuck if an error occurred and we did not restart *   the input DMA. * * Cosmetics (indentation, some code made into inlines) * * Some more debug options * * Actually shut down the serial port (DMA irq, DMA reset, receiver stop) *   when the last open is closed. Corresponding fixes in startup(). * * rs_close() "tx FIFO wait" code moved into right place, bug & -> && fixed *   and make a special case out of port 1 (R_DMA_CHx_STATUS is broken for that) * * e100_disable_rx/enable_rx just disables/enables the receiver, not RTS * * Revision 1.23  2000/01/24 17:46:19  johana * Wait for flush of DMA/FIFO when closing port. * * Revision 1.22  2000/01/20 18:10:23  johana * Added TIOCMGET ioctl to return modem status. * Implemented modem status/control that works with the extra signals * (DTR, DSR, RI,CD) as well. * 3 different modes supported: * ser0 on PB (Bundy), ser1 on PB (Lisa) and ser2 on PA (Bundy) * Fixed DEF_TX value that caused the serial transmitter pin (txd) to go to 0 when * closing the last filehandle, NASTY!. * Added break generation, not tested though! * Use SA_SHIRQ when request_irq() for ser2 and ser3 (shared with) par0 and par1. * You can't use them at the same time (yet..), but you can hopefully switch * between ser2/par0, ser3/par1 with the same kernel config. * Replaced some magic constants with defines * * */static char *serial_version = "$Revision: 1.58 $";#include <linux/config.h>#include <linux/version.h>#include <linux/types.h>#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/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/kernel.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/system.h>#include <asm/segment.h>#include <asm/bitops.h>#include <linux/delay.h>#include <asm/svinto.h>/* non-arch dependent serial structures are in linux/serial.h */#include <linux/serial.h>/* while we keep our own stuff (struct e100_serial) in a local .h file */#include "serial.h"#include <asm/fasttimer.h>#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST#error "Disable SERIAL_FLUSH_DMA_FAST to use SERIAL_FAST_TIMER"#endif#ifndef CONFIG_ETRAX_FAST_TIMER#error "Enable FAST_TIMER to use SERIAL_FAST_TIMER"#endif#endif#if defined(CONFIG_ETRAX_FAST_TIMER) && defined(CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST)#error "Disable either ETRAX_SERIAL_FLUSH_DMA_FAST or ETRAX_FAST_TIMER"#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#if 1 /* Set to 0 to avoid inlining - easier to see how size of parts */#define _INLINE_ inline#else#define _INLINE_#endifstatic DECLARE_TASK_QUEUE(tq_serial);struct tty_driver serial_driver, callout_driver;static int serial_refcount;/* 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//#define SERIAL_DEBUG_INTR//#define SERIAL_DEBUG_OPEN //#define SERIAL_DEBUG_FLOW//#define SERIAL_DEBUG_DATA//#define SERIAL_DEBUG_THROTTLE//#define SERIAL_DEBUG_IO  /* Debug for Extra control and status pins */#define SERIAL_DEBUG_LINE 3 /* What serport we want to debug *//* Enable this to use serial interrupts to handle when you   expect the first received event on the serial port to   be an error, break or similar. Used to be able to flash IRMA   from eLinux */#define SERIAL_HANDLE_EARLY_ERRORS/* Defined and used in n_tty.c, but we need it here as well */#define TTY_THRESHOLD_THROTTLE 128/* Due to buffersizes and threshold values, our SERIAL_DESCR_BUF_SIZE * must not be to high or flow control won't work if we leave it to the tty * layer so we have our own throttling in flush_to_flip * TTY_FLIPBUF_SIZE=512, * TTY_THRESHOLD_THROTTLE/UNTHROTTLE=128 * BUF_SIZE can't be > 128 *//* Currently 16 descriptors x 128 bytes = 2048 bytes */#define SERIAL_DESCR_BUF_SIZE 256#define SERIAL_PRESCALE_BASE 3125000 /* 3.125MHz */#define DEF_BAUD_BASE SERIAL_PRESCALE_BASE/* We don't want to load the system with massive fast timer interrupt * on high baudrates so limit it to 250 us (4kHz) */#define MIN_FLUSH_TIME_USEC 250/* Add an x here to log a lot of timer stuff */#define TIMERD(x)/* Debug details of interrupt handling */#define DINTR1(x)  /* irq on/off, errors */#define DINTR2(x)    /* tx and rx *//* Debug flip buffer stuff */#define DFLIP(x)/* Debug flow control and overview of data flow */#define DFLOW(x)#define DBAUD(x)#ifdef CONFIG_ETRAX_DEBUG_INTERRUPT#define DLOG_INT_TRIG(x) #else#define DLOG_INT_TRIG(x)#endif//#define DEBUG_LOG_INCLUDED#ifndef DEBUG_LOG_INCLUDED#define DEBUG_LOG(line, string, value)#elsestruct debug_log_info {	unsigned long time;	unsigned long timer_data;//  int line;	const char *string;	int value;};#define DEBUG_LOG_SIZE 4096struct debug_log_info debug_log[DEBUG_LOG_SIZE];int debug_log_pos = 0;  #define DEBUG_LOG(_line, _string, _value) do { \  if ((_line) == SERIAL_DEBUG_LINE) {\    debug_log_func(_line, _string, _value); \  }\}while(0)void debug_log_func(int line, const char *string, int value){	if (debug_log_pos < DEBUG_LOG_SIZE) { 		debug_log[debug_log_pos].time = jiffies;		debug_log[debug_log_pos].timer_data = *R_TIMER_DATA;//    debug_log[debug_log_pos].line = line;		debug_log[debug_log_pos].string = string;		debug_log[debug_log_pos].value = value;		debug_log_pos++; 	}	/*printk(string, value);*/} #endif#ifndef CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS/* Default number of timer ticks before flushing rx fifo  * When using "little data, low latency applications: use 0 * When using "much data applications (PPP)" use ~5 */#define CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS 5 #endifunsigned long timer_data_to_ns(unsigned long timer_data);static void change_speed(struct e100_serial *info);static void rs_throttle(struct tty_struct * tty);static void rs_wait_until_sent(struct tty_struct *tty, int timeout);static int rs_write(struct tty_struct * tty, int from_user,                    const unsigned char *buf, int count);extern _INLINE_ int rs_raw_write(struct tty_struct * tty, int from_user,                            const unsigned char *buf, int count);#ifdef CONFIG_ETRAX_RS485static int e100_write_rs485(struct tty_struct * tty, int from_user,                            const unsigned char *buf, int count);#endifstatic int get_lsr_info(struct e100_serial * info, unsigned int *value);#define DEF_BAUD 115200   /* 115.2 kbit/s */#define STD_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)#define DEF_RX 0x20  /* or SERIAL_CTRL_W >> 8 *//* Default value of tx_ctrl register: has txd(bit 7)=1 (idle) as default */#define DEF_TX 0x80  /* or SERIAL_CTRL_B *//* offsets from R_SERIALx_CTRL */#define REG_DATA 0#define REG_DATA_STATUS32 0 /* this is the 32 bit register R_SERIALx_READ */#define REG_TR_DATA 0#define REG_STATUS 1#define REG_TR_CTRL 1#define REG_REC_CTRL 2#define REG_BAUD 3#define REG_XOFF 4  /* this is a 32 bit register *//* The bitfields are the same for all serial ports */#define SER_RXD_MASK         IO_MASK(R_SERIAL0_STATUS, rxd)#define SER_DATA_AVAIL_MASK  IO_MASK(R_SERIAL0_STATUS, data_avail)#define SER_FRAMING_ERR_MASK IO_MASK(R_SERIAL0_STATUS, framing_err)#define SER_PAR_ERR_MASK     IO_MASK(R_SERIAL0_STATUS, par_err)#define SER_OVERRUN_MASK     IO_MASK(R_SERIAL0_STATUS, overrun)#define SER_ERROR_MASK (SER_OVERRUN_MASK | SER_PAR_ERR_MASK | SER_FRAMING_ERR_MASK)/* Values for info->errorcode */#define ERRCODE_SET_BREAK    (TTY_BREAK)#define ERRCODE_INSERT        0x100#define ERRCODE_INSERT_BREAK (ERRCODE_INSERT | TTY_BREAK)#define FORCE_EOP(info)  *R_SET_EOP = 1U << info->iseteop;/* * General note regarding the use of IO_* macros in this file:  * * We will use the bits defined for DMA channel 6 when using various * IO_* macros (e.g. IO_STATE, IO_MASK, IO_EXTRACT) and _assume_ they are * the same for all channels (which of course they are). * * We will also use the bits defined for serial port 0 when writing commands * to the different ports, as these bits too are the same for all ports. *//* Mask for the irqs possibly enabled in R_IRQ_MASK1_RD etc. */static const unsigned long e100_ser_int_mask = 0#ifdef CONFIG_ETRAX_SERIAL_PORT0| IO_MASK(R_IRQ_MASK1_RD, ser0_data) | IO_MASK(R_IRQ_MASK1_RD, ser0_ready)#endif#ifdef CONFIG_ETRAX_SERIAL_PORT1| IO_MASK(R_IRQ_MASK1_RD, ser1_data) | IO_MASK(R_IRQ_MASK1_RD, ser1_ready)#endif#ifdef CONFIG_ETRAX_SERIAL_PORT2| IO_MASK(R_IRQ_MASK1_RD, ser2_data) | IO_MASK(R_IRQ_MASK1_RD, ser2_ready)#endif#ifdef CONFIG_ETRAX_SERIAL_PORT3| IO_MASK(R_IRQ_MASK1_RD, ser3_data) | IO_MASK(R_IRQ_MASK1_RD, ser3_ready)#endif	; unsigned long r_alt_ser_baudrate_shadow = 0;/* this is the data for the four serial ports in the etrax100 *//*  DMA2(ser2), DMA4(ser3), DMA6(ser0) or DMA8(ser1) *//* R_DMA_CHx_CLR_INTR, R_DMA_CHx_FIRST, R_DMA_CHx_CMD */static struct e100_serial rs_table[] = {	{ .baud        = DEF_BAUD,	  .port        = (unsigned char *)R_SERIAL0_CTRL,	  .irq         = 1U << 12, /* uses DMA 6 and 7 */	  .oclrintradr = R_DMA_CH6_CLR_INTR,	  .ofirstadr   = R_DMA_CH6_FIRST,	  .ocmdadr     = R_DMA_CH6_CMD,	  .ostatusadr  = R_DMA_CH6_STATUS,	  .iclrintradr = R_DMA_CH7_CLR_INTR,	  .ifirstadr   = R_DMA_CH7_FIRST,	  .icmdadr     = R_DMA_CH7_CMD,	  .idescradr   = R_DMA_CH7_DESCR,	  .flags       = STD_FLAGS,	  .rx_ctrl     = DEF_RX,	  .tx_ctrl     = DEF_TX,	  .iseteop     = 2,#ifdef CONFIG_ETRAX_SERIAL_PORT0          .enabled  = 1,#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT	  .dma_out_enabled = 1,#else	  .dma_out_enabled = 0,#endif#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN	  .dma_in_enabled = 1,#else	  .dma_in_enabled = 0#endif#else          .enabled  = 0,	  .dma_out_enabled = 0,	  .dma_in_enabled = 0	  #endif},  /* ttyS0 */#ifndef CONFIG_SVINTO_SIM	{ .baud        = DEF_BAUD,	  .port        = (unsigned char *)R_SERIAL1_CTRL,	  .irq         = 1U << 16, /* uses DMA 8 and 9 */	  .oclrintradr = R_DMA_CH8_CLR_INTR,	  .ofirstadr   = R_DMA_CH8_FIRST,	  .ocmdadr     = R_DMA_CH8_CMD,	  .ostatusadr  = R_DMA_CH8_STATUS,	  .iclrintradr = R_DMA_CH9_CLR_INTR,	  .ifirstadr   = R_DMA_CH9_FIRST,	  .icmdadr     = R_DMA_CH9_CMD,	  .idescradr   = R_DMA_CH9_DESCR,	  .flags       = STD_FLAGS,	  .rx_ctrl     = DEF_RX,	  .tx_ctrl     = DEF_TX,	  .iseteop     = 3,#ifdef CONFIG_ETRAX_SERIAL_PORT1          .enabled  = 1,#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT	  .dma_out_enabled = 1,#else	  .dma_out_enabled = 0,#endif#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN	  .dma_in_enabled = 1,#else	  .dma_in_enabled = 0#endif#else          .enabled  = 0,	  .dma_out_enabled = 0,	  .dma_in_enabled = 0#endif},  /* ttyS1 */	{ .baud        = DEF_BAUD,	  .port        = (unsigned char *)R_SERIAL2_CTRL,	  .irq         = 1U << 4,  /* uses DMA 2 and 3 */	  .oclrintradr = R_DMA_CH2_CLR_INTR,	  .ofirstadr   = R_DMA_CH2_FIRST,	  .ocmdadr     = R_DMA_CH2_CMD,	  .ostatusadr  = R_DMA_CH2_STATUS,	  .iclrintradr = R_DMA_CH3_CLR_INTR,	  .ifirstadr   = R_DMA_CH3_FIRST,	  .icmdadr     = R_DMA_CH3_CMD,	  .idescradr   = R_DMA_CH3_DESCR,	  .flags       = STD_FLAGS,	  .rx_ctrl     = DEF_RX,	  .tx_ctrl     = DEF_TX,	  .iseteop     = 0,#ifdef CONFIG_ETRAX_SERIAL_PORT2          .enabled  = 1,#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT	  .dma_out_enabled = 1,#else	  .dma_out_enabled = 0,#endif#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN	  .dma_in_enabled = 1,#else	  .dma_in_enabled = 0#endif#else          .enabled  = 0,	  .dma_out_enabled = 0,	  .dma_in_enabled = 0#endif },  /* ttyS2 */	{ .baud        = DEF_BAUD,	  .port        = (unsigned char *)R_SERIAL3_CTRL,	  .irq         = 1U << 8,  /* uses DMA 4 and 5 */	  .oclrintradr = R_DMA_CH4_CLR_INTR,	  .ofirstadr   = R_DMA_CH4_FIRST,	  .ocmdadr     = R_DMA_CH4_CMD,	  .ostatusadr  = R_DMA_CH4_STATUS,

⌨️ 快捷键说明

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