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

📄 serial.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
//#define SERIAL_DEBUG_IO  /* Debug for Extra control and status pins */#define SERIAL_DEBUG_LINE 0 /* 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#define TTY_THROTTLE_LIMIT (TTY_FLIPBUF_SIZE/10)#define SERIAL_DESCR_BUF_SIZE 256/* Add an x here to log a lot of timer stuff */#define TIMERD(x)#define DEBUG_LOG(line, string, value)#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 #endifstatic void change_speed(struct e100_serial *info);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 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 0x99   /* 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_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. *//* 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[] = {	{ DEF_BAUD, (unsigned char *)R_SERIAL0_CTRL, 1U << 12, /* uses DMA 6 and 7 */	  R_DMA_CH6_CLR_INTR, R_DMA_CH6_FIRST, R_DMA_CH6_CMD,	  R_DMA_CH6_STATUS, R_DMA_CH6_HWSW, R_DMA_CH6_DESCR,	  R_DMA_CH7_CLR_INTR, R_DMA_CH7_FIRST, R_DMA_CH7_CMD,	  R_DMA_CH7_STATUS, R_DMA_CH7_HWSW, R_DMA_CH7_DESCR,	  STD_FLAGS, DEF_RX, DEF_TX, 2,#ifdef CONFIG_ETRAX_SERIAL_PORT0          1#else          0#endif},  /* ttyS0 */#ifndef CONFIG_SVINTO_SIM	{ DEF_BAUD, (unsigned char *)R_SERIAL1_CTRL, 1U << 16, /* uses DMA 8 and 9 */	  R_DMA_CH8_CLR_INTR, R_DMA_CH8_FIRST, R_DMA_CH8_CMD,	  R_DMA_CH8_STATUS, R_DMA_CH8_HWSW, R_DMA_CH8_DESCR,	  R_DMA_CH9_CLR_INTR, R_DMA_CH9_FIRST, R_DMA_CH9_CMD,	  R_DMA_CH9_STATUS, R_DMA_CH9_HWSW, R_DMA_CH9_DESCR,	  STD_FLAGS, DEF_RX, DEF_TX, 3 ,#ifdef CONFIG_ETRAX_SERIAL_PORT1          1#else          0#endif},  /* ttyS1 */	{ DEF_BAUD, (unsigned char *)R_SERIAL2_CTRL, 1U << 4,  /* uses DMA 2 and 3 */	  R_DMA_CH2_CLR_INTR, R_DMA_CH2_FIRST, R_DMA_CH2_CMD,	  R_DMA_CH2_STATUS, R_DMA_CH2_HWSW, R_DMA_CH2_DESCR,	  R_DMA_CH3_CLR_INTR, R_DMA_CH3_FIRST, R_DMA_CH3_CMD,	  R_DMA_CH3_STATUS, R_DMA_CH3_HWSW, R_DMA_CH3_DESCR,	  STD_FLAGS, DEF_RX, DEF_TX, 0,#ifdef CONFIG_ETRAX_SERIAL_PORT2          1#else          0#endif },  /* ttyS2 */	{ DEF_BAUD, (unsigned char *)R_SERIAL3_CTRL, 1U << 8,  /* uses DMA 4 and 5 */	  R_DMA_CH4_CLR_INTR, R_DMA_CH4_FIRST, R_DMA_CH4_CMD,	  R_DMA_CH4_STATUS, R_DMA_CH4_HWSW, R_DMA_CH4_DESCR,	  R_DMA_CH5_CLR_INTR, R_DMA_CH5_FIRST, R_DMA_CH5_CMD,	  R_DMA_CH5_STATUS, R_DMA_CH5_HWSW, R_DMA_CH5_DESCR,	  STD_FLAGS, DEF_RX, DEF_TX, 1,#ifdef CONFIG_ETRAX_SERIAL_PORT3          1#else          0#endif }   /* ttyS3 */#endif};#define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial))  static struct tty_struct *serial_table[NR_PORTS]; static struct termios *serial_termios[NR_PORTS];static struct termios *serial_termios_locked[NR_PORTS];#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMERstatic struct fast_timer fast_timers[NR_PORTS];#endif#ifdef CONFIG_ETRAX_SERIAL_PROC_ENTRY#define PROCSTAT(x) xstruct ser_statistics_type {	int overrun_cnt;	int early_errors_cnt;	int ser_ints_ok_cnt;	int errors_cnt;	unsigned long int processing_flip;	unsigned long processing_flip_still_room;	unsigned long int timeout_flush_cnt;	int rx_dma_ints;	int tx_dma_ints;	int rx_tot;	int tx_tot;};static struct ser_statistics_type ser_stat[NR_PORTS];#else#define PROCSTAT(x)#endif /* CONFIG_ETRAX_SERIAL_PROC_ENTRY *//* RS-485 */#if defined(CONFIG_ETRAX_RS485)#ifdef CONFIG_ETRAX_FAST_TIMERstatic struct fast_timer fast_timers_rs485[NR_PORTS];#endif#if defined(CONFIG_ETRAX_RS485_ON_PA)static int rs485_pa_bit = CONFIG_ETRAX_RS485_ON_PA_BIT;#endif#endif/* Info and macros needed for each ports extra control/status signals. */#define E100_STRUCT_PORT(line, pinname) \ ((CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT >= 0)? \		(R_PORT_PA_DATA): ( \ (CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT >= 0)? \		(R_PORT_PB_DATA):&dummy_ser[##line##]))#define E100_STRUCT_SHADOW(line, pinname) \ ((CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT >= 0)? \		(&port_pa_data_shadow): ( \ (CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT >= 0)? \		(&port_pb_data_shadow):&dummy_ser[line]))#define E100_STRUCT_MASK(line, pinname) \ ((CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT >= 0)? \		(1<<CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT): ( \ (CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT >= 0)? \		(1<<CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT):DUMMY_##pinname##_MASK))#define DUMMY_DTR_MASK 1#define DUMMY_RI_MASK  2#define DUMMY_DSR_MASK 4#define DUMMY_CD_MASK  8static unsigned char dummy_ser[NR_PORTS] = {0xFF, 0xFF, 0xFF,0xFF};#if defined(CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED) || \    defined(CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED) || \    defined(CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED) || \    defined(CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED)#define CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED#endif#ifdef CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED/* The pins can be mixed on PA and PB */#define CONTROL_PINS_PORT_NOT_USED(line) \  &dummy_ser[line], &dummy_ser[line], \  &dummy_ser[line], &dummy_ser[line], \  &dummy_ser[line], &dummy_ser[line], \  &dummy_ser[line], &dummy_ser[line], \  DUMMY_DTR_MASK, DUMMY_RI_MASK, DUMMY_DSR_MASK, DUMMY_CD_MASK    struct control_pins{	volatile unsigned char *dtr_port;	unsigned char          *dtr_shadow;	volatile unsigned char *ri_port;	unsigned char          *ri_shadow;	volatile unsigned char *dsr_port;	unsigned char          *dsr_shadow;	volatile unsigned char *cd_port;	unsigned char          *cd_shadow;	unsigned char dtr_mask;	unsigned char ri_mask;	unsigned char dsr_mask;	unsigned char cd_mask;};static const struct control_pins e100_modem_pins[NR_PORTS] = {	/* Ser 0 */	{#ifdef CONFIG_ETRAX_SERIAL_PORT0	E100_STRUCT_PORT(0,DTR), E100_STRUCT_SHADOW(0,DTR),	E100_STRUCT_PORT(0,RI),  E100_STRUCT_SHADOW(0,RI),	E100_STRUCT_PORT(0,DSR), E100_STRUCT_SHADOW(0,DSR),	E100_STRUCT_PORT(0,CD),  E100_STRUCT_SHADOW(0,CD),	E100_STRUCT_MASK(0,DTR),	E100_STRUCT_MASK(0,RI),	E100_STRUCT_MASK(0,DSR),	E100_STRUCT_MASK(0,CD)#else	CONTROL_PINS_PORT_NOT_USED(0)#endif		},	/* Ser 1 */	{#ifdef CONFIG_ETRAX_SERIAL_PORT1	  	E100_STRUCT_PORT(1,DTR), E100_STRUCT_SHADOW(1,DTR),	E100_STRUCT_PORT(1,RI),  E100_STRUCT_SHADOW(1,RI),	E100_STRUCT_PORT(1,DSR), E100_STRUCT_SHADOW(1,DSR),	E100_STRUCT_PORT(1,CD),  E100_STRUCT_SHADOW(1,CD),	E100_STRUCT_MASK(1,DTR),	E100_STRUCT_MASK(1,RI),	E100_STRUCT_MASK(1,DSR),	E100_STRUCT_MASK(1,CD)#else	CONTROL_PINS_PORT_NOT_USED(1)#endif			},	/* Ser 2 */	{#ifdef CONFIG_ETRAX_SERIAL_PORT2	  	E100_STRUCT_PORT(2,DTR), E100_STRUCT_SHADOW(2,DTR),	E100_STRUCT_PORT(2,RI),  E100_STRUCT_SHADOW(2,RI),	E100_STRUCT_PORT(2,DSR), E100_STRUCT_SHADOW(2,DSR),	E100_STRUCT_PORT(2,CD),  E100_STRUCT_SHADOW(2,CD),	E100_STRUCT_MASK(2,DTR),	E100_STRUCT_MASK(2,RI),	E100_STRUCT_MASK(2,DSR),	E100_STRUCT_MASK(2,CD)#else	CONTROL_PINS_PORT_NOT_USED(2)#endif			},	/* Ser 3 */	{#ifdef CONFIG_ETRAX_SERIAL_PORT3	  	E100_STRUCT_PORT(3,DTR), E100_STRUCT_SHADOW(3,DTR),	E100_STRUCT_PORT(3,RI),  E100_STRUCT_SHADOW(3,RI),	E100_STRUCT_PORT(3,DSR), E100_STRUCT_SHADOW(3,DSR),	E100_STRUCT_PORT(3,CD),  E100_STRUCT_SHADOW(3,CD),	E100_STRUCT_MASK(3,DTR),	E100_STRUCT_MASK(3,RI),	E100_STRUCT_MASK(3,DSR),	E100_STRUCT_MASK(3,CD)#else	CONTROL_PINS_PORT_NOT_USED(3)#endif			}};#else  /* CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED *//* All pins are on either PA or PB for each serial port */#define CONTROL_PINS_PORT_NOT_USED(line) \  &dummy_ser[line], &dummy_ser[line], \  DUMMY_DTR_MASK, DUMMY_RI_MASK, DUMMY_DSR_MASK, DUMMY_CD_MASK    struct control_pins{	volatile unsigned char *port;	unsigned char          *shadow;	unsigned char dtr_mask;	unsigned char ri_mask;	unsigned char dsr_mask;	unsigned char cd_mask;};#define dtr_port port#define dtr_shadow shadow#define ri_port port#define ri_shadow shadow#define dsr_port port#define dsr_shadow shadow#define cd_port port#define cd_shadow shadowstatic const struct control_pins e100_modem_pins[NR_PORTS] = {	/* Ser 0 */	{#ifdef CONFIG_ETRAX_SERIAL_PORT0	E100_STRUCT_PORT(0,DTR), E100_STRUCT_SHADOW(0,DTR),	E100_STRUCT_MASK(0,DTR),	E100_STRUCT_MASK(0,RI),	E100_STRUCT_MASK(0,DSR),	E100_STRUCT_MASK(0,CD)#else	CONTROL_PINS_PORT_NOT_USED(0)#endif		},	/* Ser 1 */	{#ifdef CONFIG_ETRAX_SERIAL_PORT1	  	E100_STRUCT_PORT(1,DTR), E100_STRUCT_SHADOW(1,DTR),	E100_STRUCT_MASK(1,DTR),	E100_STRUCT_MASK(1,RI),	E100_STRUCT_MASK(1,DSR),	E100_STRUCT_MASK(1,CD)#else	CONTROL_PINS_PORT_NOT_USED(1)#endif			},	/* Ser 2 */	{#ifdef CONFIG_ETRAX_SERIAL_PORT2	  	E100_STRUCT_PORT(2,DTR), E100_STRUCT_SHADOW(2,DTR),	E100_STRUCT_MASK(2,DTR),	E100_STRUCT_MASK(2,RI),	E100_STRUCT_MASK(2,DSR),	E100_STRUCT_MASK(2,CD)#else	CONTROL_PINS_PORT_NOT_USED(2)#endif			},	/* Ser 3 */	{#ifdef CONFIG_ETRAX_SERIAL_PORT3	  	E100_STRUCT_PORT(3,DTR), E100_STRUCT_SHADOW(3,DTR),	E100_STRUCT_MASK(3,DTR),	E100_STRUCT_MASK(3,RI),	E100_STRUCT_MASK(3,DSR),	E100_STRUCT_MASK(3,CD)#else	CONTROL_PINS_PORT_NOT_USED(3)#endif			}};#endif /* !CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED */#if defined(CONFIG_ETRAX_RS485) && defined(CONFIG_ETRAX_RS485_ON_PA)unsigned char rs485_pa_port = CONFIG_ETRAX_RS485_ON_PA_BIT;#endif#define E100_RTS_MASK 0x20#define E100_CTS_MASK 0x40/* All serial port signals are active low: * active   = 0 -> 3.3V to RS-232 driver -> -12V on RS-232 level * inactive = 1 -> 0V   to RS-232 driver -> +12V on RS-232 level * * These macros returns the pin value: 0=0V, >=1 = 3.3V on ETRAX chip *//* Output */#define E100_RTS_GET(info) ((info)->rx_ctrl & E100_RTS_MASK)/* Input */#define E100_CTS_GET(info) ((info)->port[REG_STATUS] & E100_CTS_MASK)/* These are typically PA or PB and 0 means 0V, 1 means 3.3V *//* Is an output */#define E100_DTR_GET(info) ((*e100_modem_pins[(info)->line].dtr_shadow) & e100_modem_pins[(info)->line].dtr_mask)/* Normally inputs */#define E100_RI_GET(info) ((*e100_modem_pins[(info)->line].ri_port) & e100_modem_pins[(info)->line].ri_mask)#define E100_CD_GET(info) ((*e100_modem_pins[(info)->line].cd_port) & e100_modem_pins[(info)->line].cd_mask)/* Input */#define E100_DSR_GET(info) ((*e100_modem_pins[(info)->line].dsr_port) & e100_modem_pins[(info)->line].dsr_mask)/* * tmp_buf is used as a temporary buffer by serial_write.  We need to * lock it in case the memcpy_fromfs 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. */

⌨️ 快捷键说明

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