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

📄 serial_tx3912.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
{	struct rs_port *port;	int retval, line;	func_enter();	if (!rs_initialized) {		return -EIO;	}	line = MINOR(tty->device) - tty->driver.minor_start;	rs_dprintk (TX3912_UART_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p)\n", 	            (int) current->pid, line, tty, current->tty);	if ((line < 0) || (line >= TX3912_UART_NPORTS))		return -ENODEV;	/* Pre-initialized already */	port = & rs_ports[line];	rs_dprintk (TX3912_UART_DEBUG_OPEN, "port = %p\n", port);	tty->driver_data = port;	port->gs.tty = tty;	port->gs.count++;	rs_dprintk (TX3912_UART_DEBUG_OPEN, "starting port\n");	/*	 * Start up serial port	 */	retval = gs_init_port(&port->gs);	rs_dprintk (TX3912_UART_DEBUG_OPEN, "done gs_init\n");	if (retval) {		port->gs.count--;		return retval;	}	port->gs.flags |= GS_ACTIVE;	rs_dprintk (TX3912_UART_DEBUG_OPEN, "before inc_use_count (count=%d.\n", 	            port->gs.count);	if (port->gs.count == 1) {		MOD_INC_USE_COUNT;	}	rs_dprintk (TX3912_UART_DEBUG_OPEN, "after inc_use_count\n");	/* Jim: Initialize port hardware here */	/* Enable high-priority interrupts for UARTA */	IntEnable6 |= INT6_UARTARXINT; 	rs_enable_rx_interrupts(&rs_ports[0]); 	retval = gs_block_til_ready(&port->gs, filp);	rs_dprintk (TX3912_UART_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n", 	            retval, port->gs.count);	if (retval) {		MOD_DEC_USE_COUNT;		port->gs.count--;		return retval;	}	/* tty->low_latency = 1; */	if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)) {		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)			*tty->termios = port->gs.normal_termios;		else 			*tty->termios = port->gs.callout_termios;		rs_set_real_termios (port);	}	port->gs.session = current->session;	port->gs.pgrp = current->pgrp;	func_exit();	/* Jim *//*	cli(); */	return 0;}static void rs_close (void *ptr){	func_enter ();	/* Anything to do here? */	MOD_DEC_USE_COUNT;	func_exit ();}/* I haven't the foggiest why the decrement use count has to happen   here. The whole linux serial drivers stuff needs to be redesigned.   My guess is that this is a hack to minimize the impact of a bug   elsewhere. Thinking about it some more. (try it sometime) Try   running minicom on a serial port that is driven by a modularized   driver. Have the modem hangup. Then remove the driver module. Then   exit minicom.  I expect an "oops".  -- REW */static void rs_hungup (void *ptr){	func_enter ();	MOD_DEC_USE_COUNT;	func_exit ();}static int rs_ioctl (struct tty_struct * tty, struct file * filp,                      unsigned int cmd, unsigned long arg){	int rc;	struct rs_port *port = tty->driver_data;	int ival;	rc = 0;	switch (cmd) {	case TIOCGSOFTCAR:		rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),		              (unsigned int *) arg);		break;	case TIOCSSOFTCAR:		if ((rc = verify_area(VERIFY_READ, (void *) arg,		                      sizeof(int))) == 0) {			get_user(ival, (unsigned int *) arg);			tty->termios->c_cflag =				(tty->termios->c_cflag & ~CLOCAL) |				(ival ? CLOCAL : 0);		}		break;	case TIOCGSERIAL:		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,		                      sizeof(struct serial_struct))) == 0)			rc = gs_getserial(&port->gs, (struct serial_struct *) arg);		break;	case TIOCSSERIAL:		if ((rc = verify_area(VERIFY_READ, (void *) arg,		                      sizeof(struct serial_struct))) == 0)			rc = gs_setserial(&port->gs, (struct serial_struct *) arg);		break;	default:		rc = -ENOIOCTLCMD;		break;	}	/* func_exit(); */	return rc;}/* * This function is used to send a high-priority XON/XOFF character to * the device */static void rs_send_xchar(struct tty_struct * tty, char ch){	struct rs_port *port = (struct rs_port *)tty->driver_data;	func_enter ();		port->x_char = ch;	if (ch) {		/* Make sure transmit interrupts are on */		rs_enable_tx_interrupts(tty);	}	func_exit();}/* * ------------------------------------------------------------ * rs_throttle() *  * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled. * ------------------------------------------------------------ */static void rs_throttle(struct tty_struct * tty){#ifdef TX3912_UART_DEBUG_THROTTLE	char	buf[64];		printk("throttle %s: %d....\n", tty_name(tty, buf),	       tty->ldisc.chars_in_buffer(tty));#endif	func_enter ();		if (I_IXOFF(tty))		rs_send_xchar(tty, STOP_CHAR(tty));	func_exit ();}static void rs_unthrottle(struct tty_struct * tty){	struct rs_port *port = (struct rs_port *)tty->driver_data;#ifdef TX3912_UART_DEBUG_THROTTLE	char	buf[64];		printk("unthrottle %s: %d....\n", tty_name(tty, buf),	       tty->ldisc.chars_in_buffer(tty));#endif	func_enter();		if (I_IXOFF(tty)) {		if (port->x_char)			port->x_char = 0;		else			rs_send_xchar(tty, START_CHAR(tty));	}	func_exit();}/* ********************************************************************** * *                    Here are the initialization routines.               * * ********************************************************************** */void * ckmalloc (int size){        void *p;        p = kmalloc(size, GFP_KERNEL);        if (p)                 memset(p, 0, size);        return p;}static int rs_init_portstructs(void){	struct rs_port *port;	int i;	/* Debugging */	func_enter();	rs_ports          = ckmalloc(TX3912_UART_NPORTS * sizeof (struct rs_port));	if (!rs_ports)		return -ENOMEM;	rs_termios        = ckmalloc(TX3912_UART_NPORTS * sizeof (struct termios *));	if (!rs_termios) {		kfree (rs_ports);		return -ENOMEM;	}	rs_termios_locked = ckmalloc(TX3912_UART_NPORTS * sizeof (struct termios *));	if (!rs_termios_locked) {		kfree (rs_ports);		kfree (rs_termios);		return -ENOMEM;	}	/* Adjust the values in the "driver" */	rs_driver.termios = rs_termios;	rs_driver.termios_locked = rs_termios_locked;	port = rs_ports;	for (i=0; i < TX3912_UART_NPORTS;i++) {		rs_dprintk (TX3912_UART_DEBUG_INIT, "initing port %d\n", i);		port->gs.callout_termios = tty_std_termios;		port->gs.normal_termios	= tty_std_termios;		port->gs.magic = SERIAL_MAGIC;		port->gs.close_delay = HZ/2;		port->gs.closing_wait = 30 * HZ;		port->gs.rd = &rs_real_driver;#ifdef NEW_WRITE_LOCKING		port->gs.port_write_sem = MUTEX;#endif#ifdef DECLARE_WAITQUEUE		init_waitqueue_head(&port->gs.open_wait);		init_waitqueue_head(&port->gs.close_wait);#endif		port->base = (i == 0) ? TX3912_UARTA_BASE : TX3912_UARTB_BASE;		port->intshift = (i == 0) ? UARTA_SHIFT : UARTB_SHIFT;		rs_dprintk (TX3912_UART_DEBUG_INIT, "base 0x%08lx intshift %d\n",			    port->base, port->intshift);		port++;	}	func_exit();	return 0;}static int rs_init_drivers(void){	int error;	func_enter();	memset(&rs_driver, 0, sizeof(rs_driver));	rs_driver.magic = TTY_DRIVER_MAGIC;	rs_driver.driver_name = "serial";	rs_driver.name = "ttyS";	rs_driver.major = TTY_MAJOR;	rs_driver.minor_start = 64;	rs_driver.num = TX3912_UART_NPORTS;	rs_driver.type = TTY_DRIVER_TYPE_SERIAL;	rs_driver.subtype = SERIAL_TYPE_NORMAL;	rs_driver.init_termios = tty_std_termios;	rs_driver.init_termios.c_cflag =		B115200 | CS8 | CREAD | HUPCL | CLOCAL;	rs_driver.refcount = &rs_refcount;	rs_driver.table = rs_table;	rs_driver.termios = rs_termios;	rs_driver.termios_locked = rs_termios_locked;	rs_driver.open	= rs_open;	rs_driver.close = gs_close;	rs_driver.write = gs_write;	rs_driver.put_char = gs_put_char; 	rs_driver.flush_chars = gs_flush_chars;	rs_driver.write_room = gs_write_room;	rs_driver.chars_in_buffer = gs_chars_in_buffer;	rs_driver.flush_buffer = gs_flush_buffer;	rs_driver.ioctl = rs_ioctl;	rs_driver.throttle = rs_throttle;	rs_driver.unthrottle = rs_unthrottle;	rs_driver.set_termios = gs_set_termios;	rs_driver.stop = gs_stop;	rs_driver.start = gs_start;	rs_driver.hangup = gs_hangup;	rs_callout_driver = rs_driver;	rs_callout_driver.name = "cua";	rs_callout_driver.major = TTYAUX_MAJOR;	rs_callout_driver.subtype = SERIAL_TYPE_CALLOUT;	if ((error = tty_register_driver(&rs_driver))) {		printk(KERN_ERR "Couldn't register serial driver, error = %d\n",		       error);		return 1;	}	if ((error = tty_register_driver(&rs_callout_driver))) {		tty_unregister_driver(&rs_driver);		printk(KERN_ERR "Couldn't register callout driver, error = %d\n",		       error);		return 1;	}	func_exit();	return 0;}void __init tx3912_rs_init(void){	int rc;	func_enter();	rs_dprintk (TX3912_UART_DEBUG_INIT, "Initing serial module... (rs_debug=%d)\n", rs_debug);	rc = rs_init_portstructs ();	rs_init_drivers ();	if (request_irq(2, rs_tx_interrupt_uarta, SA_SHIRQ | SA_INTERRUPT,			"serial", &rs_ports[0])) {		printk(KERN_ERR "rs: Cannot allocate irq for UARTA.\n");		rc = 0;	}	if (request_irq(3, rs_rx_interrupt_uarta, SA_SHIRQ | SA_INTERRUPT,			"serial", &rs_ports[0])) {		printk(KERN_ERR "rs: Cannot allocate irq for UARTA.\n");		rc = 0;	}	IntEnable6 |= INT6_UARTARXINT; 	rs_enable_rx_interrupts(&rs_ports[0]); #ifndef CONFIG_SERIAL_TX3912_CONSOLE{	unsigned int scratch = 0;	/* Setup master clock for UART */	scratch = inl(TX3912_CLK_CTRL_BASE);	scratch &= ~TX3912_CLK_CTRL_SIBMCLKDIV_MASK;	scratch |= ((0x2 << TX3912_CLK_CTRL_SIBMCLKDIV_SHIFT) &				TX3912_CLK_CTRL_SIBMCLKDIV_MASK)			| TX3912_CLK_CTRL_SIBMCLKDIR			| TX3912_CLK_CTRL_ENSIBMCLK			| TX3912_CLK_CTRL_CSERSEL;	outl(scratch, TX3912_CLK_CTRL_BASE);	/* Configure UARTA clock */	scratch = inl(TX3912_CLK_CTRL_BASE);	scratch |= ((0x3 << TX3912_CLK_CTRL_CSERDIV_SHIFT) &				TX3912_CLK_CTRL_CSERDIV_MASK)			| TX3912_CLK_CTRL_ENCSERCLK			| TX3912_CLK_CTRL_ENUARTACLK;	outl(scratch, TX3912_CLK_CTRL_BASE);			/* Setup UARTA for 115200,8N1 */	outl(0, TX3912_UARTA_BASE + TX3912_UART_CTRL1);	outl(TX3912_UART_CTRL2_B115200, TX3912_UARTA_BASE + TX3912_UART_CTRL2);	outl(0, TX3912_UARTA_BASE + TX3912_UART_DMA_CTRL1);	outl(0, TX3912_UARTA_BASE + TX3912_UART_DMA_CTRL2);	/* Enable UARTA */	outl(TX3912_UART_CTRL1_ENUART, TX3912_UARTA_BASE + TX3912_UART_CTRL1);	while (~inl(TX3912_UARTA_BASE + TX3912_UART_CTRL1) &		TX3912_UART_CTRL1_UARTON);}#endif	/* Note: I didn't do anything to enable the second UART */	if (rc >= 0) 		rs_initialized++;	func_exit();}/* * Begin serial console routines */#ifdef CONFIG_SERIAL_TX3912_CONSOLEvoid serial_outc(unsigned char c){	int i;	unsigned long int2;	#define BUSY_WAIT 10000	/*	 * Turn UARTA interrupts off	 */	int2 = IntEnable2;	IntEnable2 &=		~(INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY);	/*	 * The UART_TX_EMPTY bit in UartA_Ctrl1 seems	 * not to be very reliable :-(	 *	 * Wait for the Tx register to become empty	 */	for (i = 0; !(IntStatus2 & INT2_UARTATXINT) && (i < BUSY_WAIT); i++);	IntClear2 = INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY;	UartA_Data = c;	for (i = 0; !(IntStatus2 & INT2_UARTATXINT) && (i < BUSY_WAIT); i++);	IntClear2 = INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY;	IntEnable2 = int2;}static int serial_console_wait_key(struct console *co){	unsigned int int2, res;	int2 = IntEnable2;	IntEnable2 = 0;	while (!(UartA_Ctrl1 & UART_RX_HOLD_FULL));	res = UartA_Data;	udelay(10);		IntEnable2 = int2;	return res;}static void serial_console_write(struct console *co, const char *s,		unsigned count){    	unsigned int i;	for (i = 0; i < count; i++) {		if (*s == '\n')			serial_outc('\r');		serial_outc(*s++);    	}}static kdev_t serial_console_device(struct console *c){	return MKDEV(TTY_MAJOR, 64 + c->index);}static __init int serial_console_setup(struct console *co, char *options){	unsigned int scratch = 0;	/* Setup master clock for UART */	scratch = inl(TX3912_CLK_CTRL_BASE);	scratch &= ~TX3912_CLK_CTRL_SIBMCLKDIV_MASK;	scratch |= ((0x2 << TX3912_CLK_CTRL_SIBMCLKDIV_SHIFT) &				TX3912_CLK_CTRL_SIBMCLKDIV_MASK)			| TX3912_CLK_CTRL_SIBMCLKDIR			| TX3912_CLK_CTRL_ENSIBMCLK			| TX3912_CLK_CTRL_CSERSEL;	outl(scratch, TX3912_CLK_CTRL_BASE);	/* Configure UARTA clock */	scratch = inl(TX3912_CLK_CTRL_BASE);	scratch |= ((0x3 << TX3912_CLK_CTRL_CSERDIV_SHIFT) &				TX3912_CLK_CTRL_CSERDIV_MASK)			| TX3912_CLK_CTRL_ENCSERCLK			| TX3912_CLK_CTRL_ENUARTACLK;	outl(scratch, TX3912_CLK_CTRL_BASE);			/* Setup UARTA for 115200,8N1 */	outl(0, TX3912_UARTA_BASE + TX3912_UART_CTRL1);	outl(TX3912_UART_CTRL2_B115200, TX3912_UARTA_BASE + TX3912_UART_CTRL2);	outl(0, TX3912_UARTA_BASE + TX3912_UART_DMA_CTRL1);	outl(0, TX3912_UARTA_BASE + TX3912_UART_DMA_CTRL2);	/* Enable UARTA */	outl(TX3912_UART_CTRL1_ENUART, TX3912_UARTA_BASE + TX3912_UART_CTRL1);	while (~inl(TX3912_UARTA_BASE + TX3912_UART_CTRL1) &		TX3912_UART_CTRL1_UARTON);	return 0;}static struct console sercons = {	name:     "ttyS",	write:    serial_console_write,	device:   serial_console_device,	wait_key: serial_console_wait_key,	setup:    serial_console_setup,	flags:    CON_PRINTBUFFER,	index:    -1};void __init tx3912_console_init(void){	register_console(&sercons);}#endif

⌨️ 快捷键说明

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