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;
}
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;
}
/* 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);
- }
}
}
}
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);
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) ) {
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)
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;