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, &param,
                                      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, &param2, 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, &param2,
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 addr...@length 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 addr...@lenght %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);
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help

Reply via email to