mc_pcmcia.c

来自「canpie 一个can bus的协议栈 - CAN interface fo」· C语言 代码 · 共 942 行 · 第 1/2 页

C
942
字号
/*****************************************************************************\*  CANpie                                                                     **                                                                             **  File        : mc_pcmcia.c                                                  **  Description : Kernel driver for the MicroControl mCAN.pc.PCMCIA            **  Author      : Uwe Koppe                                                    **  e-mail      : koppe@microcontrol.net                                       **                                                                             ** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - **                                                                             **   This program is free software; you can redistribute it and/or modify      **   it under the terms of the GNU General Public License as published by      **   the Free Software Foundation; either version 2 of the License, or         **   (at your option) any later version.                                       **                                                                             ** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - **                                                                             **                                                                             *\*****************************************************************************/#include <asm/atomic.h>          // atomic data types and operations#include <asm/delay.h>           // delay()#include <asm/io.h>              // inb() and outb()#include <linux/timer.h>         // add_timer()#include <linux/sched.h>         // schedule()#include <net/can/canpie.h>#include <net/can/canpie_hal.h>#include <net/can/cpcanmsg.h>#include "mc_pcmcia_cs.h"/*------------------------------------------------------------------------** Global variables used for the core functions***//*------------------------------------------------------------------------** Global variables used for access to the CAN card***/#define  PCMCIA_BUFFER_SIZE      16#define  PCMCIA_CHANNEL_MAX       2#define  PCMCIA_COM_SIZE         16          // size of communication buffer      static _U08 aubDataReadBufG[PCMCIA_COM_SIZE];      // buffer for read operationstatic _U08 aubDataWriteBufG[PCMCIA_COM_SIZE];     // buffer for write operationstatic _TsMcPcmciaInfo *   ptsInfoS = NULL;static struct timer_list   tsTimerS;static int  aslCanLogIf[PCMCIA_CHANNEL_MAX];       // assignment of logical CAN-I/Fstatic atomic_t   ulTimerStopS;//extern _U16 uwCpPcmciaInterruptG;extern _TsCpCanMsg   tsCanRcvMsgG;_TsCpCanMsg   tsCanTrmMsgG;//-----------------------------------------------------------------------------// the CpVar_InitFlag is used to keep track if a channel// is already initialized,// Bit 0 = channel 0// Bit 1 = channel 1// ....// Bit 15 = channel 15// a bit value of 0 means not initialized// a bit value of 1 means initialized_U16 CpVar_InitFlag = 0;/*------------------------------------------------------------------------** CpStruct_BitTimingTable** The bit timing structure has to be fitted to the used CAN controller.** If more than one CAN channel is used the structure has to be extended.*/const _TsCpBitrate atsBitTimingTable[] = {   { 0x00, 0x31, 0x1C, 0x00 },   /*  10 KBit/sec   */   { 0x01, 0x18, 0x1C, 0x01 },   /*  20 KBit/sec   */   { 0x02, 0x09, 0x1C, 0x02 },   /*  50 KBit/sec   */   { 0x03, 0x04, 0x1C, 0x03 },   /* 100 KBit/sec   */   { 0x04, 0x03, 0x1C, 0x04 },   /* 125 KBit/sec   */   { 0x05, 0x01, 0x1C, 0x05 },   /* 250 KBit/sec   */   { 0x06, 0x00, 0x1C, 0x06 },   /* 500 KBit/sec   */   { 0x07, 0x00, 0x16, 0x07 },   /* 800 KBit/sec   */   { 0x08, 0x00, 0x14, 0x08 },   /*   1 MBit/sec   */};/*------------------------------------------------------------------------** constants when reading the status of the CAN interface***/const _U08 FIFO_MASK_RCV_EMPTY = 0x01;const _U08 FIFO_MASK_TRM_FULL  = 0x04;enum  FifoStatus_e {   eFIFO_STATUS_EMPTY = 0,    // no data in FIFO   eFIFO_STATUS_DATA,         // data in FIFO available   eFIFO_STATUS_FULL};static _U08 mc_pcmcia_data_read(void);static _U08 mc_pcmcia_data_write(void);static _U08 mc_pcmcia_status(_U08 ubFifoTypeV);static void mc_pcmcia_task(unsigned long ulParamV);/*------------------------------------------------------------------------**	CpCoreAllocBuffer()***/#if   CP_FULL_CAN == 1_U08 Cp_PREFIX CpCoreAllocBuffer (_U08 channel, CpStruct_CAN * msg,                                  _U08 direction){#if   CP_SMALL_CODE == 0   //---	test the channel number ------------------------------------	if( (channel + 1) > CP_CHANNEL_MAX) return (CpErr_CHANNEL);#endif   return (CpErr_OK);}#endif//----------------------------------------------------------------------------//// CpPcmciaBitrate()                                                          //// setup baudrate                                                             ////----------------------------------------------------------------------------//_TvCpStatus CpPcmciaBitrate(_TsCpPort * ptsPortV, _TsCpBitrate * ptsBitrateV){   _U16  uwCountT;   _U08  ubCanBtr0T;       // value written in btr0 register   _U08  ubCanBtr1T;       // value written in btr1 register   _U08  ubCanNumT;        // CAN number for PCMCIA interface         //----------------------------------------------------------------   // test the physical channel number   //   if( ptsPortV->slPhyIf >= PCMCIA_CHANNEL_MAX) return (CpErr_CHANNEL);   //----------------------------------------------------------------   // setup the values for btr0 and btr1   //   if(ptsBitrateV->ubBaudSel == CP_BAUD_BTR)   {      ubCanBtr0T = ptsBitrateV->ubBtr0;      ubCanBtr1T = ptsBitrateV->ubBtr1;   }   else   {      //--- take values from table -----------------------------      ubCanBtr0T = atsBitTimingTable[ptsBitrateV->ubBaudSel].ubBtr0;      ubCanBtr1T = atsBitTimingTable[ptsBitrateV->ubBaudSel].ubBtr1;   }   PK_DBG("btr0=%X btr1=%X\n", ubCanBtr0T, ubCanBtr1T);   //----------------------------------------------------------------   // init the CAN port and setup baudrate   //   ubCanNumT = (_U08) (ptsPortV->slPhyIf) + 1;      //--- setup the data in the write buffer ---------------   aubDataWriteBufG[0] = 0x30;   aubDataWriteBufG[1] = ubCanNumT;   aubDataWriteBufG[2] = 0x00;   aubDataWriteBufG[3] = 0x00;   aubDataWriteBufG[4] = 0x00;   aubDataWriteBufG[5] = 0x00;   aubDataWriteBufG[6] = ubCanBtr0T;   aubDataWriteBufG[7] = ubCanBtr1T;   aubDataWriteBufG[8] = 0x00;   aubDataWriteBufG[9] = 0x00;   aubDataWriteBufG[10] = 0x00;   aubDataWriteBufG[11] = 0x00;   aubDataWriteBufG[12] = 0xFF;   aubDataWriteBufG[13] = 0xE0;   aubDataWriteBufG[14] = 0x00;   aubDataWriteBufG[15] = 0x00;   //--- send the data to the CAN card ------------------------------   mc_pcmcia_data_write();   //--- wait for 500 ms --------------------------------------------   for(uwCountT = 0; uwCountT < 500; uwCountT++)   {      udelay(1000);   }   //--- read data from card ----------------------------------------   mc_pcmcia_data_read();   if( (aubDataReadBufG[0] == 0x00) && (aubDataReadBufG[1] == 0x01) )   {      PK_DBG("Baudrate setting OK\n");      return (CpErr_OK);   }   PK_DBG("Baudrate setting failed\n");   return (CpErr_BAUDRATE);}/*------------------------------------------------------------------------** CpCoreBufferTransmit()***/#if   CP_FULL_CAN == 1_U08 Cp_PREFIX CpCoreBufferTransmit(_U08 channel, CpStruct_CAN * msg){#if   CP_SMALL_CODE == 0   //--- test the channel number ------------------------------------   if( (channel + 1) > CP_CHANNEL_MAX) return (CpErr_CHANNEL);#endif   return (CpErr_OK);}#endif//----------------------------------------------------------------------------//// CpPcmciaCanMode()                                                          //// Set mode of CAN controller                                                 ////----------------------------------------------------------------------------//_TvCpStatus CpPcmciaCanMode(_TsCpPort * ptsPortV, _U08 ubModeV){   _U08  ubReturnT = CpErr_OK;   //----------------------------------------------------------------   // test the channel number   //   return(ubReturnT);}//----------------------------------------------------------------------------//// CpPcmciaCanStatus()                                                        //// Retrive status of CAN controller                                           ////----------------------------------------------------------------------------//_TvCpStatus CpPcmciaCanStatus(_TsCpPort * ptsPortV, _U08 * pubStatusV){   _U08  ubStatusT = 0;   _U08  ubReturnT = CpErr_OK;   //----------------------------------------------------------------   // test the channel number   //   *pubStatusV = ubStatusT;              return(ubReturnT);}//----------------------------------------------------------------------------//// CpPcmciaDriverInit()                                                       //// initialize the CAN card                                                    ////----------------------------------------------------------------------------//_TvCpStatus CpPcmciaDriverInit(_U08 ubPhysPortV, _TsCpPort * ptvPortV){   //----------------------------------------------------------------   return (CpErr_OK);}//----------------------------------------------------------------------------//// CpPcmciaDriverRelease()                                                    //// release the CAN driver                                                     ////----------------------------------------------------------------------------//_TvCpStatus CpPcmciaDriverRelease(_TsCpPort * ptvPortV){   _U08  ubReturnT = CpErr_OK;   return(ubReturnT);}/*------------------------------------------------------------------------** CpCoreIntHandler()***/void CpCoreIntHandler(void){}//----------------------------------------------------------------------------//// CpCoreHDI()                                                                ////                                                                            ////----------------------------------------------------------------------------//_U08 CpCoreHDI(_U08 ubChannelV, CpStruct_HDI * hdi){   //----------------------------------------------------------------   // test the channel number   //   #if   CP_SMALL_CODE == 0   if( (ubChannelV + 1) > CP_CHANNEL_MAX) return (CpErr_CHANNEL);   #endif   //----------------------------------------------------------------   // set the support flags according to the configuration   // options   //   return (CpErr_OK);}/*------------------------------------------------------------------------** CpCoreFilterAll()***/_U08 Cp_PREFIX CpCoreFilterAll(_U08 channel, _BIT enable){#if   CP_SMALL_CODE == 0   //--- test the channel number ------------------------------------   if( (channel + 1) > CP_CHANNEL_MAX) return (CpErr_CHANNEL);#endif   return (CpErr_OK);}/*------------------------------------------------------------------------** CpCoreFilterMsg()***/_U08 Cp_PREFIX CpCoreFilterMsg(_U08 channel, _U16 id, _BIT enable){#if   CP_SMALL_CODE == 0   //--- test the channel number ------------------------------------   if( (channel + 1) > CP_CHANNEL_MAX) return (CpErr_CHANNEL);#endif   return (CpErr_OK);}//----------------------------------------------------------------------------//// CpPcmciaMsgRead()                                                          //// Read CAN message from controller                                           ////----------------------------------------------------------------------------//_TvCpStatus CpPcmciaMsgRead(  _TsCpPort * ptsPortV, _TsCpCanMsg * ptsCanMsgV,                              _U16 * puwMsgCntV){   _U08  ubReturnT = CpErr_OK;   _U16  uwMsgCntT = 0;      //----------------------------------------------------------------   // read data from the receive queue   //   uwMsgCntT = can_queue_rcv_pop(ptsPortV, ptsCanMsgV, *puwMsgCntV);   *puwMsgCntV = uwMsgCntT;   return(ubReturnT);   }//----------------------------------------------------------------------------//// CpPcmciaMsgWrite()                                                         //// send CAN message                                                           ////----------------------------------------------------------------------------//_TvCpStatus CpPcmciaMsgWrite( _TsCpPort * ptsPortV, _TsCpCanMsg * ptsCanMsgV,                              _U16 * puwMsgCntV){   _U08           ubTrmFifoStatusT;   _U08           ubDataCntT;   _U32           ulIdentifierT;   _TsCpCanMsg    tsCanMsgT;         //----------------------------------------------------------------   // get status from PCMCIA transmit FIFO   //   ubTrmFifoStatusT = mc_pcmcia_status(CP_FIFO_TRM);      //----------------------------------------------------------------   // read as long from the transmit FIFO (memory) until the FIFO   // on the PCMCIA card is full   //   while(ubTrmFifoStatusT != eFIFO_STATUS_FULL)   {      //---------------------------------------------------      // copy data from the transmit queue      //      if( can_queue_trm_pop(ptsPortV, &tsCanMsgT, 1) != 1)      {         //--- no more messages to read --------------         break;      }         //---------------------------------------------------      // setup the data in the write buffer      //      if( CpMsgIsExtended(&tsCanMsgT) )      {         aubDataWriteBufG[0x00] = 0x45;            // command: extended message         ulIdentifierT = CpMsgGetExtId(&tsCanMsgT);      }      else      {         aubDataWriteBufG[0x00] = 0x44;            // command: standard message         ulIdentifierT = CpMsgGetStdId(&tsCanMsgT);      }      aubDataWriteBufG[0x01] = ptsPortV->slPhyIf + 1;     // channel      aubDataWriteBufG[0x02] = CpMsgGetDlc(&tsCanMsgT);      if(CpMsgIsRemote(&tsCanMsgT))      {         aubDataWriteBufG[0x02] |= 0x10;      }            //--- identifier --------------------------      aubDataWriteBufG[0x03] = (_U08) ulIdentifierT;      ulIdentifierT = ulIdentifierT >> 8;      aubDataWriteBufG[0x04] = (_U08) ulIdentifierT;      ulIdentifierT = ulIdentifierT >> 8;      aubDataWriteBufG[0x05] = (_U08) ulIdentifierT;      ulIdentifierT = ulIdentifierT >> 8;      aubDataWriteBufG[0x07] = (_U08) ulIdentifierT;            //--- data --------------------------------      for(ubDataCntT = 7; ubDataCntT < 15; ubDataCntT++)      {         aubDataWriteBufG[ubDataCntT] = CpMsgGetData(&tsCanMsgT, ubDataCntT - 7);      }      //--- send the data to the CAN card ------------------------------      mc_pcmcia_data_write();         }         return (CpErr_OK);}/*----------------------------------------------------------------------------*\** module init and exit code                                                  **** function implementation                                                    **\*----------------------------------------------------------------------------*/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?