linux-rt-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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);
}

      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).