From 043f872725a79617ec651d16d940c647ea184afc Mon Sep 17 00:00:00 2001 From: ppisa Date: Sun, 21 Mar 2004 18:07:51 +0000 Subject: [PATCH] Intel 82527 chip now configures acceptance identifiers and mask 15 according to edges. --- lincan/include/can_queue.h | 2 + lincan/include/constants.h | 2 + lincan/include/main.h | 2 + lincan/src/can_queue.c | 41 ++++++++++++++ lincan/src/devcommon.c | 9 ++++ lincan/src/i82527.c | 106 ++++++++++++++++++++++++++++++------- lincan/src/setup.c | 1 + 7 files changed, 144 insertions(+), 19 deletions(-) diff --git a/lincan/include/can_queue.h b/lincan/include/can_queue.h index 709dda7..c3df3ad 100644 --- a/lincan/include/can_queue.h +++ b/lincan/include/can_queue.h @@ -527,6 +527,8 @@ int canqueue_ends_kill_inlist(struct canque_ends_t *qends, int send_rest); int canqueue_ends_kill_outlist(struct canque_ends_t *qends); +int canqueue_ends_filt_conjuction(struct canque_ends_t *qends, struct canfilt_t *filt); + /* edge reference and traversal functions */ void canque_edge_do_dead(struct canque_edge_t *edge, int dead_fl); diff --git a/lincan/include/constants.h b/lincan/include/constants.h index 81d39e1..e466e2d 100644 --- a/lincan/include/constants.h +++ b/lincan/include/constants.h @@ -47,12 +47,14 @@ #define MSGOBJ_TX_LOCK_b 2 #define MSGOBJ_IRQ_REQUEST_b 3 #define MSGOBJ_WORKER_WAKE_b 4 +#define MSGOBJ_FILTCH_REQUEST_b 5 #define MSGOBJ_OPENED (1<obj_flags) diff --git a/lincan/include/main.h b/lincan/include/main.h index f92d1c4..5ff9104 100644 --- a/lincan/include/main.h +++ b/lincan/include/main.h @@ -309,6 +309,7 @@ struct hwspecops_t { * @remote_request: configures message object and asks for RTR message * @check_tx_stat: checks state of transmission engine * @wakeup_tx: wakeup TX processing + * @set_filter: if * @enable_configuration: enable chip configuration mode * @disable_configuration: disable chip configuration mode * @set_btregs: configures bitrate registers @@ -336,6 +337,7 @@ struct chipspecops_t { int (*remote_request)(struct chip_t *chip, struct msgobj_t *obj); int (*check_tx_stat)(struct chip_t *chip); int (*wakeup_tx)(struct chip_t *chip, struct msgobj_t *obj); + int (*filtch_rq)(struct chip_t *chip, struct msgobj_t *obj); int (*enable_configuration)(struct chip_t *chip); int (*disable_configuration)(struct chip_t *chip); int (*set_btregs)(struct chip_t *chip, unsigned short btr0, diff --git a/lincan/src/can_queue.c b/lincan/src/can_queue.c index f061f4f..be65c55 100644 --- a/lincan/src/can_queue.c +++ b/lincan/src/can_queue.c @@ -636,4 +636,45 @@ int canqueue_ends_kill_outlist(struct canque_ends_t *qends) } +/** + * canqueue_ends_filt_conjuction - computes conjunction of incoming edges filters filters + * @qends: pointer to ends structure + * @qends: pointer the filter structure filled by computed filters conjunction + * + * Return Value: Number of incoming edges + */ +int canqueue_ends_filt_conjuction(struct canque_ends_t *qends, struct canfilt_t *filt) +{ + struct canque_edge_t *edge; + int cnt=0; + unsigned long filtid=0; + unsigned long filtmask=~0; + unsigned long local_only=canque_filtid2internal(0,MSG_LOCAL); + + canque_for_each_inedge(qends, edge){ + /* skip edges processing only local messages */ + if(edge->filtid & edge->filtmask & local_only) + continue; + + if(!cnt++) + filtid = edge->filtid; + else + filtmask &= ~(filtid ^ edge->filtid); + + filtmask &= edge->filtmask; + } + + filt->id = filtid & MSG_ID_MASK; + filt->mask = filtmask & MSG_ID_MASK; + filtid >>= 28; + filtmask >>= 28; + filt->flags = filtid & MSG_EXT; + if(filtmask & (MSG_EXT)) + filt->flags |= MSG_EXT_MASK; + if(filtid & (MSG_RTR<<1)) + filt->flags |= MSG_RTR<<1; + if(filtmask & (MSG_RTR<<1)) + filt->flags |= MSG_RTR_MASK; + return cnt; +} diff --git a/lincan/src/devcommon.c b/lincan/src/devcommon.c index e17a061..16d21db 100644 --- a/lincan/src/devcommon.c +++ b/lincan/src/devcommon.c @@ -62,6 +62,15 @@ void canqueue_notify_chip(struct canque_ends_t *qends, struct canque_edge_t *qed canque_edge_decref(qedge); break; case CANQUEUE_NOTIFY_ATTACH: + break; + case CANQUEUE_NOTIFY_FILTCH: + if(!chip->chipspecops->filtch_rq) + break; + #ifndef CAN_WITH_RTL + chip->chipspecops->filtch_rq(chip, obj); + #else /*CAN_WITH_RTL*/ + #endif /*CAN_WITH_RTL*/ + break; } } diff --git a/lincan/src/i82527.c b/lincan/src/i82527.c index 86e340d..68feef7 100644 --- a/lincan/src/i82527.c +++ b/lincan/src/i82527.c @@ -402,7 +402,8 @@ int i82527_stop_chip(struct chip_t *chip) return 0; } -inline void i82527_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) +static inline +void i82527_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) { int cmd; @@ -436,10 +437,12 @@ inline void i82527_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot); obj->tx_slot=NULL; return; - } + } + return; } -inline void i82527_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj, int objnum) +static inline +void i82527_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj, int objnum) { int i; unsigned long message_id; @@ -541,6 +544,66 @@ inline void i82527_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj, i i82527_irq_read_handler(chip, obj, message_id); */ + +static inline +void i82527_irq_update_filter(struct chip_t *chip, struct msgobj_t *obj) +{ + struct canfilt_t filt; + unsigned long id; + + if(canqueue_ends_filt_conjuction(obj->qends, &filt)) { + canobj_write_reg(chip,obj,(MVAL_RES|TXIE_RES|RXIE_RES|INTPD_RES),iMSGCTL0); + if(obj->object == 15) { + i82527_message15_mask(chip,filt.id,filt.mask); + } + if (filt.flags&MSG_EXT) { + id=filt.id<<3; + canobj_write_reg(chip,obj,id,iMSGID3); + canobj_write_reg(chip,obj,id>>8,iMSGID2); + canobj_write_reg(chip,obj,id>>16,iMSGID1); + canobj_write_reg(chip,obj,id>>24,iMSGID0); + canobj_write_reg(chip,obj,MCFG_XTD,iMSGCFG); + } + else { + id=filt.id<<5; + canobj_write_reg(chip,obj,id,iMSGID1); + canobj_write_reg(chip,obj,id>>8,iMSGID0); + canobj_write_reg(chip,obj,0x00,iMSGCFG); + } + + canobj_write_reg(chip,obj,(NEWD_RES|MLST_RES|TXRQ_RES|RMPD_RES), iMSGCTL1); + canobj_write_reg(chip,obj,(MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES),iMSGCTL0); + + CANMSG("i82527_irq_update_filter: obj at 0x%08lx\n",obj->obj_base_addr); + + } +} + + +void i82527_irq_sync_activities(struct chip_t *chip, struct msgobj_t *obj) +{ + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)) { + + if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) { + if(canobj_read_reg(chip,obj,iMSGCTL1)&TXRQ_RES) + i82527_irq_write_handler(chip, obj); + } + + if(!obj->tx_slot) { + if(can_msgobj_test_and_clear_fl(obj,FILTCH_REQUEST)) { + i82527_irq_update_filter(chip, obj); + } + } + + can_msgobj_clear_fl(obj,TX_LOCK); + if(can_msgobj_test_fl(obj,TX_REQUEST)) + continue; + if(can_msgobj_test_fl(obj,FILTCH_REQUEST) && !obj->tx_slot) + continue; + break; + } +} + can_irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { unsigned char msgcfg; @@ -583,15 +646,9 @@ can_irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs) msgcfg = canobj_read_reg(chip,obj,iMSGCFG); if (msgcfg & MCFG_DIR) { can_msgobj_set_fl(obj,TX_REQUEST); - while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){ - can_msgobj_clear_fl(obj,TX_REQUEST); - - if(canobj_read_reg(chip,obj,iMSGCTL1)&TXRQ_RES) - i82527_irq_write_handler(chip, obj); - - can_msgobj_clear_fl(obj,TX_LOCK); - if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; - } + + /* calls i82527_irq_write_handler synchronized with other invocations */ + i82527_irq_sync_activities(chip, obj); } else { @@ -629,18 +686,28 @@ int i82527_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) can_preempt_disable(); can_msgobj_set_fl(obj,TX_REQUEST); - while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){ - can_msgobj_clear_fl(obj,TX_REQUEST); - if(canobj_read_reg(chip,obj,iMSGCTL1)&TXRQ_RES) - i82527_irq_write_handler(chip, obj); + /* calls i82527_irq_write_handler synchronized with other invocations + from kernel and IRQ context */ + i82527_irq_sync_activities(chip, obj); + + can_preempt_enable(); + return 0; +} + +int i82527_filtch_rq(struct chip_t *chip, struct msgobj_t *obj) +{ + can_preempt_disable(); - can_msgobj_clear_fl(obj,TX_LOCK); - if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; - } + can_msgobj_set_fl(obj,FILTCH_REQUEST); + + /* setups filter synchronized with other invocations from kernel and IRQ context */ + i82527_irq_sync_activities(chip, obj); can_preempt_enable(); return 0; + + return 0; } int i82527_register(struct chipspecops_t *chipspecops) @@ -657,6 +724,7 @@ int i82527_register(struct chipspecops_t *chipspecops) chipspecops->send_msg = i82527_send_msg; chipspecops->check_tx_stat = i82527_check_tx_stat; chipspecops->wakeup_tx = i82527_wakeup_tx; + chipspecops->filtch_rq = i82527_filtch_rq; chipspecops->remote_request = i82527_remote_request; chipspecops->enable_configuration = i82527_enable_configuration; chipspecops->disable_configuration = i82527_disable_configuration; diff --git a/lincan/src/setup.c b/lincan/src/setup.c index 75ca0ef..6a59e2f 100644 --- a/lincan/src/setup.c +++ b/lincan/src/setup.c @@ -443,6 +443,7 @@ int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudr chip->chipspecops=can_checked_malloc(sizeof(struct chipspecops_t)); if (chip->chipspecops==NULL) return -ENOMEM; + memset(chip->chipspecops,0,sizeof(struct chipspecops_t)); chip->chip_idx=chipnr; chip->hostdevice=candev; -- 2.39.2