#include <linux/module.h> // module_init module_exit
#include <linux/init.h> // __init __exit
#include <linux/fs.h>
#include <linux/string.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <mach/gpio-bank.h>
//物理地址
#define GPJ0CON 0xE0200240
#define GPJ0DAT 0xE0200244
static int test_major=-1;
char kbuf[10]="987654321";
volatile unsigned int *pGPJ0CON,*pGPJ0DAT;
static int test_open(struct inode *inode, struct file *file)
{
*pGPJ0CON = 0x11111111;
*pGPJ0DAT = ((0<<3) | (0<<4) | (0<<5)); // 亮
return 0;
}
static int test_release(struct inode *inode, struct file *file)
{
*pGPJ0CON = 0x11111111;
*pGPJ0DAT = ((1<<3) | (1<<4) | (1<<5)); // 亮
return 0;
}
static ssize_t test_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
int ret=-1;
printk(KERN_INFO "test_chrdev_read\n");
ret=copy_to_user(buf,kbuf,10);
if(ret)
{
printk(KERN_ERR "copy_to_user error, ret = %d.\n", ret);
return ret;
}
printk(KERN_INFO "copy_to_user ok, ret = %d.\n", ret);
return 0;
}
static ssize_t test_write(struct file *file, const char __user *buf,size_t siz, loff_t *ppos)
{
int ret=-1;
printk(KERN_INFO "test_chrdev_write\n");
memset(kbuf, 0, 10);
ret=copy_from_user(kbuf,buf,10);
if(ret)
{
printk(KERN_ERR "copy_from_user error, ret = %d.\n", ret);
return ret;
}
printk(KERN_INFO "copy_from_user ok, ret = %d.\n", ret);
printk(KERN_INFO "buf = %s.\n", kbuf);
return 0;
}
static const struct file_operations test_fops = {
.owner = THIS_MODULE,
.open = test_open,
.release = test_release,
.read = test_read,
.write = test_write,
};
// 模块安装函数
static int __init chrdev_init(void)
{
printk(KERN_INFO "chrdev_init helloworld init\n");
//printk("<7>" "chrdev_init helloworld init\n");
//printk("<7> chrdev_init helloworld init\n");
if ((test_major = register_chrdev (0, "test", &test_fops)) < 0)
printk(KERN_WARNING "test: could not get major number\n");
printk(KERN_INFO "test: get major number done!\n");
//申请动态映射所需内存资源
if (!request_mem_region(GPJ0CON, 4,"GPJ0CON,"))
return -EBUSY;
if (!request_mem_region(GPJ0DAT, 4, "GPJ0DAT"))
return -EINVAL;
//建立动态映射
pGPJ0CON = ioremap(GPJ0CON, 4);
pGPJ0DAT = ioremap(GPJ0DAT, 4);
return 0;
}
// 模块下载函数
static void __exit chrdev_exit(void)
{
printk(KERN_INFO "chrdev_exit helloworld exit\n");
//销毁动态映射
iounmap(pGPJ0CON);
iounmap(pGPJ0DAT);
//释放动态映射资源
release_mem_region(GPJ0CON, 4);
release_mem_region(GPJ0DAT, 4);
unregister_chrdev(test_major,"test");
}
module_init(chrdev_init);
module_exit(chrdev_exit);
// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL"); // 描述模块的许可证
MODULE_AUTHOR("aston"); // 描述模块的作者
MODULE_DESCRIPTION("module test"); // 描述模块的介绍信息
MODULE_ALIAS("alias xxx"); // 描述模块的别名信息