📄 irq.c
字号:
/* irq.c * * Written by Sebastian Stolzenberg email:stolzi@sebastian-stolzenberg.de * Version 1.0 04 Feb 2003 */#include <linux/time.h>#include <linux/timer.h>#include "../include/candrv.h"#include "../include/irq.h"#include "../include/c_can.h"/* prototypes of irq sub functions */inline void c_can_irq_read_handler( struct chip_t *pchip, u32 msgid, struct timeval tv );inline void c_can_irq_write_handler( struct chip_t *pchip );void c_can_irq_rtr_handler( struct chip_t *pchip, u32 msgid, struct timeval tv );/* bit masks for CAN controller */u16 readMaskCM = IFXCM_ARB | IFXCM_CNTRL | IFXCM_CLRINTPND | IFXCM_TRND | IFXCM_DA | IFXCM_DB;u16 msgLstReadMaskCM = IFXCM_CNTRL;u16 msgLstWriteMaskCM = IFXCM_CNTRL | IFXCM_WRRD;u8 idxobj = 0;/* prototypes of bus off and error passiv counter functions */void startTimer (struct chip_t *pchip, time_t seconds, long nanosec, void (*function)(unsigned long));void functBusOffTimer (unsigned long chip_ptr);void functTimeTrigTimer (unsigned long chip_ptr);/* helps to map data from word to byte format */union Data{ unsigned short wdata[4]; unsigned char bdata[8];};////////////////////////////////////////////////////////////////////////////////** * c_can_irq_write_handler * * Send a message from the output fifo ( if any ). */inline void c_can_irq_write_handler( struct chip_t *pchip){ /* Get ready to send next message */ spin_lock( &pchip->spwlock ); DEBUGMSG("(c%dm%d)calling c_can_irq_write_handler(...)", pchip->chip_nr, pchip->pmsgobj[idxobj]->object); /* is buffer empty ? */ if ( pchip->pmsgobj[idxobj]->fifo->txrp == pchip->pmsgobj[idxobj]->fifo->txwp ) { /* Nothing to write */ DEBUGMSG("(c%dm%d)Nothin to write", pchip->chip_nr, pchip->pmsgobj[idxobj]->object); spin_unlock( &pchip->spwlock ); /* stop transmission and wake up any waiting writer */ pchip->pmsgobj[idxobj]->fifo->flags &= ~TX_IN_PROGRESS; pchip->pmsgobj[idxobj]->rv = 0; wake_up_interruptible( &pchip->pmsgobj[idxobj]->fifo->writeq ); return; } /* Send the message */ pchip->pmsgobj[idxobj]->fifo->flags |= TX_IN_PROGRESS; if ( pchip->send_msg( pchip->pmsgobj[idxobj], (struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->txrp )) { /* Failed... */ spin_unlock( &pchip->spwlock ); DEBUGMSG("(c%dm%d)c_can_irq_handler: Unable to send message", pchip->chip_nr, pchip->pmsgobj[idxobj]->object ); pchip->rv = -1; } else { /* Another message sent */ pchip->stat.cntTxPkt++; pchip->stat.cntTxData += ((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->txrp)->length; pchip->pmsgobj[idxobj]->fifo->txrp += sizeof( struct canmsg_t ); if ( pchip->pmsgobj[idxobj]->fifo->txrp >= ( pchip->pmsgobj[idxobj]->fifo->ptxbuf + pchip->pmsgobj[idxobj]->fifo->txsize )) { pchip->pmsgobj[idxobj]->fifo->txrp = pchip->pmsgobj[idxobj]->fifo->ptxbuf; /* wrapped */ } } /* Wake up any waiting writer */ spin_unlock( &pchip->spwlock ); wake_up_interruptible( &pchip->pmsgobj[idxobj]->fifo->writeq ); return;}////////////////////////////////////////////////////////////////////////////////** * c_can_irq_read_handler * * Message received from the line. Write it in the input fifo-> */inline void c_can_irq_read_handler( struct chip_t *pchip, u32 msgid, struct timeval tv ){ int i=0; u16 bDataAvail=1 ; u16 msgCntlReg = 0; u16 spacefree = 0; union Data readData; DEBUGMSG("(c%dm%d)calling c_can_irq_read_handler(...)", pchip->chip_nr, pchip->pmsgobj[idxobj]->object); /* run till no new data was received */ while ( bDataAvail ) { spin_lock( &pchip->sprlock ); if ( pchip->pmsgobj[idxobj]->fifo->rxrp == pchip->pmsgobj[idxobj]->fifo->rxwp ) { spacefree = pchip->pmsgobj[idxobj]->fifo->rxsize; } else { spacefree = ( ( pchip->pmsgobj[idxobj]->fifo->rxrp + pchip->pmsgobj[idxobj]->fifo->rxsize - pchip->pmsgobj[idxobj]->fifo->rxwp ) % pchip->pmsgobj[idxobj]->fifo->rxsize ); } /* is enough buffer space available */ if ( spacefree <= sizeof( struct canmsg_t )) { CANMSG("(c%dm%d)Fifo full - Message lost!", pchip->chip_nr, pchip->pmsgobj[idxobj]->object); if ( ! (pchip->pmsgobj[idxobj]->fifo->flags & RD_BUFF_OVRWRT ) ) { wake_up_interruptible( &pchip->pmsgobj[idxobj]->fifo->readq ); pchip->stat.cntRxFifoOvr++; pchip->pmsgobj[idxobj]->rv = -1; } else { /* move read pointer forward one message */ pchip->pmsgobj[idxobj]->fifo->rxrp += sizeof( struct canmsg_t ); if ( pchip->pmsgobj[idxobj]->fifo->rxrp >= ( pchip->pmsgobj[idxobj]->fifo->prxbuf + pchip->pmsgobj[idxobj]->fifo->rxsize )) { pchip->pmsgobj[idxobj]->fifo->rxrp = pchip->pmsgobj[idxobj]->fifo->prxbuf; /* wrapped */ } } } if ( ( spacefree > sizeof( struct canmsg_t ) ) || ( pchip->pmsgobj[idxobj]->fifo->flags & RD_BUFF_OVRWRT ) ) { /* Message length */ msgCntlReg = pchip->read_register( pchip, CCIF1DMC ); ((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp)->length = msgCntlReg & 0x000F; /* Message id */ ((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp )->id = (u32)msgid; /* Timestamp */ ((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp )->timestamp_sec = tv.tv_sec; ((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp )->timestamp_usec = tv.tv_usec; /* Fetch message bytes */ if (((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp)->length > 0) readData.wdata[0] = pchip->read_register(pchip, CCIF1DA1); if (((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp)->length > 2) readData.wdata[1] = pchip->read_register(pchip, CCIF1DA2); if (((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp)->length > 4) readData.wdata[2] = pchip->read_register(pchip, CCIF1DB1); if (((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp)->length > 6) readData.wdata[3] = pchip->read_register(pchip, CCIF1DB2); /* write to fifo */ for ( i=0; i < ((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp)->length; i++ ) { ((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp)->data[ i ] = readData.bdata[i]; } /* fill unused data bytes with 00 */ for ( ; i < 8; i++ ) { ((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp)->data[ i ] = 0; } DEBUGMSG("(c%dm%d)Received Message:", pchip->chip_nr, pchip->pmsgobj[idxobj]->object); DEBUGMSG(" id = %d", ((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp)->id); DEBUGMSG(" length = %d", ((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp)->length); for ( i=0; i < ((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp)->length; i++ ) DEBUGMSG(" data[%d] = 0x%.2x", i, ((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp)->data[i] = readData.bdata[i]); /* Another received packet */ pchip->stat.cntRxPkt++; /* Add databytes read to statistics block */ pchip->stat.cntRxData += ((struct canmsg_t *)pchip->pmsgobj[idxobj]->fifo->rxwp)->length; /* One message has been read -> move fifo pointers */ pchip->pmsgobj[idxobj]->fifo->rxwp += sizeof( struct canmsg_t ); if ( pchip->pmsgobj[idxobj]->fifo->rxwp >= ( pchip->pmsgobj[idxobj]->fifo->prxbuf + pchip->pmsgobj[idxobj]->fifo->rxsize )) { pchip->pmsgobj[idxobj]->fifo->rxwp = pchip->pmsgobj[idxobj]->fifo->prxbuf; /* wrapped */ } } spin_unlock( &pchip->sprlock ); /* Check if new data arrived */ c_can_if1_busycheck(pchip); pchip->write_register(readMaskCM, pchip, CCIF1CM); pchip->write_register(idxobj+1, pchip, CCIF1CR); c_can_if1_busycheck(pchip); if ( !( ( bDataAvail = pchip->read_register( pchip, CCIF1DMC ) ) & IFXMC_NEWDAT )) break; if ( bDataAvail & IFXMC_MSGLST ) { CANMSG("(c%dm%d)c-can fifo full: Message lost!", pchip->chip_nr, pchip->pmsgobj[idxobj]->object); } } /* while */ /* Wake up any waiting reader */ wake_up_interruptible( &pchip->pmsgobj[idxobj]->fifo->readq );}////////////////////////////////////////////////////////////////////////////////* * c_can_irq_rtr_handler */void c_can_irq_rtr_handler( struct chip_t *pchip, u32 msgid, struct timeval tv ){ short int i=0; struct rtr_id *prtr_search = pchip->prtr_queue; union Data rtrData; spin_lock( &pchip->rtr_lock ); prtr_search->rtr_message->id = msgid; prtr_search->rtr_message->length = ( pchip->read_register( pchip, CCIF1DMC ) & 0x000f); /* Fetch message bytes */ if (prtr_search->rtr_message->length > 0) rtrData.wdata[0] = pchip->read_register(pchip, CCIF1DA1); if (prtr_search->rtr_message->length > 2) rtrData.wdata[1] = pchip->read_register(pchip, CCIF1DA2); if (prtr_search->rtr_message->length > 4) rtrData.wdata[2] = pchip->read_register(pchip, CCIF1DB1); if (prtr_search->rtr_message->length > 6) rtrData.wdata[3] = pchip->read_register(pchip, CCIF1DB2); for ( i=0; i<prtr_search->rtr_message->length; i++ ) { prtr_search->rtr_message->data[ i ] = rtrData.bdata[i]; } /* Timestamp */ prtr_search->rtr_message->timestamp_sec= tv.tv_sec; prtr_search->rtr_message->timestamp_usec = tv.tv_usec; spin_unlock( &pchip->rtr_lock ); wake_up_interruptible( &prtr_search->rtr_wq ); return;}////////////////////////////////////////////////////////////////////////////////* * c_can_irq_handler * * IRQ-handler called by linux kernel */void c_can_irq_handler( int irq, void *dev_id, struct pt_regs *regs ){ struct chip_t *pchip = (struct chip_t *)dev_id; struct rtr_id *rtr_search = pchip->prtr_queue; int id0=0, id1=0; u16 errcount = 0; u16 irqreg = 0; u32 msgid = 0; u16 tempCntlReg = 0; struct timeval tv; u16 i; if (pchip->ntype != CAN_CHIPTYPE_C_CAN) { DEBUGMSG("\n(c%d)IRQ not for c_can_irq_handler(...)", pchip->chip_nr); return; } /* read IRQ register which gives us the interrupt reason */ irqreg = pchip->read_register( pchip, CCINTR ); /* Run till no more interrupts are pending */ while ( irqreg ) { DEBUGMSG( "(c%d)IRQ handler: addr=%.8lx irqreg=0x%.4x", pchip->chip_nr, (long)( pchip->/*v*/base_addr/* + CCSR*/), irqreg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -