ioc4_serial.c

来自「linux 内核源代码」· C语言 代码 · 共 2,250 行 · 第 1/5 页

C
2,250
字号
/* * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 2003-2006 Silicon Graphics, Inc.  All Rights Reserved. *//* * This file contains a module version of the ioc4 serial driver. This * includes all the support functions needed (support functions, etc.) * and the serial driver itself. */#include <linux/errno.h>#include <linux/tty.h>#include <linux/serial.h>#include <linux/serialP.h>#include <linux/circ_buf.h>#include <linux/serial_reg.h>#include <linux/module.h>#include <linux/pci.h>#include <linux/ioc4.h>#include <linux/serial_core.h>/* * interesting things about the ioc4 */#define IOC4_NUM_SERIAL_PORTS	4	/* max ports per card */#define IOC4_NUM_CARDS		8	/* max cards per partition */#define	GET_SIO_IR(_n)	(_n == 0) ? (IOC4_SIO_IR_S0) : \				(_n == 1) ? (IOC4_SIO_IR_S1) : \				(_n == 2) ? (IOC4_SIO_IR_S2) : \				(IOC4_SIO_IR_S3)#define	GET_OTHER_IR(_n)  (_n == 0) ? (IOC4_OTHER_IR_S0_MEMERR) : \				(_n == 1) ? (IOC4_OTHER_IR_S1_MEMERR) : \				(_n == 2) ? (IOC4_OTHER_IR_S2_MEMERR) : \				(IOC4_OTHER_IR_S3_MEMERR)/* * All IOC4 registers are 32 bits wide. *//* * PCI Memory Space Map */#define IOC4_PCI_ERR_ADDR_L     0x000	/* Low Error Address */#define IOC4_PCI_ERR_ADDR_VLD	        (0x1 << 0)#define IOC4_PCI_ERR_ADDR_MST_ID_MSK    (0xf << 1)#define IOC4_PCI_ERR_ADDR_MST_NUM_MSK   (0xe << 1)#define IOC4_PCI_ERR_ADDR_MST_TYP_MSK   (0x1 << 1)#define IOC4_PCI_ERR_ADDR_MUL_ERR       (0x1 << 5)#define IOC4_PCI_ERR_ADDR_ADDR_MSK      (0x3ffffff << 6)/* Interrupt types */#define	IOC4_SIO_INTR_TYPE	0#define	IOC4_OTHER_INTR_TYPE	1#define	IOC4_NUM_INTR_TYPES	2/* Bitmasks for IOC4_SIO_IR, IOC4_SIO_IEC, and IOC4_SIO_IES  */#define IOC4_SIO_IR_S0_TX_MT	   0x00000001	/* Serial port 0 TX empty */#define IOC4_SIO_IR_S0_RX_FULL	   0x00000002	/* Port 0 RX buf full */#define IOC4_SIO_IR_S0_RX_HIGH	   0x00000004	/* Port 0 RX hiwat */#define IOC4_SIO_IR_S0_RX_TIMER	   0x00000008	/* Port 0 RX timeout */#define IOC4_SIO_IR_S0_DELTA_DCD   0x00000010	/* Port 0 delta DCD */#define IOC4_SIO_IR_S0_DELTA_CTS   0x00000020	/* Port 0 delta CTS */#define IOC4_SIO_IR_S0_INT	   0x00000040	/* Port 0 pass-thru intr */#define IOC4_SIO_IR_S0_TX_EXPLICIT 0x00000080	/* Port 0 explicit TX thru */#define IOC4_SIO_IR_S1_TX_MT	   0x00000100	/* Serial port 1 */#define IOC4_SIO_IR_S1_RX_FULL	   0x00000200	/* */#define IOC4_SIO_IR_S1_RX_HIGH	   0x00000400	/* */#define IOC4_SIO_IR_S1_RX_TIMER	   0x00000800	/* */#define IOC4_SIO_IR_S1_DELTA_DCD   0x00001000	/* */#define IOC4_SIO_IR_S1_DELTA_CTS   0x00002000	/* */#define IOC4_SIO_IR_S1_INT	   0x00004000	/* */#define IOC4_SIO_IR_S1_TX_EXPLICIT 0x00008000	/* */#define IOC4_SIO_IR_S2_TX_MT	   0x00010000	/* Serial port 2 */#define IOC4_SIO_IR_S2_RX_FULL	   0x00020000	/* */#define IOC4_SIO_IR_S2_RX_HIGH	   0x00040000	/* */#define IOC4_SIO_IR_S2_RX_TIMER	   0x00080000	/* */#define IOC4_SIO_IR_S2_DELTA_DCD   0x00100000	/* */#define IOC4_SIO_IR_S2_DELTA_CTS   0x00200000	/* */#define IOC4_SIO_IR_S2_INT	   0x00400000	/* */#define IOC4_SIO_IR_S2_TX_EXPLICIT 0x00800000	/* */#define IOC4_SIO_IR_S3_TX_MT	   0x01000000	/* Serial port 3 */#define IOC4_SIO_IR_S3_RX_FULL	   0x02000000	/* */#define IOC4_SIO_IR_S3_RX_HIGH	   0x04000000	/* */#define IOC4_SIO_IR_S3_RX_TIMER	   0x08000000	/* */#define IOC4_SIO_IR_S3_DELTA_DCD   0x10000000	/* */#define IOC4_SIO_IR_S3_DELTA_CTS   0x20000000	/* */#define IOC4_SIO_IR_S3_INT	   0x40000000	/* */#define IOC4_SIO_IR_S3_TX_EXPLICIT 0x80000000	/* *//* Per device interrupt masks */#define IOC4_SIO_IR_S0		(IOC4_SIO_IR_S0_TX_MT | \				 IOC4_SIO_IR_S0_RX_FULL | \				 IOC4_SIO_IR_S0_RX_HIGH | \				 IOC4_SIO_IR_S0_RX_TIMER | \				 IOC4_SIO_IR_S0_DELTA_DCD | \				 IOC4_SIO_IR_S0_DELTA_CTS | \				 IOC4_SIO_IR_S0_INT | \				 IOC4_SIO_IR_S0_TX_EXPLICIT)#define IOC4_SIO_IR_S1		(IOC4_SIO_IR_S1_TX_MT | \				 IOC4_SIO_IR_S1_RX_FULL | \				 IOC4_SIO_IR_S1_RX_HIGH | \				 IOC4_SIO_IR_S1_RX_TIMER | \				 IOC4_SIO_IR_S1_DELTA_DCD | \				 IOC4_SIO_IR_S1_DELTA_CTS | \				 IOC4_SIO_IR_S1_INT | \				 IOC4_SIO_IR_S1_TX_EXPLICIT)#define IOC4_SIO_IR_S2		(IOC4_SIO_IR_S2_TX_MT | \				 IOC4_SIO_IR_S2_RX_FULL | \				 IOC4_SIO_IR_S2_RX_HIGH | \				 IOC4_SIO_IR_S2_RX_TIMER | \				 IOC4_SIO_IR_S2_DELTA_DCD | \				 IOC4_SIO_IR_S2_DELTA_CTS | \				 IOC4_SIO_IR_S2_INT | \				 IOC4_SIO_IR_S2_TX_EXPLICIT)#define IOC4_SIO_IR_S3		(IOC4_SIO_IR_S3_TX_MT | \				 IOC4_SIO_IR_S3_RX_FULL | \				 IOC4_SIO_IR_S3_RX_HIGH | \				 IOC4_SIO_IR_S3_RX_TIMER | \				 IOC4_SIO_IR_S3_DELTA_DCD | \				 IOC4_SIO_IR_S3_DELTA_CTS | \				 IOC4_SIO_IR_S3_INT | \				 IOC4_SIO_IR_S3_TX_EXPLICIT)/* Bitmasks for IOC4_OTHER_IR, IOC4_OTHER_IEC, and IOC4_OTHER_IES  */#define IOC4_OTHER_IR_ATA_INT		0x00000001  /* ATAPI intr pass-thru */#define IOC4_OTHER_IR_ATA_MEMERR	0x00000002  /* ATAPI DMA PCI error */#define IOC4_OTHER_IR_S0_MEMERR		0x00000004  /* Port 0 PCI error */#define IOC4_OTHER_IR_S1_MEMERR		0x00000008  /* Port 1 PCI error */#define IOC4_OTHER_IR_S2_MEMERR		0x00000010  /* Port 2 PCI error */#define IOC4_OTHER_IR_S3_MEMERR		0x00000020  /* Port 3 PCI error */#define IOC4_OTHER_IR_KBD_INT		0x00000040  /* Keyboard/mouse */#define IOC4_OTHER_IR_RESERVED		0x007fff80  /* Reserved */#define IOC4_OTHER_IR_RT_INT		0x00800000  /* INT_OUT section output */#define IOC4_OTHER_IR_GEN_INT		0xff000000  /* Generic pins */#define IOC4_OTHER_IR_SER_MEMERR (IOC4_OTHER_IR_S0_MEMERR | IOC4_OTHER_IR_S1_MEMERR | \				  IOC4_OTHER_IR_S2_MEMERR | IOC4_OTHER_IR_S3_MEMERR)/* Bitmasks for IOC4_SIO_CR */#define IOC4_SIO_CR_CMD_PULSE_SHIFT              0  /* byte bus strobe shift */#define IOC4_SIO_CR_ARB_DIAG_TX0	0x00000000#define IOC4_SIO_CR_ARB_DIAG_RX0	0x00000010#define IOC4_SIO_CR_ARB_DIAG_TX1	0x00000020#define IOC4_SIO_CR_ARB_DIAG_RX1	0x00000030#define IOC4_SIO_CR_ARB_DIAG_TX2	0x00000040#define IOC4_SIO_CR_ARB_DIAG_RX2	0x00000050#define IOC4_SIO_CR_ARB_DIAG_TX3	0x00000060#define IOC4_SIO_CR_ARB_DIAG_RX3	0x00000070#define IOC4_SIO_CR_SIO_DIAG_IDLE	0x00000080  /* 0 -> active request among							   serial ports (ro) *//* Defs for some of the generic I/O pins */#define IOC4_GPCR_UART0_MODESEL	   0x10	/* Pin is output to port 0						   mode sel */#define IOC4_GPCR_UART1_MODESEL	   0x20	/* Pin is output to port 1						   mode sel */#define IOC4_GPCR_UART2_MODESEL	   0x40	/* Pin is output to port 2						   mode sel */#define IOC4_GPCR_UART3_MODESEL	   0x80	/* Pin is output to port 3						   mode sel */#define IOC4_GPPR_UART0_MODESEL_PIN   4	/* GIO pin controlling					   uart 0 mode select */#define IOC4_GPPR_UART1_MODESEL_PIN   5	/* GIO pin controlling					   uart 1 mode select */#define IOC4_GPPR_UART2_MODESEL_PIN   6	/* GIO pin controlling					   uart 2 mode select */#define IOC4_GPPR_UART3_MODESEL_PIN   7	/* GIO pin controlling					   uart 3 mode select *//* Bitmasks for serial RX status byte */#define IOC4_RXSB_OVERRUN       0x01	/* Char(s) lost */#define IOC4_RXSB_PAR_ERR	0x02	/* Parity error */#define IOC4_RXSB_FRAME_ERR	0x04	/* Framing error */#define IOC4_RXSB_BREAK	        0x08	/* Break character */#define IOC4_RXSB_CTS	        0x10	/* State of CTS */#define IOC4_RXSB_DCD	        0x20	/* State of DCD */#define IOC4_RXSB_MODEM_VALID   0x40	/* DCD, CTS, and OVERRUN are valid */#define IOC4_RXSB_DATA_VALID    0x80	/* Data byte, FRAME_ERR PAR_ERR					 * & BREAK valid *//* Bitmasks for serial TX control byte */#define IOC4_TXCB_INT_WHEN_DONE 0x20	/* Interrupt after this byte is sent */#define IOC4_TXCB_INVALID	0x00	/* Byte is invalid */#define IOC4_TXCB_VALID	        0x40	/* Byte is valid */#define IOC4_TXCB_MCR	        0x80	/* Data<7:0> to modem control reg */#define IOC4_TXCB_DELAY	        0xc0	/* Delay data<7:0> mSec *//* Bitmasks for IOC4_SBBR_L */#define IOC4_SBBR_L_SIZE	0x00000001  /* 0 == 1KB rings, 1 == 4KB rings *//* Bitmasks for IOC4_SSCR_<3:0> */#define IOC4_SSCR_RX_THRESHOLD  0x000001ff  /* Hiwater mark */#define IOC4_SSCR_TX_TIMER_BUSY 0x00010000  /* TX timer in progress */#define IOC4_SSCR_HFC_EN	0x00020000  /* Hardware flow control enabled */#define IOC4_SSCR_RX_RING_DCD   0x00040000  /* Post RX record on delta-DCD */#define IOC4_SSCR_RX_RING_CTS   0x00080000  /* Post RX record on delta-CTS */#define IOC4_SSCR_DIAG	        0x00200000  /* Bypass clock divider for sim */#define IOC4_SSCR_RX_DRAIN	0x08000000  /* Drain RX buffer to memory */#define IOC4_SSCR_DMA_EN	0x10000000  /* Enable ring buffer DMA */#define IOC4_SSCR_DMA_PAUSE	0x20000000  /* Pause DMA */#define IOC4_SSCR_PAUSE_STATE   0x40000000  /* Sets when PAUSE takes effect */#define IOC4_SSCR_RESET	        0x80000000  /* Reset DMA channels *//* All producer/comsumer pointers are the same bitfield */#define IOC4_PROD_CONS_PTR_4K   0x00000ff8	/* For 4K buffers */#define IOC4_PROD_CONS_PTR_1K   0x000003f8	/* For 1K buffers */#define IOC4_PROD_CONS_PTR_OFF           3/* Bitmasks for IOC4_SRCIR_<3:0> */#define IOC4_SRCIR_ARM	        0x80000000	/* Arm RX timer *//* Bitmasks for IOC4_SHADOW_<3:0> */#define IOC4_SHADOW_DR	 0x00000001	/* Data ready */#define IOC4_SHADOW_OE	 0x00000002	/* Overrun error */#define IOC4_SHADOW_PE	 0x00000004	/* Parity error */#define IOC4_SHADOW_FE	 0x00000008	/* Framing error */#define IOC4_SHADOW_BI	 0x00000010	/* Break interrupt */#define IOC4_SHADOW_THRE 0x00000020	/* Xmit holding register empty */#define IOC4_SHADOW_TEMT 0x00000040	/* Xmit shift register empty */#define IOC4_SHADOW_RFCE 0x00000080	/* Char in RX fifo has an error */#define IOC4_SHADOW_DCTS 0x00010000	/* Delta clear to send */#define IOC4_SHADOW_DDCD 0x00080000	/* Delta data carrier detect */#define IOC4_SHADOW_CTS	 0x00100000	/* Clear to send */#define IOC4_SHADOW_DCD	 0x00800000	/* Data carrier detect */#define IOC4_SHADOW_DTR	 0x01000000	/* Data terminal ready */#define IOC4_SHADOW_RTS	 0x02000000	/* Request to send */#define IOC4_SHADOW_OUT1 0x04000000	/* 16550 OUT1 bit */#define IOC4_SHADOW_OUT2 0x08000000	/* 16550 OUT2 bit */#define IOC4_SHADOW_LOOP 0x10000000	/* Loopback enabled *//* Bitmasks for IOC4_SRTR_<3:0> */#define IOC4_SRTR_CNT	        0x00000fff	/* Reload value for RX timer */#define IOC4_SRTR_CNT_VAL	0x0fff0000	/* Current value of RX timer */#define IOC4_SRTR_CNT_VAL_SHIFT         16#define IOC4_SRTR_HZ                 16000	/* SRTR clock frequency *//* Serial port register map used for DMA and PIO serial I/O */struct ioc4_serialregs {	uint32_t sscr;	uint32_t stpir;	uint32_t stcir;	uint32_t srpir;	uint32_t srcir;	uint32_t srtr;	uint32_t shadow;};/* IOC4 UART register map */struct ioc4_uartregs {	char i4u_lcr;	union {		char iir;	/* read only */		char fcr;	/* write only */	} u3;	union {		char ier;	/* DLAB == 0 */		char dlm;	/* DLAB == 1 */	} u2;	union {		char rbr;	/* read only, DLAB == 0 */		char thr;	/* write only, DLAB == 0 */		char dll;	/* DLAB == 1 */	} u1;	char i4u_scr;	char i4u_msr;	char i4u_lsr;	char i4u_mcr;};/* short names */#define i4u_dll u1.dll#define i4u_ier u2.ier#define i4u_dlm u2.dlm#define i4u_fcr u3.fcr/* Serial port registers used for DMA serial I/O */struct ioc4_serial {	uint32_t sbbr01_l;	uint32_t sbbr01_h;	uint32_t sbbr23_l;	uint32_t sbbr23_h;	struct ioc4_serialregs port_0;	struct ioc4_serialregs port_1;	struct ioc4_serialregs port_2;	struct ioc4_serialregs port_3;	struct ioc4_uartregs uart_0;	struct ioc4_uartregs uart_1;	struct ioc4_uartregs uart_2;	struct ioc4_uartregs uart_3;} ioc4_serial;/* UART clock speed */#define IOC4_SER_XIN_CLK_66     66666667#define IOC4_SER_XIN_CLK_33     33333333#define IOC4_W_IES		0#define IOC4_W_IEC		1typedef void ioc4_intr_func_f(void *, uint32_t);typedef ioc4_intr_func_f *ioc4_intr_func_t;static unsigned int Num_of_ioc4_cards;/* defining this will get you LOTS of great debug info *///#define DEBUG_INTERRUPTS#define DPRINT_CONFIG(_x...)	;//#define DPRINT_CONFIG(_x...)	printk _x/* number of characters left in xmit buffer before we ask for more */#define WAKEUP_CHARS	256/* number of characters we want to transmit to the lower level at a time */#define IOC4_MAX_CHARS	256#define IOC4_FIFO_CHARS	255/* Device name we're using */#define DEVICE_NAME_RS232  "ttyIOC"#define DEVICE_NAME_RS422  "ttyAIOC"#define DEVICE_MAJOR	   204#define DEVICE_MINOR_RS232 50#define DEVICE_MINOR_RS422 84/* register offsets */#define IOC4_SERIAL_OFFSET	0x300/* flags for next_char_state */#define NCS_BREAK	0x1#define NCS_PARITY	0x2#define NCS_FRAMING	0x4#define NCS_OVERRUN	0x8/* cause we need SOME parameters ... */#define MIN_BAUD_SUPPORTED	1200#define MAX_BAUD_SUPPORTED	115200/* protocol types supported */#define PROTO_RS232	3#define PROTO_RS422	7/* Notification types */#define N_DATA_READY	0x01#define N_OUTPUT_LOWAT	0x02#define N_BREAK		0x04#define N_PARITY_ERROR	0x08#define N_FRAMING_ERROR	0x10#define N_OVERRUN_ERROR	0x20#define N_DDCD		0x40#define N_DCTS		0x80#define N_ALL_INPUT	(N_DATA_READY | N_BREAK |			\			 N_PARITY_ERROR | N_FRAMING_ERROR |		\			 N_OVERRUN_ERROR | N_DDCD | N_DCTS)#define N_ALL_OUTPUT	N_OUTPUT_LOWAT#define N_ALL_ERRORS	(N_PARITY_ERROR | N_FRAMING_ERROR | N_OVERRUN_ERROR)#define N_ALL		(N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK |	\			 N_PARITY_ERROR | N_FRAMING_ERROR |		\			 N_OVERRUN_ERROR | N_DDCD | N_DCTS)#define SER_DIVISOR(_x, clk)		(((clk) + (_x) * 8) / ((_x) * 16))#define DIVISOR_TO_BAUD(div, clk)	((clk) / 16 / (div))/* Some masks */#define LCR_MASK_BITS_CHAR	(UART_LCR_WLEN5 | UART_LCR_WLEN6 \					| UART_LCR_WLEN7 | UART_LCR_WLEN8)#define LCR_MASK_STOP_BITS	(UART_LCR_STOP)#define PENDING(_p)	(readl(&(_p)->ip_mem->sio_ir.raw) & _p->ip_ienb)#define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir.raw)/* Default to 4k buffers */#ifdef IOC4_1K_BUFFERS#define RING_BUF_SIZE 1024#define IOC4_BUF_SIZE_BIT 0#define PROD_CONS_MASK IOC4_PROD_CONS_PTR_1K#else#define RING_BUF_SIZE 4096#define IOC4_BUF_SIZE_BIT IOC4_SBBR_L_SIZE#define PROD_CONS_MASK IOC4_PROD_CONS_PTR_4K#endif#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4)/* * This is the entry saved by the driver - one per card */#define UART_PORT_MIN		0#define UART_PORT_RS232		UART_PORT_MIN#define UART_PORT_RS422		1#define UART_PORT_COUNT		2	/* one for each mode */struct ioc4_control {	int ic_irq;	struct {		/* uart ports are allocated here - 1 for rs232, 1 for rs422 */		struct uart_port icp_uart_port[UART_PORT_COUNT];		/* Handy reference material */		struct ioc4_port *icp_port;	} ic_port[IOC4_NUM_SERIAL_PORTS];	struct ioc4_soft *ic_soft;};/* * per-IOC4 data structure */#define MAX_IOC4_INTR_ENTS	(8 * sizeof(uint32_t))struct ioc4_soft {	struct ioc4_misc_regs __iomem *is_ioc4_misc_addr;	struct ioc4_serial __iomem *is_ioc4_serial_addr;	/* Each interrupt type has an entry in the array */	struct ioc4_intr_type {		/*		 * Each in-use entry in this array contains at least		 * one nonzero bit in sd_bits; no two entries in this		 * array have overlapping sd_bits values.		 */		struct ioc4_intr_info {			uint32_t sd_bits;			ioc4_intr_func_f *sd_intr;			void *sd_info;		} is_intr_info[MAX_IOC4_INTR_ENTS];		/* Number of entries active in the above array */		atomic_t is_num_intrs;	} is_intr_type[IOC4_NUM_INTR_TYPES];	/* is_ir_lock must be held while	 * modifying sio_ie values, so	 * we can be sure that sio_ie is	 * not changing when we read it	 * along with sio_ir.	 */	spinlock_t is_ir_lock;	/* SIO_IE[SC] mod lock */};

⌨️ 快捷键说明

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