Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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