PCI device driver file operations question
- From: "elliotng.ee@xxxxxxxxx" <elliotng.ee@xxxxxxxxx>
- Date: 27 Dec 2006 13:52:15 -0800
In a previous entry, I wrote about how I used a userspace C program to
read and write 32-bit binary data from/to custom PCI device memory by
opening /dev/mem and mmaping the memory range that I want. This program
worked well.
To try something similar, I wrote a PCI device driver and a userspace
program. The PCI device driver contains file operations calls. The PCI
device driver contains the following file operation functions:
int test_fopsopen(struct inode *inode, struct file *file){
return 0;
}
int test_fopsrelease(struct inode *inode, struct file *file){
return 0;
}
ssize_t test_fopsread(struct file *file, char *buf, size_t count,
loff_t *ppos) {
u32 readData;
char* region0;
int offset = 0;
u32 bar0;
unsigned int barLen;
struct pci_dev *dev;
dev = pci_get_device(TEST_VENDORID, TEST_DEVICEID, NULL);
if (dev) {
pci_request_region(dev, 0, "testdriver");
bar0 = pci_resource_start(dev, 0);
barLen = pci_resource_len(dev, 0);
region0 = ioremap_nocache(bar0, barLen);
readData = readl(region0+offset);
iounmap(region0);
pci_dev_put(dev);
if (copy_to_user(buf, &readData, sizeof(u32))) return -EFAULT;
return 0;
}
else {
printk(KERN_ALERT "Error in reading data at BA0\n");
return 1;
}
}
ssize_t test_fopswrite(struct file *file, char *buf, size_t count,
loff_t *ppos) {
u32 writeData;
char* region0;
int offset = 0;
u32 bar0;
unsigned int barLen;
struct pci_dev *dev;
dev = pci_get_device(TEST_VENDORID, TEST_DEVICEID, NULL);
if (dev) {
pci_request_region(dev, 0, "testdriver");
bar0 = pci_resource_start(dev, 0);
barLen = pci_resource_len(dev, 0);
region0 = ioremap_nocache(bar0, barLen);
if (copy_from_user(&writeData, buf, sizeof(writeData))) return
-EFAULT;
writel(wroteData, region0+offset);
iounmap(region0);
pci_dev_put(dev);
return 0;
}
else {
printk(KERN_ALERT "ERROR in writing data at BA0\n");
return 1;
}
}
where TEST_VENDORID and TEST_DEVICEID are defined by the Vendor ID and
Device ID of the PCI device. My user program is a simple read test:
int main(){
int fd, len;
char c[32];
fd = open("/dev/test", O_RDWR);
if (fd == -1) {
printf("Error in opening /dev/test\n");
return 1;
}
len = read(fd, c, 32);
printf("Result: %s", c);
close(fd);
}
Both the user program and the device driver compiled with no errors.
Some questions:
1) I went ahead and "mknod /dev/test c XXX 0" where XXX is the PCI
device major number. I also "chmod 666 /dev/test" so that anyone can
access it. After I insmod the kernel module, I went ahead to run the
user program. The user program gave me the following error: Error in
opening /dev/test. What caused the error to occur?
2) How does the functions in the device driver and the user program
look? Are there any improvements that can be made?
3) Eventually, I want to be able to read and write to different offsets
from base address 0. How can I send the offset number that I want from
userspace?
4) If I want the device driver to load automatically from bootup, how
do I do that? What script do I need to edit?
.
- Follow-Ups:
- Re: PCI device driver file operations question
- From: Elliot
- Re: PCI device driver file operations question
- Prev by Date: Re: why inter-changing pci slot works?
- Next by Date: Re: why inter-changing pci slot works?
- Previous by thread: why inter-changing pci slot works?
- Next by thread: Re: PCI device driver file operations question
- Index(es):
Relevant Pages
|
|