ans-lcd.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:3k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * /dev/lcd driver for Apple Network Servers.
  3.  */
  4. #include <linux/types.h>
  5. #include <linux/errno.h>
  6. #include <linux/kernel.h>
  7. #include <linux/miscdevice.h>
  8. #include <linux/fcntl.h>
  9. #include <linux/init.h>
  10. #include <linux/delay.h>
  11. #include <asm/uaccess.h>
  12. #include <asm/sections.h>
  13. #include <asm/prom.h>
  14. #include <asm/ans-lcd.h>
  15. #include <asm/io.h>
  16. #define ANSLCD_ADDR 0xf301c000
  17. #define ANSLCD_CTRL_IX 0x00
  18. #define ANSLCD_DATA_IX 0x10
  19. static unsigned long anslcd_short_delay = 80;
  20. static unsigned long anslcd_long_delay = 3280;
  21. static volatile unsigned char* anslcd_ptr;
  22. #undef DEBUG
  23. static void __pmac
  24. anslcd_write_byte_ctrl ( unsigned char c )
  25. {
  26. #ifdef DEBUG
  27. printk(KERN_DEBUG "LCD: CTRL byte: %02xn",c);
  28. #endif
  29. out_8(anslcd_ptr + ANSLCD_CTRL_IX, c);
  30. switch(c) {
  31. case 1:
  32. case 2:
  33. case 3:
  34. udelay(anslcd_long_delay); break;
  35. default: udelay(anslcd_short_delay);
  36. }
  37. }
  38. static void __pmac
  39. anslcd_write_byte_data ( unsigned char c )
  40. {
  41. out_8(anslcd_ptr + ANSLCD_DATA_IX, c);
  42. udelay(anslcd_short_delay);
  43. }
  44. static ssize_t __pmac
  45. anslcd_write( struct file * file, const char * buf, 
  46. size_t count, loff_t *ppos )
  47. {
  48. const char * p = buf;
  49. int i;
  50. #ifdef DEBUG
  51. printk(KERN_DEBUG "LCD: writen");
  52. #endif
  53. if ( verify_area(VERIFY_READ, buf, count) )
  54. return -EFAULT;
  55. for ( i = *ppos; count > 0; ++i, ++p, --count ) 
  56. {
  57. char c;
  58. __get_user(c, p);
  59. anslcd_write_byte_data( c );
  60. }
  61. *ppos = i;
  62. return p - buf;
  63. }
  64. static int __pmac
  65. anslcd_ioctl( struct inode * inode, struct file * file,
  66. unsigned int cmd, unsigned long arg )
  67. {
  68. char ch, *temp;
  69. #ifdef DEBUG
  70. printk(KERN_DEBUG "LCD: ioctl(%d,%d)n",cmd,arg);
  71. #endif
  72. switch ( cmd )
  73. {
  74. case ANSLCD_CLEAR:
  75. anslcd_write_byte_ctrl ( 0x38 );
  76. anslcd_write_byte_ctrl ( 0x0f );
  77. anslcd_write_byte_ctrl ( 0x06 );
  78. anslcd_write_byte_ctrl ( 0x01 );
  79. anslcd_write_byte_ctrl ( 0x02 );
  80. return 0;
  81. case ANSLCD_SENDCTRL:
  82. temp = (char *) arg;
  83. __get_user(ch, temp);
  84. for (; ch; temp++) { /* FIXME: This is ugly, but should work, as a  byte is not a valid command code */
  85. anslcd_write_byte_ctrl ( ch );
  86. __get_user(ch, temp);
  87. }
  88. return 0;
  89. case ANSLCD_SETSHORTDELAY:
  90. if (!capable(CAP_SYS_ADMIN))
  91. return -EACCES;
  92. anslcd_short_delay=arg;
  93. return 0;
  94. case ANSLCD_SETLONGDELAY:
  95. if (!capable(CAP_SYS_ADMIN))
  96. return -EACCES;
  97. anslcd_long_delay=arg;
  98. return 0;
  99. default:
  100. return -EINVAL;
  101. }
  102. }
  103. static int __pmac
  104. anslcd_open( struct inode * inode, struct file * file )
  105. {
  106. return 0;
  107. }
  108. struct file_operations anslcd_fops = {
  109. write: anslcd_write,
  110. ioctl: anslcd_ioctl,
  111. open: anslcd_open,
  112. };
  113. static struct miscdevice anslcd_dev = {
  114. ANSLCD_MINOR,
  115. "anslcd",
  116. &anslcd_fops
  117. };
  118. const char anslcd_logo[] = "********************"  /* Line #1 */
  119. "*      LINUX!      *"  /* Line #3 */
  120. "*    Welcome to    *"  /* Line #2 */
  121. "********************"; /* Line #4 */
  122. int __init
  123. anslcd_init(void)
  124. {
  125. int a;
  126. struct device_node* node;
  127. node = find_devices("lcd");
  128. if (!node || !node->parent)
  129. return -ENODEV;
  130. if (strcmp(node->parent->name, "gc"))
  131. return -ENODEV;
  132. anslcd_ptr = (volatile unsigned char*)ioremap(ANSLCD_ADDR, 0x20);
  133. misc_register(&anslcd_dev);
  134. #ifdef DEBUG
  135. printk(KERN_DEBUG "LCD: initn");
  136. #endif
  137. anslcd_write_byte_ctrl ( 0x38 );
  138. anslcd_write_byte_ctrl ( 0x0c );
  139. anslcd_write_byte_ctrl ( 0x06 );
  140. anslcd_write_byte_ctrl ( 0x01 );
  141. anslcd_write_byte_ctrl ( 0x02 );
  142. for(a=0;a<80;a++) {
  143. anslcd_write_byte_data(anslcd_logo[a]);
  144. }
  145. return 0;
  146. }
  147. __initcall(anslcd_init);