|
楼主 |
发表于 2003-9-4 14:11:55
|
显示全部楼层
请问这个文件是什么字符设备的驱动,?全吗?
- /*
- * linux/drivers/char/serial_21285.c
- *
- * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
- *
- * Based on drivers/char/serial.c
- */
- #include <linux/config.h>
- #include <linux/module.h>
- #include <linux/errno.h>
- #include <linux/signal.h>
- #include <linux/sched.h>
- #include <linux/interrupt.h>
- #include <linux/tty.h>
- #include <linux/tty_flip.h>
- #include <linux/serial.h>
- #include <linux/major.h>
- #include <linux/ptrace.h>
- #include <linux/ioport.h>
- #include <linux/mm.h>
- #include <linux/slab.h>
- #include <linux/init.h>
- #include <linux/console.h>
- #include <asm/io.h>
- #include <asm/irq.h>
- #include <asm/uaccess.h>
- #include <asm/dec21285.h>
- #include <asm/hardware.h>
- #define BAUD_BASE (mem_fclk_21285/64)
- #define SERIAL_21285_NAME "ttyFB"
- #define SERIAL_21285_MAJOR 204
- #define SERIAL_21285_MINOR 4
- #define SERIAL_21285_AUXNAME "cuafb"
- #define SERIAL_21285_AUXMAJOR 205
- #define SERIAL_21285_AUXMINOR 4
- static struct tty_driver rs285_driver, callout_driver;
- static int rs285_refcount;
- static struct tty_struct *rs285_table[1];
- static struct termios *rs285_termios[1];
- static struct termios *rs285_termios_locked[1];
- static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char;
- static struct tty_struct *rs285_tty;
- static int rs285_use_count;
- static int rs285_write_room(struct tty_struct *tty)
- {
- return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1);
- }
- static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs)
- {
- if (!rs285_tty) {
- disable_irq(IRQ_CONRX);
- return;
- }
- while (!(*CSR_UARTFLG & 0x10)) {
- int ch, flag;
- ch = *CSR_UARTDR;
- flag = *CSR_RXSTAT;
- if (flag & 4)
- tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN);
- if (flag & 2)
- flag = TTY_PARITY;
- else if (flag & 1)
- flag = TTY_FRAME;
- tty_insert_flip_char(rs285_tty, ch, flag);
- }
- tty_flip_buffer_push(rs285_tty);
- }
- static void rs285_send_xchar(struct tty_struct *tty, char ch)
- {
- x_char = ch;
- enable_irq(IRQ_CONTX);
- }
- static void rs285_throttle(struct tty_struct *tty)
- {
- if (I_IXOFF(tty))
- rs285_send_xchar(tty, STOP_CHAR(tty));
- }
- static void rs285_unthrottle(struct tty_struct *tty)
- {
- if (I_IXOFF(tty)) {
- if (x_char)
- x_char = 0;
- else
- rs285_send_xchar(tty, START_CHAR(tty));
- }
- }
- static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs)
- {
- while (!(*CSR_UARTFLG & 0x20)) {
- if (x_char) {
- *CSR_UARTDR = x_char;
- x_char = 0;
- continue;
- }
- if (putp == getp) {
- disable_irq(IRQ_CONTX);
- break;
- }
- *CSR_UARTDR = *getp;
- if (++getp >= wbuf + sizeof(wbuf))
- getp = wbuf;
- }
- if (rs285_tty)
- wake_up_interruptible(&rs285_tty->write_wait);
- }
- static inline int rs285_xmit(int ch)
- {
- if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf))
- return 0;
- *putp = ch;
- if (++putp >= wbuf + sizeof(wbuf))
- putp = wbuf;
- enable_irq(IRQ_CONTX);
- return 1;
- }
- static int rs285_write(struct tty_struct *tty, int from_user,
- const u_char * buf, int count)
- {
- int i;
- if (from_user && verify_area(VERIFY_READ, buf, count))
- return -EINVAL;
- for (i = 0; i < count; i++) {
- char ch;
- if (from_user)
- __get_user(ch, buf + i);
- else
- ch = buf[i];
- if (!rs285_xmit(ch))
- break;
- }
- return i;
- }
- static void rs285_put_char(struct tty_struct *tty, u_char ch)
- {
- rs285_xmit(ch);
- }
- static int rs285_chars_in_buffer(struct tty_struct *tty)
- {
- return sizeof(wbuf) - rs285_write_room(tty);
- }
- static void rs285_flush_buffer(struct tty_struct *tty)
- {
- disable_irq(IRQ_CONTX);
- putp = getp = wbuf;
- if (x_char)
- enable_irq(IRQ_CONTX);
- }
- static inline void rs285_set_cflag(int cflag)
- {
- int h_lcr, baud, quot;
- switch (cflag & CSIZE) {
- case CS5:
- h_lcr = 0x10;
- break;
- case CS6:
- h_lcr = 0x30;
- break;
- case CS7:
- h_lcr = 0x50;
- break;
- default: /* CS8 */
- h_lcr = 0x70;
- break;
- }
- if (cflag & CSTOPB)
- h_lcr |= 0x08;
- if (cflag & PARENB)
- h_lcr |= 0x02;
- if (!(cflag & PARODD))
- h_lcr |= 0x04;
- switch (cflag & CBAUD) {
- case B200: baud = 200; break;
- case B300: baud = 300; break;
- case B1200: baud = 1200; break;
- case B1800: baud = 1800; break;
- case B2400: baud = 2400; break;
- case B4800: baud = 4800; break;
- default:
- case B9600: baud = 9600; break;
- case B19200: baud = 19200; break;
- case B38400: baud = 38400; break;
- case B57600: baud = 57600; break;
- case B115200: baud = 115200; break;
- }
- /*
- * The documented expression for selecting the divisor is:
- * BAUD_BASE / baud - 1
- * However, typically BAUD_BASE is not divisible by baud, so
- * we want to select the divisor that gives us the minimum
- * error. Therefore, we want:
- * int(BAUD_BASE / baud - 0.5) ->
- * int(BAUD_BASE / baud - (baud >> 1) / baud) ->
- * int((BAUD_BASE - (baud >> 1)) / baud)
- */
- quot = (BAUD_BASE - (baud >> 1)) / baud;
- *CSR_UARTCON = 0;
- *CSR_L_UBRLCR = quot & 0xff;
- *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
- *CSR_H_UBRLCR = h_lcr;
- *CSR_UARTCON = 1;
- }
- static void rs285_set_termios(struct tty_struct *tty, struct termios *old)
- {
- if (old && tty->termios->c_cflag == old->c_cflag)
- return;
- rs285_set_cflag(tty->termios->c_cflag);
- }
- static void rs285_stop(struct tty_struct *tty)
- {
- disable_irq(IRQ_CONTX);
- }
- static void rs285_start(struct tty_struct *tty)
- {
- enable_irq(IRQ_CONTX);
- }
- static void rs285_wait_until_sent(struct tty_struct *tty, int timeout)
- {
- int orig_jiffies = jiffies;
- while (*CSR_UARTFLG & 8) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- if (signal_pending(current))
- break;
- if (timeout && time_after(jiffies, orig_jiffies + timeout))
- break;
- }
- current->state = TASK_RUNNING;
- }
- static int rs285_open(struct tty_struct *tty, struct file *filp)
- {
- int line;
- MOD_INC_USE_COUNT;
- line = MINOR(tty->device) - tty->driver.minor_start;
- if (line) {
- MOD_DEC_USE_COUNT;
- return -ENODEV;
- }
- tty->driver_data = NULL;
- if (!rs285_tty)
- rs285_tty = tty;
- enable_irq(IRQ_CONRX);
- rs285_use_count++;
- return 0;
- }
- static void rs285_close(struct tty_struct *tty, struct file *filp)
- {
- if (!--rs285_use_count) {
- rs285_wait_until_sent(tty, 0);
- disable_irq(IRQ_CONRX);
- disable_irq(IRQ_CONTX);
- rs285_tty = NULL;
- }
- MOD_DEC_USE_COUNT;
- }
- static int __init rs285_init(void)
- {
- int baud = B9600;
- if (machine_is_personal_server())
- baud = B57600;
- rs285_driver.magic = TTY_DRIVER_MAGIC;
- rs285_driver.driver_name = "serial_21285";
- rs285_driver.name = SERIAL_21285_NAME;
- rs285_driver.major = SERIAL_21285_MAJOR;
- rs285_driver.minor_start = SERIAL_21285_MINOR;
- rs285_driver.num = 1;
- rs285_driver.type = TTY_DRIVER_TYPE_SERIAL;
- rs285_driver.subtype = SERIAL_TYPE_NORMAL;
- rs285_driver.init_termios = tty_std_termios;
- rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL;
- rs285_driver.flags = TTY_DRIVER_REAL_RAW;
- rs285_driver.refcount = &rs285_refcount;
- rs285_driver.table = rs285_table;
- rs285_driver.termios = rs285_termios;
- rs285_driver.termios_locked = rs285_termios_locked;
- rs285_driver.open = rs285_open;
- rs285_driver.close = rs285_close;
- rs285_driver.write = rs285_write;
- rs285_driver.put_char = rs285_put_char;
- rs285_driver.write_room = rs285_write_room;
- rs285_driver.chars_in_buffer = rs285_chars_in_buffer;
- rs285_driver.flush_buffer = rs285_flush_buffer;
- rs285_driver.throttle = rs285_throttle;
- rs285_driver.unthrottle = rs285_unthrottle;
- rs285_driver.send_xchar = rs285_send_xchar;
- rs285_driver.set_termios = rs285_set_termios;
- rs285_driver.stop = rs285_stop;
- rs285_driver.start = rs285_start;
- rs285_driver.wait_until_sent = rs285_wait_until_sent;
- callout_driver = rs285_driver;
- callout_driver.name = SERIAL_21285_AUXNAME;
- callout_driver.major = SERIAL_21285_AUXMAJOR;
- callout_driver.subtype = SERIAL_TYPE_CALLOUT;
- if (request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL))
- panic("Couldn't get rx irq for rs285");
- if (request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285", NULL))
- panic("Couldn't get tx irq for rs285");
- if (tty_register_driver(&rs285_driver))
- printk(KERN_ERR "Couldn't register 21285 serial driver\n");
- if (tty_register_driver(&callout_driver))
- printk(KERN_ERR "Couldn't register 21285 callout driver\n");
- return 0;
- }
- static void __exit rs285_fini(void)
- {
- unsigned long flags;
- int ret;
- save_flags(flags);
- cli();
- ret = tty_unregister_driver(&callout_driver);
- if (ret)
- printk(KERN_ERR "Unable to unregister 21285 callout driver "
- "(%d)\n", ret);
- ret = tty_unregister_driver(&rs285_driver);
- if (ret)
- printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n",
- ret);
- free_irq(IRQ_CONTX, NULL);
- free_irq(IRQ_CONRX, NULL);
- restore_flags(flags);
- }
- module_init(rs285_init);
- module_exit(rs285_fini);
- #ifdef CONFIG_SERIAL_21285_CONSOLE
- /************** console driver *****************/
- static void rs285_console_write(struct console *co, const char *s, u_int count)
- {
- int i;
- disable_irq(IRQ_CONTX);
- for (i = 0; i < count; i++) {
- while (*CSR_UARTFLG & 0x20);
- *CSR_UARTDR = s[i];
- if (s[i] == '\n') {
- while (*CSR_UARTFLG & 0x20);
- *CSR_UARTDR = '\r';
- }
- }
- enable_irq(IRQ_CONTX);
- }
- static kdev_t rs285_console_device(struct console *c)
- {
- return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
- }
- static int __init rs285_console_setup(struct console *co, char *options)
- {
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int cflag = CREAD | HUPCL | CLOCAL;
- if (machine_is_personal_server())
- baud = 57600;
- if (options) {
- char *s = options;
- baud = simple_strtoul(options, NULL, 10);
- while (*s >= '0' && *s <= '9')
- s++;
- if (*s)
- parity = *s++;
- if (*s)
- bits = *s - '0';
- }
- /*
- * Now construct a cflag setting.
- */
- switch (baud) {
- case 1200:
- cflag |= B1200;
- break;
- case 2400:
- cflag |= B2400;
- break;
- case 4800:
- cflag |= B4800;
- break;
- case 9600:
- cflag |= B9600;
- break;
- case 19200:
- cflag |= B19200;
- break;
- case 38400:
- cflag |= B38400;
- break;
- case 57600:
- cflag |= B57600;
- break;
- case 115200:
- cflag |= B115200;
- break;
- default:
- cflag |= B9600;
- break;
- }
- switch (bits) {
- case 7:
- cflag |= CS7;
- break;
- default:
- cflag |= CS8;
- break;
- }
- switch (parity) {
- case 'o':
- case 'O':
- cflag |= PARODD;
- break;
- case 'e':
- case 'E':
- cflag |= PARENB;
- break;
- }
- co->cflag = cflag;
- rs285_set_cflag(cflag);
- rs285_console_write(NULL, "\e[2J\e[Hboot ", 12);
- if (options)
- rs285_console_write(NULL, options, strlen(options));
- else
- rs285_console_write(NULL, "no options", 10);
- rs285_console_write(NULL, "\n", 1);
- return 0;
- }
- static struct console rs285_cons =
- {
- name: SERIAL_21285_NAME,
- write: rs285_console_write,
- device: rs285_console_device,
- setup: rs285_console_setup,
- flags: CON_PRINTBUFFER,
- index: -1,
- };
- void __init rs285_console_init(void)
- {
- register_console(&rs285_cons);
- }
- #endif /* CONFIG_SERIAL_21285_CONSOLE */
- MODULE_LICENSE("GPL");
- EXPORT_NO_SYMBOLS;
复制代码 |
|