#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include "rainleddrv.h"
#define DEVICE_NAME "ledmiscdev"
//struct miscdevice miscdev;
char *led_mem = NULL;
static int misc_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
int err = 0;
unsigned int val = 0;
int ret = 0;
//以下命令都是惯例,记住即可
if (_IOC_TYPE(cmd) != LED_IOC_MAGIC)
return -EINVAL; //检测是不是同一个命令
if (_IOC_NR(cmd) > LED_IOC_MAX)
return -EINVAL;//检测命令数是不是超过最大的
if(_IOC_DIR(cmd) & _IOC_READ) //检测是否可读
err = !access_ok(VERIFY_WRITE,(void __user*)arg,_IOC_SIZE(cmd));
else if(_IOC_DIR(cmd) & _IOC_WRITE)//检测是否可写
err = !access_ok(VERIFY_READ,(void __user*)arg,_IOC_SIZE(cmd));
if (err) //如果出错则处理
return -EINVAL;
//以上命令都是惯例,记住即可
switch(cmd)
{
case LED_IOC_PRT:
printk("<0>CMD IS LED_IOCPRT!\n");
// ret = __get_user (val,(unsigned int *)arg);
// printk ("<0>on cmd %x is %d\n",cmd,val);
//iowrite32(val,io_mem+4);
break;
case LED_IOCSET_ON:
printk("<0>CMD IS LED_IOCSET_ON!\n");
ret = __get_user(val,(unsigned int *)arg);
printk ("<0>on cmd %x is %d\n",cmd,val);
iowrite32(val,led_mem+4);
break;
case LED_IOCSET_OFF:
printk("<0>CMD IS LED_IOCSET_OFF!\n");
ret = __get_user (val,(unsigned int *)arg);
printk ("<0>on cmd %x is %d\n",cmd,val);
iowrite32(val,led_mem+4);
break;
default:
return -EINVAL;
}
return ret;
}
static const struct file_operations miscops =
{
.owner = THIS_MODULE,
.ioctl = misc_ioctl,
};
static struct miscdevice misc =
{
.minor = 30,
.name = DEVICE_NAME,
.fops = &miscops,
};
static int miscdev_init(void)
{
int result;
unsigned int cmd;
result = misc_register(&misc);
printk("<0>misc device driver inited!\n");
//申请IO内存
if(request_mem_region(rGPBCON,8,DEVICE_NAME)==NULL)
{
printk("<0>request mem err!\n");
}
if ((led_mem = (char*)ioremap(rGPBCON,8)) == NULL)
{
printk("<0>led mem err!\n");
return -1;
}
cmd &= ~((3<<10)|(3<<12)|(3<<14)|(3<<16));
cmd |= (1<<10)|(1<<12)|(1<<14)|(1<<16);
iowrite32(cmd,led_mem);
cmd = LED_OFF;
iowrite32(cmd,led_mem+4);
return 0;
}
static void miscdev_exit()
{
iounmap(led_mem);
release_mem_region(rGPBCON,8);
misc_deregister(&misc);
}
module_init(miscdev_init);
module_exit(miscdev_exit);
MODULE_LICENSE("GPL");
|