1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
/*
* /dev/nvram driver for Power Macintosh.
*/
#define NVRAM_VERSION "1.0"
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/fcntl.h>
#include <linux/nvram.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/nvram.h>
#define NVRAM_SIZE 8192
/* when building as a module, __openfirmware is both unavailable
* and unnecessary. */
#ifndef MODULE
__openfirmware
#endif
static long long nvram_llseek(struct file *file, loff_t offset, int origin)
{
switch (origin) {
case 1:
offset += file->f_pos;
break;
case 2:
offset += NVRAM_SIZE;
break;
}
if (offset < 0)
return -EINVAL;
file->f_pos = offset;
return file->f_pos;
}
static ssize_t read_nvram(struct file *file, char *buf,
size_t count, loff_t *ppos)
{
unsigned int i;
char *p = buf;
if (verify_area(VERIFY_WRITE, buf, count))
return -EFAULT;
if (*ppos >= NVRAM_SIZE)
return 0;
for (i = *ppos; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count)
if (__put_user(nvram_read_byte(i), p))
return -EFAULT;
*ppos = i;
return p - buf;
}
static ssize_t write_nvram(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
unsigned int i;
const char *p = buf;
char c;
if (verify_area(VERIFY_READ, buf, count))
return -EFAULT;
if (*ppos >= NVRAM_SIZE)
return 0;
for (i = *ppos; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count) {
if (__get_user(c, p))
return -EFAULT;
nvram_write_byte(c, i);
}
*ppos = i;
return p - buf;
}
static int nvram_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
switch(cmd) {
case PMAC_NVRAM_GET_OFFSET:
{
int part, offset;
if (copy_from_user(&part,(void*)arg,sizeof(part))!=0)
return -EFAULT;
if (part < pmac_nvram_OF || part > pmac_nvram_NR)
return -EINVAL;
offset = pmac_get_partition(part);
if (copy_to_user((void*)arg,&offset,sizeof(offset))!=0)
return -EFAULT;
break;
}
default:
return -EINVAL;
}
return 0;
}
static int nvram_open(struct inode *inode, struct file *file)
{
MOD_INC_USE_COUNT;
return 0;
}
static int nvram_release(struct inode *inode, struct file *file)
{
MOD_DEC_USE_COUNT;
return 0;
}
struct file_operations nvram_fops = {
nvram_llseek,
read_nvram,
write_nvram,
NULL, /* nvram_readdir */
NULL, /* nvram_select */
nvram_ioctl,
NULL, /* nvram_mmap */
nvram_open,
NULL, /* flush */
nvram_release,
NULL /* fsync */
};
static struct miscdevice nvram_dev = {
NVRAM_MINOR,
"nvram",
&nvram_fops
};
__initfunc(int nvram_init(void))
{
printk(KERN_INFO "Macintosh non-volatile memory driver v%s\n",
NVRAM_VERSION);
misc_register(&nvram_dev);
return 0;
}
#ifdef MODULE
int init_module (void)
{
return( nvram_init() );
}
void cleanup_module (void)
{
misc_deregister( &nvram_dev );
}
#endif
|