1 #include <linux/config.h>
2 #include <linux/module.h>
3 #include <linux/init.h>
4 #include <linux/kernel.h>
5 #include <linux/miscdevice.h>
6 #include <linux/slab.h>
7 #include <asm/gsc.h>
8 #include <asm/uaccess.h>
9 #include <asm/eisa_eeprom.h>
10 
11 #define 	EISA_EEPROM_MINOR 241
12 
13 static unsigned long eeprom_addr;
14 
eisa_eeprom_llseek(struct file * file,loff_t offset,int origin)15 static long long eisa_eeprom_llseek(struct file *file, loff_t offset, int origin )
16 {
17 	switch (origin) {
18 	  case 0:
19 		/* nothing to do */
20 		break;
21 	  case 1:
22 		offset += file->f_pos;
23 		break;
24 	  case 2:
25 		offset += HPEE_MAX_LENGTH;
26 		break;
27 	}
28 	return (offset >= 0 && offset < HPEE_MAX_LENGTH) ? (file->f_pos = offset) : -EINVAL;
29 }
30 
eisa_eeprom_read(struct file * file,char * buf,size_t count,loff_t * ppos)31 static ssize_t eisa_eeprom_read(struct file * file,
32 			      char *buf, size_t count, loff_t *ppos )
33 {
34 	unsigned char *tmp;
35 	ssize_t ret;
36 	int i;
37 	loff_t n = *ppos;
38 	unsigned pos = n;
39 
40 	if (n != pos || pos >= HPEE_MAX_LENGTH)
41 		return 0;
42 
43 	if (count > HPEE_MAX_LENGTH - pos)
44 		count = HPEE_MAX_LENGTH - pos;
45 
46 	tmp = kmalloc(count, GFP_KERNEL);
47 	if (tmp) {
48 		for (i = 0; i < count; i++)
49 			tmp[i] = gsc_readb(eeprom_addr+(pos)++);
50 
51 		if (copy_to_user (buf, tmp, count))
52 			ret = -EFAULT;
53 		else {
54 			ret = count;
55 			*ppos = pos;
56 		}
57 		kfree (tmp);
58 	} else
59 		ret = -ENOMEM;
60 
61 	return ret;
62 }
63 
eisa_eeprom_ioctl(struct inode * inode,struct file * file,unsigned int cmd,unsigned long arg)64 static int eisa_eeprom_ioctl(struct inode *inode, struct file *file,
65 			   unsigned int cmd,
66 			   unsigned long arg)
67 {
68 	return -ENOTTY;
69 }
70 
eisa_eeprom_open(struct inode * inode,struct file * file)71 static int eisa_eeprom_open(struct inode *inode, struct file *file)
72 {
73 	if (file->f_mode & 2 || eeprom_addr == 0)
74 		return -EINVAL;
75 
76 	return 0;
77 }
78 
eisa_eeprom_release(struct inode * inode,struct file * file)79 static int eisa_eeprom_release(struct inode *inode, struct file *file)
80 {
81 	return 0;
82 }
83 
84 /*
85  *	The various file operations we support.
86  */
87 static struct file_operations eisa_eeprom_fops = {
88 	owner:		THIS_MODULE,
89 	llseek:		eisa_eeprom_llseek,
90 	read:		eisa_eeprom_read,
91 	ioctl:		eisa_eeprom_ioctl,
92 	open:		eisa_eeprom_open,
93 	release:	eisa_eeprom_release,
94 };
95 
96 static struct miscdevice eisa_eeprom_dev=
97 {
98 	EISA_EEPROM_MINOR,
99 	"eisa eeprom",
100 	&eisa_eeprom_fops
101 };
102 
eisa_eeprom_init(unsigned long addr)103 int __init eisa_eeprom_init(unsigned long addr)
104 {
105 	if (addr) {
106 		eeprom_addr = addr;
107 		misc_register(&eisa_eeprom_dev);
108 		printk(KERN_INFO "EISA EEPROM at 0x%lx\n", eeprom_addr);
109 	}
110 	return 0;
111 }
112 
113 MODULE_LICENSE("GPL");
114