LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Embedded & Single-board computer (https://www.linuxquestions.org/questions/linux-embedded-and-single-board-computer-78/)
-   -   Using ioctl for writing different types (https://www.linuxquestions.org/questions/linux-embedded-and-single-board-computer-78/using-ioctl-for-writing-different-types-4175607846/)

cyapicioglu 06-13-2017 08:26 AM

Using ioctl for writing different types
 
In my project, I want to develop a Linux driver for communicating FPGA through PCIe.In the ioctl method I have,


//-------------------------------------------------------------
static long fpgaIoctl(struct file *filePtr, unsigned int flag, unsigned long data)
{
struct DevInfo_t *devInfo = 0;
devInfo = (struct DevInfo_t *) filePtr->private_data;
SFPGA_IOCTL* pIoctl = (SFPGA_IOCTL*)data;

switch(flag)
{

//#define FPGA_WRITE_BYTE 0x101 ///< Defined for writing BYTE format
case FPGA_WRITE_BYTE:
//FPGA_WRITEB(filePtr->, pIoctl->datab, pIoctl->offset);
//writeb(data, devInfo->resource[0].RegsBase+offset);
printk(KERN_INFO "FPGA_WRITEB calisiyor");
printk(KERN_ALERT "---%s---", (char *)data);

writeb((u8)data,devInfo->resource[0].RegsBase+pIoctl->offset);
printk(KERN_INFO "Written value: %d", (char)devInfo->resource[0].RegsBase+pIoctl->offset);
break;


}

return 0;
}
//------------------------------------------------------------

My first question is that can I use the following definitions to write different format like qword,word,long and so on? or something possible to write differetn types of data?

//------------------------------------------------------------
#if 0
extern u8 readb(const volatile void __iomem *addr);
extern u16 readw(const volatile void __iomem *addr);
extern u32 readl(const volatile void __iomem *addr);
extern u64 readq(const volatile void __iomem *addr);
extern void writeb(u8 b, volatile void __iomem *addr);
extern void writew(u16 b, volatile void __iomem *addr);
extern void writel(u32 b, volatile void __iomem *addr);
extern void writeq(u64 b, volatile void __iomem *addr);
#endif
//-------------------------------------------------------------

My devInfo structure is like the following;

//-------------------------------------------------------------

struct DevInfo_t
{
struct
{
int type;
int flag;
void* RegsBase; ///< Register base address
PHYSICAL_ADDRESS PhysBase;
u32 RegsLength;
}resource[6];

/* the kernel pci device data structure */
struct pci_dev *pciDev;
__iomem u32 *registers;


/* upstream root node */
struct pci_dev *upstream;

/* kernel's virtual addr. for the mapped BARs */
void * __iomem bar[NUM_BARS];

/* length of each memory region. Used for error checking. */
size_t barLengths[NUM_BARS];

/* temporary buffer. If allocated, will be BUFFER_SIZE. */
char *buffer;
wait_queue_head_t wait_q;

/* Mutex for this device. */
struct semaphore sem;

/* PID of process that called open() */
int userPID;
int flag;

/* character device */
dev_t cdevNum;
struct cdev cdev;
struct class *myClass;
struct device *device;

};

//-------------------------------------------------------------

and SFPGA_IOCTL structure is;


//-------------------------------------------------------------
typedef struct
{
union
{
u8 datab;
u16 dataw;
u32 datal;
u64 dataqw;
};
u64 offset;

}SFPGA_IOCTL;

//-------------------------------------------------------------


Subsequently,I take the RegisteryBase as follows in the probe function,

//------------------------------------------------------------
if((pci_resource_flags(dev,i)&IORESOURCE_TYPE_BITS)==IORESOURCE_MEM)
{
printk(KERN_INFO "memmap1");
devInfo->resource[i].type=IORESOURCE_MEM;
devInfo->resource[i].flag=pci_resource_flags(dev,i);
devInfo->resource[i].RegsLength=(u32)pci_resource_len(dev,i);
devInfo->resource[i].RegsBase=ioremap_nocache(pci_resource_start(dev,i),pci_resource_len(dev,i));
devInfo->resource[i].PhysBase.QuadPart=(u64)pci_resource_start(dev,i);

if(devInfo->resource[i].RegsBase==NULL)
{
printk(KERN_ERR "pci_ioremap_bar da hata olustu!\n");
return -ENOMEM;
}
printk(KERN_INFO "%d. bar icin type:%d",i,devInfo->resource[i].type);
printk(KERN_INFO "%d. bar icin register length:%d",i,devInfo->resource[i].RegsLength);
printk(KERN_INFO "%d. bar icin RegsBase:%p",i,devInfo->resource[i].RegsBase);

}

//-------------------------------------------------------------

And my mapping function for BAR of FPGA is;

static int mapBars(struct DevInfo_t *devInfo)
{
int ct = 0;
unsigned long barStart, barEnd, barLength; ///<Used for specifying bar start and end points and it's length
for (ct = 0; ct < NUM_BARS; ct++)
{
printk(KERN_INFO "BAR Map edilmeye calisiliyor #%d of %d.\n", ct, NUM_BARS);
barStart = pci_resource_start(devInfo->pciDev, ct);
barEnd = pci_resource_end(devInfo->pciDev, ct);
barLength = barEnd - barStart + 1;

devInfo->barLengths[ct] = barLength;

//Check for empty BAR
if (!barStart || !barEnd)
{
devInfo->barLengths[ct] = 0;
printk(KERN_INFO "Boş bar! #%d.\n", ct);
continue;
}

//Check for messed up BAR
if (barLength < 1)
{
printk(KERN_WARNING "BAR #%d uzunluğu 1 byte'dan daha az!.\n", ct);
continue;
}

// If we have a valid bar region then map the device memory or
// IO region into kernel virtual address space
devInfo->bar[ct] = pci_iomap(devInfo->pciDev, ct, barLength);

if (!devInfo->bar[ct])
{
printk(KERN_WARNING "BAR #%d map edilemedi.\n", ct);
return -1;
}

printk(KERN_INFO "BAR%d mapped at 0x%p with length %lu.\n", ct, devInfo->bar[ct], barLength);
}
return 0;
}
//------------------------------------------------------------
So,I am very new to develop Linux kernel and device drivers and when I run my testcode I face a trouble and computer is rebooting itself and then I can not login the system with my username and password and also I can not success the write operation.What can be a problem with my driver code?

Other thing is

static long fpgaIoctl(struct file *filePtr, unsigned int flag, unsigned long data)
{
struct DevInfo_t *devInfo = 0;
devInfo = (struct DevInfo_t *) filePtr->private_data;
SFPGA_IOCTL* pIoctl = (SFPGA_IOCTL*)data;
}

From the above code I took the devInfo with "devInfo = (struct DevInfo_t *) filePtr->private_data;" Is that true for taking driver information?

Thanks for your attentions and answers,
Best Regards.


All times are GMT -5. The time now is 05:02 AM.