LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1126|回复: 8

求一个字符设备的驱动,要求是一个文件的。

[复制链接]
发表于 2003-9-3 08:16:04 | 显示全部楼层 |阅读模式
我想找一个简单些,但实际的字符设备驱动的例子。来看看。由于我没看过内核,没有找到。
最好是一个文件。我在读书上的例子,大部分都是说散了的。如:
----------------------
写版本号的什么宏或#include语句。
为file_operations结构写函数调用。
看起来不难的。可是没有一个像完整的例子。
-----------------------
所以来这请朋友们帮一下忙。谢谢了。
发表于 2003-9-3 14:55:39 | 显示全部楼层
老大你也要写驱动了
兄弟正在痛苦中
到内核中找点来看吧,先看点简单的(键盘,鼠标之类的)
要不就看ldd2,还有它的源码:ftp://ftp.ora.com/pub/examples/linux/drivers(我已经下了,而且编译了几个,可以实用的哦!)
痛苦ing,郁闷ing!
希望能探讨探讨,共同进步.

btw:linuxforum上有个linux device driver版
    但是上面的高手好象都不怎么喜欢回答问题
 楼主| 发表于 2003-9-3 20:30:16 | 显示全部楼层
是的,那的高手都没有时间。很高兴能与你聊这方面的问题。
 楼主| 发表于 2003-9-4 13:26:44 | 显示全部楼层
我对鼠标,键盘不是了解,所以我想从串口,并口这方面来写点什么,或找个例子看。这方面还可以自己找点硬件来试试。
 楼主| 发表于 2003-9-4 14:11:55 | 显示全部楼层

请问这个文件是什么字符设备的驱动,?全吗?


  1. /*
  2. * linux/drivers/char/serial_21285.c
  3. *
  4. * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
  5. *
  6. * Based on drivers/char/serial.c
  7. */

  8. #include <linux/config.h>
  9. #include <linux/module.h>
  10. #include <linux/errno.h>
  11. #include <linux/signal.h>
  12. #include <linux/sched.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/tty.h>
  15. #include <linux/tty_flip.h>
  16. #include <linux/serial.h>
  17. #include <linux/major.h>
  18. #include <linux/ptrace.h>
  19. #include <linux/ioport.h>
  20. #include <linux/mm.h>
  21. #include <linux/slab.h>
  22. #include <linux/init.h>
  23. #include <linux/console.h>

  24. #include <asm/io.h>
  25. #include <asm/irq.h>
  26. #include <asm/uaccess.h>
  27. #include <asm/dec21285.h>
  28. #include <asm/hardware.h>

  29. #define BAUD_BASE                (mem_fclk_21285/64)

  30. #define SERIAL_21285_NAME        "ttyFB"
  31. #define SERIAL_21285_MAJOR        204
  32. #define SERIAL_21285_MINOR        4

  33. #define SERIAL_21285_AUXNAME        "cuafb"
  34. #define SERIAL_21285_AUXMAJOR        205
  35. #define SERIAL_21285_AUXMINOR        4

  36. static struct tty_driver rs285_driver, callout_driver;
  37. static int rs285_refcount;
  38. static struct tty_struct *rs285_table[1];

  39. static struct termios *rs285_termios[1];
  40. static struct termios *rs285_termios_locked[1];

  41. static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char;
  42. static struct tty_struct *rs285_tty;
  43. static int rs285_use_count;

  44. static int rs285_write_room(struct tty_struct *tty)
  45. {
  46.         return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1);
  47. }

  48. static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs)
  49. {
  50.         if (!rs285_tty) {
  51.                 disable_irq(IRQ_CONRX);
  52.                 return;
  53.         }
  54.         while (!(*CSR_UARTFLG & 0x10)) {
  55.                 int ch, flag;
  56.                 ch = *CSR_UARTDR;
  57.                 flag = *CSR_RXSTAT;
  58.                 if (flag & 4)
  59.                         tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN);
  60.                 if (flag & 2)
  61.                         flag = TTY_PARITY;
  62.                 else if (flag & 1)
  63.                         flag = TTY_FRAME;
  64.                 tty_insert_flip_char(rs285_tty, ch, flag);
  65.         }
  66.         tty_flip_buffer_push(rs285_tty);
  67. }

  68. static void rs285_send_xchar(struct tty_struct *tty, char ch)
  69. {
  70.         x_char = ch;
  71.         enable_irq(IRQ_CONTX);
  72. }

  73. static void rs285_throttle(struct tty_struct *tty)
  74. {
  75.         if (I_IXOFF(tty))
  76.                 rs285_send_xchar(tty, STOP_CHAR(tty));
  77. }

  78. static void rs285_unthrottle(struct tty_struct *tty)
  79. {
  80.         if (I_IXOFF(tty)) {
  81.                 if (x_char)
  82.                         x_char = 0;
  83.                 else
  84.                         rs285_send_xchar(tty, START_CHAR(tty));
  85.         }
  86. }

  87. static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs)
  88. {
  89.         while (!(*CSR_UARTFLG & 0x20)) {
  90.                 if (x_char) {
  91.                         *CSR_UARTDR = x_char;
  92.                         x_char = 0;
  93.                         continue;
  94.                 }
  95.                 if (putp == getp) {
  96.                         disable_irq(IRQ_CONTX);
  97.                         break;
  98.                 }
  99.                 *CSR_UARTDR = *getp;
  100.                 if (++getp >= wbuf + sizeof(wbuf))
  101.                         getp = wbuf;
  102.         }
  103.         if (rs285_tty)
  104.                 wake_up_interruptible(&rs285_tty->write_wait);
  105. }

  106. static inline int rs285_xmit(int ch)
  107. {
  108.         if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf))
  109.                 return 0;
  110.         *putp = ch;
  111.         if (++putp >= wbuf + sizeof(wbuf))
  112.                 putp = wbuf;
  113.         enable_irq(IRQ_CONTX);
  114.         return 1;
  115. }

  116. static int rs285_write(struct tty_struct *tty, int from_user,
  117.                        const u_char * buf, int count)
  118. {
  119.         int i;

  120.         if (from_user && verify_area(VERIFY_READ, buf, count))
  121.                 return -EINVAL;

  122.         for (i = 0; i < count; i++) {
  123.                 char ch;
  124.                 if (from_user)
  125.                         __get_user(ch, buf + i);
  126.                 else
  127.                         ch = buf[i];
  128.                 if (!rs285_xmit(ch))
  129.                         break;
  130.         }
  131.         return i;
  132. }

  133. static void rs285_put_char(struct tty_struct *tty, u_char ch)
  134. {
  135.         rs285_xmit(ch);
  136. }

  137. static int rs285_chars_in_buffer(struct tty_struct *tty)
  138. {
  139.         return sizeof(wbuf) - rs285_write_room(tty);
  140. }

  141. static void rs285_flush_buffer(struct tty_struct *tty)
  142. {
  143.         disable_irq(IRQ_CONTX);
  144.         putp = getp = wbuf;
  145.         if (x_char)
  146.                 enable_irq(IRQ_CONTX);
  147. }

  148. static inline void rs285_set_cflag(int cflag)
  149. {
  150.         int h_lcr, baud, quot;

  151.         switch (cflag & CSIZE) {
  152.         case CS5:
  153.                 h_lcr = 0x10;
  154.                 break;
  155.         case CS6:
  156.                 h_lcr = 0x30;
  157.                 break;
  158.         case CS7:
  159.                 h_lcr = 0x50;
  160.                 break;
  161.         default: /* CS8 */
  162.                 h_lcr = 0x70;
  163.                 break;

  164.         }
  165.         if (cflag & CSTOPB)
  166.                 h_lcr |= 0x08;
  167.         if (cflag & PARENB)
  168.                 h_lcr |= 0x02;
  169.         if (!(cflag & PARODD))
  170.                 h_lcr |= 0x04;

  171.         switch (cflag & CBAUD) {
  172.         case B200:        baud = 200;                break;
  173.         case B300:        baud = 300;                break;
  174.         case B1200:        baud = 1200;                break;
  175.         case B1800:        baud = 1800;                break;
  176.         case B2400:        baud = 2400;                break;
  177.         case B4800:        baud = 4800;                break;
  178.         default:
  179.         case B9600:        baud = 9600;                break;
  180.         case B19200:        baud = 19200;                break;
  181.         case B38400:        baud = 38400;                break;
  182.         case B57600:        baud = 57600;                break;
  183.         case B115200:        baud = 115200;                break;
  184.         }

  185.         /*
  186.          * The documented expression for selecting the divisor is:
  187.          *  BAUD_BASE / baud - 1
  188.          * However, typically BAUD_BASE is not divisible by baud, so
  189.          * we want to select the divisor that gives us the minimum
  190.          * error.  Therefore, we want:
  191.          *  int(BAUD_BASE / baud - 0.5) ->
  192.          *  int(BAUD_BASE / baud - (baud >> 1) / baud) ->
  193.          *  int((BAUD_BASE - (baud >> 1)) / baud)
  194.          */
  195.         quot = (BAUD_BASE - (baud >> 1)) / baud;

  196.         *CSR_UARTCON = 0;
  197.         *CSR_L_UBRLCR = quot & 0xff;
  198.         *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
  199.         *CSR_H_UBRLCR = h_lcr;
  200.         *CSR_UARTCON = 1;
  201. }

  202. static void rs285_set_termios(struct tty_struct *tty, struct termios *old)
  203. {
  204.         if (old && tty->termios->c_cflag == old->c_cflag)
  205.                 return;
  206.         rs285_set_cflag(tty->termios->c_cflag);
  207. }


  208. static void rs285_stop(struct tty_struct *tty)
  209. {
  210.         disable_irq(IRQ_CONTX);
  211. }

  212. static void rs285_start(struct tty_struct *tty)
  213. {
  214.         enable_irq(IRQ_CONTX);
  215. }

  216. static void rs285_wait_until_sent(struct tty_struct *tty, int timeout)
  217. {
  218.         int orig_jiffies = jiffies;
  219.         while (*CSR_UARTFLG & 8) {
  220.                 current->state = TASK_INTERRUPTIBLE;
  221.                 schedule_timeout(1);
  222.                 if (signal_pending(current))
  223.                         break;
  224.                 if (timeout && time_after(jiffies, orig_jiffies + timeout))
  225.                         break;
  226.         }
  227.         current->state = TASK_RUNNING;
  228. }

  229. static int rs285_open(struct tty_struct *tty, struct file *filp)
  230. {
  231.         int line;

  232.         MOD_INC_USE_COUNT;
  233.         line = MINOR(tty->device) - tty->driver.minor_start;
  234.         if (line) {
  235.                 MOD_DEC_USE_COUNT;
  236.                 return -ENODEV;
  237.         }

  238.         tty->driver_data = NULL;
  239.         if (!rs285_tty)
  240.                 rs285_tty = tty;

  241.         enable_irq(IRQ_CONRX);
  242.         rs285_use_count++;
  243.         return 0;
  244. }

  245. static void rs285_close(struct tty_struct *tty, struct file *filp)
  246. {
  247.         if (!--rs285_use_count) {
  248.                 rs285_wait_until_sent(tty, 0);
  249.                 disable_irq(IRQ_CONRX);
  250.                 disable_irq(IRQ_CONTX);
  251.                 rs285_tty = NULL;
  252.         }
  253.         MOD_DEC_USE_COUNT;
  254. }

  255. static int __init rs285_init(void)
  256. {
  257.         int baud = B9600;

  258.         if (machine_is_personal_server())
  259.                 baud = B57600;

  260.         rs285_driver.magic = TTY_DRIVER_MAGIC;
  261.         rs285_driver.driver_name = "serial_21285";
  262.         rs285_driver.name = SERIAL_21285_NAME;
  263.         rs285_driver.major = SERIAL_21285_MAJOR;
  264.         rs285_driver.minor_start = SERIAL_21285_MINOR;
  265.         rs285_driver.num = 1;
  266.         rs285_driver.type = TTY_DRIVER_TYPE_SERIAL;
  267.         rs285_driver.subtype = SERIAL_TYPE_NORMAL;
  268.         rs285_driver.init_termios = tty_std_termios;
  269.         rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL;
  270.         rs285_driver.flags = TTY_DRIVER_REAL_RAW;
  271.         rs285_driver.refcount = &rs285_refcount;
  272.         rs285_driver.table = rs285_table;
  273.         rs285_driver.termios = rs285_termios;
  274.         rs285_driver.termios_locked = rs285_termios_locked;

  275.         rs285_driver.open = rs285_open;
  276.         rs285_driver.close = rs285_close;
  277.         rs285_driver.write = rs285_write;
  278.         rs285_driver.put_char = rs285_put_char;
  279.         rs285_driver.write_room = rs285_write_room;
  280.         rs285_driver.chars_in_buffer = rs285_chars_in_buffer;
  281.         rs285_driver.flush_buffer = rs285_flush_buffer;
  282.         rs285_driver.throttle = rs285_throttle;
  283.         rs285_driver.unthrottle = rs285_unthrottle;
  284.         rs285_driver.send_xchar = rs285_send_xchar;
  285.         rs285_driver.set_termios = rs285_set_termios;
  286.         rs285_driver.stop = rs285_stop;
  287.         rs285_driver.start = rs285_start;
  288.         rs285_driver.wait_until_sent = rs285_wait_until_sent;

  289.         callout_driver = rs285_driver;
  290.         callout_driver.name = SERIAL_21285_AUXNAME;
  291.         callout_driver.major = SERIAL_21285_AUXMAJOR;
  292.         callout_driver.subtype = SERIAL_TYPE_CALLOUT;

  293.         if (request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL))
  294.                 panic("Couldn't get rx irq for rs285");

  295.         if (request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285", NULL))
  296.                 panic("Couldn't get tx irq for rs285");

  297.         if (tty_register_driver(&rs285_driver))
  298.                 printk(KERN_ERR "Couldn't register 21285 serial driver\n");
  299.         if (tty_register_driver(&callout_driver))
  300.                 printk(KERN_ERR "Couldn't register 21285 callout driver\n");

  301.         return 0;
  302. }

  303. static void __exit rs285_fini(void)
  304. {
  305.         unsigned long flags;
  306.         int ret;

  307.         save_flags(flags);
  308.         cli();
  309.         ret = tty_unregister_driver(&callout_driver);
  310.         if (ret)
  311.                 printk(KERN_ERR "Unable to unregister 21285 callout driver "
  312.                         "(%d)\n", ret);
  313.         ret = tty_unregister_driver(&rs285_driver);
  314.         if (ret)
  315.                 printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n",
  316.                         ret);
  317.         free_irq(IRQ_CONTX, NULL);
  318.         free_irq(IRQ_CONRX, NULL);
  319.         restore_flags(flags);
  320. }

  321. module_init(rs285_init);
  322. module_exit(rs285_fini);

  323. #ifdef CONFIG_SERIAL_21285_CONSOLE
  324. /************** console driver *****************/

  325. static void rs285_console_write(struct console *co, const char *s, u_int count)
  326. {
  327.         int i;

  328.         disable_irq(IRQ_CONTX);
  329.         for (i = 0; i < count; i++) {
  330.                 while (*CSR_UARTFLG & 0x20);
  331.                 *CSR_UARTDR = s[i];
  332.                 if (s[i] == '\n') {
  333.                         while (*CSR_UARTFLG & 0x20);
  334.                         *CSR_UARTDR = '\r';
  335.                 }
  336.         }
  337.         enable_irq(IRQ_CONTX);
  338. }

  339. static kdev_t rs285_console_device(struct console *c)
  340. {
  341.         return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
  342. }

  343. static int __init rs285_console_setup(struct console *co, char *options)
  344. {
  345.         int baud = 9600;
  346.         int bits = 8;
  347.         int parity = 'n';
  348.         int cflag = CREAD | HUPCL | CLOCAL;

  349.         if (machine_is_personal_server())
  350.                 baud = 57600;

  351.         if (options) {
  352.                 char *s = options;
  353.                 baud = simple_strtoul(options, NULL, 10);
  354.                 while (*s >= '0' && *s <= '9')
  355.                         s++;
  356.                 if (*s)
  357.                         parity = *s++;
  358.                 if (*s)
  359.                         bits = *s - '0';
  360.         }

  361.         /*
  362.          *    Now construct a cflag setting.
  363.          */
  364.         switch (baud) {
  365.         case 1200:
  366.                 cflag |= B1200;
  367.                 break;
  368.         case 2400:
  369.                 cflag |= B2400;
  370.                 break;
  371.         case 4800:
  372.                 cflag |= B4800;
  373.                 break;
  374.         case 9600:
  375.                 cflag |= B9600;
  376.                 break;
  377.         case 19200:
  378.                 cflag |= B19200;
  379.                 break;
  380.         case 38400:
  381.                 cflag |= B38400;
  382.                 break;
  383.         case 57600:
  384.                 cflag |= B57600;
  385.                 break;
  386.         case 115200:
  387.                 cflag |= B115200;
  388.                 break;
  389.         default:
  390.                 cflag |= B9600;
  391.                 break;
  392.         }
  393.         switch (bits) {
  394.         case 7:
  395.                 cflag |= CS7;
  396.                 break;
  397.         default:
  398.                 cflag |= CS8;
  399.                 break;
  400.         }
  401.         switch (parity) {
  402.         case 'o':
  403.         case 'O':
  404.                 cflag |= PARODD;
  405.                 break;
  406.         case 'e':
  407.         case 'E':
  408.                 cflag |= PARENB;
  409.                 break;
  410.         }
  411.         co->cflag = cflag;
  412.         rs285_set_cflag(cflag);
  413.         rs285_console_write(NULL, "\e[2J\e[Hboot ", 12);
  414.         if (options)
  415.                 rs285_console_write(NULL, options, strlen(options));
  416.         else
  417.                 rs285_console_write(NULL, "no options", 10);
  418.         rs285_console_write(NULL, "\n", 1);

  419.         return 0;
  420. }

  421. static struct console rs285_cons =
  422. {
  423.         name:                SERIAL_21285_NAME,
  424.         write:                rs285_console_write,
  425.         device:                rs285_console_device,
  426.         setup:                rs285_console_setup,
  427.         flags:                CON_PRINTBUFFER,
  428.         index:                -1,
  429. };

  430. void __init rs285_console_init(void)
  431. {
  432.         register_console(&rs285_cons);
  433. }

  434. #endif        /* CONFIG_SERIAL_21285_CONSOLE */

  435. MODULE_LICENSE("GPL");
  436. EXPORT_NO_SYMBOLS;
复制代码
发表于 2003-9-4 14:20:10 | 显示全部楼层
wide288,你也不上irc了
 楼主| 发表于 2003-9-4 15:57:16 | 显示全部楼层
我也想上啊。可是没有宽带了。家里只能用猫拔号了。debian 下没有我猫的驱动。驱动是rpm的。
现在工作了。时间少了。在单位还没有自己的机器,我也想你们啊。昨天还是21点10分到家的呢。
发表于 2003-9-5 09:43:46 | 显示全部楼层
"Based on drivers/char/serial.c"
先看这个吧,
serial_21285.c是针对特定的芯片的

呵呵,偶也是刚刚上班
 楼主| 发表于 2003-9-5 10:00:52 | 显示全部楼层
昨天下午看了,有很多的地方不懂。
如,这个接收字符的函数,是怎么个定义法呢。

  1. drivers/char/serial.c
  2. -------------------------------------
  3. 564行
  4. static _INLINE_ void receive_chars(struct async_struct *info, int *status, struct pt_regs *regs)
复制代码


串口还有针对什么片?不就是收发吗?在加上中断。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表