* Version lincan-0.2 9 Jul 2003
*/
-#include <linux/autoconf.h>
-
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <asm/irq.h>
-
+#include "../include/can.h"
+#include "../include/can_sysdep.h"
#include "../include/main.h"
#include "../include/sja1000p.h"
+/**
+ * sja1000p_enable_configuration - enable chip configuration mode
+ * @chip: pointer to chip state structure
+ */
int sja1000p_enable_configuration(struct chip_t *chip)
{
int i=0;
enum sja1000_PeliCAN_MOD flags;
- disable_irq(chip->chip_irq);
+ can_disable_irq(chip->chip_irq);
flags=can_read_reg(chip,SJAMOD);
}
if (i>=10) {
CANMSG("Reset error\n");
- enable_irq(chip->chip_irq);
+ can_enable_irq(chip->chip_irq);
return -ENODEV;
}
return 0;
}
+/**
+ * sja1000p_disable_configuration - disable chip configuration mode
+ * @chip: pointer to chip state structure
+ */
int sja1000p_disable_configuration(struct chip_t *chip)
{
int i=0;
return -ENODEV;
}
- enable_irq(chip->chip_irq);
+ can_enable_irq(chip->chip_irq);
return 0;
}
*/
int sja1000p_chip_config(struct chip_t *chip)
{
+ int i;
+ unsigned char n, r;
+
if (sja1000p_enable_configuration(chip))
return -ENODEV;
can_write_reg(chip,CDR_PELICAN|chip->sja_cdr_reg,SJACDR);
/* Set driver output configuration */
can_write_reg(chip,chip->sja_ocr_reg,SJAOCR);
+
+ /* Simple check for chip presence */
+ for (i=0, n=0x5a; i<8; i++, n+=0xf) {
+ can_write_reg(chip,n,SJAACR0+i);
+ }
+ for (i=0, n=0x5a; i<8; i++, n+=0xf) {
+ r = n^can_read_reg(chip,SJAACR0+i);
+ if (r) {
+ CANMSG("sja1000p_chip_config: chip connection broken,"
+ " readback differ 0x%02x\n", r);
+ return -ENODEV;
+ }
+ }
+
if (sja1000p_extended_mask(chip,0x00000000, 0xffffffff))
return -ENODEV;
- if (!baudrate)
- baudrate=1000;
- if (sja1000p_baud_rate(chip,1000*baudrate,chip->clock,0,75,0))
+ if (!chip->baudrate)
+ chip->baudrate=1000000;
+ if (sja1000p_baud_rate(chip,chip->baudrate,chip->clock,0,75,0))
return -ENODEV;
/* Enable hardware interrupts */
((flags & FRM_RTR) ? MSG_RTR : 0) |
((flags & FRM_FF) ? MSG_EXT : 0);
len = flags & FRM_DLC_M;
+ obj->rx_msg.length = len;
+ if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
for(i=0; i< len; i++) {
obj->rx_msg.data[i]=can_read_reg(chip,datastart+i);
}
- obj->rx_msg.length = len;
canque_filter_msg2edges(obj->qends, &obj->rx_msg);
int i=0;
unsigned int id;
int status;
+ int len;
/* Wait until Transmit Buffer Status is released */
while ( !((status=can_read_reg(chip, SJASR)) & SR_TBS) &&
return -EIO;
}
}
- msg->length &= FRM_DLC_M;
+ len = msg->length;
+ if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
+ /* len &= FRM_DLC_M; ensured by above condition already */
can_write_reg(chip, ((msg->flags&MSG_EXT)?FRM_FF:0) |
- ((msg->flags & MSG_RTR) ? FRM_RTR : 0) |
- msg->length, SJAFRM);
+ ((msg->flags & MSG_RTR) ? FRM_RTR : 0) | len, SJAFRM);
if(msg->flags&MSG_EXT) {
id=msg->id<<3;
can_write_reg(chip, id & 0xff, SJAID3);
can_write_reg(chip, id & 0xff, SJAID1);
id >>= 8;
can_write_reg(chip, id, SJAID0);
- for(i=0; i < msg->length; i++) {
+ for(i=0; i < len; i++) {
can_write_reg(chip, msg->data[i], SJADATE+i);
}
} else {
id=msg->id<<5;
can_write_reg(chip, (id >> 8) & 0xff, SJAID0);
can_write_reg(chip, id & 0xff, SJAID1);
- for(i=0; i < msg->length; i++) {
+ for(i=0; i < len; i++) {
can_write_reg(chip, msg->data[i], SJADATS+i);
}
}
}
/**
- * sja1000p_stop_chip: - starts chip message processing
+ * sja1000p_start_chip: - starts chip message processing
* @chip: pointer to chip state structure
*
* Return Value: negative value reports error.
int cmd;
if(obj->tx_slot){
+ /* Do local transmitted message distribution if enabled */
+ if (processlocal){
+ obj->tx_slot->msg.flags |= MSG_LOCAL;
+ canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg);
+ }
+ /* Free transmitted slot */
canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
obj->tx_slot=NULL;
}
* message queues.
* File: src/sja1000p.c
*/
-irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+can_irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
int irq_register, status, error_code;
- int static retransmitted=0; /* FIXME - should go into chip struct */
struct chip_t *chip=(struct chip_t *)dev_id;
struct msgobj_t *obj=chip->msgobj[0];
// can_read_reg(chip,SJASR));
if ((irq_register & (IR_BEI|IR_EPI|IR_DOI|IR_EI|IR_TI|IR_RI)) == 0)
- return IRQ_NONE;
+ return CAN_IRQ_NONE;
- if(!obj->flags & OBJ_BUFFERS_ALLOCATED) {
- CANMSG("sja1000p_irq_handler: called with device closed, irq_register 0x%02x\n", irq_register);
- return IRQ_NONE;
+ if(!(chip->flags&CHIP_CONFIGURED)) {
+ CANMSG("sja1000p_irq_handler: called for non-configured device, irq_register 0x%02x\n", irq_register);
+ return CAN_IRQ_NONE;
}
if ((irq_register & IR_RI) != 0) {
if ((irq_register & IR_TI) != 0) {
DEBUGMSG("sja1000_irq_handler: TI\n");
obj->ret = 0;
- set_bit(OBJ_TX_REQUEST,&obj->flags);
- while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){
- clear_bit(OBJ_TX_REQUEST,&obj->flags);
+ 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 (can_read_reg(chip, SJASR) & SR_TBS)
sja1000p_irq_write_handler(chip, obj);
- clear_bit(OBJ_TX_LOCK,&obj->flags);
- if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break;
+ can_msgobj_clear_fl(obj,TX_LOCK);
+ if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
DEBUGMSG("TX looping in sja1000_irq_handler\n");
}
}
obj->ret= -ENXIO;
/* no such device or address - no ACK received */
}
- if(retransmitted++>MAX_RETR) {
+ if(obj->tx_retry_cnt++>MAX_RETR) {
can_write_reg(chip, CMR_AT, SJACMR); // cancel any transmition
- retransmitted = 0;
+ obj->tx_retry_cnt = 0;
}
if(status&SR_BS) {
CANMSG("bus-off, resetting sja1000p\n");
}
} else {
- retransmitted=0;
+ obj->tx_retry_cnt=0;
}
- return IRQ_HANDLED;
+ return CAN_IRQ_HANDLED;
}
/**
*/
int sja1000p_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj)
{
- /* dummy lock to prevent preemption fully portable way */
- spinlock_t dummy_lock;
- /* preempt_disable() */
- spin_lock_init(&dummy_lock);
- spin_lock(&dummy_lock);
+ can_preempt_disable();
- set_bit(OBJ_TX_REQUEST,&obj->flags);
- while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){
- clear_bit(OBJ_TX_REQUEST,&obj->flags);
+ 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 (can_read_reg(chip, SJASR) & SR_TBS)
+ if (can_read_reg(chip, SJASR) & SR_TBS){
+ obj->tx_retry_cnt=0;
sja1000p_irq_write_handler(chip, obj);
+ }
- clear_bit(OBJ_TX_LOCK,&obj->flags);
- if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break;
+ can_msgobj_clear_fl(obj,TX_LOCK);
+ if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
DEBUGMSG("TX looping in sja1000p_wakeup_tx\n");
}
- /* preempt_enable(); */
- spin_unlock(&dummy_lock);
+ can_preempt_enable();
return 0;
}