#include <linux/version.h>
#include "pcie_test_driver.h"
#include <linux/platform_device.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ioctl.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/kdev_t.h>
#include <linux/kthread.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/percpu.h>
#include <linux/poison.h>
#include <linux/ptrace.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/types.h>
#define IOCTL_SET_ADDR _IOW(0xF0, 13, struct pcie_attr)
#define IOCTL_GET_ADDR _IOR(0xF0, 14, struct pcie_attr)
#if 1
#define DEBUG(fmt...) printk(fmt)
#else
#define DEBUG(fmt...) do { } while (0)
#endif
#define FL_BASE0 0x0000
#define FL_BASE1 0x0001
#define FL_BASE2 0x0002
#define FL_BASE3 0x0003
#define FL_BASE4 0x0004
#define FL_BASE5 0x0005
static struct semaphore pcie_handle_sem;
static int pcie_dev_open(struct inode *inode, struct file *file)
{
//do_nothing
return 0;
}
static int pcie_dev_release(struct inode *inode, struct file *file)
{
//do_nothing
return 0;
}
static ssize_t pcie_dev_read(struct file *file, char __user *buf,
size_t count, loff_t *f_pos)
{
//do_nothing
return -1;
}
static ssize_t pcie_dev_write(struct file *file, const char __user *buf,
size_t count, loff_t *f_pos)
{
int ret=0;
//do_nothing
return ret;
}
static long pcie_dev_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct pcie_attr attr;
int ret=-1;
struct miscdevice *mcc_userdev=(struct miscdevice *)file->private_data;
struct pcie_platform_config *pcie_data=container_of(mcc_userdev, struct pcie_platform_config, miscdev);
if (copy_from_user((void *)&attr, (void *)arg,
sizeof(struct pcie_attr)))
{
ret = -1;
goto ioctl_end;
}
DEBUG("In %s ---------membase=0x%x-------addr=0x%x, value=0x%x\n",__FUNCTION__,pcie_data->membase,attr.offset_addr,attr.value);
switch(cmd){
case IOCTL_SET_ADDR:
writel(attr.value,pcie_data->membase+attr.offset_addr);
ret=0;
break;
case IOCTL_GET_ADDR:
attr.value=readl(pcie_data->membase+attr.offset_addr);
DEBUG("In %s ----------------value=0x%x\n",__FUNCTION__,attr.value);
copy_to_user((void *)arg, (void *)&attr,sizeof(struct pcie_attr));
ret=0;
break;
default:
printk(KERN_ERR,"pcie_dev_ioctl no define cmd\n");
ret=-1;
break;
}
ioctl_end:
return ret;
}
static unsigned int pcie_dev_poll(struct file *file,
struct poll_table_struct *table)
{
//do_nothing
return 0;
}
static const struct file_operations pcie_dev_fops = {
.owner = THIS_MODULE,
.open = pcie_dev_open,
.release = pcie_dev_release,
.unlocked_ioctl = pcie_dev_ioctl,
.write = pcie_dev_write,
.read = pcie_dev_read,
.poll = pcie_dev_poll,
};
const char * msc_name[]={"pcie_dev"};
static struct pci_device_id pcie_tbl[] = {
{PCI_DEVICE(0x2022, 0x0321) },
{0 },
};
//PCI drivers probe function
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
static int pcie_probe(struct pci_dev *dev, const struct pci_device_id *ent)
#else
static int __devinit pcie_probe(struct pci_dev *dev, const struct pci_device_id *ent)
#endif
{
int retval=0;
unsigned char __iomem *pcie_membase;
struct pcie_platform_config *pcie_data = devm_kzalloc(&dev->dev, sizeof(struct pcie_platform_config), GFP_KERNEL);
DEBUG("In %s ---------------------------------------START\n",__FUNCTION__);
sema_init(&pcie_handle_sem, 1);
retval = pci_enable_device(dev);
pci_set_master(dev);
//使能msi,然后才能得到dev->irq
//retval= pci_enable_msi(dev);
if (retval) {
dev_err(&dev->dev, "Device enable FAILED\n");
return retval;
}
pci_set_drvdata(dev, pcie_data);
int len = pci_resource_len(dev, (FL_BASE0 ));
unsigned int basea = pci_resource_start(dev, (FL_BASE0 ));
//DEBUG("In %d ------------0x%x---------------------------START\n",len,basea);
pcie_membase=ioremap(basea,len);
DEBUG("In %d ------------0x%x-----------membase=0x%x----------------START\n",len,basea,pcie_membase);
pcie_data->membase=pcie_membase;
pcie_data->miscdev.fops=&pcie_dev_fops;
pcie_data->miscdev.name=msc_name[0];
pcie_data->miscdev.minor=MISC_DYNAMIC_MINOR;
misc_register(&pcie_data->miscdev);
return 0;
}
static int pcie_suspend(struct pci_dev *dev, pm_message_t state)
{
pci_disable_device(dev);
pci_save_state(dev);
pci_enable_wake(dev, PCI_D3hot, 1);
pci_set_power_state(dev, PCI_D3hot);
return 0;
};
static int pcie_resume(struct pci_dev *dev)
{
pci_set_power_state(dev, PCI_D0);
pci_restore_state(dev);
pci_enable_wake(dev, PCI_D0, 0);
if (pci_enable_device(dev) < 0) {
printk(KERN_ERR"pci_enable_device failed, ""disabling device\n");
return -EIO;
}
pci_set_master(dev);
return 0;
}
static void pcie_remove(struct pci_dev *dev)
{
struct pcie_platform_config *priv = pci_get_drvdata(dev);
misc_deregister(&priv->miscdev);
devm_kfree(&dev->dev, priv);
pci_set_drvdata(dev, NULL);
pci_disable_device(dev);
}
static struct pci_driver pcie_driver = {
.name = "pcie_test",
.probe = pcie_probe,
.id_table = pcie_tbl,
.suspend = pcie_suspend,
.resume = pcie_resume,
.remove = pcie_remove,
};
//Drivers entry function. register with the pci core and the serial core
static int __init pcie_init(void)
{
int ret;
DEBUG("In %s---------------------------------------START\n",__FUNCTION__);
if (ret){
DEBUG("In %s uart_register_driver FAILED\n",__FUNCTION__);
return ret;
}
ret = pci_register_driver(&pcie_driver);
if (ret < 0){
DEBUG("In %s pci_register_driver FAILED\n",__FUNCTION__);
}
DEBUG("In %s ---------------------------------------END\n",__FUNCTION__);
return ret;
}
//Drivers exit function. Unregister with the PCI core as well as serial core
static void __exit pcie_exit(void)
{
DEBUG("In %s ---------------------------------------START\n",__FUNCTION__);
pci_unregister_driver(&pcie_driver);
DEBUG("In %s ---------------------------------------END\n",__FUNCTION__);
}
module_init(pcie_init);
module_exit(pcie_exit);
MODULE_DESCRIPTION("pcie test driver module");
MODULE_SUPPORTED_DEVICE("pcie test");
MODULE_LICENSE("GPL");
评论0