LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Hardware
User Name
Password
Linux - Hardware This forum is for Hardware issues.
Having trouble installing a piece of hardware? Want to know if that peripheral is compatible with Linux?

Notices


Reply
  Search this Thread
Old 04-27-2020, 10:55 AM   #1
drakonof
LQ Newbie
 
Registered: Apr 2020
Posts: 5

Rep: Reputation: Disabled
DMA for PCIe


Hi all!

Could you say please, what I am doing wrong?

Debian 10.

I am trying send data through PCIe + DMA. But I cannot fill sending array correctly. The data which I send from a host are received not which that I expect.

Code:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>

#include "vi_cntr.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Drakonof");
MODULE_DESCRIPTION("PCI");
MODULE_VERSION("0.1");
 

#define CDMA_BAR  0
#define PCI_BAR   1
#define DDR_BAR    2

// cdma regs
#define CDMACR  0x00
#define CDMASR  0x04
#define CURDESC_PNTR  0x08
#define CURDESC_PNTR_MSB  0x0C
#define TAILDESC_PNTR  0x10
#define TAILDESC_PNTR_MSB 0x14
#define SA  0x18
#define SA_MSB  0x1C
#define DA  0x20
#define DA_MSB  0x24
#define BTT  0x28

#define DEVICE_NAME "drakonof_pci"

static dma_addr_t dma_handle = 0;
static void * dmabuf = NULL;
static volatile uint32_t *pci_reg_mem = NULL, *cdma_reg_mem = NULL;
static volatile uint32_t  *ddr_mem = NULL;
static resource_size_t cdma_start,cdma_len,pci_start,pci_len,ddr_start,ddr_len;


static struct pci_device_id vi_cntr_pci_id[] = {
{ PCI_DEVICE(VI_CNTR_VENDOR, VI_CNTR_ID), },
{ 0, }
};


MODULE_DEVICE_TABLE(pci, vi_cntr_pci_id);


static int vi_cntr_probe(struct pci_dev *pDev, const struct pci_device_id *id);
static void vi_cntr_remove(struct pci_dev *pDev);


static struct pci_driver vi_cntr_pci = {
    .name = DEVICE_NAME,
    .id_table = vi_cntr_pci_id,
    .probe = vi_cntr_probe,
    .remove = vi_cntr_remove
};


static int __init pci_init(void)
{
    struct pci_dev *p_pci_dev = NULL;

    if((p_pci_dev = pci_get_device(VI_CNTR_VENDOR,VI_CNTR_ID,                     p_pci_dev)) == NULL)
    {
        printk(KERN_NOTICE "PCI device not finded\n");
    }

    return pci_register_driver(&vi_cntr_pci);
}


static void __exit pci_exit(void)
{
    pci_unregister_driver(&vi_cntr_pci);
}


static int vi_cntr_probe(struct pci_dev *p_pci_dev, const struct pci_device_id *pId)
{
    u16 vendor = 0,
        id = 0;

    u32 i = 0;


    if(pci_enable_device(p_pci_dev))
    {
        printk(KERN_INFO "pci_enable_device error\n");
    }

    pci_read_config_word(p_pci_dev, PCI_VENDOR_ID, &vendor);
    pci_read_config_word(p_pci_dev, PCI_DEVICE_ID, &id);

    printk(KERN_INFO "\n----------------------------------\n");
    printk(KERN_INFO "Device vendor: 0x%X\nDevice id: 0x%X\n", vendor, id);

    cdma_start = pci_resource_start(p_pci_dev,CDMA_BAR);
    cdma_len = pci_resource_len(p_pci_dev,CDMA_BAR);
    pci_start = pci_resource_start(p_pci_dev,PCI_BAR);
    pci_len = pci_resource_len(p_pci_dev,PCI_BAR);
    ddr_start = pci_resource_start(p_pci_dev,DDR_BAR);
    ddr_len = pci_resource_len(p_pci_dev,DDR_BAR);

    if(pci_set_dma_mask(p_pci_dev, DMA_BIT_MASK(64)))
    {
        printk(KERN_INFO "pci_set_dma_mask error.\n");
        return -1;
    }


    if((dmabuf=dma_alloc_coherent(&p_pci_dev->dev,8192,&dma_handle,GFP_USER)) == NULL)
    {
        printk(KERN_INFO "dma_alloc_coherent error.\n");
        return -1;
    }

    if(pci_request_regions(p_pci_dev, DEVICE_NAME))
    {
        printk(KERN_INFO "pci_request_regions error.\n");
        return -1;
    }

    pci_set_master(p_pci_dev);

    if((cdma_reg_mem = ioremap(cdma_start,cdma_len)) == NULL)
    {
        printk(KERN_INFO "ioremap pci_reg_mem error.\n");
        return -1;
    }

    if((pci_reg_mem = ioremap(pci_start,pci_len)) == NULL)
    {
        printk(KERN_INFO "ioremap pci_reg_mem error.\n");
        return -1;
    }

    if((ddr_mem = ioremap(ddr_start,ddr_len)) == NULL)
    {
        printk(KERN_INFO "ioremap pci_reg_mem error.\n");
        return -1;
    }

    // filling test array by const
    dma_sync_single_for_cpu(&p_pci_dev->dev, dma_handle, 8192, DMA_TO_DEVICE);
    for(i = 0; i < 256; i++)
    {
        *(u32*)(dmabuf + i)= 0xABCDEF89;
    }
    dma_sync_single_for_device(&p_pci_dev->dev, dma_handle, 8192, DMA_TO_DEVICE);

    // filling device pcie regs by phys host memory
    // upper half of address to 0x208
    pci_reg_mem[0x208/4]=(dma_handle >> 32);
    // lower half to 0x20c
    pci_reg_mem[0x20c/4]=(dma_handle & 0xFFFFFFFF);

    // filling cdma regs
    cdma_reg_mem[0x18/4]=0x30000000;
    cdma_reg_mem[0x20/4]=0x80000000;
    cdma_reg_mem[0x28/4]=256;

    // checking received data
    for(i = 0; i < 240; i++)
    {
        printk(KERN_INFO "%d. DDR %X vs ADDR %X\n",i,ddr_mem[i], *(u8*)    (dmabuf + i));
    }

    printk(KERN_INFO "dma %llX\n",dma_handle);
    printk(KERN_INFO "AXIU %X\n",pci_reg_mem[0x208/4]);
    printk(KERN_INFO "AXIL %X\n",pci_reg_mem[0x20C/4]);
    printk(KERN_INFO "SA %X\n",cdma_reg_mem[0x18/4]);
    printk(KERN_INFO "DA %X\n",cdma_reg_mem[0x20/4]);
    printk(KERN_INFO "SR %X\n",cdma_reg_mem[0x4/4]);

    cdma_reg_mem[0x4/4] = 0x1000;


    iounmap(pci_reg_mem);
    iounmap(cdma_reg_mem);
    iounmap(ddr_mem);
    pci_release_regions(p_pci_dev);
    pci_disable_device(p_pci_dev);
    dma_free_coherent(&p_pci_dev->dev, 8192, dmabuf, dma_handle);

  return 0;
}
Thank you in advance!

Last edited by drakonof; 04-27-2020 at 02:37 PM.
 
Old 05-12-2020, 08:49 AM   #2
business_kid
LQ Guru
 
Registered: Jan 2006
Location: Ireland
Distribution: Slackware, Slarm64 & Android
Posts: 17,543

Rep: Reputation: 2608Reputation: 2608Reputation: 2608Reputation: 2608Reputation: 2608Reputation: 2608Reputation: 2608Reputation: 2608Reputation: 2608Reputation: 2608Reputation: 2608
Quote:
Originally Posted by drakonof
I am trying send data through PCIe + DMA. But I cannot fill sending array correctly. The data which I send from a host are received not which that I expect.
That's like the "Sad Mac" that came on early Macintoshes or the 'something went wrong' errors you see. NO information.
And now you've got 402 views, and no replies That tells you something about your question.

There's gdb and strace, both debugging programs for software guys. Have you used them? Let's see meaningful output. There's core dumps if things crash. There's error numbers that mean something if things exit. We don't even know what box/distro/kernel you're on. What have your investigations narrowed it down to? If you haven't put time into it, why should we?
 
  


Reply

Tags
dma, kernel, pcie


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Can PCIe device driver support to read a particlualr buffer in the PCIe device with mutiple buffers? cwang_sh Linux - Hardware 3 07-02-2018 09:17 AM
LXer: Skylake-U Mini-ITX features mini-PCIe and PCIe x4 LXer Syndicated Linux News 0 08-24-2017 01:25 AM
LXer: Compact, rugged box-PC expands via PCIe and Mini-PCIe LXer Syndicated Linux News 0 02-09-2014 02:10 PM
PCIe re-enumation in linux driver question (pcie hotplug doesn't work) blavo Programming 5 08-02-2012 02:12 PM
[SOLVED] Best PCIe 2.0 graphics card for for PCIe 1.1, Pentium Dual Core system. ags1 Linux - Hardware 12 04-27-2012 03:54 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Hardware

All times are GMT -5. The time now is 11:42 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration