hcan2.c : some bug fixes, IRQ read optimalisation
authortermitt <termitt>
Sun, 27 Apr 2008 02:59:33 +0000 (02:59 +0000)
committertermitt <termitt>
Sun, 27 Apr 2008 02:59:33 +0000 (02:59 +0000)
open.c : pre_read_config is called once for each message object not only when configuring chip

lincan/src/hcan2.c
lincan/src/open.c

index a31490f..e960685 100644 (file)
@@ -311,18 +311,19 @@ int hcan2_standard_mask(struct canchip_t *chip, unsigned short code, unsigned sh
        else
            return -ENODEV;
 
-       chip->chip_data = (void*)0; /* reset mbox number */
+       chip->chip_data = (void*)0;     /* reset mbox number */
 
 
        ctrl0 = ((code & 0x07ff) << 4);
        lafm0 = ((mask & 0x07ff) << 4);
+       lafm0 |= 0x0003;                /* ignore Ext ID 17:16  */
        
        can_write_reg_w(chip, ctrl0, (int) obj->obj_base_addr + HCAN2_MB_CTRL0);
        can_write_reg_w(chip, 0x0000, (int) obj->obj_base_addr + HCAN2_MB_CTRL1);
        can_write_reg_w(chip, lafm0, (int) obj->obj_base_addr + HCAN2_MB_MASK);
        can_write_reg_w(chip, 0xffff, (int) obj->obj_base_addr + HCAN2_MB_MASK + 2);
 
-       DEBUGMSG("Set standard_mask [id:0x%04x, m:0x%04x]\n", code, mask);
+       DEBUGMSG("MB%02d: Set standard_mask [id:0x%04x, m:0x%04x]\n", obj_idx, code, lafm0);
        return 0;
 }
 
@@ -355,7 +356,7 @@ int hcan2_extended_mask(struct canchip_t *chip, unsigned long code, unsigned lon
        can_write_reg_w(chip, lafm0, (int) obj->obj_base_addr + HCAN2_MB_MASK);
        can_write_reg_w(chip, lafm1, (int) obj->obj_base_addr + HCAN2_MB_MASK + 2);
        
-       DEBUGMSG("Set extended_mask [id:0x%08x, m:0x%08x]\n", (uint32_t)code, (uint32_t)mask);
+       DEBUGMSG("MB%02d: Set extended_mask [id:0x%08x, m:0x%08x]\n", obj_idx, (uint32_t)code, (uint32_t)mask);
     
         return 0;
 }
@@ -454,25 +455,24 @@ int hcan2_irq_handler(int irq, struct canchip_t *chip)
                /* Received message */
                if (irq_reg & HCAN2_IRR_DFRI)
                {
-                       rxdf = (can_read_reg_w(chip, HCAN2_RXPR1) << 16) +
-                           can_read_reg_w(chip, HCAN2_RXPR0);
+                       rxdf = (can_read_reg_w(chip, HCAN2_RXPR1) << 16) +
+                               can_read_reg_w(chip, HCAN2_RXPR0);
 
-                       DEBUGMSG("Received message [0x%08x]\n", rxdf);
+                       while(rxdf) {
+                               DEBUGMSG("Received message [0x%08x]\n", rxdf);
 
-                       while (rxdf) {
                                /* find the message object */
-                               for (idx = 0; (idx < chip->max_objects) && !(rxdf & (1<<idx)); idx++) { }
-                               
-                               /* realy i got one? */
-                               if (idx < chip->max_objects) {
-                                       hcan2_irq_read_handler(chip, chip->msgobj[idx]);
-                               
-                                       /* clear RXPR flag for this msgobj */
-                                       can_write_reg_w(chip, (1 << (idx % 16)), HCAN2_RXPR0 - 2*(idx / 16));
-                                       
-                                       rxdf = (can_read_reg_w(chip, HCAN2_RXPR1) << 16) +
+                               for (idx = 0; (idx < chip->max_objects) && rxdf; idx++)
+                                       if ((rxdf & (1<<idx))) {
+                                               hcan2_irq_read_handler(chip, chip->msgobj[idx]);
+                                               /* RXPR flag for this msgobj is cleared during irq_read_handler*/
+                                               rxdf &= ~(1 << idx);
+                                       }
+
+
+                               DEBUGMSG("Before reset flags [0x%08x]\n", rxdf);
+                               rxdf = (can_read_reg_w(chip, HCAN2_RXPR1) << 16) +
                                        can_read_reg_w(chip, HCAN2_RXPR0);
-                               }
                        }
                }
 
@@ -695,22 +695,22 @@ void hcan2_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj)
        }
        else
            obj->rx_msg.id = (ctrl0 & HCAN2_MBCT0_STDID)>>4;
-           
+
 
        if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
        for (i = 0; i < len; i++)
        {
                /* rcanqueue_ends_filt_conjuctionead 16bit data - two data bytes*/
                data = can_read_reg_w(chip, (int) obj->obj_base_addr + HCAN2_MB_DATA1 + i);
-               obj->rx_msg.data[i] = (data & 0xff00) >> 8;
-               if (++i < len) obj->rx_msg.data[i] = data & 0x00ff;
+               obj->rx_msg.data[i] = (data & 0xff00) >> 8;             // one data byte
+               if (++i < len) obj->rx_msg.data[i] = data & 0x00ff;     // second data byte
        }
 
        /* Computes correct offset address of register from MSGBOX_IDX and RTR flag
         * result is one of these:
         * HCAN2_RXPR1, HCAN2_RXPR0, HCAN2_RFPR1, HCAN2_RFPR0
         */
-       flag_addr = ((ctrl0 & HCAN2_MBCT0_RTR) << 3) + HCAN2_RXPR0 - ((obj->object - 1) / 16) * 2;
+       flag_addr = HCAN2_RXPR0 - (int)((obj->object - 1) / 16) * 2;
                
        /* Reset flag by writing 1 to its position */
        can_write_reg_w(chip, (1 << ((obj->object - 1) % 16)), flag_addr);
index 45406fc..76fb9ee 100644 (file)
@@ -24,6 +24,7 @@ int can_open(struct inode *inode, struct file *file)
        struct canque_ends_t *qends;
        struct canque_edge_t *edge;
        can_spin_irqflags_t iflags;
+       char openflag;          // Martin Petera: Object already opened
 
        if ( ((obj=objects_p[MINOR_NR]) == NULL) || 
                        ((chip=objects_p[MINOR_NR]->hostchip) == NULL) ) {
@@ -33,6 +34,7 @@ int can_open(struct inode *inode, struct file *file)
 
        atomic_inc(&obj->obj_used);
        DEBUGMSG("Device %d opened %d times.\n", MINOR_NR, atomic_read(&obj->obj_used));
+       openflag = can_msgobj_test_fl(obj,OPENED);      // Martin Petera: store previous status
        can_msgobj_set_fl(obj,OPENED);
 
        if (chip->flags & CHIP_CONFIGURED) 
@@ -42,11 +44,19 @@ int can_open(struct inode *inode, struct file *file)
                        CANMSG("Error configuring chip.\n");
                else
                        chip->flags |= CHIP_CONFIGURED; 
+       } /* End of chip configuration */
+
 
+       /* Martin Petera: Fix for HCAN2
+        * pre_read was called only once -> Opening second MSG object from userspace
+        * didn't call function to configure MSG object for receive.
+        * FIX: Call pre_read once for each MSG object
+        **/
+       if (!openflag) {
                if (chip->chipspecops->pre_read_config(chip,obj)<0)
                        CANMSG("Error initializing chip for receiving\n");
+       }
 
-       } /* End of chip configuration */
 
        canuser = (struct canuser_t *)kmalloc(sizeof(struct canuser_t), GFP_KERNEL);
        if(canuser == NULL) goto no_canuser;