]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/ipci165.c
Actual driver code for directly mapped SJA1000 into PCI mem region 0.
[lincan.git] / lincan / src / ipci165.c
index 3dbbcb314824c5cf9c1ca1dd4f368a83c5b10c44..bff48dd57618ad50892980d6c3c80aca1388aff4 100644 (file)
@@ -1,10 +1,37 @@
-/* ipci165.c
- * Linux CAN-bus device driver for IXXAT iPC-I 165 (PCI) compatible HW.
- * Written for new CAN driver version by Radim Kalas
- * email:kalas@unicontrols.cz
- * This software is released under the GPL-License.
- * Version lincan-0.3  17 Jun 2004
- */
+/**************************************************************************/
+/* File: ipci165.c - support for IXXAT iPC-I 165 (PCI) compatible HW      */
+/*                                                                        */
+/* LinCAN - (Not only) Linux CAN bus driver                               */
+/* Copyright (C) 2002-2009 DCE FEE CTU Prague <http://dce.felk.cvut.cz>   */
+/* Copyright (C) 2002-2009 Pavel Pisa <pisa@cmp.felk.cvut.cz>             */
+/* Copyright (C) 2004-2005 Radim Kalas <kalas@unicontrols.cz>             */
+/* Funded by OCERA and FRESCOR IST projects                               */
+/* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl>      */
+/*                                                                        */
+/* LinCAN is free software; you can redistribute it and/or modify it      */
+/* under terms of the GNU General Public License as published by the      */
+/* Free Software Foundation; either version 2, or (at your option) any    */
+/* later version.  LinCAN is distributed in the hope that it will be      */
+/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty    */
+/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU    */
+/* General Public License for more details. You should have received a    */
+/* copy of the GNU General Public License along with LinCAN; see file     */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                              */
+/*                                                                        */
+/* To allow use of LinCAN in the compact embedded systems firmware        */
+/* and RT-executives (RTEMS for example), main authors agree with next    */
+/* special exception:                                                     */
+/*                                                                        */
+/* Including LinCAN header files in a file, instantiating LinCAN generics */
+/* or templates, or linking other files with LinCAN objects to produce    */
+/* an application image/executable, does not by itself cause the          */
+/* resulting application image/executable to be covered by                */
+/* the GNU General Public License.                                        */
+/* This exception does not however invalidate any other reasons           */
+/* why the executable file might be covered by the GNU Public License.    */
+/* Publication of enhanced or derived LinCAN files is required although.  */
+/**************************************************************************/
 
 #include "../include/can.h"
 #include "../include/can_sysdep.h"
 
 #include <ctype.h>
 
-can_irqreturn_t ipci165_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+#ifndef IRQF_SHARED
+#define IRQF_SHARED SA_SHIRQ
+#endif  /*IRQF_SHARED*/
+
+can_irqreturn_t ipci165_irq_handler(CAN_IRQ_HANDLER_ARGS(irq_number, dev_id));
 int ipci165_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw,
                       int sampl_pt, int flags);
 int ipci165_set_btregs(struct canchip_t *chip, unsigned short btr0,
@@ -62,9 +93,9 @@ static void ipci165_delay(long msdelay)
  */
 void ipci165_generate_irq(struct candevice_t *candev)
 {
-  unsigned long crm_addr = candev->io_addr;
-  writeb(readb(crm_addr + CRM_UCR) & 0xFB, crm_addr + CRM_UCR);
-  writeb(readb(crm_addr + CRM_UCR) | 0x04, crm_addr + CRM_UCR);
+  can_ioptr_t crm_addr = candev->aux_base_addr;
+  can_writeb(can_readb(crm_addr + CRM_UCR) & 0xFB, crm_addr + CRM_UCR);
+  can_writeb(can_readb(crm_addr + CRM_UCR) | 0x04, crm_addr + CRM_UCR);
 }
 
 /**
@@ -79,7 +110,7 @@ void ipci165_generate_irq(struct candevice_t *candev)
  */
 int bci_command(struct candevice_t *candev, char cmd, int size, char *data)
 {
-  unsigned long dpram_addr = candev->dev_base_addr;
+  can_ioptr_t dpram_addr = candev->dev_base_addr;
 
   DEBUGMSG ("ipci165_bci_command\n");
 
@@ -90,24 +121,24 @@ int bci_command(struct candevice_t *candev, char cmd, int size, char *data)
   }
 
   /* grant access to the command buffer */
-  can_spin_lock(candev->device_lock);
+  can_spin_lock(&candev->device_lock);
 
   // check command buffer status
-  if (readb(dpram_addr + OF_BCI_SYNC) != 0)
+  if (can_readb(dpram_addr + OF_BCI_SYNC) != 0)
   {
     /* something went wrong ... */
-    can_spin_unlock(candev->device_lock);
+    can_spin_unlock(&candev->device_lock);
     DEBUGMSG ("ipci165_bci_command: command buffer is busy\n");
     return (-EBUSY);
   }
 
   // prepare command
-  writeb(cmd, dpram_addr + OF_BCI_CMD);
-  writeb(size + 1, dpram_addr + OF_BCI_NUM);
+  can_writeb(cmd, dpram_addr + OF_BCI_CMD);
+  can_writeb(size + 1, dpram_addr + OF_BCI_NUM);
   memcpy_toio(dpram_addr + OF_BCI_DATA, data, size);
 
   // set flag for firmware
-  writeb(1, dpram_addr + OF_BCI_SYNC);
+  can_writeb(1, dpram_addr + OF_BCI_SYNC);
 
   // generate interrupt to microcontroller
   ipci165_generate_irq (candev);
@@ -127,14 +158,14 @@ int bci_command(struct candevice_t *candev, char cmd, int size, char *data)
  */
 int bci_response(struct candevice_t *candev, char cmd, int *size, char *data)
 {
-  unsigned long dpram_addr = candev->dev_base_addr;
+  can_ioptr_t dpram_addr = candev->dev_base_addr;
   char tmp;
   int delay;
 
   DEBUGMSG ("ipci165_bci_response\n");
 
   delay = 1000;
-  while (readb(dpram_addr + OF_BCI_SYNC) != 2)
+  while (can_readb(dpram_addr + OF_BCI_SYNC) != 2)
   {
     /* wait 1 ms */
     /*    ipci165_delay(1); */
@@ -143,22 +174,22 @@ int bci_response(struct candevice_t *candev, char cmd, int *size, char *data)
     {
       /* timeout occured */
       /* release the lock */
-      can_spin_unlock(candev->device_lock);
+      can_spin_unlock(&candev->device_lock);
       CANMSG ("BCI timeout!\n");
       return -EBUSY;
     }
   }
 
   /* we will not copy the command filed, so decrement the size by 1 */
-  tmp = readb(dpram_addr + OF_BCI_NUM) - 1;
+  tmp = can_readb(dpram_addr + OF_BCI_NUM) - 1;
   if (*size > tmp) *size = tmp;
 
-  if (readb(dpram_addr + OF_BCI_CMD) != cmd)
+  if (can_readb(dpram_addr + OF_BCI_CMD) != cmd)
   {
     /* release the buffer */
-    writeb(0, dpram_addr + OF_BCI_SYNC);
+    can_writeb(0, dpram_addr + OF_BCI_SYNC);
     /* unlock the access */
-    can_spin_unlock(candev->device_lock);
+    can_spin_unlock(&candev->device_lock);
 
     DEBUGMSG ("ipci165_bci_command: invalid answer\n");
     return -EIO;
@@ -166,9 +197,9 @@ int bci_response(struct candevice_t *candev, char cmd, int *size, char *data)
   memcpy_fromio(data, dpram_addr + OF_BCI_DATA, *size);
 
   /* release the buffer */
-  writeb(0, dpram_addr + OF_BCI_SYNC);
+  can_writeb(0, dpram_addr + OF_BCI_SYNC);
   /* unlock the access */
-  can_spin_unlock(candev->device_lock);
+  can_spin_unlock(&candev->device_lock);
   return 0;
 }
 
@@ -206,8 +237,8 @@ int ipci165_restart_can(struct canchip_t *chip)
 
   for (i = 0; i< BCI_QUEUE_SIZE; i++)
   {
-    writeb(BCI_MSG_STATUS_FREE, chip_data->rx_queue.addr + msg_ofs);
-    writeb(BCI_MSG_STATUS_FREE, chip_data->tx_queue.addr + msg_ofs);
+    can_writeb(BCI_MSG_STATUS_FREE, chip_data->rx_queue.addr + msg_ofs);
+    can_writeb(BCI_MSG_STATUS_FREE, chip_data->tx_queue.addr + msg_ofs);
     msg_ofs += BCI_MSG_SIZE;
   }
 
@@ -314,22 +345,22 @@ long ipci165_qfull_latency(struct msgobj_t *obj)
  */
 int ipci165_connect_irq(struct candevice_t *candev)
 {
-  unsigned long crm_addr = candev->io_addr;
+  can_ioptr_t crm_addr = candev->aux_base_addr;
   unsigned char icr;
   DEBUGMSG ("ipci165_connect_irq\n");
 
   /* install interrupt routine */
   if (request_irq(candev->sysdevptr.pcidev->irq,
                   ipci165_irq_handler,
-                  SA_SHIRQ,
+                  IRQF_SHARED,
                   DEVICE_NAME,
                   candev))
     return -ENODEV;
 
   // Enable interrupt to PC
-  writeb(readb(crm_addr + CRM_ICR) | 0x40, crm_addr + CRM_ICR);
+  can_writeb(can_readb(crm_addr + CRM_ICR) | 0x40, crm_addr + CRM_ICR);
   udelay (100);
-  icr = readb(crm_addr + CRM_ICR);
+  icr = can_readb(crm_addr + CRM_ICR);
   return 0;
 }
 
@@ -342,14 +373,14 @@ int ipci165_connect_irq(struct candevice_t *candev)
  */
 void ipci165_disconnect_irq(struct candevice_t *candev)
 {
-  unsigned long crm_addr = candev->io_addr;
+  can_ioptr_t crm_addr = candev->aux_base_addr;
   unsigned char icr;
   DEBUGMSG ("ipci165_disconnect_irq\n");
 
   // Enable interrupt to PC
-  writeb(readb(crm_addr + CRM_ICR) & ~0x40, crm_addr + CRM_ICR);
+  can_writeb(can_readb(crm_addr + CRM_ICR) & ~0x40, crm_addr + CRM_ICR);
   udelay (100);
-  icr = readb(crm_addr + CRM_ICR);
+  icr = can_readb(crm_addr + CRM_ICR);
   /* deinstall interrupt routine */
   free_irq(candev->sysdevptr.pcidev->irq, candev);
 }
@@ -461,12 +492,12 @@ int ipci165_set_btregs(struct canchip_t *chip, unsigned short btr0,
 
   DEBUGMSG ("ipci165_set_btregs[%i]: btr0=%02x, btr1=%02x\n",chip->chip_idx,
             (unsigned)btr0,(unsigned)btr1);
-  
+
   /* configure the chip */
   data[0] = chip->chip_idx;
   data[1] = btr0;
   data[2] = btr1;
-  
+
   size = 1;
   if (bci_command(chip->hostdevice, CMD_INIT_CAN, 3, data) ||
       bci_response(chip->hostdevice, CMD_INIT_CAN, &size, data) ||
@@ -491,10 +522,10 @@ int ipci165_start_chip(struct canchip_t *chip)
   int size;
 
   DEBUGMSG ("ipci165_start_chip[%i]\n",chip->chip_idx);
-  
+
   /* start CAN */
   data[0] = chip->chip_idx;
-  
+
   size = 1;
   if (bci_command(chip->hostdevice, CMD_START_CAN, 1, data) ||
       bci_response(chip->hostdevice, CMD_START_CAN, &size, data) ||
@@ -519,10 +550,10 @@ int ipci165_stop_chip(struct canchip_t *chip)
   int size;
 
   DEBUGMSG ("ipci165_stop_chip[%i]\n",chip->chip_idx);
-  
+
   /* configure the chip */
   data[0] = chip->chip_idx;
-  
+
   size = 1;
   if (bci_command(chip->hostdevice, CMD_STOP_CAN, 1, data) ||
       bci_response(chip->hostdevice, CMD_STOP_CAN, &size, data) ||
@@ -607,8 +638,8 @@ void ipci165_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj)
 {
   struct ipci165_chip_t *chip_data = (struct ipci165_chip_t *)chip->chip_data;
   struct bci_queue_t *queue = &(chip_data)->rx_queue;
-  unsigned long       queue_addr = queue->addr;
-  unsigned long       msg_addr   = queue_addr + queue->idx * BCI_MSG_SIZE;
+  can_ioptr_t         queue_addr = queue->addr;
+  can_ioptr_t         msg_addr   = queue_addr + queue->idx * BCI_MSG_SIZE;
 
   int len;
   unsigned char frame_info;
@@ -620,27 +651,27 @@ void ipci165_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj)
 
   do {
     dump_mem(msg_addr, BCI_MSG_SIZE);
-    if (readb(msg_addr + BCI_MSG_TYPE) == BCI_MSG_TYPE_CAN)
+    if (can_readb(msg_addr + BCI_MSG_TYPE) == BCI_MSG_TYPE_CAN)
     {
 #if 0
-      printk("ST(0)=%x, ST(1)=%x\n",readw(chip->chip_base_addr+OF_CAN1_STATUS),
-             readw(chip->chip_base_addr+OF_CAN2_STATUS));
+      printk("ST(0)=%x, ST(1)=%x\n",can_readw(chip->chip_base_addr+OF_CAN1_STATUS),
+             can_readw(chip->chip_base_addr+OF_CAN2_STATUS));
       for (tmp16 = 0 ; tmp16 < BCI_QUEUE_SIZE ; tmp16 ++)
-        printk ("MSG_ST(%i)=%x\n",tmp16,readb(chip->chip_base_addr + OF_CH2_TX_QUEUE + tmp16*BCI_MSG_SIZE + BCI_MSG_STATUS));
+        printk ("MSG_ST(%i)=%x\n",tmp16,can_readb(chip->chip_base_addr + OF_CH2_TX_QUEUE + tmp16*BCI_MSG_SIZE + BCI_MSG_STATUS));
       /* this is a can message */
       DEBUGMSG ("ipci165_irq_read_handler[%i]: message in buffer\n",chip->chip_idx);
 #endif
 
-      frame_info = readb(msg_addr + BCI_MSG_FRAME);
+      frame_info = can_readb(msg_addr + BCI_MSG_FRAME);
       len =  frame_info & 0x0f;
       if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
       obj->rx_msg.length = len;
       obj->rx_msg.flags  = (frame_info & BCI_MSG_FRAME_RTR ? MSG_RTR : 0);
       obj->rx_msg.cob    = 0;
       obj->rx_msg.timestamp.tv_sec = 0;
-      obj->rx_msg.timestamp.tv_usec = 
-          BCI_TIMESTAMP_RES * readl(msg_addr + BCI_MSG_TIMESTAMP);
-      /*  BCI_TIMESTAMP_RES * le32_to_cpu(readl(msg_addr + BCI_MSG_TIMESTAMP)); */
+      obj->rx_msg.timestamp.tv_usec =
+          BCI_TIMESTAMP_RES * can_readl(msg_addr + BCI_MSG_TIMESTAMP);
+      /*  BCI_TIMESTAMP_RES * le32_to_cpu(can_readl(msg_addr + BCI_MSG_TIMESTAMP)); */
 
       /* fill CAN message timestamp */
       /* can_filltimestamp(&obj->rx_msg.timestamp); */
@@ -650,7 +681,7 @@ void ipci165_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj)
         /* extended frame - 29 bit identifier */
         obj->rx_msg.flags |= MSG_EXT;
         /* the ID is stored in motorola format (big endian), left justified  */
-        /* obj->rx_msg.id = be32_to_cpu(readl(msg_addr + BCI_MSG_ID) >> 3); */
+        /* obj->rx_msg.id = be32_to_cpu(can_readl(msg_addr + BCI_MSG_ID) >> 3); */
         memcpy_fromio(&tmp32, msg_addr + BCI_MSG_ID, 4);
         obj->rx_msg.id = be32_to_cpu(tmp32 >> 3);
         if (len > 0)
@@ -659,7 +690,7 @@ void ipci165_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj)
       {
         /* standard frame - 11 bit identifier */
         /* the ID is stored in motorola format (big endian), left justified */
-        /* obj->rx_msg.id = be16_to_cpu(readw(msg_addr + BCI_MSG_ID) >> 5); */
+        /* obj->rx_msg.id = be16_to_cpu(can_readw(msg_addr + BCI_MSG_ID) >> 5); */
         memcpy_fromio(&tmp16, msg_addr + BCI_MSG_ID, 2);
         obj->rx_msg.id = be16_to_cpu(tmp16 >> 5);
         if (len > 0)
@@ -670,11 +701,11 @@ void ipci165_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj)
     else
     {
       /* this is a status message */
-      status = readw(msg_addr + BCI_MSG_CAN_STATUS);
+      status = can_readw(msg_addr + BCI_MSG_CAN_STATUS);
       DEBUGMSG ("ipci165_irq_read_handler[%i]: CAN status=%04x\n",chip->chip_idx, status);
 
       /* wake up the reset thread if the CAN is in bus off */
-      if (status & BCI_CAN_STATUS_BUS_OFF) 
+      if (status & BCI_CAN_STATUS_BUS_OFF)
       {
         CANMSG ("BUS-OFF detected! Restarting\n");
         set_bit(CHIP_FLAG_BUS_OFF,&chip_data->flags);
@@ -693,10 +724,10 @@ void ipci165_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj)
     /* update pointer */
     queue->idx = (queue->idx + 1) % BCI_QUEUE_SIZE;
     /* release the buffer */
-    writeb(BCI_MSG_STATUS_FREE, msg_addr + BCI_MSG_STATUS);
+    can_writeb(BCI_MSG_STATUS_FREE, msg_addr + BCI_MSG_STATUS);
     msg_addr = queue_addr + queue->idx * BCI_MSG_SIZE;
 
-  } while (readb(msg_addr + BCI_MSG_STATUS) == BCI_MSG_STATUS_FULL);
+  } while (can_readb(msg_addr + BCI_MSG_STATUS) == BCI_MSG_STATUS_FULL);
 
 }
 
@@ -713,8 +744,8 @@ void ipci165_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
 {
   struct ipci165_chip_t *chip_data = ((struct ipci165_chip_t *)chip->chip_data);
   struct bci_queue_t *queue      = &chip_data->tx_queue;
-  unsigned long       queue_addr = queue->addr;
-  unsigned long       msg_addr   = queue_addr + queue->idx * BCI_MSG_SIZE;
+  can_ioptr_t         queue_addr = queue->addr;
+  can_ioptr_t         msg_addr   = queue_addr + queue->idx * BCI_MSG_SIZE;
   struct canque_slot_t *tx_slot;
 
   int len;
@@ -727,7 +758,7 @@ void ipci165_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
   while ((canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot) >=0))
   {
     if (test_bit(CHIP_FLAG_RESET,&chip_data->flags) ||
-        (readb(msg_addr + BCI_MSG_STATUS) == BCI_MSG_STATUS_FULL))
+        (can_readb(msg_addr + BCI_MSG_STATUS) == BCI_MSG_STATUS_FULL))
     {
       canque_again_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
 
@@ -757,9 +788,9 @@ void ipci165_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
         ((tx_slot->msg.flags & MSG_RTR) ? BCI_MSG_FRAME_RTR : 0) |
         ((tx_slot->msg.flags & MSG_EXT) ? BCI_MSG_FRAME_EXT : 0);
 
-    writeb(BCI_MSG_SIZE - 2, msg_addr + BCI_MSG_NUM);
-    writeb(BCI_MSG_TYPE_CAN, msg_addr + BCI_MSG_TYPE);
-    writeb(frame_info, msg_addr + BCI_MSG_FRAME);
+    can_writeb(BCI_MSG_SIZE - 2, msg_addr + BCI_MSG_NUM);
+    can_writeb(BCI_MSG_TYPE_CAN, msg_addr + BCI_MSG_TYPE);
+    can_writeb(frame_info, msg_addr + BCI_MSG_FRAME);
     if (frame_info & BCI_MSG_FRAME_EXT)
     {
       /* extended frame - 29 bit identifier */
@@ -783,7 +814,7 @@ void ipci165_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
     /* update pointer */
     queue->idx = (queue->idx + 1) % BCI_QUEUE_SIZE;
     /* mark the buffer as full */
-    writeb(BCI_MSG_STATUS_FULL, msg_addr + BCI_MSG_STATUS);
+    can_writeb(BCI_MSG_STATUS_FULL, msg_addr + BCI_MSG_STATUS);
     /* wake up the controller */
     ipci165_generate_irq(chip->hostdevice);
 
@@ -814,9 +845,9 @@ void ipci165_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
  */
 void ipci165_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj)
 {
-  while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)) 
+  while(!can_msgobj_test_and_set_fl(obj,TX_LOCK))
   {
-    if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) 
+    if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST))
     {
       ipci165_irq_write_handler(chip, obj);
     }
@@ -835,25 +866,25 @@ void ipci165_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj)
  * @chip: pointer to chip state structure
  *
  * The main purpose of this function is to perform all necessary channel
- * operations as a reaction on signalled interrupt. 
+ * operations as a reaction on signalled interrupt.
  * File: src/ipci165.c
  */
 void ipci165_irq_chip_handler(struct canchip_t *chip)
 {
   struct msgobj_t       *obj = chip->msgobj[0];
   struct ipci165_chip_t *chip_data = chip->chip_data;
-  struct bci_queue_t    *queue; 
+  struct bci_queue_t    *queue;
 
   DEBUGMSG ("ipci165_irq_chip_handler[%i]\n",chip->chip_idx);
 
   /* check receive queue for messages */
   queue = &chip_data->rx_queue;
-  if (readb(queue->addr + queue->idx * BCI_MSG_SIZE + BCI_MSG_STATUS)
+  if (can_readb(queue->addr + queue->idx * BCI_MSG_SIZE + BCI_MSG_STATUS)
       == BCI_MSG_STATUS_FULL)
     ipci165_irq_read_handler(chip, obj);
 
   queue = &chip_data->tx_queue;
-/*  if (readb(queue->addr + queue->idx * BCI_MSG_SIZE + BCI_MSG_STATUS)
+/*  if (can_readb(queue->addr + queue->idx * BCI_MSG_SIZE + BCI_MSG_STATUS)
   == BCI_MSG_STATUS_FREE) */
   {
     can_msgobj_set_fl(obj,TX_REQUEST);
@@ -873,19 +904,19 @@ void ipci165_irq_chip_handler(struct canchip_t *chip)
  *     The CAN driver uses this pointer to store relationship of interrupt
  *     to chip state structure - @struct canchip_t
  * @regs: system dependent value pointing to registers stored in exception frame
- * 
+ *
  * The interrupt handler is activated when the ipci165 controller generates
  * an interrupt as a reaction an internal state change. The interrupt is
  * acknowledged and ipci165_irq_chip_handler is called for every channel.
  * File: src/ipci165.c
  */
-can_irqreturn_t ipci165_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+can_irqreturn_t ipci165_irq_handler(CAN_IRQ_HANDLER_ARGS(irq_number, dev_id))
 {
   int retval;
   struct candevice_t *candev = (struct candevice_t *)dev_id;
 
-  unsigned long crm_addr   = candev->io_addr;
-  unsigned long ucr1_addr  = crm_addr + CRM_UCR + 1;
+  can_ioptr_t crm_addr   = candev->aux_base_addr;
+  can_ioptr_t ucr1_addr  = crm_addr + CRM_UCR + 1;
   struct canchip_t *chip;
   unsigned char icr;
   int i;
@@ -893,15 +924,15 @@ can_irqreturn_t ipci165_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
   /* DEBUGMSG ("ipci165_irq_handler\n"); */
 
   /* read interrupt control register (byte 0) */
-  icr = readb(crm_addr + CRM_ICR);
+  icr = can_readb(crm_addr + CRM_ICR);
 
   if ((icr & 0x44) == 0x44)
   {
     DEBUGMSG ("ipci165_irq_handler: pending interrupt\n");
 
     /* confirm pending interrupt */
-    writeb(readb(ucr1_addr) | 0x01,  ucr1_addr);
-    writeb(readb(ucr1_addr) & ~0x01, ucr1_addr);
+    can_writeb(can_readb(ucr1_addr) | 0x01,  ucr1_addr);
+    can_writeb(can_readb(ucr1_addr) & ~0x01, ucr1_addr);
 
     /* call interrupt handler for every channel */
     for (i=0 ; i < candev->nr_all_chips ; i++)
@@ -967,6 +998,32 @@ void ipci165_do_tx_timeout(unsigned long data)
   DEBUGMSG ("ipci165_do_tx_timeout: finished\n");
 }
 
+/**
+ * ipci165_attach_to_chip: - attaches to the chip, setups registers and state
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/ipci165.c
+ */
+int ipci165_attach_to_chip(struct canchip_t *chip)
+{
+  return 0;
+}
+
+/**
+ * ipci165_release_chip: - called before chip structure removal if %CHIP_ATTACHED is set
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/ipci165.c
+ */
+int ipci165_release_chip(struct canchip_t *chip)
+{
+  ipci165_stop_chip(chip);
+  /* disable interrupts in the hardware, etc. */
+  return 0;
+}
+
 /* * * iPC-I 165/PCI Board Functionality * * */
 
 /**
@@ -979,9 +1036,9 @@ void ipci165_do_tx_timeout(unsigned long data)
  */
 int ipci165_request_io(struct candevice_t *candev)
 {
-  unsigned long dpram_addr;
-  unsigned long crm_addr;
-  unsigned long fix_addr;
+  unsigned long dpram_addr; /* physical address before remap for this function */
+  unsigned long crm_addr;   /* physical address before remap for this function */
+  unsigned long fix_addr;   /* physical address before remap for this function */
   int i,j;
 
   DEBUGMSG ("ipci165_request_io\n");
@@ -1003,18 +1060,18 @@ int ipci165_request_io(struct candevice_t *candev)
     {
       CANMSG ("This card was not fixed!\n");
 
-      if (candev->io_addr == 0)
+      if (candev->aux_base_addr == NULL)
       {
         CANMSG ("You have to specify IO address parameter!\n");
         return -EINVAL;
       }
       CANMSG ("Using specified IO address value for the memory [0x%lx]\n",
-              candev->io_addr);
+              can_ioptr2ulong(candev->aux_base_addr));
     }
     else
     {
       CANMSG ("Fixed card. Using of 3 region [0x%lx]\n", fix_addr);
-      candev->io_addr = fix_addr;
+      candev->aux_base_addr = fix_addr;
     }
 
     pci_write_config_dword (candev->sysdevptr.pcidev,
@@ -1032,17 +1089,16 @@ int ipci165_request_io(struct candevice_t *candev)
   {
 #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
 
-      if ((candev->dev_base_addr = (long) ioremap(dpram_addr, 
+      if ((candev->dev_base_addr = ioremap(dpram_addr,
            pci_resource_len(candev->sysdevptr.pcidev,2))))
       {
         DEBUGMSG ("ipci165_request_io: dpram remapped to 0x%lx\n", candev->dev_base_addr);
 
-        if ((candev->io_addr = (long) ioremap(crm_addr, 
+        if ((candev->aux_base_addr = ioremap(crm_addr,
              pci_resource_len(candev->sysdevptr.pcidev,0))))
         {
-          DEBUGMSG ("ipci165_request_io: crm remapped to 0x%lx\n", candev->io_addr);
+          DEBUGMSG ("ipci165_request_io: crm remapped to 0x%lx\n", can_ioptr2ulong(candev->aux_base_addr));
           /* all resources has been allocated */
-          candev->res_addr=candev->io_addr;
 
           /* Because of my mapping, I cannot use the
              can_base_addr_fixup(candev, remap_addr) to remap the addresses */
@@ -1056,10 +1112,10 @@ int ipci165_request_io(struct candevice_t *candev)
           return 0;
 
         } else CANMSG("Unable to remap memory at: 0x%lx\n", crm_addr);
-        iounmap((void*)candev->io_addr);
+        iounmap(candev->aux_base_addr);
 
       } else CANMSG("Unable to remap memory at: 0x%lx\n", dpram_addr);
-      iounmap((void*)candev->dev_base_addr);
+      iounmap(candev->dev_base_addr);
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
       pci_release_region(candev->sysdevptr.pcidev, 0);
@@ -1087,7 +1143,7 @@ int ipci165_release_io(struct candevice_t *candev)
 {
   struct ipci165_chip_t *chip_data;
   int i;
-  
+
   /* disable irq on HW */
   ipci165_disconnect_irq(candev);
 
@@ -1100,8 +1156,8 @@ int ipci165_release_io(struct candevice_t *candev)
   }
 #endif
 
-  iounmap((void*)candev->io_addr);
-  iounmap((void*)candev->dev_base_addr);
+  iounmap(candev->aux_base_addr);
+  iounmap(candev->dev_base_addr);
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
   pci_release_region(candev->sysdevptr.pcidev, 2);
@@ -1122,7 +1178,7 @@ int ipci165_release_io(struct candevice_t *candev)
  */
 int ipci165_download_fw(struct candevice_t *candev)
 {
-  unsigned long dpram_addr = candev->dev_base_addr;
+  can_ioptr_t dpram_addr = candev->dev_base_addr;
   char board_name[BOARD_NAME_LEN+1];
   char hw_version[HW_VERSION_LEN+1];
   char mode[MODE_LEN+1];
@@ -1132,7 +1188,7 @@ int ipci165_download_fw(struct candevice_t *candev)
 
   DEBUGMSG ("ipci165_download_fw\n");
 
-  /* read name and version */  
+  /* read name and version */
   memcpy_fromio (board_name, dpram_addr + BOARD_NAME_OFS, BOARD_NAME_LEN);
   board_name[BOARD_NAME_LEN] = 0;
 
@@ -1163,13 +1219,13 @@ int ipci165_download_fw(struct candevice_t *candev)
   while (fwArray->len)
   {
     /* fill buffer */
-    writeb(LD_CMD_DOWNLOAD, dpram_addr + OF_LD_CMD);
-    writeb(fwArray->len, dpram_addr + OF_LD_NUM);
-    writeb(0, dpram_addr + OF_LD_NUM + 1);
+    can_writeb(LD_CMD_DOWNLOAD, dpram_addr + OF_LD_CMD);
+    can_writeb(fwArray->len, dpram_addr + OF_LD_NUM);
+    can_writeb(0, dpram_addr + OF_LD_NUM + 1);
 
-    writel(fwArray->addr, dpram_addr + OF_LD_ADDRESS);
-    /*    writel already performes the cpu_to_le32 conversion by itself   */
-    /*    writel(cpu_to_le32(fwArray->addr), dpram_addr + OF_LD_ADDRESS); */
+    can_writel(fwArray->addr, dpram_addr + OF_LD_ADDRESS);
+    /*    can_writel already performes the cpu_to_le32 conversion by itself   */
+    /*    can_writel(cpu_to_le32(fwArray->addr), dpram_addr + OF_LD_ADDRESS); */
 
     memcpy_toio(dpram_addr + OF_LD_DATA, fwArray->a_data, fwArray->len);
 
@@ -1177,14 +1233,14 @@ int ipci165_download_fw(struct candevice_t *candev)
     dump_mem((void *)(dpram_addr + OF_LD_SYNC), fwArray->len + 8);
 #endif
     /* buffer is prepared, set flag for loader */
-    writeb(1, dpram_addr + OF_LD_SYNC);
+    can_writeb(1, dpram_addr + OF_LD_SYNC);
 
     /* update pointer */
     fwArray++;
 
     /* wait for the loader */
     attempt = 1000;
-    while (readb(dpram_addr + OF_LD_SYNC) != 0)
+    while (can_readb(dpram_addr + OF_LD_SYNC) != 0)
     {
       udelay(100);
       if (--attempt == 0)
@@ -1198,8 +1254,8 @@ int ipci165_download_fw(struct candevice_t *candev)
   CANMSG ("Firmware downladed successfully\n");
 
   /* start the FW */
-  writeb(LD_CMD_START_FW, dpram_addr + OF_LD_CMD);
-  writeb(1, dpram_addr + OF_LD_SYNC);
+  can_writeb(LD_CMD_START_FW, dpram_addr + OF_LD_CMD);
+  can_writeb(1, dpram_addr + OF_LD_SYNC);
   ipci165_delay (500);
 
   return 0;
@@ -1214,7 +1270,7 @@ int ipci165_download_fw(struct candevice_t *candev)
  */
 int ipci165_reset(struct candevice_t *candev)
 {
-  unsigned long crm_addr = candev->io_addr;
+  can_ioptr_t crm_addr = candev->aux_base_addr;
   unsigned long test_data;
   char buffer[BCI_CMD_MAX_LEN];
   int i, size, chips;
@@ -1225,10 +1281,10 @@ int ipci165_reset(struct candevice_t *candev)
   DEBUGMSG ("ipci165_reset: hardware reset\n");
 
   /* reset the HW */
-  ucr = readb(crm_addr + CRM_UCR + 3);
-  writeb(ucr | 0x40, crm_addr + CRM_UCR + 3);
+  ucr = can_readb(crm_addr + CRM_UCR + 3);
+  can_writeb(ucr | 0x40, crm_addr + CRM_UCR + 3);
   udelay(100);
-  writeb(ucr & ~0x40, crm_addr + CRM_UCR + 3);
+  can_writeb(ucr & ~0x40, crm_addr + CRM_UCR + 3);
 
   /* wait a little bit */
   ipci165_delay(200);
@@ -1302,7 +1358,7 @@ int ipci165_reset(struct candevice_t *candev)
     candev->nr_all_chips = chips;
     canchip_done(candev->chip[1]);
 
-  } else CANMSG ("Chip 2 Type: %s\n",buffer+OF_BOARD_INFO_CHIP2_TYPE); 
+  } else CANMSG ("Chip 2 Type: %s\n",buffer+OF_BOARD_INFO_CHIP2_TYPE);
 
   /* start kernel threads */
   for (i = 0 ; i < chips ; i++)
@@ -1327,21 +1383,20 @@ int ipci165_reset(struct candevice_t *candev)
 int ipci165_init_hw_data(struct candevice_t *candev)
 {
   struct pci_dev *pcidev = NULL;
-  unsigned short SubsystemID;
 
   DEBUGMSG ("ipci165_init_hw_data\n");
 
   /* find iPC-I 165 on PCI bus */
   do
   {
-    pcidev = pci_find_device(IPCI165_VENDOR_ID, IPCI165_DEVICE_ID, pcidev);
-    if(pcidev == NULL) return -ENODEV;
+    pcidev = can_pci_get_device(IPCI165_VENDOR_ID, IPCI165_DEVICE_ID, pcidev);
+    if(pcidev == NULL)
+      return -ENODEV;
 
     /* check subvendor ID */
-    pci_read_config_word (pcidev, PCI_SUBSYSTEM_ID, &SubsystemID);
-    if ((SubsystemID != IPCI165_SUBSYSTEM_ID) &&
-        (SubsystemID != CP350_SUBSYSTEM_ID))
-      break;
+    if ((pcidev->subsystem_vendor != IPCI165_SUBSYSTEM_ID) &&
+        (pcidev->subsystem_vendor != CP350_SUBSYSTEM_ID))
+      continue;
   }
   while(can_check_dev_taken(pcidev));
 
@@ -1349,6 +1404,7 @@ int ipci165_init_hw_data(struct candevice_t *candev)
   if (pci_enable_device (pcidev))
   {
     CANMSG ("Cannot enable PCI device\n");
+    can_pci_dev_put(pcidev);
     return -EIO;
   }
 
@@ -1359,14 +1415,20 @@ int ipci165_init_hw_data(struct candevice_t *candev)
   /* we do not know yet, whether our HW has one or two chan chips. Let's
      prepare configuration for maximal configuration = 2. This will be
      corrected later on */
-  candev->nr_all_chips=2; 
+  candev->nr_all_chips=2;
   candev->flags |= CANDEV_PROGRAMMABLE_IRQ*0;
   /* initialize device spinlock */
-  can_spin_lock_init(candev->device_lock);
+  can_spin_lock_init(&candev->device_lock);
 
   return 0;
 }
 
+void ipci165_done_hw_data(struct candevice_t *candev)
+{
+  struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+  can_pci_dev_put(pcidev);
+}
+
 #define CHIP_TYPE "ipci165"
 
 /**
@@ -1419,6 +1481,8 @@ int ipci165_init_chip_data(struct candevice_t *candev, int chipnr)
   chip->chip_data = chip_data;
 
   CANMSG("initializing ipci165 chip operations\n");
+  chip->chipspecops->attach_to_chip=ipci165_attach_to_chip;
+  chip->chipspecops->release_chip=ipci165_release_chip;
   chip->chipspecops->chip_config=ipci165_chip_config;
   chip->chipspecops->baud_rate=ipci165_baud_rate;
   chip->chipspecops->set_btregs=ipci165_set_btregs;
@@ -1455,9 +1519,9 @@ int ipci165_init_chip_data(struct candevice_t *candev, int chipnr)
 int ipci165_init_obj_data(struct canchip_t *chip, int objnr)
 {
   struct msgobj_t *obj=chip->msgobj[objnr];
-  
+
   DEBUGMSG ("ipci165_init_obj_data\n");
-  
+
   obj->obj_base_addr = 0; /* not known yet */
   obj->tx_timeout.function = ipci165_do_tx_timeout;
   obj->tx_timeout.data = (unsigned long)obj;
@@ -1489,6 +1553,7 @@ int ipci165_register(struct hwspecops_t *hwspecops)
   hwspecops->release_io = ipci165_release_io;
   hwspecops->reset = ipci165_reset;
   hwspecops->init_hw_data = ipci165_init_hw_data;
+  hwspecops->done_hw_data = ipci165_done_hw_data;
   hwspecops->init_chip_data = ipci165_init_chip_data;
   hwspecops->init_obj_data = ipci165_init_obj_data;
   hwspecops->write_register = NULL;
@@ -1511,7 +1576,7 @@ void dump_mem(char *ptr, int size)
     strp = str;
     for (j = 0; j < to ; j++)
       strp += sprintf(strp, "%02x ",buf[j]);
-    for (; j < 16 ; j++) 
+    for (; j < 16 ; j++)
       strp += sprintf(strp, "   ");
     for (j = 0; j < to ; j++)
       *strp++= isprint(buf[j]) ? buf[j] : '.';