]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/i82527.c
Added support for fasync system call and replacement of spinXXX by can_spinXXX
[lincan.git] / lincan / src / i82527.c
index c10db6b707d88602b2db92135d98501c8e179289..7a57f45c7e7601753cd0b11b35e7a5db5f01ebde 100644 (file)
@@ -7,14 +7,8 @@
  * Version lincan-0.2  9 Jul 2003
  */
 
-#define __NO_VERSION__
-#include <linux/module.h>
-
-#include <linux/autoconf.h>
-
-#include <linux/sched.h>
-#include <linux/fs.h>
-
+#include "../include/can.h"
+#include "../include/can_sysdep.h"
 #include "../include/main.h"
 #include "../include/i82527.h"
 
@@ -89,10 +83,10 @@ int i82527_chip_config(struct chip_t *chip)
        else
                DEBUGMSG("Could read back, hardware is probably configured correctly\n");
 
-       if (baudrate == 0)
-               baudrate=1000;
+       if (chip->baudrate == 0)
+               chip->baudrate=1000000;
 
-       if (i82527_baud_rate(chip,baudrate*1000,chip->clock,0,75,0)) {
+       if (i82527_baud_rate(chip,chip->baudrate,chip->clock,0,75,0)) {
                CANMSG("Error configuring baud rate\n");
                return -ENODEV;
        }
@@ -302,16 +296,16 @@ int i82527_pre_write_config(struct chip_t *chip, struct msgobj_t *obj,
                                                        struct canmsg_t *msg)
 {
        int i=0,id0=0,id1=0,id2=0,id3=0;
+       int len;
+       
+       len = msg->length;
+       if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
 
        canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_RES|CPUU_SET|NEWD_RES),iMSGCTL1);
        canobj_write_reg(chip,obj,(MVAL_SET|TXIE_SET|RXIE_RES|INTPD_RES),iMSGCTL0);
-       if (extended) {
-               canobj_write_reg(chip,obj,(msg->length<<4)+(MCFG_DIR|MCFG_XTD),iMSGCFG);
-       }
-       else {
-               canobj_write_reg(chip,obj,(msg->length<<4)+MCFG_DIR,iMSGCFG);
-       }
-       if (extended) {
+
+       if (extended || (msg->flags&MSG_EXT)) {
+               canobj_write_reg(chip,obj,(len<<4)|(MCFG_DIR|MCFG_XTD),iMSGCFG);
                id0 = (unsigned char) (msg->id<<3);
                id1 = (unsigned char) (msg->id>>5);
                id2 = (unsigned char) (msg->id>>13);
@@ -322,13 +316,14 @@ int i82527_pre_write_config(struct chip_t *chip, struct msgobj_t *obj,
                canobj_write_reg(chip,obj,id3,iMSGID0);
        }
        else {
+               canobj_write_reg(chip,obj,(len<<4)|MCFG_DIR,iMSGCFG);
                id1 = (unsigned char) (msg->id<<5);
                id0 = (unsigned char) (msg->id>>3);
                canobj_write_reg(chip,obj,id1,iMSGID1);
                canobj_write_reg(chip,obj,id0,iMSGID0);
        }
        canobj_write_reg(chip,obj,0xfa,iMSGCTL1);
-       for (i=0; i<msg->length; i++) {
+       for (i=0; i<len; i++) {
                canobj_write_reg(chip,obj,msg->data[i],iMSGDAT0+i);
        }
 
@@ -409,6 +404,12 @@ inline void i82527_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj)
        canobj_write_reg(chip,obj,(MVAL_RES|TXIE_RES|RXIE_RES|INTPD_RES),+iMSGCTL0);
 
        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;
        }
@@ -436,19 +437,20 @@ inline void i82527_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj)
 inline void i82527_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj,
                                    unsigned long message_id)
 {
-       int i=0, tmp=1 ;
+       int i=0, tmp=1, len;
        
        while (tmp) {
                canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_RES|MLST_RES|NEWD_RES),iMSGCTL1);
                canobj_write_reg(chip,obj,(MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES),iMSGCTL0);
 
-               obj->rx_msg.length =(canobj_read_reg(chip,obj,iMSGCFG) & 0xf0) >> 4;
+               len = (canobj_read_reg(chip,obj,iMSGCFG) >> 4) & 0xf;
+               obj->rx_msg.length = len;
                obj->rx_msg.id = message_id;
+
+               if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
                for (i=0; i < obj->rx_msg.length; i++)
                        obj->rx_msg.data[i] = canobj_read_reg(chip,obj,iMSGDAT0+i);
 
-//FIXME: Add buffer overflow check, currently it's silently over written!
-
                canque_filter_msg2edges(obj->qends, &obj->rx_msg);
 
                if (!((tmp=canobj_read_reg(chip,obj,iMSGCTL1)) & NEWD_SET)) {
@@ -518,14 +520,14 @@ irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
                                message_id=(id0|id1)>>5;
                        }
 
-                       spin_lock(&hardware_p->rtr_lock);
+                       can_spin_lock(&hardware_p->rtr_lock);
                        rtr_search=hardware_p->rtr_queue;
                        while (rtr_search != NULL) {
                                if (rtr_search->id == message_id)
                                        break;
                                rtr_search=rtr_search->next;
                        }
-                       spin_unlock(&hardware_p->rtr_lock);
+                       can_spin_unlock(&hardware_p->rtr_lock);
                        if ((rtr_search!=NULL) && (rtr_search->id==message_id))
                                i82527_irq_rtr_handler(chip, obj, rtr_search, message_id);
                        else
@@ -545,27 +547,27 @@ void i82527_irq_rtr_handler(struct chip_t *chip, struct msgobj_t *obj,
        canobj_write_reg(chip,obj,(MVAL_RES|TXIE_RES|RXIE_RES|INTPD_RES),iMSGCTL0);
        canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_RES|MLST_RES|NEWD_RES),iMSGCTL1);
        
-       spin_lock(&hardware_p->rtr_lock);
+       can_spin_lock(&hardware_p->rtr_lock);
 
        rtr_search->rtr_message->id=message_id;
        rtr_search->rtr_message->length=(canobj_read_reg(chip,obj,iMSGCFG) & 0xf0)>>4;
        for (i=0; i<rtr_search->rtr_message->length; i++)
                rtr_search->rtr_message->data[i]=canobj_read_reg(chip,obj,iMSGDAT0+i);
        
-       spin_unlock(&hardware_p->rtr_lock);
+       can_spin_unlock(&hardware_p->rtr_lock);
 
        if (waitqueue_active(&rtr_search->rtr_wq))
-               wake_up_interruptible(&rtr_search->rtr_wq);
+               wake_up(&rtr_search->rtr_wq);
 }
 
 int i82527_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj)
 {
         /* dummy lock to prevent preemption fully portable way */
-       spinlock_t dummy_lock;
+       can_spinlock_t dummy_lock;
        
        /*  preempt_disable() */
-       spin_lock_init(&dummy_lock);
-       spin_lock(&dummy_lock);
+       can_spin_lock_init(&dummy_lock);
+       can_spin_lock(&dummy_lock);
        
        set_bit(OBJ_TX_REQUEST,&obj->flags);
        while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){
@@ -579,7 +581,7 @@ int i82527_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj)
        }
 
        /* preempt_enable(); */
-       spin_unlock(&dummy_lock);
+       can_spin_unlock(&dummy_lock);
        return 0;
 }