root/drivers/macintosh/ans-lcd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. anslcd_write_byte_ctrl
  2. anslcd_write_byte_data
  3. anslcd_write
  4. anslcd_ioctl
  5. anslcd_open
  6. anslcd_init
  7. anslcd_exit

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

/* [<][>][^][v][top][bottom][index][help] */