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

📄 uart00.c

📁 linux下的串口口驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	/* first, disable everything */	save_flags(flags); cli();	old_ies = UART_GET_IES(port); 	if ((port->flags & ASYNC_HARDPPS_CD) ||	    (cflag & CRTSCTS) || !(cflag & CLOCAL))		old_ies |= UART_IES_ME_MSK;	/* Set baud rate */	UART_PUT_DIV_LO(port, (quot & 0xff));	UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));   	UART_PUT_MC(port, uart_mc);	UART_PUT_IES(port, old_ies);	restore_flags(flags);}static int uart00_startup(struct uart_port *port, struct uart_info *info){	int retval;	/* 	 * Use iobase to store a pointer to info. We need this to start a 	 * transmission as the tranmittr interrupt is only generated on	 * the transition to the idle state 	 */	port->iobase=(u_int)info;		/*	 * Allocate the IRQ	 */	retval = request_irq(port->irq, uart00_int, 0, "uart00", info);	if (retval)		return retval;	/*	 * Finally, enable interrupts. Use the TII interrupt to minimise 	 * the number of interrupts generated. If higher performance is 	 * needed, consider using the TI interrupt with a suitable FIFO	 * threshold	 */	UART_PUT_IES(port, UART_IES_RE_MSK | UART_IES_TIE_MSK);	return 0;}static void uart00_shutdown(struct uart_port *port, struct uart_info *info){	/*	 * disable all interrupts, disable the port	 */	UART_PUT_IEC(port, 0xff);	/* disable break condition and fifos */	UART_PUT_MCR(port, UART_GET_MCR(port) &~UART_MCR_BR_MSK);	/*	 * Free the interrupt	 */	free_irq(port->irq, info);}static const char *uart00_type(struct uart_port *port){        return port->type == PORT_UART00 ? "Altera UART00" : NULL;}/* * Release the memory region(s) being used by 'port' */static void uart00_release_port(struct uart_port *port){	release_mem_region(port->mapbase, UART_PORT_SIZE);#ifdef CONFIG_ARCH_CAMELOT	if(port->membase!=(void*)IO_ADDRESS(EXC_UART00_BASE)){		iounmap(port->membase);	}#endif}/* * Request the memory region(s) being used by 'port' */static int uart00_request_port(struct uart_port *port){	int result;	result = request_mem_region(port->mapbase, UART_PORT_SIZE,				    "serial_uart00") != NULL ? 0 : -EBUSY;	if (result)		return result;	port->membase = ioremap(port->mapbase, SZ_4K);	if (!port->membase) {		printk(KERN_ERR "serial00: cannot map io memory\n");		release_mem_region(port->mapbase, UART_PORT_SIZE);	}	return port->membase ? 0 : -ENOMEM;}/* * Configure/autoconfigure the port. */static void uart00_config_port(struct uart_port *port, int flags){	if (flags & UART_CONFIG_TYPE) {		if (uart00_request_port(port) == 0)			port->type = PORT_UART00;	}}/* * verify the new serial_struct (for TIOCSSERIAL). */static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser){	int ret = 0;	if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)		ret = -EINVAL;	if (ser->irq < 0 || ser->irq >= NR_IRQS)		ret = -EINVAL;	if (ser->baud_base < 9600)		ret = -EINVAL;	return ret;}static struct uart_ops uart00_pops = {	tx_empty:	uart00_tx_empty,	set_mctrl:	uart00_set_mctrl,	get_mctrl:	uart00_get_mctrl,	stop_tx:	uart00_stop_tx,	start_tx:	uart00_start_tx,	stop_rx:	uart00_stop_rx,	enable_ms:	uart00_enable_ms,	break_ctl:	uart00_break_ctl,	startup:	uart00_startup,	shutdown:	uart00_shutdown,	change_speed:	uart00_change_speed,	type:		uart00_type,	release_port:	uart00_release_port,	request_port:	uart00_request_port,	config_port:	uart00_config_port,	verify_port:	uart00_verify_port,};static struct uart_port uart00_ports[UART_NR] = {#ifdef CONFIG_ARCH_CAMELOT{	membase:	(void*)IO_ADDRESS(EXC_UART00_BASE),	mapbase:        EXC_UART00_BASE,	iotype:		SERIAL_IO_MEM,	irq:		IRQ_UART,	uartclk:	EXC_AHB2_CLK_FREQUENCY,	fifosize:	16,	ops:		&uart00_pops,	flags:          ASYNC_BOOT_AUTOCONF,}#endif};#ifdef CONFIG_SERIAL_UART00_CONSOLEstatic void uart00_console_write(struct console *co, const char *s, unsigned count){#ifdef CONFIG_ARCH_CAMELOT	struct uart_port *port = &uart00_ports[0];	unsigned int status, old_ies;	int i;	/*	 *	First save the CR then disable the interrupts	 */	old_ies = UART_GET_IES(port);	UART_PUT_IEC(port,0xff);	/*	 *	Now, do each character	 */	for (i = 0; i < count; i++) {		do {			status = UART_GET_TSR(port);		} while (!UART_TX_READY(status));		UART_PUT_CHAR(port, s[i]);		if (s[i] == '\n') {			do {				status = UART_GET_TSR(port);			} while (!UART_TX_READY(status));			UART_PUT_CHAR(port, '\r');		}	}	/*	 *	Finally, wait for transmitter to become empty	 *	and restore the IES	 */	do {		status = UART_GET_TSR(port);	} while (status & UART_TSR_TX_LEVEL_MSK);	UART_PUT_IES(port, old_ies);#endif}static kdev_t uart00_console_device(struct console *co){       return MKDEV(SERIAL_UART00_MAJOR, SERIAL_UART00_MINOR + co->index);}static void /*__init*/ uart00_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits){	u_int uart_mc, quot;	uart_mc= UART_GET_MC(port);	*parity = 'n';	if (uart_mc & UART_MC_PE_MSK) {		if (uart_mc & UART_MC_EP_MSK)			*parity = 'e';		else			*parity = 'o';	}	switch (uart_mc & UART_MC_CLS_MSK){	case UART_MC_CLS_CHARLEN_5:		*bits = 5;		break;	case UART_MC_CLS_CHARLEN_6:		*bits = 6;		break;	case UART_MC_CLS_CHARLEN_7:		*bits = 7;		break;	case UART_MC_CLS_CHARLEN_8:		*bits = 8;		break;	}	quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);	*baud = port->uartclk / (16 *quot );}static int __init uart00_console_setup(struct console *co, char *options){	struct uart_port *port;	int baud = 38400;	int bits = 8;	int parity = 'n';	int flow= 'n';#ifdef CONFIG_ARCH_CAMELOT	/*	 * Check whether an invalid uart number has been specified, and	 * if so, search for the first available port that does have	 * console support.	 */	port = &uart00_ports[0];	co->index = 0;#else	return -ENODEV;#endif	if (options)		uart_parse_options(options, &baud, &parity, &bits, &flow);	else		uart00_console_get_options(port, &baud, &parity, &bits);	return uart_set_options(port, co, baud, parity, bits, flow);}static struct console uart00_console = {	name:           SERIAL_UART00_NAME,	write:		uart00_console_write,	device:		uart00_console_device,	setup:		uart00_console_setup,	flags:		CON_PRINTBUFFER,	index:		0,};void __init uart00_console_init(void){	register_console(&uart00_console);}#define UART00_CONSOLE	&uart00_console#else#define UART00_CONSOLE	NULL#endifstatic struct uart_driver uart00_reg = {	owner:                  NULL,	normal_major:		SERIAL_UART00_MAJOR,	normal_name:		SERIAL_UART00_NAME,	normal_driver:		&normal,	callout_major:		CALLOUT_UART00_MAJOR,	callout_name:		CALLOUT_UART00_NAME,	callout_driver:		&callout,	table:			uart00_table,	termios:		uart00_termios,	termios_locked:		uart00_termios_locked,	minor:			SERIAL_UART00_MINOR,	nr:			UART_NR,	port:			uart00_ports,	state:			NULL,	cons:			UART00_CONSOLE,};struct dev_port_entry{       struct uart_port *port;};static struct dev_port_entry dev_port_map[UART_NR];#ifdef CONFIG_PLD_HOTSWAP/* * Keep a mapping of dev_info addresses -> port lines to use when * removing ports dev==NULL indicates unused entry */struct uart00_ps_data{       unsigned int clk;       unsigned int fifosize;};int uart00_add_device(struct pldhs_dev_info* dev_info, void* dev_ps_data){       struct uart00_ps_data* dev_ps=dev_ps_data;       struct uart_port * port;       int i,result;       i=0;       while(dev_port_map[i].port)               i++;       if(i==UART_NR){               printk(KERN_WARNING "uart00: Maximum number of ports reached\n");               return 0;       }       port=kmalloc(sizeof(struct uart_port),GFP_KERNEL);       if(!port)               return -ENOMEM;       printk("clk=%d fifo=%d\n",dev_ps->clk,dev_ps->fifosize);       port->membase=0;       port->mapbase=dev_info->base_addr;       port->iotype=SERIAL_IO_MEM;       port->irq=dev_info->irq;       port->uartclk=dev_ps->clk;       port->fifosize=dev_ps->fifosize;       port->ops=&uart00_pops;       port->line=i;       port->flags=ASYNC_BOOT_AUTOCONF;       result=uart_register_port(&uart00_reg, port);       if(result<0){               printk("uart_register_port returned %d\n",result);               return result;       }       dev_port_map[i].port=port;       printk("uart00: added device at %lx as ttyUA%d\n",dev_port_map[i].port->mapbase,i);       return 0;}int uart00_remove_devices(void){       int i,result;       result=0;       for(i=1;i<UART_NR;i++){               if(dev_port_map[i].port){                       uart_unregister_port(&uart00_reg,i);                       /* port removed sucessfully, so now tidy up */                       kfree(dev_port_map[i].port);                       dev_port_map[i].port=NULL;               }       }       return 0;}#if CONFIG_PROC_FSint uart00_proc_read(char* buf,char** start,off_t offset,int count,int *eof,void *data){       int i,len=0;       struct uart_port *port;       int limit = count - 80;       char ps_data[80];       if(*start)               buf=*start;       for(i=0;(i<UART_NR)&&(len<limit);i++){               if(dev_port_map[i].port){                       port=dev_port_map[i].port;                       sprintf(ps_data,"clk, %dHz, fifo size, %dbytes",                               port->uartclk,port->fifosize);                       len+=PLDHS_READ_PROC_DATA(buf+len,"uart00",i,                                           port->mapbase,port->irq,ps_data);               }       }       *eof=1;       return len;}#endifstruct pld_hotswap_ops uart00_pldhs_ops={       name: "uart00",       add_device: uart00_add_device,       remove_devices:uart00_remove_devices,       proc_read:uart00_proc_read};#endifstatic int __init uart00_init(void){       int ret;       int i;       for(i=0;i<UART_NR;i++){               uart00_ports[i].ops=&uart00_pops;       }	printk(KERN_WARNING "uart00:Using temporary major/minor pairs - these WILL change in the future\n");#ifdef CONFIG_PLD_HOTSWAP       pldhs_register_driver(&uart00_pldhs_ops);#endif       unregister_console(&uart00_console);       ret=uart_register_driver(&uart00_reg);       register_console(&uart00_console);#ifdef CONFIG_ARCH_CAMELOT       dev_port_map[0].port=uart00_ports;#endif       return ret;}__initcall(uart00_init);

⌨️ 快捷键说明

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