- 论坛徽章:
- 0
|
程序中使用pio方式写入fpga,然后通过dma方式从fpga的ram读取数据,通过dma方式写回,但是始终得不到数据?请教各位是哪里问题~驱动程序如下
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
//#include <asm/floppy.h>
#define PCI_VENDOR_ID_XILINX 0x10ee
#define PCI_DEVICE_ID_XILINX_PCIE 0x6011
#define OAD_DEV_NAME "oad"
#define OAD_DRV_MAJOR 247
#define OAD_BAR_NUM 2
#define OAD_DRIVER_NAME "oad_driver"
#define BUF_SIZE (1 * 1024)
#define CARD_VERSION_OFFSET 0
#define GENERAL_STATUS_OFFSET 4
#define PIO_STATUS_OFFSET 8
#define DMA_STATUS_OFFSET 12
#define INTERRUPT_STATUS_OFFSET 16
#define ERROR_STATUS_OFFSET 20
#define PIO_READ_ADDRESS_OFFSET 24
#define PIO_READ_DATA_OFFSET 28
#define PIO_WRITE_ADDRESS_OFFSET 32
#define PIO_WRITE_DATA_OFFSET 36
#define DMA_UPSTREAM_TIME_COST_OFFSET 40
#define DMA_DOWNSTREAM_TIME_COST_OFFSET 44
#define DMA_REQUEST_LENGTH_OFFSET 48
#define DMA_ACTUAL_TRANSFERRED_LENGTH_OFFSET 52
#define DMA_EXTERN_MEMORY_ADDRESS_OFFSET 56
#define DMA_HOST_MEMORY_ADDRESS_OFFSET 60
#define DMA_UPSTREAM_LENGTH_OFFSET 64
#define DMA_NEXT_DESCRIPTOR_ADDRESS_OFFSET 68
enum {
SUCCESS = 0,
FAIL
};
struct oad_private {
char *name;
struct pci_dev* pci_dev;
unsigned long pci_bar_phy[OAD_BAR_NUM];
unsigned long pci_bar_len[OAD_BAR_NUM];
void *pci_bar_virt[OAD_BAR_NUM];
dma_addr_t dma_read_phy;
unsigned long dma_read_size;
wait_queue_head_t dma_read_wait;
};
static struct oad_private *oad;
static int oad_probe(struct pci_dev *pdev, const struct pci_device_id *id);
static void oad_remove(struct pci_dev *pdev);
static ssize_t oad_pio_write(struct file *fp, const char __user *buf, size_t cnt, loff_t *f_pos);
static ssize_t oad_pio_read(struct file *fp, char __user *buf, size_t cnt, loff_t *f_pos);
static ssize_t oad_dma_write(struct file *fp, const char __user *buf, size_t cnt, loff_t *f_pos);
static ssize_t oad_dma_read(struct file *fp, char __user *buf, size_t cnt, loff_t *f_pos);
static void oad_interrupt(int irq, void *dev, struct pt_regs *regs);
int oad_open(struct inode *inode, struct file *fp)
{
printk(KERN_INFO "%s: open: module opened\n", oad->name);
return SUCCESS;
}
int oad_release(struct inode *inode, struct file *fp)
{
printk(KERN_INFO "%s: release: module released\n", oad->name);
return SUCCESS;
}
struct file_operations oad_fops =
{
.owner = THIS_MODULE,
.open = oad_open,
.release = oad_release,
.read = oad_dma_read,
.write = oad_pio_write,
};
struct pci_device_id oad_ids[] = {
{PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILINX_PCIE),},
{0,}
};
MODULE_DEVICE_TABLE(pci, oad_ids);
static struct pci_driver oad_driver =
{
.name = OAD_DEV_NAME,
.id_table = oad_ids,
.probe = oad_probe,
.remove = oad_remove,
};
static int oad_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
int i;
printk(KERN_INFO "\t[OAD_DEBUG] start of oad_probe\n");
if(pci_enable_device(pdev))
{
printk(KERN_INFO "\t pci_enable_device error\n");
return FAIL;
}
if(pci_set_dma_mask(pdev, (u32)0xffffffff))
{
printk(KERN_INFO "\t pci_set_dma_mask error\n");
return FAIL;
}
pci_set_master(pdev);
oad = kmalloc(sizeof(struct oad_private), GFP_KERNEL);
if(NULL == oad)
{
printk(KERN_INFO "\t kmalloc of oad_private error\n");
return FAIL;
}
oad->name = OAD_DEV_NAME;
oad->pci_dev = pdev;
for(i = 0; i < OAD_BAR_NUM; i++)
{
oad->pci_bar_phy[i] = pci_resource_start(pdev, i);
oad->pci_bar_len[i] = pci_resource_len(pdev, i);
request_mem_region(oad->pci_bar_phy[i], oad->pci_bar_len[i], OAD_DEV_NAME);
oad->pci_bar_virt[i] = ioremap(oad->pci_bar_phy[i], oad->pci_bar_len[i]);
printk(KERN_INFO "\t oad->pci_bar_phy[%d] = 0x%8lx\n", i, (unsigned long)oad->pci_bar_phy[i]);
printk(KERN_INFO "\t oad->pci_bar_len[%d] = %ld\n", i, oad->pci_bar_len[i]);
printk(KERN_INFO "\t oad->pci_bar_virt[%d] = 0x%8lx\n", i, (unsigned long)oad->pci_bar_virt[i]);
}
//init_waitqueue_head(&(oad->dma_read_wait));
//if(request_irq(pdev->irq, oad_interrupt, 0, OAD_DEV_NAME, NULL))
//{
// printk(KERN_INFO "\t request_irq error\n");
// return FAIL;
//}
if(register_chrdev(OAD_DRV_MAJOR, OAD_DEV_NAME, &oad_fops))
{
printk(KERN_INFO "\t register_chrdev error\n");
return FAIL;
}
return SUCCESS;
}
static void oad_remove(struct pci_dev *pdev)
{
int i;
printk(KERN_INFO "\t[OAD_DEBUG] start of oad_remove\n");
for(i = 0; i < OAD_BAR_NUM; i++)
{
iounmap(oad->pci_bar_virt);
release_mem_region(oad->pci_bar_phy[i], oad->pci_bar_len[i]);
}
pci_disable_device(pdev);
unregister_chrdev(OAD_DRV_MAJOR, OAD_DEV_NAME);
kfree(oad);
}
static int __init oad_init(void)
{
int rc;
printk(KERN_INFO "\t[OAD_DEBUG] start of oad_init\n");
rc = pci_register_driver(&oad_driver);
return rc;
}
static void __exit oad_exit(void)
{
printk(KERN_INFO "\t[OAD_DEBUG] start of oad_exit\n");
pci_unregister_driver(&oad_driver);
}
module_init(oad_init);
module_exit(oad_exit);
static ssize_t oad_pio_write(struct file *fp, const char __user *buf, size_t cnt, loff_t *f_pos)
{
int i;
void *virt;
printk(KERN_INFO "\t[OAD_DEBUG] start of oad_pio_write\n");
virt = kmalloc(cnt, GFP_KERNEL);
printk(KERN_INFO "\t virt = 0x%8lx\n", (unsigned long)virt);
printk(KERN_INFO "\t oad->pci_bar_phy[0] = 0x%8lx\n", (unsigned long)oad->pci_bar_virt[1]);
copy_from_user(virt, buf, cnt);
for(i = 0; i < cnt/4; i++)
{
udelay(1);
iowrite32(*((u32*)(virt + i*4)), ((unsigned long *)(oad->pci_bar_virt[1] + i*4)));
}
kfree(virt);
return SUCCESS;
}
static ssize_t oad_pio_read(struct file *fp, char __user *buf, size_t cnt, loff_t *f_pos)
{
int i;
void *virt;
printk(KERN_INFO "\t[OAD_DEBUG] start of oad_pio_read\n");
virt = kmalloc(cnt, GFP_KERNEL);
printk(KERN_INFO "\t virt = 0x%8lx\n", (unsigned long)virt);
printk(KERN_INFO "\t oad->pci_bar_phy[0] = 0x%8lx\n", (unsigned long)oad->pci_bar_virt[1]);
for(i = 0; i < cnt/4; i++)
{
*((u32*)(virt + i*4)) = ioread32(((unsigned long *)(oad->pci_bar_virt[1] + i*4)));
}
copy_to_user(buf, virt, cnt);
kfree(virt);
return SUCCESS;
}
static ssize_t oad_dma_write(struct file *fp, const char __user *buf, size_t cnt, loff_t *f_pos)
{
printk(KERN_INFO "\t[OAD_DEBUG] start of oad_dma_write\n");
printk(KERN_INFO "\t[OAD_DEBUG] end of oad_dma_write\n");
return SUCCESS;
}
static ssize_t oad_dma_read(struct file *fp, char __user *buf, size_t cnt, loff_t *f_pos)
{
void *dma_addr_virt = NULL;
dma_addr_t dma_addr_phy;
//dma_addr_t *dap;
int i;
u32 dma_extn_addr, dma_host_addr, dma_up_len, dma_next_desc_addr;
dma_extn_addr = 0x00000000;
dma_host_addr = 0x00000000;
dma_up_len = 0x00000000; // byte based
dma_next_desc_addr = 0x00000000;
dma_addr_virt = kmalloc(cnt, GFP_KERNEL|__GFP_DMA);
//dma_addr_virt = ((void *)dma_mem_alloc(cnt);
printk("\t size of allocated mem is %d\n", cnt);
printk("\t addr of dma_addr_virt is 0x%p\n", dma_addr_virt);
printk("\t addr of buf is %p\n", buf);
if(NULL == dma_addr_virt)
{
printk("\t kmalloc error!\n");
return FAIL;
}
//dma_addr_phy = pci_map_single(oad->pci_dev, dma_addr_virt, cnt, PCI_DMA_FROMDEVICE);
dma_addr_phy = dma_map_single(oad->pci_dev, dma_addr_virt, cnt, PCI_DMA_FROMDEVICE);
dap = dma_addr_phy;
printk("\t addr of dma_addr_phy is 0x%p\n", dma_addr_phy);
if(NULL == dma_addr_phy)
{
printk("\t pci_map_signle error!\n");
return FAIL;
}
//printk(KERN_INFO "\t dma_addr_virt = 0x%8lx, dma_addr_phy = 0x%8lx", (unsigned long)dma_addr_virt, (unsigned long)dma_addr_phy);
//pci_dma_sync_single_for_cpu(oad->pci_dev, dma_addr_phy, cnt, PCI_DMA_FROMDEVICE);
//oad->dma_read_phy = dma_addr_t
dma_extn_addr = 0x00000000;
dma_host_addr = (u32)dma_addr_phy;
dma_up_len = (u32)cnt;
dma_next_desc_addr = 0x00000000;
iowrite32(dma_extn_addr, (oad->pci_bar_virt[0] + DMA_EXTERN_MEMORY_ADDRESS_OFFSET));
iowrite32(dma_host_addr, (oad->pci_bar_virt[0] + DMA_HOST_MEMORY_ADDRESS_OFFSET));
iowrite32(dma_up_len, (oad->pci_bar_virt[0] + DMA_UPSTREAM_LENGTH_OFFSET));
iowrite32(dma_next_desc_addr, (oad->pci_bar_virt[0] + DMA_NEXT_DESCRIPTOR_ADDRESS_OFFSET));
iowrite32(0x80000000, (oad->pci_bar_virt[0] + DMA_STATUS_OFFSET));
//wait_event_interruptible((oad->dma_read_wait), 0);
for(i = 0; i < 1000; i++)
udelay(100);
//pci_dma_sync_single_for_cpu(oad->pci_dev, (dma_addr_t)dma_addr_phy, cnt, PCI_DMA_FROMDEVICE);
iowrite32(0x40000000, (oad->pci_bar_virt[0] + INTERRUPT_STATUS_OFFSET));
//pci_unmap_single(oad->pci_dev, dma_host_addr, dma_up_len, PCI_DMA_FROMDEVICE);
dma_unmap_single(oad->pci_dev, dma_host_addr, dma_up_len, PCI_DMA_FROMDEVICE);
pci_dma_sync_single_for_cpu(oad->pci_dev, dma_addr_phy, cnt, PCI_DMA_FROMDEVICE);
copy_to_user(buf, dma_addr_virt, cnt);
kfree(dma_addr_virt);
printk(KERN_INFO "\t[OAD_DEBUG] start of oad_dma_read\n");
return SUCCESS;
}
static void oad_interrupt(int irq, void *dev, struct pt_regs *regs)
{
printk(KERN_INFO "\t[OAD_DEBUG] start of oad_interrupt\n");
iowrite32(0x40000000, (oad->pci_bar_virt[0] + INTERRUPT_STATUS_OFFSET));
pci_unmap_single(oad->pci_dev, oad->dma_read_phy, oad->dma_read_size, PCI_DMA_FROMDEVICE);
wake_up_interruptible(&(oad->dma_read_wait));
printk(KERN_INFO "\t[OAD_DEBUG] end of oad_interrupt\n");
}
|
|