dz.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 828 行 · 第 1/2 页

C
828
字号
	struct dz_port *dport = (struct dz_port *)uport;	unsigned long flags;	unsigned short tmp;	/* The dz lines for the mouse/keyboard must be	 * opened using their respective drivers.	 */	if ((dport->port.line == DZ_KEYBOARD) ||	    (dport->port.line == DZ_MOUSE))		return -ENODEV;	spin_lock_irqsave(&dport->port.lock, flags);	/* enable the interrupt and the scanning */	tmp = dz_in(dport, DZ_CSR);	tmp |= DZ_RIE | DZ_TIE | DZ_MSE;	dz_out(dport, DZ_CSR, tmp);	spin_unlock_irqrestore(&dport->port.lock, flags);	return 0;}/*  * ------------------------------------------------------------------- * shutdown () * * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. * -------------------------------------------------------------------  */static void dz_shutdown(struct uart_port *uport){	dz_stop_tx(uport, 0);}/* * get_lsr_info - get line status register info * * Purpose: Let user call ioctl() to get info when the UART physically *          is emptied.  On bus types like RS485, the transmitter must *          release the bus after transmitting. This must be done when *          the transmit shift register is empty, not be done when the *          transmit holding register is empty.  This functionality *          allows an RS485 driver to be written in user space.  */static unsigned int dz_tx_empty(struct uart_port *uport){	struct dz_port *dport = (struct dz_port *)uport;	unsigned short status = dz_in(dport, DZ_LPR);	/* FIXME: this appears to be obviously broken --rmk. */	return status ? TIOCSER_TEMT : 0;}static void dz_break_ctl(struct uart_port *uport, int break_state){	struct dz_port *dport = (struct dz_port *)uport;	unsigned long flags;	unsigned short tmp, mask = 1 << uport->line;	spin_lock_irqsave(&uport->lock, flags);	tmp = dz_in(dport, DZ_TCR);	if (break_state)		tmp |= mask;	else		tmp &= ~mask;	dz_out(dport, DZ_TCR, tmp);	spin_unlock_irqrestore(&uport->lock, flags);}static void dz_set_termios(struct uart_port *uport, struct termios *termios,			   struct termios *old_termios){	struct dz_port *dport = (struct dz_port *)uport;	unsigned long flags;	unsigned int cflag, baud;	cflag = dport->port.line;	switch (termios->c_cflag & CSIZE) {	case CS5:		cflag |= DZ_CS5;		break;	case CS6:		cflag |= DZ_CS6;		break;	case CS7:		cflag |= DZ_CS7;		break;	case CS8:	default:		cflag |= DZ_CS8;	}	if (termios->c_cflag & CSTOPB)		cflag |= DZ_CSTOPB;	if (termios->c_cflag & PARENB)		cflag |= DZ_PARENB;	if (termios->c_cflag & PARODD)		cflag |= DZ_PARODD;	baud = uart_get_baud_rate(uport, termios, old_termios, 50, 9600);	switch (baud) {	case 50:		cflag |= DZ_B50;		break;	case 75:		cflag |= DZ_B75;		break;	case 110:		cflag |= DZ_B110;		break;	case 134:		cflag |= DZ_B134;		break;	case 150:		cflag |= DZ_B150;		break;	case 300:		cflag |= DZ_B300;		break;	case 600:		cflag |= DZ_B600;		break;	case 1200:		cflag |= DZ_B1200;		break;	case 1800:		cflag |= DZ_B1800;		break;	case 2000:		cflag |= DZ_B2000;		break;	case 2400:		cflag |= DZ_B2400;		break;	case 3600:		cflag |= DZ_B3600;		break;	case 4800:		cflag |= DZ_B4800;		break;	case 7200:		cflag |= DZ_B7200;		break;	case 9600:	default:		cflag |= DZ_B9600;	}	if (termios->c_cflag & CREAD)		cflag |= DZ_RXENAB;	spin_lock_irqsave(&dport->port.lock, flags);	dz_out(dport, DZ_LPR, cflag);	dport->cflag = cflag;	/* setup accept flag */	dport->port.read_status_mask = DZ_OERR;	if (termios->c_iflag & INPCK)		dport->port.read_status_mask |= DZ_FERR | DZ_PERR;	/* characters to ignore */	uport->ignore_status_mask = 0;	if (termios->c_iflag & IGNPAR)		dport->port.ignore_status_mask |= DZ_FERR | DZ_PERR;	spin_unlock_irqrestore(&dport->port.lock, flags);}static const char *dz_type(struct uart_port *port){	return "DZ";}static void dz_release_port(struct uart_port *port){	/* nothing to do */}static int dz_request_port(struct uart_port *port){	return 0;}static void dz_config_port(struct uart_port *port, int flags){	if (flags & UART_CONFIG_TYPE)		port->type = PORT_DZ;}/* * verify the new serial_struct (for TIOCSSERIAL). */static int dz_verify_port(struct uart_port *port, struct serial_struct *ser){	int ret = 0;	if (ser->type != PORT_UNKNOWN && ser->type != PORT_DZ)		ret = -EINVAL;	if (ser->irq != port->irq)		ret = -EINVAL;	return ret;}static struct uart_ops dz_ops = {	.tx_empty	= dz_tx_empty,	.get_mctrl	= dz_get_mctrl,	.set_mctrl	= dz_set_mctrl,	.stop_tx	= dz_stop_tx,	.start_tx	= dz_start_tx,	.stop_rx	= dz_stop_rx,	.enable_ms	= dz_enable_ms,	.break_ctl	= dz_break_ctl,	.startup	= dz_startup,	.shutdown	= dz_shutdown,	.set_termios	= dz_set_termios,	.type		= dz_type,	.release_port	= dz_release_port,	.request_port	= dz_request_port,	.config_port	= dz_config_port,	.verify_port	= dz_verify_port,};static void __init dz_init_ports(void){	static int first = 1;	struct dz_port *dport;	unsigned long base;	int i;	if (!first)		return;	first = 0;	if (mips_machtype == MACH_DS23100 ||	    mips_machtype == MACH_DS5100)		base = (unsigned long) KN01_DZ11_BASE;	else		base = (unsigned long) KN02_DZ11_BASE;	for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) {		spin_lock_init(&dport->port.lock);		dport->port.membase	= (char *) base;		dport->port.iotype	= SERIAL_IO_PORT;		dport->port.irq		= dec_interrupt[DEC_IRQ_DZ11];		dport->port.line	= i;		dport->port.fifosize	= 1;		dport->port.ops		= &dz_ops;		dport->port.flags	= UPF_BOOT_AUTOCONF;	}}static void dz_reset(struct dz_port *dport){	dz_out(dport, DZ_CSR, DZ_CLR);	while (dz_in(dport, DZ_CSR) & DZ_CLR);		/* FIXME: cpu_relax? */	iob();	/* enable scanning */	dz_out(dport, DZ_CSR, DZ_MSE);}#ifdef CONFIG_SERIAL_DZ_CONSOLEstatic void dz_console_put_char(struct dz_port *dport, unsigned char ch){	unsigned long flags;	int loops = 2500;	unsigned short tmp = ch;	/* this code sends stuff out to serial device - spinning its	   wheels and waiting. */	spin_lock_irqsave(&dport->port.lock, flags);	/* spin our wheels */	while (((dz_in(dport, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--)		/* FIXME: cpu_relax, udelay? --rmk */		;	/* Actually transmit the character. */	dz_out(dport, DZ_TDR, tmp);	spin_unlock_irqrestore(&dport->port.lock, flags);}/*  * ------------------------------------------------------------------- * dz_console_print () * * dz_console_print is registered for printk. * The console must be locked when we get here. * -------------------------------------------------------------------  */static void dz_console_print(struct console *cons,			     const char *str,			     unsigned int count){	struct dz_port *dport = &dz_ports[CONSOLE_LINE];#ifdef DEBUG_DZ	prom_printf((char *) str);#endif	while (count--) {		if (*str == '\n')			dz_console_put_char(dport, '\r');		dz_console_put_char(dport, *str++);	}}static int __init dz_console_setup(struct console *co, char *options){	struct dz_port *dport = &dz_ports[CONSOLE_LINE];	int baud = 9600;	int bits = 8;	int parity = 'n';	int flow = 'n';	int ret;	unsigned short mask, tmp;	if (options)		uart_parse_options(options, &baud, &parity, &bits, &flow);	dz_reset(dport);	ret = uart_set_options(&dport->port, co, baud, parity, bits, flow);	if (ret == 0) {		mask = 1 << dport->port.line;		tmp = dz_in(dport, DZ_TCR);	/* read the TX flag */		if (!(tmp & mask)) {			tmp |= mask;		/* set the TX flag */			dz_out(dport, DZ_TCR, tmp);		}	}	return ret;}static struct console dz_sercons ={	.name	= "ttyS",	.write	= dz_console_print,	.device	= uart_console_device,	.setup	= dz_console_setup,	.flags	= CON_CONSDEV | CON_PRINTBUFFER,	.index	= CONSOLE_LINE,};void __init dz_serial_console_init(void){	dz_init_ports();	register_console(&dz_sercons);}#define SERIAL_DZ_CONSOLE	&dz_sercons#else#define SERIAL_DZ_CONSOLE	NULL#endif /* CONFIG_SERIAL_DZ_CONSOLE */static struct uart_driver dz_reg = {	.owner			= THIS_MODULE,	.driver_name		= "serial",#ifdef CONFIG_DEVFS	.dev_name		= "tts/%d",#else	.dev_name		= "ttyS%d",#endif	.major			= TTY_MAJOR,	.minor			= 64,	.nr			= DZ_NB_PORT,	.cons			= SERIAL_DZ_CONSOLE,};int __init dz_init(void){	unsigned long flags;	int ret, i;	printk("%s%s\n", dz_name, dz_version);	dz_init_ports();	save_flags(flags);	cli();#ifndef CONFIG_SERIAL_DZ_CONSOLE	/* reset the chip */	dz_reset(&dz_ports[0]);#endif	/* order matters here... the trick is that flags	   is updated... in request_irq - to immediatedly obliterate	   it is unwise. */	restore_flags(flags);	if (request_irq(dz_ports[0].port.irq, dz_interrupt,			SA_INTERRUPT, "DZ", &dz_ports[0]))		panic("Unable to register DZ interrupt");	ret = uart_register_driver(&dz_reg);	if (ret != 0)		return ret;	for (i = 0; i < DZ_NB_PORT; i++)		uart_add_one_port(&dz_reg, &dz_ports[i].port);	return ret;}MODULE_DESCRIPTION("DECstation DZ serial driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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