]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/unican.c
Changes, which should enable to handle more VME Unican cards under RT-Linux.
[lincan.git] / lincan / src / unican.c
index 66466d653ba161700f6180516562473cfaa0b682..f72bacc169eca68433c8f865ae82fa69df807abc 100644 (file)
@@ -3,7 +3,7 @@
  * Written for new CAN driver version by Pavel Pisa - OCERA team member
  * email:pisa@cmp.felk.cvut.cz
  * This software is released under the GPL-License.
- * Version lincan-0.2  9 Jul 2003
+ * Version lincan-0.3  17 Jun 2004
  */ 
 
 #include "../include/can.h"
@@ -43,12 +43,12 @@ long unican_bus_latency(struct msgobj_t *obj)
 
 /* * * unican Chip Functionality * * */
 
-int unican_enable_configuration(struct chip_t *chip)
+int unican_enable_configuration(struct canchip_t *chip)
 {
        return 0;
 }
 
-int unican_disable_configuration(struct chip_t *chip)
+int unican_disable_configuration(struct canchip_t *chip)
 {
        return 0;
 }
@@ -60,7 +60,7 @@ int unican_disable_configuration(struct chip_t *chip)
  * Return Value: negative value reports error.
  * File: src/unican.c
  */
-int unican_chip_config(struct chip_t *chip)
+int unican_chip_config(struct canchip_t *chip)
 {
        int ret;
        sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data;
@@ -125,7 +125,7 @@ int unican_chip_config(struct chip_t *chip)
  * Return Value: negative value reports error.
  * File: src/unican.c
  */
-int unican_extended_mask(struct chip_t *chip, unsigned long code, unsigned  long mask)
+int unican_extended_mask(struct canchip_t *chip, unsigned long code, unsigned  long mask)
 {
        return 0;
 }
@@ -142,7 +142,7 @@ int unican_extended_mask(struct chip_t *chip, unsigned long code, unsigned  long
  * Return Value: negative value reports error.
  * File: src/unican.c
  */
-int unican_baud_rate(struct chip_t *chip, int rate, int clock, int sjw,
+int unican_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw,
                                                        int sampl_pt, int flags)
 {
        int ret;
@@ -184,7 +184,7 @@ int unican_baud_rate(struct chip_t *chip, int rate, int clock, int sjw,
  *
  * File: src/unican.c
  */
-void unican_read(struct chip_t *chip, struct msgobj_t *obj) {
+void unican_read(struct canchip_t *chip, struct msgobj_t *obj) {
        sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data;
        __u16 *ptr16;
        __u16 u;
@@ -259,7 +259,7 @@ void unican_read(struct chip_t *chip, struct msgobj_t *obj) {
  *     Positive value indicates immediate reception of message.
  * File: src/unican.c
  */
-int unican_pre_read_config(struct chip_t *chip, struct msgobj_t *obj)
+int unican_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj)
 {
        return 0;
 }
@@ -274,7 +274,7 @@ int unican_pre_read_config(struct chip_t *chip, struct msgobj_t *obj)
  * Return Value: negative value reports error.
  * File: src/unican.c
  */
-int unican_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, 
+int unican_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj, 
                                                        struct canmsg_t *msg)
 {
        return 0;
@@ -291,7 +291,7 @@ int unican_pre_write_config(struct chip_t *chip, struct msgobj_t *obj,
  * Return Value: negative value reports error.
  * File: src/unican.c
  */
-int unican_send_msg(struct chip_t *chip, struct msgobj_t *obj, 
+int unican_send_msg(struct canchip_t *chip, struct msgobj_t *obj, 
                                                        struct canmsg_t *msg)
 {
        return 0;
@@ -306,7 +306,7 @@ int unican_send_msg(struct chip_t *chip, struct msgobj_t *obj,
  *     Zero value indicates finishing of all issued transmission requests.
  * File: src/unican.c
  */
-int unican_check_tx_stat(struct chip_t *chip)
+int unican_check_tx_stat(struct canchip_t *chip)
 {
        return 0;
 }
@@ -320,7 +320,7 @@ int unican_check_tx_stat(struct chip_t *chip)
  * Return Value: negative value reports error.
  * File: src/unican.c
  */
-int unican_set_btregs(struct chip_t *chip, unsigned short btr0, 
+int unican_set_btregs(struct canchip_t *chip, unsigned short btr0, 
                                                        unsigned short btr1)
 {
        int ret;
@@ -342,7 +342,7 @@ int unican_set_btregs(struct chip_t *chip, unsigned short btr0,
  * Return Value: negative value reports error.
  * File: src/unican.c
  */
-int unican_start_chip(struct chip_t *chip)
+int unican_start_chip(struct canchip_t *chip)
 {
        return 0;
 }
@@ -354,7 +354,7 @@ int unican_start_chip(struct chip_t *chip)
  * Return Value: negative value reports error.
  * File: src/unican.c
  */
-int unican_stop_chip(struct chip_t *chip)
+int unican_stop_chip(struct canchip_t *chip)
 {
        return 0;
 }
@@ -368,7 +368,7 @@ int unican_stop_chip(struct chip_t *chip)
  * Return Value: negative value reports error.
  * File: src/unican.c
  */
-int unican_remote_request(struct chip_t *chip, struct msgobj_t *obj)
+int unican_remote_request(struct canchip_t *chip, struct msgobj_t *obj)
 {
        CANMSG("unican_remote_request not implemented\n");
        return -ENOSYS;
@@ -383,7 +383,7 @@ int unican_remote_request(struct chip_t *chip, struct msgobj_t *obj)
  * Return Value: negative value reports error.
  * File: src/unican.c
  */
-int unican_standard_mask(struct chip_t *chip, unsigned short code,
+int unican_standard_mask(struct canchip_t *chip, unsigned short code,
                unsigned short mask)
 {
        CANMSG("unican_standard_mask not implemented\n");
@@ -397,7 +397,7 @@ int unican_standard_mask(struct chip_t *chip, unsigned short code,
  * Return Value: negative value reports error.
  * File: src/unican.c
  */
-int unican_clear_objects(struct chip_t *chip)
+int unican_clear_objects(struct canchip_t *chip)
 {
        CANMSG("unican_clear_objects not implemented\n");
        return -ENOSYS;
@@ -411,7 +411,7 @@ int unican_clear_objects(struct chip_t *chip)
  * Return Value: negative value reports error.
  * File: src/unican.c
  */
-int unican_config_irqs(struct chip_t *chip, short irqs)
+int unican_config_irqs(struct canchip_t *chip, short irqs)
 {
 
        CANMSG("unican_config_irqs not implemented\n");
@@ -429,7 +429,7 @@ int unican_config_irqs(struct chip_t *chip, short irqs)
  * unican_irq_write_handler() for transmit events.
  * File: src/unican.c
  */
-void unican_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj)
+void unican_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
 {
        int cmd;
        sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data;
@@ -531,7 +531,7 @@ void unican_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj)
 
 }
 
-void unican_irq_sync_activities(struct chip_t *chip, struct msgobj_t *obj)
+void unican_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj)
 {
        while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)) {
 
@@ -558,10 +558,7 @@ void unican_irq_sync_activities(struct chip_t *chip, struct msgobj_t *obj)
 /**
  * unican_irq_handler: - interrupt service routine
  * @irq: interrupt vector number, this value is system specific
- * @dev_id: driver private pointer registered at time of request_irq() call.
- *     The CAN driver uses this pointer to store relationship of interrupt
- *     to chip state structure - @struct chip_t
- * @regs: system dependent value pointing to registers stored in exception frame
+ * @chip: pointer to chip state structure
  * 
  * Interrupt handler is activated when state of CAN controller chip changes,
  * there is message to be read or there is more space for new messages or
@@ -570,9 +567,8 @@ void unican_irq_sync_activities(struct chip_t *chip, struct msgobj_t *obj)
  * message queues.
  * File: src/unican.c
  */
-can_irqreturn_t unican_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+int unican_irq_handler(int irq, struct canchip_t *chip)
 {
-       struct chip_t *chip=(struct chip_t *)dev_id;
        sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data;
        struct msgobj_t *obj=chip->msgobj[0];
        __u16 status;
@@ -580,11 +576,16 @@ can_irqreturn_t unican_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
 
        if(!(chip->flags&CHIP_CONFIGURED)) {
                CANMSG("unican_irq_handler: called for non-configured device\n");
-               return CAN_IRQ_NONE;
+               return CANCHIP_IRQ_NONE;
        }
 
-       if (cl2_get_status(chipext, &status) == CL2_NO_REQUEST)
-               return CAN_IRQ_NONE;
+       if (cl2_get_status(chipext, &status) == CL2_NO_REQUEST) {
+               /* Reenable interrupts generation, this has to be even there, 
+                * because irq_accept disables interrupts
+                */
+               cl2_gen_interrupt(chipext);
+               return CANCHIP_IRQ_NONE;
+       }
 
        cl2_clear_interrupt(chipext);
 
@@ -607,12 +608,31 @@ can_irqreturn_t unican_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
                unican_read(chip, obj);
        }
 
+       /* Reenable interrupts generation */
        cl2_gen_interrupt(chipext);
 
-       return CAN_IRQ_HANDLED;
+       return CANCHIP_IRQ_HANDLED;
 }
 
 
+/**
+ * unican_irq_accept: - fast irq accept routine, blocks further interrupts
+ * @irq: interrupt vector number, this value is system specific
+ * @chip: pointer to chip state structure
+ * 
+ * This routine only accepts interrupt reception and stops further
+ * incoming interrupts, but does not handle situation causing interrupt.
+ * File: src/unican.c
+ */
+int unican_irq_accept(int irq, struct canchip_t *chip)
+{
+       sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data;
+
+       cl2_clear_interrupt(chipext);
+
+       return CANCHIP_IRQ_ACCEPTED;
+}
+
 /*void unican_do_tx_timeout(unsigned long data)
 {
        struct msgobj_t *obj=(struct msgobj_t *)data;
@@ -627,7 +647,7 @@ can_irqreturn_t unican_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
  * Return Value: negative value reports error.
  * File: src/unican.c
  */
-int unican_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj)
+int unican_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
 {
        can_preempt_disable();
 
@@ -698,7 +718,7 @@ int unican_reset(struct candevice_t *candev)
 {
        int ret;
        int i;
-       struct chip_t *chip = candev->chip[0];
+       struct canchip_t *chip = candev->chip[0];
        sCAN_CARD *chipext;
        
 
@@ -759,8 +779,6 @@ int unican_init_hw_data(struct candevice_t *candev)
        return 0;
 }
 
-#define CHIP_TYPE "unican"
-
 /**
  * unican_init_chip_data - Initialize chips
  * @candev: Pointer to candevice/board structure
@@ -771,8 +789,8 @@ int unican_init_hw_data(struct candevice_t *candev)
  */
 int unican_init_chip_data(struct candevice_t *candev, int chipnr)
 {
-       struct chip_t *chip = candev->chip[chipnr];
-       chip->chip_type = CHIP_TYPE;
+       struct canchip_t *chip = candev->chip[chipnr];
+       chip->chip_type = "unican";
        chip->chip_base_addr = 0;
        chip->clock = 10000000;
        chip->int_clk_reg = 0x0;
@@ -800,6 +818,7 @@ int unican_init_chip_data(struct candevice_t *candev, int chipnr)
        chip->chipspecops->start_chip=unican_start_chip;
        chip->chipspecops->stop_chip=unican_stop_chip;
        chip->chipspecops->irq_handler=unican_irq_handler;
+       chip->chipspecops->irq_accept=unican_irq_accept;
 
        return 0;
 }
@@ -812,7 +831,7 @@ int unican_init_chip_data(struct candevice_t *candev, int chipnr)
  * Return Value: The function always returns zero
  * File: src/unican.c
  */
-int unican_init_obj_data(struct chip_t *chip, int objnr)
+int unican_init_obj_data(struct canchip_t *chip, int objnr)
 {
        struct msgobj_t *obj=chip->msgobj[objnr];
        obj->obj_base_addr=chip->chip_base_addr;
@@ -854,6 +873,8 @@ int unican_register(struct hwspecops_t *hwspecops)
 
 int unican_pci_request_io(struct candevice_t *candev)
 {
+        unsigned long remap_addr;
+
     #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
        if(pci_request_region(candev->sysdevptr.pcidev, 0, "unican_pci") != 0){
                CANMSG("Request of Unican PCI range failed\n");
@@ -866,12 +887,32 @@ int unican_pci_request_io(struct candevice_t *candev)
        }
     #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
 
+       candev->dev_base_addr=pci_resource_start(candev->sysdevptr.pcidev,0);
+       candev->io_addr=candev->dev_base_addr;
+       candev->res_addr=candev->dev_base_addr;
+
+       if ( !( remap_addr = (long) ioremap( candev->io_addr, IO_RANGE ) ) ) {
+               CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
+           #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
+               pci_release_region(candev->sysdevptr.pcidev, 0);
+           #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+               pci_release_regions(candev->sysdevptr.pcidev);
+           #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+               return -ENODEV;
+       
+       }
+       can_base_addr_fixup(candev, remap_addr);
+       DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
+       DEBUGMSG("VMA: dev_base_addr: 0x%lx chip_base_addr: 0x%lx\n", 
+               candev->dev_base_addr, candev->chip[0]->chip_base_addr);
+
        return 0;
 }
 
 
 int unican_pci_release_io(struct candevice_t *candev)
 {
+       iounmap((void*)candev->dev_base_addr);
     #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
        pci_release_region(candev->sysdevptr.pcidev, 0);
     #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
@@ -900,7 +941,7 @@ int unican_pci_init_hw_data(struct candevice_t *candev)
                printk(KERN_CRIT "Unican PCI region 0 is not MEM\n");
                return -EIO;
        }
-       candev->dev_base_addr=pci_resource_start(pcidev,0); /*S5920*/
+       candev->dev_base_addr=pci_resource_start(pcidev,0);
        candev->io_addr=candev->dev_base_addr;
        candev->res_addr=candev->dev_base_addr;