LQ Newbie
Registered: Jun 2017
Posts: 3
Rep:
|
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.
|