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 + -
显示快捷键?