#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include "mailbox.h"
MODULE_LICENSE("Dual BSD/GPL");
int mailbox_major = MAILBOX_MAJOR;
int mailbox_minor =   0;
struct cdev cdev; 
struct mailbox_dev* mailbox_devp;
/*文件打开函数*/
int mailbox_open(struct inode *inode, struct file *filp)
{
    struct mailbox_dev *dev;
     
    /*获取次设备号*/
    int num = MINOR(inode->i_rdev);
 
    if (num >= 1) 
            return -ENODEV;
    dev = &mailbox_devp[num];
     
    /*将设备描述结构指针赋值给文件私有数据指针*/
    filp->private_data = dev; //方便以后对该指针的使用
     printk("mailbox_open\n");
    return 0; 
}
 
/*文件释放函数*/
int mailbox_release(struct inode *inode, struct file *filp)
{
     printk("mailbox_release\n");
  return 0;
}
 
/*读函数*/
static ssize_t mailbox_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
  unsigned long p =  *ppos;
  unsigned int count = size;
  int ret = 0;
  struct mailbox_dev *dev = filp->private_data; /*获得设备结构体指针*/
 
  
 printk("mailbox_read\n");
  return ret;
}
 
/*写函数*/
static ssize_t mailbox_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{

  int ret = 0;
  struct mailbox_devp *dev = filp->private_data; /*获得设备结构体指针*/
   
    printk("mailbox_write\n");
  return ret;
}
 
/* seek文件定位函数 */
static loff_t mailbox_llseek(struct file *filp, loff_t offset, int whence)
{ 
    
    return 0;
 
}
static const struct file_operations mailbox_fops =
{
	.owner = THIS_MODULE,
	.llseek = mailbox_llseek,
	.read = mailbox_read,
	.write = mailbox_write,
	.open = mailbox_open,
	.release = mailbox_release,
};
static int mailbox_init(void)
{
	int result,i;
	dev_t devno = MKDEV(mailbox_major, mailbox_minor);
	printk("11111\n");
	if (mailbox_major) {
		result = register_chrdev_region(devno, 1, "mailbox");
	} else {
		result = alloc_chrdev_region(&devno, mailbox_major, 1,
				"mailbox");
		mailbox_major = MAJOR(devno);
	}
	if (result < 0) {
		printk(KERN_WARNING "mailbox: can't get major %d\n", mailbox_major);
		return result;
	}
	printk("22222\n");
	cdev_init(&cdev, &mailbox_fops);
	cdev.owner = THIS_MODULE;
	cdev.ops = &mailbox_fops;
   
	cdev_add(&cdev, devno, 1);
		printk("3333\n");
	mailbox_devp = kmalloc(sizeof(struct mailbox_dev),GFP_KERNEL);
	if (!mailbox_devp)    /*申请失败*/
	{
		result =  - ENOMEM;
		goto fail_malloc;
	}
	memset(mailbox_devp, 0, sizeof(struct mailbox_dev));
	
	unsigned char* v_addr  = ioremap_nocache(0x48140000,0x1000);
	printk("1read 0x%x\n",ioread32(v_addr+0x48));
	iowrite32(0x8f000000,v_addr+0x48);
	printk("2read 0x%x\n",ioread32(v_addr+0x48));
	iounmap(v_addr);
	printk(KERN_ALERT "Hello, world\n");
	return 0;

fail_malloc:
	unregister_chrdev_region(devno, 1);
	return result;	
}

static void mailbox_exit(void)
{
	int i;
	dev_t devno = MKDEV(mailbox_major, mailbox_minor);
	cdev_del(&cdev);   /*注销设备*/
	kfree(mailbox_devp); 
	/* cleanup_module is never called if registering failed */
	unregister_chrdev_region(devno, 1);

	/* and call the cleanup functions for friend devices */
	printk(KERN_ALERT "Goodbye, cruel world\n");
}

module_init(mailbox_init);
module_exit(mailbox_exit);
