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

📄 serial_8250.c

📁 16c554的驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
	case CS5: lcr = LCR_CS5; break;
	case CS6: lcr = LCR_CS6; break;
	case CS7: lcr = LCR_CS7; break;
	default:  lcr = LCR_CS8; break;
	}
	if(cflag&CSTOPB)
		lcr |= LCR_STOPB; //停止位为2或1.5;
		
	if(cflag&PARENB){
		lcr |= LCR_PARITY;   //使能奇偶校验
		if(!(cflag&PARODD))
			lcr |= LCR_PEVEN;   //偶校验
	}

	//port->read_status_mask = UART_OE;
	//if(iflag&INPCK)
	//	port->read_status_mask |= UART_PE|UART_FE;

//	port->ignore_status_mask = 0;
	//if(iflag&IGNPAR)
	//	port->ignore_status_mask |= UART_PE|UART_FE;
//	if(iflag&IGNBRK){
	//	port->ignore_status_mask |= UART_BE;
	//	if(iflag&IGNPAR)
	//		port->ignore_status_mask |= UART_OE;
	//}

	save_flags_cli(flags);      //在system.h里定义,存储状态在flags里
	lcr=inb(LCR)&0x80;//使能DLL和DLM寄存器
	outb(lcr, LCR);
	outb((quot-1)%256, DLL);    //设置波特率
	outb((quot-1)/256, DLM);
  lcr=inb(LCR)&0x7F;
  outb(lcr,LCR);
  
//	DLL = (auot-1)%256;
//	DLM = (auot-1)/256;
	restore_flags(flags);//在system.h里定义,将flags里存储的状态恢复

}

static const char *port4_type(struct  uart_port *port)// 返回一个描述特定端口的常量string的指针
{
	return port->type == PORT_16654 ? "PORT4" : NULL;
}

/*
 * Release the memory region(s) being used by 'port'
 */
static void port4_release_port(struct uart_port *port)
{
}

/*
 * Request the memory region(s) being used by 'port'
 */
static int port4_request_port(struct uart_port *port)
{
	return 0;
}

/*
 * Configure/autoconfigure the port.
 */
static void port4_config_port(struct uart_port *port, int flags)
{
	if(flags & UART_CONFIG_TYPE)//UART_CONFIG_TYPE定义在serial_core.h里,等于(1《0)
		port->type =PORT_16654 ;
}

/*
 * verify the new serial_struct (for TIOCSSERIAL).
 */
static int port4_verify_port(struct uart_port *port, struct serial_struct *ser)
{
	return 0;
}

static struct uart_ops port4_pops = {
	tx_empty:	port4_tx_empty,
	set_mctrl:	port4_set_mctrl,
	get_mctrl:	port4_get_mctrl,
	stop_tx:	port4_stop_tx,
	start_tx:	port4_start_tx,
	stop_rx:	port4_stop_rx,
	enable_ms:	port4_enable_ms,
	break_ctl:	port4_break_ctl,
	startup:	port4_startup,
	shutdown:	port4_shutdown,
	change_speed:	port4_change_speed,
	type:		port4_type,
	release_port:	port4_release_port,
	request_port:	port4_request_port,
	config_port:	port4_config_port,
	verify_port:	port4_verify_port,
};
//#define UB_RHR 	REGL2(0x00)
#define UB_RHR (*(volatile unsigned int*)(0x06000000))
#define UC_RHR (*(volatile unsigned int*)(0x0A000000))
#define UD_RHR (*(volatile unsigned int*)(0x0E000000))
static struct uart_port port4_ports[4] = {
	{
		iobase:		(void *)&UA_RHR,
		irq:		21,                        //外部中断4
		uartclk:	CONFIG_PORT4_CLK,//29491200,
		fifosize:	16,
		ops:		&port4_pops,
		flags:		ASYNC_BOOT_AUTOCONF, //0x10000000 ;定义在serial.h里
	},
	{
		iobase:		(void *)&UB_RHR,
		irq:		23,                    //外部中断2
		uartclk:	CONFIG_PORT4_CLK,//29491200,
		fifosize:	16,
		ops:		&port4_pops,
		flags:		ASYNC_BOOT_AUTOCONF,
	},
	{
		iobase:		(void *)&UC_RHR,
		irq:		24,                     //外部中断1
		uartclk:	CONFIG_PORT4_CLK,//29491200,
		fifosize:	16,
		ops:		&port4_pops,
		flags:		ASYNC_BOOT_AUTOCONF,
	},
	{
		iobase:		(void *)&UD_RHR,
		irq:		25,                    //外部中断0
		uartclk:	CONFIG_PORT4_CLK,//29491200,   //在autoconf.h中定义
		fifosize:	16,
		ops:		&port4_pops,
		flags:		ASYNC_BOOT_AUTOCONF,
	}
};

#ifdef CONFIG_SERIAL_PORT4_CONSOLE
static void port4_console_write(struct console *co, const char *s, u_int count)
{
	struct uart_port *port = port4_ports + co->index;
unsigned	char status1,status2, intmask;
	int i;

	intmask = inb(IER);
	INT_DISABLE(port->irq);    //定义在irq.h里
		// status=(inb(IER)&0xFD);   //禁止接收和发送数据中断
	//outl(status,IER);
	for (i = 0; i < count; i++) {
		do {
			status1 = inb(LSR);
		} while (status1&TEMP); //等待发送空时,传输
		outb(s[i], THR);
		if (s[i] == '\n') {
			do {
				status1 = inb(LSR);
			} while (status1&TEMP);
			outb('\r',THR);
		}
	}

	do {
		status2 = inb(LSR);
	} while ((status2&TEMP)==0); //当发送队列都为空时,恢复原来的中断标志
	outb(intmask,IER);
}

static kdev_t port4_console_device(struct console *co)   //为系统增加一个设备
{
	return MKDEV(SERIAL_PORT4_MAJOR, SERIAL_PORT4_MINOR+co->index);
}

static int port4_console_wait_key(struct console *co)    //系统调用时接收数据
{
	struct uart_port *port = port4_ports + co->index;
	unsigned char  ch;
		//int intmask = inl(IER);        // save the IER 
		//int status=(inl(IER)&0xFC);// disable the interrupts so	that the real driver for the port does not get the
	                             //character.
		unsigned char status1;

	do{
		status1 = inb(LSR);
	}while(status1&0x01==0);  //等待数据准备好,也就是等待接收中有数据
	ch = inb(RHR);
	//outl(intmask,IER);

	return ch;
}

static void __init port4_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
{
unsigned char quotl,quoth, quot,status;

//	status = inl(UCON);
	//if(!status)
	//	return;

	status = inb(LCR);
	*bits = (status&3)+5;

	*parity = 'n';
	if(status&LCR_PARITY){
		if(status&LCR_PEVEN)
			*parity = 'e';
		else
			*parity = 'o';
	}

	quotl = inb(DLL);
	quoth=inb(DLM);
	quot=quoth*256+quotl+1;
	//*baud = port->uartclk/(16*(quot+1));

	if(quot<2&quot>=1){
		*baud = 115200;
		return;
	}
	if(quot<3&quot>=2){
		*baud = 57600;
		return;
	}
	if(quot<6&& quot>=3){
		*baud = 38400;
		return;
	}
//	if(*baud>34000 && *baud<42000){
	//	*baud = 38400;
	//	return;
	//}
	if(quot<12 && quot>=6){
		*baud = 19200;
		return;
	}
	if(quot<24 && quot>=12){
		*baud = 9600;
		return;
	}
	if(quot<48 && quot>=24){
		*baud = 4800;
		return;
	}
	if(quot<96&&quot>=48){
		*baud = 2400;
		return;
	}
	if(quot<192 && quot>=96){
		*baud = 1200;
		return;
	}
if(quot<384 && quot>=192){
		*baud = 600;
		return;
	}
	if(quot<2304&&quot>=384){
		*baud = 300;
		return;
	}
	if(quot<65535&&quot>=2304){
		*baud = 50;
		return;
	}
}

static int __init port4_console_setup(struct console *co, char *options)
{
	struct uart_port *port;
	int baud = 115200;
	int bits = 8;
	int parity = 'n';
	int flow = 'n';

	/*
	 * Check whether an invalid uart number has been specified, and
	 * if so, search for the first available port that does have
	 * console support.
	*/
	port = uart_get_console(port4_ports, UART_NR, co);


	if (options)
		uart_parse_options(options, &baud, &parity, &bits, &flow);
	else
		port4_console_get_options(port, &baud, &parity, &bits);

	outb(0xC7, FCR);
	//outl(0x05, UCON);
	return uart_set_options(port, co, baud, parity, bits, flow);
/*
	outl(0x97, UFCON);
	outl(0x03, ULCON);
	outl(0x20, UBRDIV);
	outl(0x05, UCON);
*/
        return 0;
}

static struct console port4_console = {
	name:		"ttyS",
	write:		port4_console_write,
	device:		port4_console_device,
	wait_key:	port4_console_wait_key,
	setup:		port4_console_setup,
	flags:		CON_PRINTBUFFER,
	index:		-1,
};

void __init port4_console_init(void)
{
	register_console(&port4_console);
}

#define PORT4_CONSOLE	&port4_console
#else
#define PORT4_CONSOLE	NULL
#endif

static struct uart_driver port4_reg = {
	owner:			THIS_MODULE,
	normal_major:		SERIAL_PORT4_MAJOR,
#ifdef CONFIG_DEVFS_FS
	normal_name:		"ttyS%d",
	callout_name:		"cua%d",
#else
	normal_name:		"ttyS",
	callout_name:		"cua",
#endif
	normal_driver:		&normal,
	callout_major:		CALLOUT_PORT4_MAJOR,
	callout_driver:		&callout,
	table:			port4_table,
	termios:		port4_termios,
	termios_locked:		port4_termios_locked,
	minor:			SERIAL_PORT4_MINOR,
	nr:			UART_NR,
	port:			port4_ports,
	cons:			PORT4_CONSOLE,
};

static int __init port4_init(void)
{
	return uart_register_driver(&port4_reg);
}

static void __exit port4_exit(void)
{
	uart_unregister_driver(&port4_reg);
}

module_init(port4_init);    //在module.h里定义
module_exit(port4_exit);

EXPORT_NO_SYMBOLS;

MODULE_AUTHOR("SMQ"); //在module.h里定义
MODULE_DESCRIPTION("ARM S3C44B0 expand serial port4 driver");
MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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