From: Armin Steinhoff <armin@steinhoff.de>
To: linux-rt-users@vger.kernel.org
Subject: mapping of PCI memory to user space not working with uio.c ?
Date: Fri, 12 Feb 2010 21:54:59 +0100 [thread overview]
Message-ID: <4B75C023.4070908@steinhoff.de> (raw)
In-Reply-To: <4B73B7B5.4070509@gmx.net>
[-- Attachment #1: Type: text/plain, Size: 507 bytes --]
Hello,
I need some help.
I'm writing a user space driver for a PCI board.
The kernel part is working well ... all infos in sysfs are correct.
The mappings of the memories behind the BARs are "working" ... but the
returned addresses are not valid.
Is it possible that the call remap_pfn_range used in uio.c are not
working with PCI memory ??
I have attached the mapping procedure of the user space and the kernel part.
The mapping of BAR[2] (it's kernel memory) is valid ...
Best Regards
--Armin
[-- Attachment #2: uio_ems.c --]
[-- Type: text/x-csrc, Size: 4119 bytes --]
/*
* UIO can CAN L2 PCI
*
* (C) Armin Steinhoff <as@steinhoff-automation.com>
* (C) 2007 Hans J. Koch <hjk@linutronix.de>
* Original code (C) 2005 Benedikt Spranger <b.spranger@linutronix.de>
*
* Licensed under GPL version 2 only.
*
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/uio_driver.h>
#include <asm/io.h>
#define DEBUG 1
#define PCI_VENDORID 0x110A
#define PCI_DEVICEID 0x2104
#define INT_QUEUE_SIZE 64
static unsigned char IntIx, * IntQ;
static void __iomem *ISR;
static void __iomem *ICR;
static irqreturn_t CAN_handler(int irq, struct uio_info *dev_info)
{
// check PITA ICR ...
if(*((unsigned long *)ICR) & 0x02) // our interrupt ?
{
IntQ[IntIx] = *((unsigned char *)ISR);
IntIx = (IntIx + 1) & 0xF ; // modulo 16
*((unsigned long *)ICR) = 0x02; // confirm interrupt
return(IRQ_HANDLED);
}
else
return(IRQ_NONE);
}
static int __devinit ems_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct uio_info *info;
int err;
info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
// if (pci_enable_device(dev)) goto out_free;
err = pci_enable_device(dev);
if (err) {
dev_err(&dev->dev, "%s: pci_enable_device failed: %d\n", __func__, err);
return err;
}
if (pci_request_regions(dev, "uio_ems"))
goto out_disable;
info->mem[0].addr = pci_resource_start(dev, 0);
if (!info->mem[0].addr)
goto out_release;
info->mem[0].size = pci_resource_len(dev, 0);
info->mem[0].memtype = UIO_MEM_PHYS;
info->mem[0].internal_addr = ioremap(info->mem[0].addr,info->mem[0].size);
if (!info->mem[0].internal_addr)
goto out_release;
// disable interrupt at PITA level
*( (unsigned long *)( info->mem[0].internal_addr )) &= ~0x20000; // reset Bit 17
info->mem[1].addr = pci_resource_start(dev, 1);
if (!info->mem[1].addr)
goto out_release;
info->mem[1].size = pci_resource_len(dev, 1);
info->mem[1].memtype = UIO_MEM_PHYS;
info->mem[1].internal_addr = ioremap(info->mem[1].addr,info->mem[1].size);
if (!info->mem[1].internal_addr)
goto out_release;
// interrupt queue
info->mem[2].addr = (unsigned long)kmalloc(64, GFP_KERNEL);
IntQ = (unsigned char * )info->mem[2].addr;
if (!info->mem[2].addr)
goto out_unmap1;
memset(IntQ, 0x00, 16);
IntIx = 0;
info->mem[2].memtype = UIO_MEM_LOGICAL;
info->mem[2].size = 64;
ISR = info->mem[1].internal_addr + 12 + 0x400; // interrupt status channel 1
ICR = info->mem[0].internal_addr;
*((unsigned long *)ICR) = 0x02; // confirm interrupt
info->name = "uio_ems";
info->version = "0.0.1";
info->irq = dev->irq;
info->irq_flags |= IRQF_SHARED;
info->handler = CAN_handler;
if (uio_register_device(&dev->dev, info))
goto out_kfree;
pci_set_drvdata(dev, info);
printk("can_pci_probe end\n");
return 0;
out_kfree:
kfree((void *)info->mem[2].addr);
out_unmap1:
iounmap(info->mem[1].internal_addr);
iounmap(info->mem[0].internal_addr);
out_release:
pci_release_regions(dev);
out_disable:
pci_disable_device(dev);
kfree (info);
printk("CAN_PCI: -ENODEV\n");
return -ENODEV;
}
static void ems_pci_remove(struct pci_dev *dev)
{
struct uio_info *info = pci_get_drvdata(dev);
uio_unregister_device(info);
pci_release_regions(dev);
pci_disable_device(dev);
pci_set_drvdata(dev, NULL);
iounmap(info->mem[0].internal_addr);
iounmap(info->mem[1].internal_addr);
kfree((void *)info->mem[2].addr);
kfree (info);
}
static struct pci_device_id ems_pci_ids[] __devinitdata = {
{
PCI_VENDORID, PCI_DEVICEID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
},
{ 0, }
};
static struct pci_driver ems_pci_driver = {
.name = "uio_ems",
.id_table = ems_pci_ids,
.probe = ems_pci_probe,
.remove = ems_pci_remove,
};
static int __init ems_init_module(void)
{
int ret;
ret = pci_register_driver(&ems_pci_driver);
return ret;
}
static void __exit ems_exit_module(void)
{
pci_unregister_driver(&ems_pci_driver);
}
module_init(ems_init_module);
module_exit(ems_exit_module);
MODULE_DEVICE_TABLE(pci, ems_pci_ids);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("A. Steinhoff");
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: user_space_mmap.c --]
[-- Type: text/x-csrc; name="user_space_mmap.c", Size: 1146 bytes --]
int do_mappings(void)
{
int size_fd;
int uio_size;
size_fd = open( UIO_SIZE0, O_RDONLY );
if( size_fd<0 || uio_fd<0 ) {
fprintf(stderr,"Can't open UIO file 0...\n");
return -1;
}
read( size_fd, uio_size_buf, sizeof(uio_size_buf) );
uio_size = (int)strtol( uio_size_buf, NULL, 0 );
BAR[0] = (BYTE *)mmap(NULL, uio_size, PROT_READ | PROT_WRITE, MAP_SHARED, uio_fd, 0);
if(BAR[0] == MAP_FAILED) perror("BAR0:\n");
close(size_fd);
size_fd = open( UIO_SIZE1, O_RDONLY );
if( size_fd<0 ) {
fprintf(stderr,"Can't open UIO file 1...\n");
return -1;
}
read( size_fd, uio_size_buf, sizeof(uio_size_buf) );
uio_size = (int)strtol( uio_size_buf, NULL, 0 );
BAR[1] = (BYTE *)mmap(NULL, uio_size, PROT_READ | PROT_WRITE, MAP_SHARED, uio_fd, getpagesize());
close(size_fd);
size_fd = open( UIO_SIZE2, O_RDONLY );
if( size_fd<0 ) {
fprintf(stderr,"Can't open UIO file 2...\n");
return -1;
}
read( size_fd, uio_size_buf, sizeof(uio_size_buf) );
uio_size = (int)strtol( uio_size_buf, NULL, 0 );
BAR[2] = (BYTE *)mmap(NULL, uio_size, PROT_READ | PROT_WRITE, MAP_SHARED, uio_fd, 2*getpagesize());
close(size_fd);
return(0);
}
prev parent reply other threads:[~2010-02-12 20:53 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-09 7:41 Tweak Latency on Intel ATOM Max Miller
2010-02-10 22:38 ` Clark Williams
2010-02-11 7:54 ` Max Müller
2010-02-11 15:34 ` Clark Williams
2010-02-15 9:32 ` Max Müller
2010-02-15 14:38 ` Clark Williams
2010-02-16 6:50 ` Max Müller
2010-02-16 12:18 ` Luis Claudio R. Goncalves
2010-02-17 6:26 ` Max Müller
2010-02-12 20:54 ` Armin Steinhoff [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4B75C023.4070908@steinhoff.de \
--to=armin@steinhoff.de \
--cc=linux-rt-users@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).