brintos

brintos / linux-shallow public Read only

0
0
Text · 4.0 KiB · fa904b2 Raw
206 lines · c
1// SPDX-License-Identifier: GPL-2.02/*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#include <linux/of.h>15 16#include <linux/uaccess.h>17#include <asm/sections.h>18#include <asm/io.h>19 20#include "ans-lcd.h"21 22#define ANSLCD_ADDR		0xf301c00023#define ANSLCD_CTRL_IX 0x0024#define ANSLCD_DATA_IX 0x1025 26static unsigned long anslcd_short_delay = 80;27static unsigned long anslcd_long_delay = 3280;28static volatile unsigned char __iomem *anslcd_ptr;29static DEFINE_MUTEX(anslcd_mutex);30 31#undef DEBUG32 33static void34anslcd_write_byte_ctrl ( unsigned char c )35{36#ifdef DEBUG37	printk(KERN_DEBUG "LCD: CTRL byte: %02x\n",c);38#endif39	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 49static void50anslcd_write_byte_data ( unsigned char c )51{52	out_8(anslcd_ptr + ANSLCD_DATA_IX, c);53	udelay(anslcd_short_delay);54}55 56static ssize_t57anslcd_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 DEBUG64	printk(KERN_DEBUG "LCD: write\n");65#endif66 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 82static long83anslcd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)84{85	char ch, __user *temp;86	long ret = 0;87 88#ifdef DEBUG89	printk(KERN_DEBUG "LCD: ioctl(%d,%d)\n",cmd,arg);90#endif91 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		else115			anslcd_short_delay=arg;116		break;117	case ANSLCD_SETLONGDELAY:118		if (!capable(CAP_SYS_ADMIN))119			ret = -EACCES;120		else121			anslcd_long_delay=arg;122		break;123	default:124		ret = -EINVAL;125	}126 127	mutex_unlock(&anslcd_mutex);128	return ret;129}130 131static int132anslcd_open( struct inode * inode, struct file * file )133{134	return 0;135}136 137const struct file_operations anslcd_fops = {138	.write		= anslcd_write,139	.unlocked_ioctl	= anslcd_ioctl,140	.open		= anslcd_open,141	.llseek		= default_llseek,142};143 144static struct miscdevice anslcd_dev = {145	LCD_MINOR,146	"anslcd",147	&anslcd_fops148};149 150static const char anslcd_logo[] __initconst =151				"********************"  /* Line #1 */152				"*      LINUX!      *"  /* Line #3 */153				"*    Welcome to    *"  /* Line #2 */154				"********************"; /* Line #4 */155 156static int __init157anslcd_init(void)158{159	int a;160	int retval;161	struct device_node* node;162 163	node = of_find_node_by_name(NULL, "lcd");164	if (!node || !of_node_name_eq(node->parent, "gc")) {165		of_node_put(node);166		return -ENODEV;167	}168	of_node_put(node);169 170	anslcd_ptr = ioremap(ANSLCD_ADDR, 0x20);171	172	retval = misc_register(&anslcd_dev);173	if(retval < 0){174		printk(KERN_INFO "LCD: misc_register failed\n");175		iounmap(anslcd_ptr);176		return retval;177	}178 179#ifdef DEBUG180	printk(KERN_DEBUG "LCD: init\n");181#endif182 183	mutex_lock(&anslcd_mutex);184	anslcd_write_byte_ctrl ( 0x38 );185	anslcd_write_byte_ctrl ( 0x0c );186	anslcd_write_byte_ctrl ( 0x06 );187	anslcd_write_byte_ctrl ( 0x01 );188	anslcd_write_byte_ctrl ( 0x02 );189	for(a=0;a<80;a++) {190		anslcd_write_byte_data(anslcd_logo[a]);191	}192	mutex_unlock(&anslcd_mutex);193	return 0;194}195 196static void __exit197anslcd_exit(void)198{199	misc_deregister(&anslcd_dev);200	iounmap(anslcd_ptr);201}202 203module_init(anslcd_init);204module_exit(anslcd_exit);205MODULE_LICENSE("GPL v2");206