📄 sja1000funcs.c
字号:
#else if( need_resched ) schedule(); #endif } DBGprint(DBG_DATA,( "CAN[%d]: tx.flags=%d tx.id=0x%lx tx.length=%d stat=0x%x", minor, tx->flags, tx->id, tx->length, stat)); tx->length %= 9; /* limit CAN message length to 8 */ ext = (tx->flags & MSG_EXT); /* read message format */ /* fill the frame info and identifier fields */ tx2reg = tx->length; if( tx->flags & MSG_RTR) { tx2reg |= CAN_RTR; } if(ext) { DBGprint(DBG_DATA, ("---> send ext message")); CANout(minor, frameinfo, CAN_EFF + tx2reg); CANout(minor, frame.extframe.canid1, (u8)(tx->id >> 21)); CANout(minor, frame.extframe.canid2, (u8)(tx->id >> 13)); CANout(minor, frame.extframe.canid3, (u8)(tx->id >> 5)); CANout(minor, frame.extframe.canid4, (u8)(tx->id << 3) & 0xff); } else { DBGprint(DBG_DATA, ("---> send std message")); CANout(minor, frameinfo, CAN_SFF + tx2reg); CANout(minor, frame.stdframe.canid1, (u8)((tx->id) >> 3) ); CANout(minor, frame.stdframe.canid2, (u8)(tx->id << 5 ) & 0xe0); } /* - fill data ---------------------------------------------------- */ if(ext) { for( i=0; i < tx->length ; i++) { CANout( minor, frame.extframe.canxdata[R_OFF * i], tx->data[i]); /* SLOW_DOWN_IO; SLOW_DOWN_IO; */ } } else { for( i=0; i < tx->length ; i++) { CANout( minor, frame.stdframe.candata[R_OFF * i], tx->data[i]); /* SLOW_DOWN_IO; SLOW_DOWN_IO; */ } } /* - /end --------------------------------------------------------- */ CANout(minor, cancmd, CAN_TRANSMISSION_REQUEST ); /* * Save last message that was sent. * Since can4linux 3.5 multiple processes can access * one CAN interface. On a CAN interrupt this message is copied into * the receive queue of each process that opened this same CAN interface. */ memcpy( (void *)&last_Tx_object[minor], (void *)tx, sizeof(canmsg_t)); DBGout();return i;}/* * The plain SJA1000 interrupt * * RX ISR TX ISR * 8/0 byte * _____ _ ___ * _____| |____ ___| |_| |__ *--------------------------------------------------------------------------- * 1) CPUPentium 75 - 200 * 75 MHz, 149.91 bogomips * AT-CAN-MINI 42/27祍 50 祍 * CPC-PCI 35/26祍 * --------------------------------------------------------------------------- * 2) AMD Athlon(tm) Processor 1M * 2011.95 bogomips * AT-CAN-MINI std 24/12祍 ?? 祍 * ext id /14祍 * * * 1) 1Byte = (42-27)/8 = 1.87 祍 * 2) 1Byte = (24-12)/8 = 1.5 祍 * * * * RX Int with to Receive channels: * 1) _____ ___ * _____| |_| |__ * 30 5 20 祍 * first ISR normal length, * time between the two ISR -- short * sec. ISR shorter than first, why? it's the same message */#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) irqreturn_t CAN_Interrupt( int irq, void *dev_id)#elseirqreturn_t CAN_Interrupt( int irq, void *dev_id, struct pt_regs *notused)#endif{int minor;int i = 0;int rx_fifo;struct timeval timestamp;unsigned long flags;int ext; /* flag for extended message format */int irqsrc, dummy;msg_fifo_t *RxFifo; msg_fifo_t *TxFifo;#if CAN_USE_FILTERmsg_filter_t *RxPass;unsigned int id;#endif #if 1int first = 0;#endif #if CONFIG_TIME_MEASURE outb(0xff, 0x378); #endif minor = *(int *)dev_id; /* printk("CAN - ISR ; minor = %d\n", *(int *)dev_id); */ RxFifo = &Rx_Buf[minor][0]; TxFifo = &Tx_Buf[minor];#if CAN_USE_FILTER RxPass = &Rx_Filter[minor];#endif /* Disable PITA Interrupt */ /* writel(0x00000000, Can_pitapci_control[minor] + 0x0); */ irqsrc = CANin(minor, canirq); if(irqsrc == 0) { /* first call to ISR, it's not for me ! */#if LINUX_VERSION_CODE >= 0x020500 return IRQ_RETVAL(IRQ_NONE);#else goto IRQdone_doneNothing;#endif }#if defined(CCPC104) pc104_irqack();#endif do { /* loop as long as the CAN controller shows interrupts */ DBGprint(DBG_DATA, (" => got IRQ[%d]: 0x%0x", minor, irqsrc)); /* can_dump(minor); */ /* fill timestamp as first action. * Getting a precises time takes a lot of time * (additional 7 祍 of ISR time ) * if a time stamp is not needed, it can be switched of * by ioctl() */ if (use_timestamp[minor]) { do_gettimeofday(×tamp); } else { timestamp.tv_sec = 0; timestamp.tv_usec = 0; } for(rx_fifo = 0; rx_fifo < CAN_MAX_OPEN; rx_fifo++) { RxFifo = &Rx_Buf[minor][rx_fifo]; RxFifo->data[RxFifo->head].timestamp = timestamp; /* preset flags */ (RxFifo->data[RxFifo->head]).flags = (RxFifo->status & BUF_OVERRUN ? MSG_BOVR : 0); }#if 1 /* how often do we loop through the ISR ? */ /* if(first) printk("n = %d\n", first); */ first++; if (first > 10) return IRQ_RETVAL(IRQ_HANDLED);#endif /*========== receive interrupt */ if( irqsrc & CAN_RECEIVE_INT ) { int length; /* printk(" CAN RX %d\n", minor); */ dummy = CANin(minor, frameinfo );/* ---------- fill frame data -------------------------------- */ /* handle all subscribed rx fifos */ for(rx_fifo = 0; rx_fifo < CAN_MAX_OPEN; rx_fifo++) { /* for every rx fifo */ /* printk(KERN_INFO " used fifos [%d][%d] = %d\n", minor, rx_fifo, */ /* CanWaitFlag[minor][rx_fifo]); */ if (CanWaitFlag[minor][rx_fifo] == 1) { /* this FIFO is in use */ RxFifo = &Rx_Buf[minor][rx_fifo]; /* prepare buffer to be used *//* printk(KERN_INFO "> filling buffer [%d][%d]\n", minor, rx_fifo); */ if( dummy & CAN_RTR ) { (RxFifo->data[RxFifo->head]).flags |= MSG_RTR; } if( dummy & CAN_EFF ) { (RxFifo->data[RxFifo->head]).flags |= MSG_EXT; } ext = (dummy & CAN_EFF); if(ext) { (RxFifo->data[RxFifo->head]).id = ((unsigned int)(CANin(minor, frame.extframe.canid1)) << 21) + ((unsigned int)(CANin(minor, frame.extframe.canid2)) << 13) + ((unsigned int)(CANin(minor, frame.extframe.canid3)) << 5) + ((unsigned int)(CANin(minor, frame.extframe.canid4)) >> 3); } else { (RxFifo->data[RxFifo->head]).id = ((unsigned int)(CANin(minor, frame.stdframe.canid1 )) << 3) + ((unsigned int)(CANin(minor, frame.stdframe.canid2 )) >> 5); } /* get message length */ length = dummy & 0x0f; /* strip length code */ (RxFifo->data[RxFifo->head]).length = length; length %= 9; /* limit count to 8 bytes */ for( i = 0; i < length; i++) { /* SLOW_DOWN_IO;SLOW_DOWN_IO; */ if(ext) { (RxFifo->data[RxFifo->head]).data[i] = CANin(minor, frame.extframe.canxdata[R_OFF * i]); } else { (RxFifo->data[RxFifo->head]).data[i] = CANin(minor, frame.stdframe.candata[R_OFF * i]); } } /* mark just written entry as OK and full */ RxFifo->status = BUF_OK; /* Handle buffer wrap-around */ RxFifo->head = ++(RxFifo->head) % MAX_BUFSIZE; if(RxFifo->head == RxFifo->tail) { printk("CAN[%d][%d] RX: FIFO overrun\n", minor, rx_fifo); RxFifo->status = BUF_OVERRUN; } /*---------- kick the select() call -*/ /* This function will wake up all processes that are waiting on this event queue, that are in interruptible sleep */ /* printk(KERN_INFO " should wake [%d][%d]\n", minor, rx_fifo); */ wake_up_interruptible(&CanWait[minor][rx_fifo]); } }/* ---------- / fill frame data -------------------------------- */ /* release the CAN controller now */ CANout(minor, cancmd, CAN_RELEASE_RECEIVE_BUFFER ); if(CANin(minor, canstat) & CAN_DATA_OVERRUN ) { printk("CAN[%d] Rx: Overrun Status \n", minor); CANout(minor, cancmd, CAN_CLEAR_OVERRUN_STATUS ); } } /*========== transmit interrupt */ if( irqsrc & CAN_TRANSMIT_INT ) { /* CAN frame successfully sent */ u8 tx2reg; unsigned int id; /* use time stamp sampled with last INT */ last_Tx_object[minor].timestamp = timestamp; /* depending on the number of open processes * the TX data has to be copied in different * rx fifos */ for(rx_fifo = 0; rx_fifo < CAN_MAX_OPEN; rx_fifo++) { /* for every rx fifo */ if (CanWaitFlag[minor][rx_fifo] == 1) { /* this FIFO is in use */ /* printk(KERN_INFO "self copy to [%d][%d]\n", minor, rx_fifo); */ /* * Don't copy the message in the receive queue * of the process that sent the message unless * this process requested selfreception. */ if ((last_Tx_object[minor].cob == rx_fifo) && (selfreception[minor][rx_fifo] == 0)) { /* printk("CAN[%d][%d] Don't copy message in my queue\n", minor, rx_fifo); */ continue; }#ifdef VERBOSE printk( "CAN[%d][%d] Copy message from %d in queue id 0x%lx 0x%x\n", minor, rx_fifo, last_Tx_object[minor].cob, last_Tx_object[minor].id, last_Tx_object[minor].data[0]);#endif /* prepare buffer to be used */ RxFifo = &Rx_Buf[minor][rx_fifo]; memcpy( (void *)&RxFifo->data[RxFifo->head], (void *)&last_Tx_object[minor], sizeof(canmsg_t)); /* Mark message as 'self sent/received' */ RxFifo->data[RxFifo->head].flags |= MSG_SELF; /* increment write index */ RxFifo->status = BUF_OK; RxFifo->head = ++(RxFifo->head) % MAX_BUFSIZE; if(RxFifo->head == RxFifo->tail) { printk("CAN[%d][%d] RX: FIFO overrun\n", minor, rx_fifo); RxFifo->status = BUF_OVERRUN; } /*---------- kick the select() call -*/ /* This function will wake up all processes that are waiting on this event queue, that are in interruptible sleep */ wake_up_interruptible(&CanWait[minor][rx_fifo]); } /* this FIFO is in use */ } /* end for loop filling all rx-fifos */ if( TxFifo->free[TxFifo->tail] == BUF_EMPTY ) { /* TX FIFO empty, nothing more to sent */ /* printk("TXE\n"); */ TxFifo->status = BUF_EMPTY; TxFifo->active = 0; /* This function will wake up all processes that are waiting on this event queue, that are in interruptible sleep */ wake_up_interruptible(&CanOutWait[minor]); goto Tx_done; } /* enter critical section */ local_irq_save(flags); /* The TX message FIFO contains other CAN frames to be sent * The next frame in the FIFO is copied into the last_Tx_object * and directly into the hardware of the CAN controller */ memcpy( (void *)&last_Tx_object[minor], (void *)&TxFifo->data[TxFifo->tail], sizeof(canmsg_t)); tx2reg = (TxFifo->data[TxFifo->tail]).length; if( (TxFifo->data[TxFifo->tail]).flags & MSG_RTR) { tx2reg |= CAN_RTR; } ext = (TxFifo->data[TxFifo->tail]).flags & MSG_EXT; id = (TxFifo->data[TxFifo->tail]).id; if(ext) { DBGprint(DBG_DATA, ("---> send ext message")); CANout(minor, frameinfo, CAN_EFF + tx2reg); CANout(minor, frame.extframe.canid1, (u8)(id >> 21)); CANout(minor, frame.extframe.canid2, (u8)(id >> 13)); CANout(minor, frame.extframe.canid3, (u8)(id >> 5)); CANout(minor, frame.extframe.canid4, (u8)(id << 3) & 0xff); } else { DBGprint(DBG_DATA, ("---> send std message")); CANout(minor, frameinfo, CAN_SFF + tx2reg); CANout(minor, frame.stdframe.canid1, (u8)((id) >> 3) ); CANout(minor, frame.stdframe.canid2, (u8)(id << 5 ) & 0xe0); } tx2reg &= 0x0f; /* restore length only */ if(ext) { for( i=0; i < tx2reg ; i++) { CANout(minor, frame.extframe.canxdata[R_OFF * i], (TxFifo->data[TxFifo->tail]).data[i]); } } else { for( i=0; i < tx2reg ; i++) { CANout(minor, frame.stdframe.candata[R_OFF * i], (TxFifo->data[TxFifo->tail]).data[i]); } } CANout(minor, cancmd, CAN_TRANSMISSION_REQUEST ); TxFifo->free[TxFifo->tail] = BUF_EMPTY; /* now this entry is EMPTY */ TxFifo->tail = ++(TxFifo->tail) % MAX_BUFSIZE; /* leave critical section */ local_irq_restore(flags); }Tx_done: /*========== error status */ if( irqsrc & CAN_ERROR_INT ) { int status; int flags = 0; /* printk("CAN[%d]: error interrupt!\n", minor); */ TxErr[minor]++; /* insert error */ status = CANin(minor,canstat); if(status & CAN_BUS_STATUS ) { flags += MSG_BUSOFF; (RxFifo->data[RxFifo->head]).flags += MSG_BUSOFF; /* printk(" MSG_BUSOF\n"); */ } if(status & CAN_ERROR_STATUS) { flags += MSG_PASSIVE; (RxFifo->data[RxFifo->head]).flags += MSG_PASSIVE; /* printk(" MSG_PASSIVE\n"); */ } for(rx_fifo = 0; rx_fifo < CAN_MAX_OPEN; rx_fifo++) { /* for every rx fifo */ if (CanWaitFlag[minor][rx_fifo] == 1) { /* this FIFO is in use */ RxFifo = &Rx_Buf[minor][rx_fifo]; /* prepare buffer to be used */ (RxFifo->data[RxFifo->head]).flags += flags; (RxFifo->data[RxFifo->head]).id = CANDRIVERERROR; (RxFifo->data[RxFifo->head]).length = 0; RxFifo->status = BUF_OK; /* handle fifo wrap around */ RxFifo->head = ++(RxFifo->head) % MAX_BUFSIZE; if(RxFifo->head == RxFifo->tail) { printk("CAN[%d][%d] RX: FIFO overrun\n", minor, rx_fifo); RxFifo->status = BUF_OVERRUN; } /* tell someone that there is a new error message */ wake_up_interruptible(&CanWait[minor][rx_fifo]); } } } if( irqsrc & CAN_OVERRUN_INT ) { int status; printk("CAN[%d]: controller overrun!\n", minor); Overrun[minor]++; /* insert error */ status = CANin(minor,canstat); for(rx_fifo = 0; rx_fifo < CAN_MAX_OPEN; rx_fifo++) { /* for every rx fifo */ if (CanWaitFlag[minor][rx_fifo] == 1) { /* this FIFO is in use */ if(status & CAN_DATA_OVERRUN) (RxFifo->data[RxFifo->head]).flags += MSG_OVR; (RxFifo->data[RxFifo->head]).id = 0xFFFFFFFF; (RxFifo->data[RxFifo->head]).length = 0; RxFifo->status = BUF_OK; RxFifo->head = ++(RxFifo->head) % MAX_BUFSIZE; if(RxFifo->head == RxFifo->tail) { printk("CAN[%d][%d] RX: FIFO overrun\n", minor, rx_fifo); RxFifo->status = BUF_OVERRUN; } /* tell someone that there is a new error message */ wake_up_interruptible(&CanWait[minor][rx_fifo]); } } CANout(minor, cancmd, CAN_CLEAR_OVERRUN_STATUS ); } } while( (irqsrc = CANin(minor, canirq)) != 0);/* IRQdone: */ DBGprint(DBG_DATA, (" => leave IRQ[%d]", minor)); board_clear_interrupts(minor);#if LINUX_VERSION_CODE < 0x020500 IRQdone_doneNothing:#endif#if CONFIG_TIME_MEASURE outb(0x00, 0x378); #endif return IRQ_RETVAL(IRQ_HANDLED);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -