* [Xenomai-help] PCI1711 Rtdm driver reading and writing error
@ 2010-12-26 18:39 adilkaraoz
2011-01-01 22:23 ` Gilles Chanteperdrix
2011-01-04 21:08 ` Gilles Chanteperdrix
0 siblings, 2 replies; 3+ messages in thread
From: adilkaraoz @ 2010-12-26 18:39 UTC (permalink / raw)
To: xenomai
[-- Attachment #1: Type: text/plain, Size: 13905 bytes --]
I am writing rtdm driver for PCI1711 card. I got base adress and configured
it. But when I write digtal output or Dac, I can't see changes at those
registers. My Code is below please help me.
#include <rtdm/rtdm_driver.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include "xeno_pci1711_driver.h"
static int __devinit pci1711_probe(struct pci_dev *dev, const struct
pci_device_id *id);
static void __devexit pci1711_remove(struct pci_dev *dev);
int xeno_pci1711_rt_open(struct rtdm_dev_context *context,
rtdm_user_info_t *user_info,
int oflags);
int xeno_pci1711_rt_close(struct rtdm_dev_context *context,
rtdm_user_info_t *user_info);
int xeno_pci1711_rt_ioctl(struct rtdm_dev_context *context,
rtdm_user_info_t *user_info,
int cmd,
void *arg);
//int pci1711_rt_rw(struct rtdm_dev_context
*,rtdm_user_info_t*,void*,size_t);
/**
* module info
*/
MODULE_DESCRIPTION("RTDM driver for PCI1711");
MODULE_AUTHOR("Adil Karaoz");
MODULE_LICENSE("GPL");
/**
* global variables
*/
int first_loop=0;
int ret_loop_val=0;
int isRegister = -1;
/**
* define devices our driver supports
*/
static struct pci_device_id pci1711_ids[]={
{PCI_VENDORID_PLX, PCI_DEVICEID_1711, PCI_SUB_VENDORID_PLX,
PCI_SUB_DEVICEID_1711, 0, 0, 0},
{ }
};
/**
* export pci_device_id structure to user space, allowing hotplug
*/
MODULE_DEVICE_TABLE (pci, pci1711_ids);
/**
* create pci_driver structure,
* and register it in pci1711_driver_init_module,
* unregister in pci1711_exit_module
*/
static struct pci_driver pci1711_driver = {
.name = DRV_NAME,
.id_table = pci1711_ids,
.probe = pci1711_probe,
.remove = __devexit_p(pci1711_remove),
};
/**
* info on our pic1711 card
*/
struct pci1711_context{
/* address in kernel space (virtual memory) */
void __iomem *base_address;
/* physical address */
unsigned long location;
/* size/length of the memory */
unsigned long mem_size;
struct rtdm_device *device;
int dev_id;
};
struct pci1711_context pci1711_struct;
struct pci1711_context *pci1711_card = &pci1711_struct;
/**
* ioctl() implementation
*/
int xeno_pci1711_rt_ioctl(struct rtdm_dev_context *context,
rtdm_user_info_t *user_info,
int cmd,
void *arg)
{
//int err = 0;
int retval = 0;
ioc_param_struct param = {0,0};
ioc_param_struct param2 = {0,0};
switch(cmd) {
case PCI1711_IORESET:
break;
case 2/*PCI1711_DIOWRITE*/:
//printk(KERN_DEBUG "writing to registers\n");
retval = rtdm_safe_copy_from_user(user_info, ¶m,
arg, sizeof(ioc_param_struct));
if(retval == 0) {//success
//@TODO do some checkins, if offset correct...
iowrite32( param.bv, pci1711_card->base_address + 16 +
param.offset );
rtdm_printk(KERN_WARNING "value = %lu port = %u\n", param.bv,
param.offset);
}else{
rtdm_printk(KERN_WARNING "yazilamadi\n");
return -EFAULT;
}
break;
case 1://PCI1711_DIOREAD:
//read from register, write to user
/*if(! capable( CAP_SYS_RAWIO | CAP_SYS_ADMIN ) ){
printk(KERN_WARNING "hata is admin\n");
return -EPERM;
}*/
retval = rtdm_safe_copy_from_user(user_info, ¶m2, arg,
sizeof(ioc_param_struct));
if(retval == 0) {//success
//@TODO some checkins, if offset incorrect...
param.bv = readl( pci1711_card->base_address + 16 + param2.offset );
rtdm_printk(KERN_WARNING "value = %lu port = %u\n", param2.bv,
param2.offset);
if( rtdm_safe_copy_to_user(user_info, arg, ¶m2,
sizeof(ioc_param_struct)) ){
rtdm_printk(KERN_WARNING "hata is copy back\n");
return -EFAULT;
}
}else{
return -EFAULT;
}
break;
default:
printk(KERN_WARNING "default reset = %u write = %lu read = %lu cmd =
%d\n", PCI1711_IORESET, PCI1711_DIOWRITE, PCI1711_DIOREAD, cmd);
return -ENOTTY;
}
return retval;
return 0;
}
/**********************************************************/
/* DRIVER OPERATIONS */
/**********************************************************/
static const struct rtdm_device xeno_pci1711_driver = {
struct_version: RTDM_DEVICE_STRUCT_VER,
device_flags: RTDM_NAMED_DEVICE,// | RTDM_EXCLUSIVE,
context_size: sizeof(struct pci1711_context),
device_name: "",
//don't try to find DEV_FILE in /dev/ - it's not there -
// this is an RTDM internal identifier
//you can find it in /proc/iomem
/* If you do not use kmalloc and kfree, and you made
sure that there is no syscall in the open/close handler, you
can declare the open_rt and close_rt handler.
*/
open_rt: NULL,//xeno_pci1711_rt_open,
open_nrt: xeno_pci1711_rt_open,
ops: {
close_rt: NULL,//xeno_pci1711_rt_close,
close_nrt: xeno_pci1711_rt_close,
ioctl_rt: (void*)xeno_pci1711_rt_ioctl,
ioctl_nrt: NULL,
read_rt: NULL,
read_nrt: NULL,//pci1711_rt_rw,
write_rt: NULL,//pci1711_rt_rw,
write_nrt: NULL,//pci1711_rt_rw,
},
device_class: 0xff00,
device_sub_class: 0, //222, //????
driver_name: DRV_NAME, //informational driver name
peripheral_name: "pci 1711 rtdm", // Informational name
// the device is attached to
provider_name: "Adil Karaoz", // Informational name
};
int xeno_pci1711_rt_open(struct rtdm_dev_context *context,
rtdm_user_info_t *user_info,
int oflags)
{
struct pci1711_context *my_context;
// get the id of the card from the rtdm_device struct
// of the owning device
int dev_id = context->device->device_id;
// get the begin of driver defined context data structure of our driver
my_context = (struct pci1711_context *)context->dev_private;
my_context->dev_id = dev_id;
rtdm_printk( KERN_DEBUG "opening dev with id:%d\n", my_context->dev_id);
return 0;
}
/**
* close named rt device
*
* as of version 0.1 nothing necessary is provided
* by this function
*/
int xeno_pci1711_rt_close(struct rtdm_dev_context *context,
rtdm_user_info_t *user_info)
{
struct pci1711_context *my_context;
// get the context struct
my_context = (struct pci1711_context *)context->dev_private;
printk( KERN_DEBUG "closing... id of dev is %d\n", my_context->dev_id);
return 0;
}
static int pci171x_reset(struct pci_dev *dev)
{
int i;
//#ifdef PCI171X_EXTDEBUG
rtdm_printk( KERN_WARNING "pci1710 EDBG: BGN: pci171x_reset(...)\n");
//#endif
writew(0x30, pci1711_card->base_address + PCI171x_CNTCTRL);
writew(Control_SW, pci1711_card->base_address + PCI171x_CONTROL); // reset
any operations
writeb(0, pci1711_card->base_address + PCI171x_CLRFIFO); // clear FIFO
writeb(0, pci1711_card->base_address + PCI171x_CLRINT); // clear INT request
//start_pacer(dev,-1,0,0); // stop 8254
//devpriv->da_ranges=0;
//if (this_board->n_aochan) {
writeb(0, pci1711_card->base_address + PCI171x_DAREF); // set DACs to 0..5V
writew(0, pci1711_card->base_address + PCI171x_DA1); // set DA outputs to
0V
//devpriv->ao_data[0]=0x0000;
//if (this_board->n_aochan>1) {
writew(0, pci1711_card->base_address + PCI171x_DA2);
//devpriv->ao_data[1]=0x0000;
//}
//}
writew(0xff, pci1711_card->base_address + PCI171x_DO); // digital outputs to
0
writeb(0, pci1711_card->base_address + PCI171x_CLRFIFO); // clear FIFO
writeb(0, pci1711_card->base_address + PCI171x_CLRINT); // clear INT request
//#ifdef PCI171X_EXTDEBUG
rtdm_printk( KERN_WARNING "pci1710 EDBG: END: pci171x_reset(...)\n");
//#endif
return 0;
}
/**
* This function is called by the PCI core when
* it has a struct pci_dev that it thinks this driver wants to control.
*
* Purpose: initialize the device properly
* +set up the rtdm_device structure for this device
*/
static int __devinit pci1711_probe(struct pci_dev *dev, const struct
pci_device_id *id){
/*
* @TODO when initializing module, this function "probe" runs two times
* WHY?
* and as a side effect base address is initialized two times...
*
* the following if-condition avoids two time execution
*/
struct rtdm_device *rtdm_dev;
int ret_val = 0;
uint8_t irq;
rtdm_printk( KERN_WARNING
"bus number: %c function index: %x vendor: %x device: %x class:
%x\n", dev->bus->number, dev->devfn, dev->vendor, dev->device, dev->class);
printk( "pci1711 card found!\n" );
//if-condition evaluates to true in the second loop
if(first_loop){
//first_loop =1;
return ret_loop_val;
}
first_loop=1;
//wake up the device
ret_val = pci_enable_device(dev);
if(ret_val!=0){
printk( KERN_WARNING
"xeno_pci1711_driver: function pci_enable_device failed\n");
goto pci_enable_device_err;
}
printk(KERN_DEBUG "device woke up!\n");
//initialization of location and mem_size
pci1711_card->location = pci_resource_start(dev, PCI_1711_BAR & 0xFFFFFFF0
);
pci1711_card->mem_size = pci_resource_len(dev, PCI_1711_BAR & 0xFFFFFFF0
);
//if(pci1711_card->location == 0){
printk( KERN_WARNING "xeno_pc1711_driver: location = %lx mem = %lx\n",
pci1711_card->location, pci1711_card->mem_size);
//}
ret_val = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
if (!ret_val){
rtdm_printk("interrupt line no:%d",irq);
}
//alloc mem for rtdm structure
rtdm_dev = kmalloc(sizeof(struct rtdm_device), GFP_KERNEL);
if(!rtdm_dev){
printk(KERN_WARNING "xeno_pc1711_driver: kmalloc failed\n");
ret_val = -ENOMEM; //Insufficient storage space is available.
goto kmalloc_err;
}
//copy the structure to the new memory
memcpy(rtdm_dev, &xeno_pci1711_driver, sizeof(struct rtdm_device));
//create filename
snprintf(rtdm_dev->device_name,
RTDM_MAX_DEVNAME_LEN, "%s%d", DRV_NAME, 0 /*i*/);
rtdm_dev->device_id = 0; //i;
//define two other members of the rtdm_device structure
rtdm_dev->proc_name = rtdm_dev->device_name;
if ((ret_val = pci_request_region(dev, PCI_1711_BAR & 0xFFFFFFF0,
rtdm_dev->device_name))){
rtdm_printk(KERN_WARNING "xeno_pci1711_driver: device memory allocation
failed!\n");
ret_val = -EBUSY;
goto request_mem_region_err;
}
printk( KERN_DEBUG "going to map memory to kernel space\n");
//map IO mem to kernel space
pci1711_card->base_address = ioremap( pci1711_card->location,
pci1711_card->mem_size );
//pci1711_card->base_address = (void*)(pci1711_card->base_address &
0xFFFFFFFC);
if(!pci1711_card->base_address){
rtdm_printk(KERN_WARNING "xeno_pci1711_driver: cannot remap memory
region\n");
ret_val = -ENODEV;
goto ioremap_err;
}
rtdm_printk(KERN_DEBUG "base address@domain.hid is %p @ %lx \n",
pci1711_card->base_address, pci1711_card->mem_size);
ret_val = rtdm_dev_register(rtdm_dev);
if(ret_val < 0){
printk(KERN_WARNING "xeno_pci1711_driver: cannot register device\n");
goto dev_register_err;
}
pci1711_card->device = rtdm_dev;
ret_val = pci_set_mwi (dev);
if( ret_val < 0 ){
printk(KERN_WARNING "xeno_pci1711_driver: pci_set_mwi error\n");
}
pci171x_reset(dev);
//outw( 0xff, pci1711_card->location + 16 );
return ret_val;
//clean up code in case of errors
dev_register_err:
iounmap(pci1711_card->base_address);
ioremap_err:
release_mem_region(pci1711_card->location,
pci1711_card->mem_size);
request_mem_region_err:
kfree(rtdm_dev);
kmalloc_err:
pci_enable_device_err:
//to get the same ret_val in the second unwanted loop...
ret_loop_val = ret_val;
return ret_val;
}
static void __devexit pci1711_remove(struct pci_dev *dev){
//@TODO:when removing module/driver this function runs two times
//WHY?
//the next if condition avoids executing the body of the function
//more than one time. if-condition evaluates to true in the second
//loop.
if(!first_loop){
//first_loop=0;
return;
}
first_loop=0;
printk( KERN_DEBUG "removing...\n" );
//remove char device from the system
//unregister RTdriver
if( pci1711_card->device != NULL )
rtdm_dev_unregister(pci1711_card->device, 1000);
if( pci1711_card->location != 0 ){
printk( KERN_DEBUG "removing base address@domain.hid %p @ %lx\n",
pci1711_card->base_address, pci1711_card->mem_size);
//release virtual memory
iounmap(pci1711_card->base_address);
pci_release_region(dev, PCI_1711_BAR & 0xFFFFFFF0 );
pci_clear_mwi(dev);
}
//free allocated memory
if( pci1711_card->device != NULL )
kfree(pci1711_card->device);
}
/**
* Init module function
*/
static int pci1711_driver_init_module(void){
static int ret_val;
printk( KERN_DEBUG "Module pci1711_driver init\n" );
ret_val = pci_register_driver(&pci1711_driver);
isRegister = ret_val;
if( isRegister < 0 ){
printk("PCI-1711 NOT register \n");
return(-EIO);
}
//pci1711_probe( pcidev, pcidev->driver->id_table );
return ret_val;
}
/**
* Exit module function
*/
static void pci1711_driver_exit_module(void){
printk( KERN_DEBUG "Module pci1711_driver exit\n" );
if( isRegister >= 0 ){
pci_unregister_driver(&pci1711_driver);
//pci1711_remove(pcidev);
}
}
module_init(pci1711_driver_init_module);
module_exit(pci1711_driver_exit_module);
[-- Attachment #2: Type: text/html, Size: 25322 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Xenomai-help] PCI1711 Rtdm driver reading and writing error
2010-12-26 18:39 [Xenomai-help] PCI1711 Rtdm driver reading and writing error adilkaraoz
@ 2011-01-01 22:23 ` Gilles Chanteperdrix
2011-01-04 21:08 ` Gilles Chanteperdrix
1 sibling, 0 replies; 3+ messages in thread
From: Gilles Chanteperdrix @ 2011-01-01 22:23 UTC (permalink / raw)
To: adilkaraoz; +Cc: xenomai
adilkaraoz wrote:
> I am writing rtdm driver for PCI1711 card. I got base adress and configured
> it. But when I write digtal output or Dac, I can't see changes at those
> registers. My Code is below please help me.
Is this issue really related to Xenomai? Do you get a different
behaviour if you try writing to these registers in a plain Linux driver?
I doubt it, and you do not give us any clue on what the system you are
running. Please do not bother sending more information unless you have
verified that the issue is specific to Xenomai.
Anyway, if I were you, I would check if the physical address correct
passed to ioremap is the corrrect one. That is print it, and look if it
is what should be expected (if you have a working Linux driver for this
hardware, the physical address should be the same).
The mask with 0xfffffff0 looks suspicious, if the system is x86_64, it
will not only mask the 4 lower bits, it will also mask the 32 upper bits.
--
Gilles.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Xenomai-help] PCI1711 Rtdm driver reading and writing error
2010-12-26 18:39 [Xenomai-help] PCI1711 Rtdm driver reading and writing error adilkaraoz
2011-01-01 22:23 ` Gilles Chanteperdrix
@ 2011-01-04 21:08 ` Gilles Chanteperdrix
1 sibling, 0 replies; 3+ messages in thread
From: Gilles Chanteperdrix @ 2011-01-04 21:08 UTC (permalink / raw)
To: adilkaraoz; +Cc: xenomai
adilkaraoz wrote:
> pci1711_card->location = pci_resource_start(dev, PCI_1711_BAR & 0xFFFFFFF0
> );
> pci1711_card->mem_size = pci_resource_len(dev, PCI_1711_BAR & 0xFFFFFFF0
> );
I really have doubts about this: the arguments passed to these functions
should be a something ranging from 0 to 5 inclusive. Now, PCI_1711_BAR &
0xFFFFFFF0 seems odd.
If PCI_1711_BAR is less than 0x10, the result of this mask will always be 0.
If PCI_1711_BAR is greater than 0xf, you end up accessing random memory.
Also note that since 2.6.28, there is a pci_ioremap_bar function, which
does all the pci_resouce and ioremap job.
>
> //if(pci1711_card->location == 0){
> printk( KERN_WARNING "xeno_pc1711_driver: location = %lx mem = %lx\n",
> pci1711_card->location, pci1711_card->mem_size);
> //}
>
> ret_val = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
> if (!ret_val){
> rtdm_printk("interrupt line no:%d",irq);
> }
That is not the way to get the interrupt line either, you should use
dev->irq.
--
Gilles.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2011-01-04 21:08 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-26 18:39 [Xenomai-help] PCI1711 Rtdm driver reading and writing error adilkaraoz
2011-01-01 22:23 ` Gilles Chanteperdrix
2011-01-04 21:08 ` Gilles Chanteperdrix
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.