-/******************************************************************************\r
-\r
-Cl2.C - PCAN and VCAN cards hardware access library\r
-"""""\r
- (C) Copyright 1997 Unicontrols a.s.\r
-\r
-PROJEKT : CANopen\r
-AUTOR : F.Spurny\r
-FIRMA : CVUT FEL, Dept. of Measurement\r
-\r
-DULEZITE UPOZORNENI:\r
-\r
-ARCHIVACNI INFORMACE:\r
-Log: unican_cl2.c,v\r
-\r
-12.12.2000, J.B., cl2_receive_data - time stamp for even number of bytes corr.\r
-26.8.1998 - cl2_buf_size - corrected, new function return code CL2_BAD_PARAM\r
- cl2_clr_async_buffer - corrected\r
-\r
-===============================================================================\r
-\r
-UCEL A FUNKCE:\r
-\r
-******************************************************************************/\r
-\r
-/* Constnt used by CL2 functions */\r
-#define CL2_TMP_RF 0x0800\r
-#define CL2_TMP_EX 0x0400\r
-#define CL2_TMP_EX2 0x0004\r
-#define CL2_TMP_EXHIGH 0x80000000L\r
-\r
-\r
-/* includes */\r
-#include "../include/canmsg.h"\r
-#include "../include/can_sysdep.h"\r
-#include "../include/unican_types.h"\r
-#include "../include/unican_cl2.h"\r
-#include "linux/delay.h"\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_init_card - initialize card to default parameters\r
-* """""""""""""\r
-*\r
-* Command installs card. The data in sCAN_CARD structure pointed\r
-* by *card are initialized to their predefined default values.\r
-* Command must be called before any operation with sCAN_CARD\r
-* structure.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed succesfuly\r
-*\r
-*/\r
-eCL2_RESULT cl2_init_card\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- void *baseAddress, /* Card base address pointer */\r
- U16 intNumber /* Card interrupt number */\r
- )\r
- {\r
- int i;\r
-\r
- card->intNumber = intNumber;\r
- card->baseAddressPtr = (U8*)baseAddress;\r
- card->rxBufBase = card->baseAddressPtr + CL2_RX_BUFFER_DEFAULT;\r
- card->asyncTxBufBase = card->baseAddressPtr + CL2_ASYNC_BUFFER_DEFAULT;\r
- card->syncTxBufBase = card->baseAddressPtr + CL2_SYNC_BUFFER_DEFAULT;\r
- card->rxBufPtr = card->rxBufBase;\r
- card->asyncTxBufPtr = card->asyncTxBufBase;\r
- card->syncTxBufPtr = card->syncTxBufBase;\r
- card->commandRegister = card->baseAddressPtr+CL2_COMMAND_REGISTER;\r
- card->dataPtr = card->baseAddressPtr + CL2_DATA_BUFFER;\r
- card->rxBufSize = CL2_RX_BUFFER_SIZE;\r
- card->syncTxBufSize = CL2_TX_SYNC_BUFFER_SIZE;\r
- card->asyncTxBufSize = CL2_TX_ASYNC_BUFFER_SIZE;\r
- card->status = 0;\r
- for ( i = 0; i < 10; i++ ) card->rtrSub[i] = 0xFFFFFFFFL;\r
- return CL2_OK;\r
- } /* cl2_init_card */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_test_card - test card\r
-* """""""""""""\r
-*\r
-* Test whether the card is installed in system and working properly\r
-* or not. If this function fails (return value is CL2_HW_FAILURE)\r
-* check if the card is present and card base address.\r
-*\r
-* RETURNS:\r
-* CL2_OK - card is present and working properly\r
-* CL2_HW_FAILURE - card not found or card error\r
-*\r
-*/\r
-eCL2_RESULT cl2_test_card\r
- (\r
- sCAN_CARD *card /* Pointer to card structure */\r
- )\r
- {\r
- BOOLEAN1 isAA = FALSE, is55 = FALSE;\r
- int i;\r
- U16 volatile tmpWord;\r
-\r
- /* timeout for card testing - 1000 read cycles */\r
- for ( i = 0; i < 10000; i++ )\r
- {\r
- if ( isAA && is55 ) return CL2_OK;\r
- tmpWord = unican_readw(card->baseAddressPtr);\r
- /*printk("cl2_test_card: %08lx %04x\n", (long)card->baseAddressPtr, tmpWord);*/\r
- udelay(100);\r
- if ( (tmpWord & 0x00FF) == 0x00AA ) isAA = TRUE;\r
- if ( (tmpWord & 0x00FF) == 0x0055 ) is55 = TRUE;\r
- }\r
-\r
- return CL2_HW_FAILURE;\r
- } /* cl2_test_card */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_reset_card - reset card\r
-* """"""""""""""\r
-*\r
-* Card pointed by *card gets hardware reset. This command resets\r
-* card processor, card settings are restored to their default\r
-* values.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-*\r
-*/\r
-eCL2_RESULT cl2_reset_card\r
- (\r
- sCAN_CARD *card /* Pointer to card structure */\r
- )\r
- {\r
- unican_writew(0x0000, card->baseAddressPtr + CL2_RESET_REGISTER);\r
- return CL2_OK;\r
- } /* cl2_reset_card */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_get_version - read card version\r
-* """""""""""""""\r
-*\r
-* Fucntion reads a value from card version register.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-*\r
-*/\r
-eCL2_RESULT cl2_get_version\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- U16 *version /* returns card version */\r
- )\r
- {\r
- *version = unican_readw(card->baseAddressPtr + CL2_VERSION_REGISTER);\r
- return CL2_OK;\r
- } /* cl2_get_version */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_gen_interrupt - request for interrupt\r
-* """""""""""""""""\r
-*\r
-* CAN card is requested to generate interrupt if there is any reason\r
-* to do it. The condition for interrupt generation is defined by\r
-* cl2_int_mode command.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-*\r
-*/\r
-eCL2_RESULT cl2_gen_interrupt\r
- (\r
- sCAN_CARD *card /* Pointer to card structure */\r
- )\r
- {\r
- unican_writew(0x0000, card->baseAddressPtr + CL2_GEN_INT_REGISTER);\r
- return CL2_OK;\r
- } /* cl2_gen_interrupt */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_start_it - start inhibit time\r
-* """"""""""""\r
-*\r
-* Command starts interrupt inhibit time. If there is any reason for\r
-* interrupt geneation, the card generates interrupt after end of\r
-* specified time interval. Time interval is set by cl2_set_iit command.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-*\r
-*/\r
-eCL2_RESULT cl2_start_it\r
- (\r
- sCAN_CARD *card /* Pointer to card structure */\r
- )\r
- {\r
- unican_writew(0x0000, card->baseAddressPtr + CL2_START_IT_REGISTER);\r
- return CL2_OK;\r
- } /* cl2_start_it */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_clear_interrupt - clear interrupt\r
-* """""""""""""""""""\r
-*\r
-* Comand clears interrupt (IRQ) generated by a card.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-*\r
-*/\r
-eCL2_RESULT cl2_clear_interrupt\r
- (\r
- sCAN_CARD *card /* Pointer to card structure */\r
- )\r
- {\r
- unican_writew(0x0000, card->baseAddressPtr + CL2_CLEAR_INT_REGISTER);\r
- return CL2_OK;\r
- } /* cl2_clear_interrupt */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_int_mode - set interrupt mode\r
-* """"""""""""\r
-*\r
-* Command controls, which event will generate interrupt. Constants\r
-* CL2_INT_XXXX are used for setting of interrupt mode.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_BAD_PARAM - bad command parameter\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_int_mode\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- U16 mode /* Interrupt mode */\r
- )\r
- {\r
- if ( mode > INT_MODE_ALL ) return CL2_BAD_PARAM;\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- unican_writew(mode, card->dataPtr);\r
- unican_writew(((U16)cmCL2_INT_MODE + CL2_COMMAND_VALID), card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_int_mode */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_iit_mode - inhibit interrupt time mode\r
-* """"""""""""\r
-*\r
-* Command enables/disables inhibit interupt time mode.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_iit_mode\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- BOOLEAN1 onoff /* IIT mode - TRUE=on, FALSE=off */\r
- )\r
- {\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID ) return\r
- CL2_COMMAND_BUSY;\r
- unican_writew((U16)onoff, card->dataPtr);\r
- unican_writew(((U16)cmCL2_IIT_MODE + CL2_COMMAND_VALID), card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_iit_mode */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_sync_mode - sync mode\r
-* """""""""""""\r
-*\r
-* Command enables/disables transmission of SYNC frames.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_sync_mode\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- BOOLEAN1 onoff /* Sync mode - TRUE=on, FALSE=off */\r
- )\r
- {\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- unican_writew((U16)onoff, card->dataPtr);\r
- unican_writew(((U16)cmCL2_SYNC_MODE + CL2_COMMAND_VALID), card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_sync_mode */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_rtr_mode - rtr mode\r
-* """"""""""""\r
-*\r
-* Command enables/disables automatic transmission of RTR frames\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_rtr_mode\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- BOOLEAN1 onoff /* RTR mode - TRUE=on, FALSE=off */\r
- )\r
- {\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- unican_writew((U16)onoff, card->dataPtr);\r
- unican_writew(((U16)cmCL2_RTR_MODE + CL2_COMMAND_VALID), card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_rtr_mode */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_buf_size - size of synchronous queue\r
-* """"""""""""\r
-*\r
-* Command sets the size of synchronous send buffer. The size is\r
-* in numbers of messages. Default buffer size is 32 messages.\r
-* The sum of synchronous_buffer_size and asynchronous_buffer_size\r
-* is constant and equal to 64. So, if the size od synchronous\r
-* buffer increases, the size of asynchronous buffer decreases and\r
-* vice versa.\r
-* NOTE: 1 message = 16 bytes\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfully\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-* CL2_BAD_PARAM - bad command parameter (bufSize>64)\r
-*\r
-*/\r
-eCL2_RESULT cl2_buf_size\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- U16 bufSize /* Size of synchronous buffer */\r
- )\r
- {\r
- if ( bufSize > 64 ) return CL2_BAD_PARAM;\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- unican_writew(bufSize, card->dataPtr);\r
- unican_writew(((U16)cmCL2_BUF_SIZE + CL2_COMMAND_VALID), card->commandRegister);\r
- card->syncTxBufSize = bufSize;\r
- card->asyncTxBufSize = 64 - bufSize;\r
- card->syncTxBufPtr = card->syncTxBufBase;\r
- card->asyncTxBufPtr = card->asyncTxBufBase = card->syncTxBufBase+bufSize*16;\r
- return CL2_OK;\r
- } /* cl2_buf_size */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_set_iit - set value of inhibit interrupt time\r
-* """""""""""\r
-*\r
-* Command sets value of inhibit interrupt time. If inhibit\r
-* interrupt time mode is enabled and started, generation of\r
-* interrupt (IRQ) is disabled during this time period.\r
-* Inhibit interrupt time can be set from 100 us to 6.5535 s\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_set_iit\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- U16 iit /* time period in x100 us */\r
- )\r
- {\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- unican_writew(iit, card->dataPtr);\r
- unican_writew(((U16)cmCL2_SET_IIT + CL2_COMMAND_VALID), card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_set_iit */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_start_firmware - start firmware\r
-* """"""""""""""""""\r
-*\r
-* Command starts card firmware\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_start_firmware\r
- (\r
- sCAN_CARD *card /* Pointer to card structure */\r
- )\r
- {\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- unican_writew((U16)cmCL2_START_FIRMWARE + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_start_firmware */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_set_rec_mode - set receive mode\r
-* """"""""""""""""\r
-*\r
-* Command sets card receive mode. This enable reception of standard\r
-* or extended frames according to CAN 2.0A and 2.0B specifications.\r
-* If value of mode is TRUE, card receives extended frames, if mode\r
-* is FALSE, card receives standard massage format (default).\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_set_rec_mode\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- BOOLEAN1 mode /* Mode - TRUE=ext, FALSE=std */\r
- )\r
- {\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- unican_writew((U16)mode, card->dataPtr);\r
- unican_writew((U16)cmCL2_SET_REC_MODE + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_set_rec_mode */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_clr_rx_buffer - clear RX buffer\r
-* """""""""""""""""\r
-*\r
-* Command clears receive (rx) buffer. All messages stored in\r
-* rx buffer will be lost.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_clr_rx_buffer\r
- (\r
- sCAN_CARD *card /* Pointer to card structure */\r
- )\r
- {\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- card->rxBufPtr = card->rxBufBase;\r
- unican_writew((U16)cmCL2_CLR_RX_BUFFER + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_clr_rx_buffer */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_clr_sync_buffer - clear synchronous buffer\r
-* """""""""""""""""""\r
-*\r
-* Command clears synchronous send buffer. All messages stored\r
-* in synchronous buffer will be lost.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_clr_sync_buffer\r
- (\r
- sCAN_CARD *card /* Pointer to card structure */\r
- )\r
- {\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- card->syncTxBufPtr = card->syncTxBufBase;\r
- unican_writew((U16)cmCL2_CLR_SYNC_BUFFER + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_clr_sync_buffer */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_clr_async_buffer - clear asynchronous buffer\r
-* """"""""""""""""""""\r
-*\r
-* Command clears asynchronnous send buffer. All messages stored\r
-* in async buffer will be lost.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_clr_async_buffer\r
- (\r
- sCAN_CARD *card /* Pointer to card structure */\r
- )\r
- {\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- card->asyncTxBufPtr = card->syncTxBufBase + card->syncTxBufSize*16;\r
- unican_writew((U16)cmCL2_CLR_ASYNC_BUFFER + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_clr_async_buffer */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_send_time_sync - send time synchronization\r
-* """"""""""""""""""\r
-*\r
-* Command forces the card to start the High Resolution Synchronization\r
-* Protocol according to the CANopen Communication profile. The SYNC\r
-* mode has to be enabled (cl2_sync_mode) otherwise this command has\r
-* no effect.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_send_time_sync\r
- (\r
- sCAN_CARD *card /* Pointer to card structure */\r
- )\r
- {\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- unican_writew((U16)cmCL2_SEND_TIME_SYNC + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_send_time_sync */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_set_time_cobid - set time COB-ID\r
-* """"""""""""""""""\r
-*\r
-* Command sets the COB-ID for high resolution synchronization\r
-* frame. The synchronization can be then made by means of\r
-* cl2_send_time_sync command.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_set_time_cobid\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- U32 COBID /* HRS frame COB-ID */\r
- )\r
- {\r
- U16 cobidL, cobidH;\r
- U16 *ptr = (U16 *)card->dataPtr;\r
-\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
-\r
- if ( COBID & CL2_TMP_EXHIGH ) /* standard or extended format? */\r
- { /* 2.0B frame */\r
- COBID <<= 3;\r
- cobidL = (U16)(COBID & 0x0000FFFFL);\r
- cobidH = (U16)((COBID & 0xFFFF0000L)>>16);\r
- cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));\r
- *ptr++ = cobidH;\r
- cobidL = ((cobidL >> 8) & 0x00FF) | (((cobidL << 8) & 0xFF00));\r
- *ptr++ = cobidL;\r
- *ptr = CL2_TMP_EX2;\r
- }\r
- else\r
- { /* 2.0A frame */\r
- COBID <<= 5;\r
- cobidH = (U16)(COBID & 0x0000FFFFL);\r
- cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));\r
- *ptr++ = cobidH;\r
- *ptr++ = 0;\r
- *ptr = 0;\r
- }\r
-\r
- unican_writew((U16)cmCL2_SET_TIME_COBID + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_set_time_cobid */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_set_receive_limit - set limit for receive signaling\r
-* """""""""""""""""""""\r
-*\r
-* Command is used to set the receive limit signalized by bit\r
-* RL (in CL2.H CL2_X_DATA_IN_RBUF) of the Status Register.\r
-* This bit is set when more then the limit number of frames\r
-* was received since the last interrupt was generated (in interrupt\r
-* mode) or since the Status Register was last time read.\r
-*\r
-* RETURNS:\r
-* CL2_OK\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-* CL2_BAD_PARAM - bad command parameter\r
-*/\r
-eCL2_RESULT cl2_set_receive_limit\r
- (\r
- sCAN_CARD *card, /* pointer to card structure */\r
- U16 limit /* limit of messages in receive buffer */\r
- )\r
- {\r
- if ( limit > 127 ) return CL2_BAD_PARAM;\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- unican_writew(limit, card->dataPtr);\r
- unican_writew((U16)cmCL2_SET_RECEIVE_LIMIT + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_set_receive_limit */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_download_rtr_list - download rtr list\r
-* """""""""""""""""""""\r
-*\r
-* Command downloads a list of up to 64 RTR frames. These frames are\r
-* periodically transmitted by the card. The parameters, how often\r
-* frames are send and in which SYNC period is defined by period and\r
-* subperiod in sRTR_FRAME structure.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-* CL2_BAD_PARAM - bad command parameter\r
-*\r
-*/\r
-eCL2_RESULT cl2_download_rtr_list\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- sRTR_LIST *rtrList /* RTR list */\r
- )\r
- {\r
- U16 *ptrTmp = (U16*)card->dataPtr;\r
- sRTR_FRAME *ptrRTR = rtrList->data;\r
- U16 tmpU16;\r
- U32 COBID;\r
- U16 cobidH, cobidL, i;\r
-\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID ) return\r
- CL2_COMMAND_BUSY;\r
- if ( rtrList->nb > 64 ) return CL2_BAD_PARAM;\r
-\r
- *ptrTmp++ = (U16)rtrList->nb;\r
- for ( i = 0; i < rtrList->nb; i++ )\r
- {\r
- if ( ptrRTR->period < ptrRTR->subperiod ) return CL2_BAD_PARAM;\r
- if ( ptrRTR->subperiod == 0 ) ptrRTR->subperiod = 1;\r
- tmpU16 = (ptrRTR->period & 0x00FF) + ((ptrRTR->subperiod & 0x00FF)<<8);\r
- *ptrTmp++ = tmpU16;\r
- COBID = ptrRTR->cob_id;\r
-\r
- if ( COBID & CL2_TMP_EXHIGH ) /* standard or extended format? */\r
- { /* 2.0B frame */\r
- COBID <<= 3;\r
- cobidL = (U16)(COBID & 0x0000FFFFL);\r
- cobidH = (U16)((COBID & 0xFFFF0000L)>>16);\r
- cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));\r
- *ptrTmp++ = cobidH;\r
- cobidL = ((cobidL >> 8) & 0x00FF) | (((cobidL << 8) & 0xFF00));\r
- *ptrTmp++ = cobidL;\r
- }\r
- else\r
- { /* 2.0A frame */\r
- COBID <<= 5;\r
- cobidH = (U16)(COBID & 0x0000FFFFL);\r
- cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));\r
- *ptrTmp++ = cobidH;\r
- *ptrTmp++ = 0;\r
- }\r
-\r
- *ptrTmp++ = 0x0000; /* rezerva */\r
- ptrRTR++;\r
- }\r
-\r
- unican_writew((U16)cmCL2_DOWNLOAD_RTR_LIST + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_download_rtrlist */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_subscribe_rtr - subscribe RTR frame\r
-* """""""""""""""""\r
-*\r
-* Command subscribes RTR frame. Incoming RTR frames which were\r
-* subscribed are accepted, while other are ignored. Up to 10\r
-* RTR frames can be subscribed.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-* CL2_BAD_PARAM - bad command parameter\r
-*\r
-*/\r
-eCL2_RESULT cl2_subscribe_rtr\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- sCAN_MESSAGE *canMessage, /* RTR frame */\r
- U16 RTRnumber /* number of RTR */\r
- )\r
- {\r
- U16 *ptrU16 = (U16*)card->dataPtr;\r
- U32 COBID;\r
- U16 cobidH, cobidL;\r
-\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- if ( RTRnumber > 9 ) return CL2_BAD_PARAM;\r
-\r
- card->rtrSub[RTRnumber] = canMessage->COB_ID;\r
- *ptrU16 = RTRnumber;\r
- ptrU16++;\r
- COBID = canMessage->COB_ID;\r
-\r
- if ( COBID & CL2_TMP_EXHIGH ) /* standard or extended format? */\r
- { /* 2.0B frame */\r
- COBID <<= 3;\r
- cobidL = (U16)(COBID & 0x0000FFFFL);\r
- cobidH = (U16)((COBID & 0xFFFF0000L)>>16);\r
- cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));\r
- *ptrU16++ = cobidH;\r
- cobidL = ((cobidL >> 8) & 0x00FF) | (((cobidL << 8) & 0xFF00));\r
- *ptrU16++ = cobidL;\r
- *ptrU16 = (U16)CL2_EXT_FRAME;\r
- }\r
- else\r
- { /* 2.0A frame */\r
- COBID <<= 5;\r
- cobidH = (U16)(COBID & 0x0000FFFFL);\r
- cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));\r
- *ptrU16++ = cobidH;\r
- *ptrU16++ = 0;\r
- *ptrU16 = 0;\r
- }\r
-\r
- unican_writew((U16)cmCL2_SUBSCRIBE_RTR + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_subscribe_rtr */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_desubscribe_rtr - desubscribe rtr frame\r
-* """""""""""""""""""\r
-*\r
-* Command desubscribes RTR frame. Card will not accept RTR frames\r
-* with this identifier.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-* CL2_BAD_PARAM - bad command parameter\r
-*\r
-*/\r
-eCL2_RESULT cl2_desubscribe_rtr\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- sCAN_MESSAGE *canMessage /* RTR frame */\r
- )\r
- {\r
- U16 i;\r
-\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
-\r
- for ( i = 0; i < 10; i++ )\r
- {\r
- if ( card->rtrSub[i] == canMessage->COB_ID )\r
- {\r
- card->rtrSub[i] = 0xFFFFFFFFL;\r
- break;\r
- }\r
- }\r
-\r
- if ( i >= 10 ) return CL2_BAD_PARAM;\r
-\r
- unican_writew(i, card->dataPtr);\r
- unican_writew((U16)cmCL2_DESUBSCRIBE_RTR + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_desubscribe_rtr */\r
-\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_set_sync_cobid - set COB-ID\r
-* """"""""""""""""""\r
-*\r
-* Command sets COB-ID of SYNC frame. In active SYNC mode, the SYNC\r
-* frame with this COB-ID is periodically sent with period defined\r
-* by cl2_set_sync_period command.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_set_sync_cobid\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- U32 COBID /* COB-ID */\r
- )\r
- {\r
- U16 cobidL, cobidH;\r
- U16 *ptr = (U16 *)card->dataPtr;\r
-\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
-\r
- if ( COBID & CL2_TMP_EXHIGH ) /* standard or extended format? */\r
- { /* 2.0B frame */\r
- COBID <<= 3;\r
- cobidL = (U16)(COBID & 0x0000FFFFL);\r
- cobidH = (U16)((COBID & 0xFFFF0000L)>>16);\r
- cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));\r
- *ptr++ = cobidH;\r
- cobidL = ((cobidL >> 8) & 0x00FF) | (((cobidL << 8) & 0xFF00));\r
- *ptr++ = cobidL;\r
- *ptr = CL2_TMP_EX2;\r
- }\r
- else\r
- { /* 2.0A frame */\r
- COBID <<= 5;\r
- cobidH = (U16)(COBID & 0x0000FFFFL);\r
- cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));\r
- *ptr++ = cobidH;\r
- *ptr++ = 0;\r
- *ptr = 0;\r
- }\r
-\r
- unican_writew(((U16)cmCL2_SET_COBID + CL2_COMMAND_VALID), card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_set_sync_cobid */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_set_sync_period - set SYNC period\r
-* """""""""""""""""""\r
-*\r
-* Coomand sets the SYNC frame send period in active SYNC mode in\r
-* x100 us. The period range is from 0 to 0xFFFF (SYNC period can\r
-* be set from 100us to 6.5535s).\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_set_sync_period\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- U16 period /* period in x100 us */\r
- )\r
- {\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- unican_writew((U16)period, card->dataPtr);\r
- unican_writew((U16)cmCL2_SET_SYNC_PERIOD + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_set_sync_period */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_set_sync_window - set SYNC window\r
-* """""""""""""""""""\r
-*\r
-* Command sets the SYNC window length. Only during this time period\r
-* after SYNC frame was send or receive the frames from the synchronous\r
-* send buffer can be sent.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_set_sync_window\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- U16 window /* period in x100 us */\r
- )\r
- {\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- unican_writew((U16)window, card->dataPtr);\r
- unican_writew((U16)cmCL2_SET_SYNC_WINDOW + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_set_sync_window */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_set_bitrate - set CAN bit-rate\r
-* """""""""""""""\r
-*\r
-* Command switches the bus bit-rate. There are some predefined\r
-* constants CL2_BITRATE_XXXX.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previous command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_set_bitrate\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- U16 bitrate /* CAN bitrate */\r
- )\r
- {\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- unican_writew(bitrate, card->dataPtr);\r
- unican_writew((U16)cmCL2_SET_BITRATE + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_set_bitrate */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_bus_reset - resets CAN controller\r
-* """""""""""""\r
-*\r
-* Command resets CAN controller\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_COMMAND_BUSY - previously command not completed\r
-*\r
-*/\r
-eCL2_RESULT cl2_bus_reset\r
- (\r
- sCAN_CARD *card\r
- )\r
- {\r
- if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )\r
- return CL2_COMMAND_BUSY;\r
- unican_writew((U16)cmCL2_BUS_RESET + CL2_COMMAND_VALID, card->commandRegister);\r
- return CL2_OK;\r
- } /* cl2_bus_reset */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_send_sync - sends synchronous frame\r
-* """""""""""""\r
-*\r
-* Command stores massage in synchronous send buffer.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_HW_QUEUE_FULL - synchronous send buffer is full\r
-* CL2_BAD_PARAM - bad command parameter\r
-* CL2_HW_FAILURE - error in HW configuration\r
-*\r
-*/\r
-eCL2_RESULT cl2_send_sync\r
- (\r
- sCAN_CARD *card, /* pointer to card */\r
- sCAN_MESSAGE *message /* massage to be sent */\r
- )\r
- {\r
- U32 cobid;\r
- U16 cobidL,cobidH;\r
- U16 *ptrU16 = (U16*)card->syncTxBufPtr;\r
- U16 tmpU16;\r
- int i;\r
- int timeStamp = 0;\r
-\r
- if ( card->syncTxBufSize==0 ) return CL2_HW_FAILURE;\r
- if ( message->dataLength > 8 ) return CL2_BAD_PARAM;\r
- if ( *ptrU16 & CL2_FRAME_VALID ) return CL2_HW_QUEUE_FULL;\r
-\r
- cobid = message->COB_ID;\r
- if ( (message->dataType & CL2_EXT_FRAME) || (cobid & CL2_TMP_EXHIGH) )\r
- { /* 2.0B frame */\r
- cobid <<= 3;\r
- cobidL = (U16)(cobid & 0x0000FFFFL);\r
- cobidH = (U16)((cobid & 0xFFFF0000L)>>16);\r
- }\r
- else\r
- { /* 2.0A frame */\r
- cobid <<= 5;\r
- cobidL = 0;\r
- cobidH = (U16)(cobid & 0x0000FFFFL);\r
- }\r
- ptrU16++;\r
- tmpU16 = (cobidH & 0x00FF) + (cobidL & 0xFF00);\r
- *ptrU16++ = tmpU16;\r
-\r
- tmpU16 = (((U16)message->dataLength) << 12) + (cobidL & 0x00FF);\r
- if ( !(message->dataType & CL2_REMOTE_FRAME) ) tmpU16 |= CL2_TMP_RF;\r
- if ( (message->dataType & CL2_EXT_FRAME) ||\r
- (message->COB_ID & CL2_TMP_EXHIGH) )\r
- tmpU16 |= CL2_TMP_EX;\r
- *ptrU16++ = tmpU16;\r
-\r
- for ( i = 0; i < message->dataLength; )\r
- {\r
- tmpU16 = (U16)message->data[i]; i++;\r
- if ( i == message->dataLength )\r
- {\r
- timeStamp = 1;\r
- tmpU16 |= ((message->timeStamp & 0x00FF)<<8);\r
- *ptrU16++ = tmpU16;\r
- }\r
- else\r
- {\r
- tmpU16 |= ((U16)message->data[i]<<8); i++;\r
- *ptrU16++ = tmpU16;\r
- }\r
- }\r
- if ( timeStamp )\r
- {\r
- tmpU16 = (message->timeStamp>>8) & 0x00FF;\r
- *ptrU16 = tmpU16;\r
- }\r
- else\r
- {\r
- *ptrU16 = message->timeStamp;\r
- }\r
-\r
- tmpU16 = (((U16)cobidH) & 0xFF00) | CL2_MESSAGE_VALID;\r
- unican_writew(tmpU16, card->syncTxBufPtr);\r
-\r
- if ( (card->syncTxBufBase + card->syncTxBufSize*16) <=\r
- (card->syncTxBufPtr += 16) )\r
- {\r
- card->syncTxBufPtr = card->syncTxBufBase;\r
- }\r
- return CL2_OK;\r
- } /* cl2_send_sync */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_send_async - sends asynchronous frame\r
-* """"""""""""""\r
-*\r
-* Command stores message in asynchronous send buffer.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_HW_QUEUE_FULL - asynchronous buffer full\r
-* CL2_HW_FAILURE - error in HW configuration\r
-* CL2_BAD_PARAM - bad command parameter\r
-*\r
-*/\r
-eCL2_RESULT cl2_send_async\r
- (\r
- sCAN_CARD *card, /* pointer to card */\r
- sCAN_MESSAGE *message /* message to be sent */\r
- )\r
- {\r
- U32 cobid;\r
- U16 cobidL,cobidH;\r
- U16 *ptrU16 = (U16*)card->asyncTxBufPtr;\r
- U16 tmpU16;\r
- int i;\r
- int timeStamp = 0;\r
-\r
- if ( card->asyncTxBufSize==0 ) return CL2_HW_FAILURE;\r
- if ( message->dataLength > 8 ) return CL2_BAD_PARAM;\r
- if ( *ptrU16 & CL2_FRAME_VALID ) return CL2_HW_QUEUE_FULL;\r
-\r
- cobid = message->COB_ID;\r
- if ( (message->dataType & CL2_EXT_FRAME) || (cobid & CL2_TMP_EXHIGH) )\r
- { /* 2.0B frame */\r
- cobid <<= 3;\r
- cobidL = (U16)(cobid & 0x0000FFFFL);\r
- cobidH = (U16)((cobid & 0xFFFF0000L)>>16);\r
- }\r
- else\r
- { /* 2.0A frame */\r
- cobid <<= 5;\r
- cobidL = 0;\r
- cobidH = (U16)(cobid & 0x0000FFFFL);\r
- }\r
- ptrU16++;\r
- tmpU16 = (cobidH & 0x00FF ) + (cobidL & 0xFF00);\r
- *ptrU16++ = tmpU16;\r
-\r
- tmpU16 = (((U16)message->dataLength) << 12) + (cobidL & 0x00FF);\r
- if ( !(message->dataType & CL2_REMOTE_FRAME) ) tmpU16 |= CL2_TMP_RF;\r
- if ( (message->dataType & CL2_EXT_FRAME) ||\r
- (message->COB_ID & CL2_TMP_EXHIGH ) )\r
- tmpU16 |= CL2_TMP_EX;\r
- *ptrU16++ = tmpU16;\r
-\r
- for ( i = 0; i < message->dataLength; )\r
- {\r
- tmpU16 = (U16)message->data[i]; i++;\r
- if ( i == message->dataLength )\r
- {\r
- timeStamp = 1;\r
- tmpU16 |= ((message->timeStamp & 0x00FF)<<8);\r
- *ptrU16++ = tmpU16;\r
- }\r
- else\r
- {\r
- tmpU16 |= ((U16)message->data[i]<<8); i++;\r
- *ptrU16++ = tmpU16;\r
- }\r
- }\r
- if ( timeStamp )\r
- {\r
- tmpU16 = (message->timeStamp>>8) & 0x00FF;\r
- *ptrU16 = tmpU16;\r
- }\r
- else\r
- {\r
- *ptrU16 = message->timeStamp;\r
- }\r
-\r
- tmpU16 = (((U16)cobidH) & 0xFF00) | CL2_MESSAGE_VALID;\r
- unican_writew(tmpU16, card->asyncTxBufPtr);\r
-\r
- if ( (card->asyncTxBufBase + card->asyncTxBufSize*16) <=\r
- (card->asyncTxBufPtr += 16) )\r
- {\r
- card->asyncTxBufPtr = card->asyncTxBufBase;\r
- }\r
- return CL2_OK;\r
- } /* cl2_send_async */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_get_status - reads card status\r
-* """"""""""""""\r
-*\r
-* Command reads card status register. If data in status register\r
-* are valid (status valid flag is set), the value of status is read\r
-* and stored in status and sCAN_CARD structure.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command completed successfuly\r
-* CL2_NO_REQUEST - status is not valid\r
-*\r
-*/\r
-eCL2_RESULT cl2_get_status\r
- (\r
- sCAN_CARD *card, /* pointer to card */\r
- U16 *status /* card status word */\r
- )\r
- {\r
- U16 *ptr;\r
-\r
- ptr = (U16*)(card->baseAddressPtr + CL2_STATUS_REGISTER);\r
- *status = *ptr;\r
- if ( (*status & CL2_STATUS_VALID_FLAG) )\r
- {\r
- *ptr = *status & ~CL2_STATUS_VALID_FLAG;\r
- card->status = *status;\r
- return CL2_OK;\r
- }\r
- return CL2_NO_REQUEST;\r
- } /* cl2_get_status */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_get_error - reads card error\r
-* """""""""""""\r
-*\r
-* Command reads card error register. If data in error register\r
-* are valid (error register valid flag is set), the value of error\r
-* register is read and stored in error and sCAN_CARD structure.\r
-*\r
-* RETURNS:\r
-* Cl2_OK - command completed successfuly\r
-*\r
-*/\r
-eCL2_RESULT cl2_get_error\r
- (\r
- sCAN_CARD *card, /* pointer to card */\r
- U16 *error /* card error word */\r
- )\r
- {\r
- U16 *ptr;\r
-\r
- ptr = (U16*)(card->baseAddressPtr + CL2_ERROR_REGISTER);\r
- *error = *ptr;\r
- card->error |= *error;\r
- *ptr = 0x0000;\r
- return CL2_OK;\r
- } /* cl2_get_error */\r
-\r
-\r
-/*******************************************************************************\r
-* cl2_receive_data - reads received frame\r
-* """"""""""""""""\r
-*\r
-* Command reads new messages received by a card.\r
-*\r
-* RETURNS:\r
-* CL2_OK - command commpleted successfuly\r
-* CL2_NO_REQUEST - there is no new message\r
-*\r
-*/\r
-eCL2_RESULT cl2_receive_data\r
- (\r
- sCAN_CARD *card, /* Pointer to card structure */\r
- sCAN_MESSAGE *canMessage /* Message */\r
- )\r
- {\r
- U16 *ptrU16 = (U16*)card->rxBufPtr;\r
- U16 tmpU16;\r
- U16 i;\r
-\r
- tmpU16 = *ptrU16++;\r
- if ( !(tmpU16 & CL2_MESSAGE_VALID) ) return CL2_NO_REQUEST;\r
- canMessage->COB_ID = ((U32)(tmpU16 & 0xFF00 )) << 16;\r
- tmpU16 = *ptrU16++;\r
- canMessage->COB_ID |= ((U32)( tmpU16 & 0x00FF )) << 16;\r
- canMessage->COB_ID |= (U32)( tmpU16 & 0xFF00 );\r
- tmpU16 = *ptrU16++;\r
- canMessage->COB_ID |= (U32)( tmpU16 & 0x00FF );\r
- canMessage->dataType = (U8)(( tmpU16 & 0xFF00 ) >> 8);\r
-\r
- if ( canMessage->dataType & CL2_EXT_FRAME )\r
- { /* 2.0B frame */\r
- canMessage->COB_ID >>= 3;\r
- /* canMessage->COB_ID |= CL2_TMP_EXHIGH; */\r
- }\r
- else\r
- { /* 2.0A frame */\r
- canMessage->COB_ID >>= 21;\r
- }\r
- canMessage->dataLength = (U8)( (tmpU16 >> 12) & 0x000F );\r
- /* if ( !(tmpU16 & CL2_TMP_RF) ) canMessage->dataType |= CL2_REMOTE_FRAME; */\r
- for ( i = 0; i < canMessage->dataLength; )\r
- {\r
- tmpU16 = *ptrU16++;\r
- canMessage->data[i++] = (U8)( tmpU16 );\r
- canMessage->data[i++] = (U8)( tmpU16 >> 8 );\r
- }\r
- if ( canMessage->dataLength & 0x01 )\r
- { /* odd */\r
- canMessage->timeStamp = ( (*ptrU16 & 0x00FF) | (tmpU16 & 0xFF00) );\r
- }\r
- else /* even */\r
- {\r
- canMessage->timeStamp = *ptrU16 << 8 | *ptrU16 >> 8;\r
- }\r
- unican_writew(0x0000, card->rxBufPtr);\r
-\r
- /* increment rx-buffer pointer */\r
- if ( (card->rxBufBase + card->rxBufSize*16 ) <= (card->rxBufPtr += 16) )\r
- {\r
- card->rxBufPtr = card->rxBufBase;\r
- }\r
-\r
- return CL2_OK;\r
- } /* cl2_receive_data */\r
-\r
-\r
-/* **************************************************************** *\r
- * END OF CL2.C *\r
- * **************************************************************** */\r
-\r
-\r
+/**************************************************************************/
+/* File: unican_cl2.c - Unicontrols PCAN,PCAN-PCI, VCAN core support */
+/* */
+/* LinCAN - (Not only) Linux CAN bus driver */
+/* Copyright (C) 2002-2009 DCE FEE CTU Prague <http://dce.felk.cvut.cz> */
+/* Copyright (C) 2002-2009 Pavel Pisa <pisa@cmp.felk.cvut.cz> */
+/* Copyright (C) 1997 F. Spurny, CVUT FEL, Dept. of Measurement */
+/* Copyright (C) 1997 Unicontrols a.s. */
+/* Funded by OCERA and FRESCOR IST projects */
+/* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl> */
+/* */
+/* LinCAN is free software; you can redistribute it and/or modify it */
+/* under terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2, or (at your option) any */
+/* later version. LinCAN is distributed in the hope that it will be */
+/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
+/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
+/* General Public License for more details. You should have received a */
+/* copy of the GNU General Public License along with LinCAN; see file */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */
+/* Cambridge, MA 02139, USA. */
+/* */
+/* To allow use of LinCAN in the compact embedded systems firmware */
+/* and RT-executives (RTEMS for example), main authors agree with next */
+/* special exception: */
+/* */
+/* Including LinCAN header files in a file, instantiating LinCAN generics */
+/* or templates, or linking other files with LinCAN objects to produce */
+/* an application image/executable, does not by itself cause the */
+/* resulting application image/executable to be covered by */
+/* the GNU General Public License. */
+/* This exception does not however invalidate any other reasons */
+/* why the executable file might be covered by the GNU Public License. */
+/* Publication of enhanced or derived LinCAN files is required although. */
+/**************************************************************************/
+
+
+/* Constnt used by CL2 functions */
+#define CL2_TMP_RF 0x0800
+#define CL2_TMP_EX 0x0400
+#define CL2_TMP_EX2 0x0004
+#define CL2_TMP_EXHIGH 0x80000000L
+
+
+/* includes */
+#include "../include/canmsg.h"
+#include "../include/can_sysdep.h"
+#include "../include/unican_types.h"
+#include "../include/unican_cl2.h"
+#include "linux/delay.h"
+
+
+/*******************************************************************************
+* cl2_init_card - initialize card to default parameters
+* """""""""""""
+*
+* Command installs card. The data in sCAN_CARD structure pointed
+* by *card are initialized to their predefined default values.
+* Command must be called before any operation with sCAN_CARD
+* structure.
+*
+* RETURNS:
+* CL2_OK - command completed succesfuly
+*
+*/
+eCL2_RESULT cl2_init_card
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ void *baseAddress, /* Card base address pointer */
+ U16 intNumber /* Card interrupt number */
+ )
+ {
+ int i;
+
+ card->intNumber = intNumber;
+ card->baseAddressPtr = (U8*)baseAddress;
+ card->rxBufBase = card->baseAddressPtr + CL2_RX_BUFFER_DEFAULT;
+ card->asyncTxBufBase = card->baseAddressPtr + CL2_ASYNC_BUFFER_DEFAULT;
+ card->syncTxBufBase = card->baseAddressPtr + CL2_SYNC_BUFFER_DEFAULT;
+ card->rxBufPtr = card->rxBufBase;
+ card->asyncTxBufPtr = card->asyncTxBufBase;
+ card->syncTxBufPtr = card->syncTxBufBase;
+ card->commandRegister = card->baseAddressPtr+CL2_COMMAND_REGISTER;
+ card->dataPtr = card->baseAddressPtr + CL2_DATA_BUFFER;
+ card->rxBufSize = CL2_RX_BUFFER_SIZE;
+ card->syncTxBufSize = CL2_TX_SYNC_BUFFER_SIZE;
+ card->asyncTxBufSize = CL2_TX_ASYNC_BUFFER_SIZE;
+ card->status = 0;
+ for ( i = 0; i < 10; i++ ) card->rtrSub[i] = 0xFFFFFFFFL;
+ return CL2_OK;
+ } /* cl2_init_card */
+
+
+/*******************************************************************************
+* cl2_test_card - test card
+* """""""""""""
+*
+* Test whether the card is installed in system and working properly
+* or not. If this function fails (return value is CL2_HW_FAILURE)
+* check if the card is present and card base address.
+*
+* RETURNS:
+* CL2_OK - card is present and working properly
+* CL2_HW_FAILURE - card not found or card error
+*
+*/
+eCL2_RESULT cl2_test_card
+ (
+ sCAN_CARD *card /* Pointer to card structure */
+ )
+ {
+ BOOLEAN1 isAA = FALSE, is55 = FALSE;
+ int i;
+ U16 volatile tmpWord;
+
+ /* timeout for card testing - 1000 read cycles */
+ for ( i = 0; i < 10000; i++ )
+ {
+ if ( isAA && is55 ) return CL2_OK;
+ tmpWord = unican_readw(card->baseAddressPtr);
+ /*printk("cl2_test_card: %08lx %04x\n", (long)card->baseAddressPtr, tmpWord);*/
+ udelay(100);
+ if ( (tmpWord & 0x00FF) == 0x00AA ) isAA = TRUE;
+ if ( (tmpWord & 0x00FF) == 0x0055 ) is55 = TRUE;
+ }
+
+ return CL2_HW_FAILURE;
+ } /* cl2_test_card */
+
+
+/*******************************************************************************
+* cl2_reset_card - reset card
+* """"""""""""""
+*
+* Card pointed by *card gets hardware reset. This command resets
+* card processor, card settings are restored to their default
+* values.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+*
+*/
+eCL2_RESULT cl2_reset_card
+ (
+ sCAN_CARD *card /* Pointer to card structure */
+ )
+ {
+ unican_writew(0x0000, card->baseAddressPtr + CL2_RESET_REGISTER);
+ return CL2_OK;
+ } /* cl2_reset_card */
+
+
+/*******************************************************************************
+* cl2_get_version - read card version
+* """""""""""""""
+*
+* Fucntion reads a value from card version register.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+*
+*/
+eCL2_RESULT cl2_get_version
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ U16 *version /* returns card version */
+ )
+ {
+ *version = unican_readw(card->baseAddressPtr + CL2_VERSION_REGISTER);
+ return CL2_OK;
+ } /* cl2_get_version */
+
+
+/*******************************************************************************
+* cl2_gen_interrupt - request for interrupt
+* """""""""""""""""
+*
+* CAN card is requested to generate interrupt if there is any reason
+* to do it. The condition for interrupt generation is defined by
+* cl2_int_mode command.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+*
+*/
+eCL2_RESULT cl2_gen_interrupt
+ (
+ sCAN_CARD *card /* Pointer to card structure */
+ )
+ {
+ unican_writew(0x0000, card->baseAddressPtr + CL2_GEN_INT_REGISTER);
+ return CL2_OK;
+ } /* cl2_gen_interrupt */
+
+
+/*******************************************************************************
+* cl2_start_it - start inhibit time
+* """"""""""""
+*
+* Command starts interrupt inhibit time. If there is any reason for
+* interrupt geneation, the card generates interrupt after end of
+* specified time interval. Time interval is set by cl2_set_iit command.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+*
+*/
+eCL2_RESULT cl2_start_it
+ (
+ sCAN_CARD *card /* Pointer to card structure */
+ )
+ {
+ unican_writew(0x0000, card->baseAddressPtr + CL2_START_IT_REGISTER);
+ return CL2_OK;
+ } /* cl2_start_it */
+
+
+/*******************************************************************************
+* cl2_clear_interrupt - clear interrupt
+* """""""""""""""""""
+*
+* Comand clears interrupt (IRQ) generated by a card.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+*
+*/
+eCL2_RESULT cl2_clear_interrupt
+ (
+ sCAN_CARD *card /* Pointer to card structure */
+ )
+ {
+ unican_writew(0x0000, card->baseAddressPtr + CL2_CLEAR_INT_REGISTER);
+ return CL2_OK;
+ } /* cl2_clear_interrupt */
+
+
+/*******************************************************************************
+* cl2_int_mode - set interrupt mode
+* """"""""""""
+*
+* Command controls, which event will generate interrupt. Constants
+* CL2_INT_XXXX are used for setting of interrupt mode.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_BAD_PARAM - bad command parameter
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_int_mode
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ U16 mode /* Interrupt mode */
+ )
+ {
+ if ( mode > INT_MODE_ALL ) return CL2_BAD_PARAM;
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ unican_writew(mode, card->dataPtr);
+ unican_writew(((U16)cmCL2_INT_MODE + CL2_COMMAND_VALID), card->commandRegister);
+ return CL2_OK;
+ } /* cl2_int_mode */
+
+
+/*******************************************************************************
+* cl2_iit_mode - inhibit interrupt time mode
+* """"""""""""
+*
+* Command enables/disables inhibit interupt time mode.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_iit_mode
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ BOOLEAN1 onoff /* IIT mode - TRUE=on, FALSE=off */
+ )
+ {
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID ) return
+ CL2_COMMAND_BUSY;
+ unican_writew((U16)onoff, card->dataPtr);
+ unican_writew(((U16)cmCL2_IIT_MODE + CL2_COMMAND_VALID), card->commandRegister);
+ return CL2_OK;
+ } /* cl2_iit_mode */
+
+
+/*******************************************************************************
+* cl2_sync_mode - sync mode
+* """""""""""""
+*
+* Command enables/disables transmission of SYNC frames.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_sync_mode
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ BOOLEAN1 onoff /* Sync mode - TRUE=on, FALSE=off */
+ )
+ {
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ unican_writew((U16)onoff, card->dataPtr);
+ unican_writew(((U16)cmCL2_SYNC_MODE + CL2_COMMAND_VALID), card->commandRegister);
+ return CL2_OK;
+ } /* cl2_sync_mode */
+
+
+/*******************************************************************************
+* cl2_rtr_mode - rtr mode
+* """"""""""""
+*
+* Command enables/disables automatic transmission of RTR frames
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_rtr_mode
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ BOOLEAN1 onoff /* RTR mode - TRUE=on, FALSE=off */
+ )
+ {
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ unican_writew((U16)onoff, card->dataPtr);
+ unican_writew(((U16)cmCL2_RTR_MODE + CL2_COMMAND_VALID), card->commandRegister);
+ return CL2_OK;
+ } /* cl2_rtr_mode */
+
+
+/*******************************************************************************
+* cl2_buf_size - size of synchronous queue
+* """"""""""""
+*
+* Command sets the size of synchronous send buffer. The size is
+* in numbers of messages. Default buffer size is 32 messages.
+* The sum of synchronous_buffer_size and asynchronous_buffer_size
+* is constant and equal to 64. So, if the size od synchronous
+* buffer increases, the size of asynchronous buffer decreases and
+* vice versa.
+* NOTE: 1 message = 16 bytes
+*
+* RETURNS:
+* CL2_OK - command completed successfully
+* CL2_COMMAND_BUSY - previous command not completed
+* CL2_BAD_PARAM - bad command parameter (bufSize>64)
+*
+*/
+eCL2_RESULT cl2_buf_size
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ U16 bufSize /* Size of synchronous buffer */
+ )
+ {
+ if ( bufSize > 64 ) return CL2_BAD_PARAM;
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ unican_writew(bufSize, card->dataPtr);
+ unican_writew(((U16)cmCL2_BUF_SIZE + CL2_COMMAND_VALID), card->commandRegister);
+ card->syncTxBufSize = bufSize;
+ card->asyncTxBufSize = 64 - bufSize;
+ card->syncTxBufPtr = card->syncTxBufBase;
+ card->asyncTxBufPtr = card->asyncTxBufBase = card->syncTxBufBase+bufSize*16;
+ return CL2_OK;
+ } /* cl2_buf_size */
+
+
+/*******************************************************************************
+* cl2_set_iit - set value of inhibit interrupt time
+* """""""""""
+*
+* Command sets value of inhibit interrupt time. If inhibit
+* interrupt time mode is enabled and started, generation of
+* interrupt (IRQ) is disabled during this time period.
+* Inhibit interrupt time can be set from 100 us to 6.5535 s
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_set_iit
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ U16 iit /* time period in x100 us */
+ )
+ {
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ unican_writew(iit, card->dataPtr);
+ unican_writew(((U16)cmCL2_SET_IIT + CL2_COMMAND_VALID), card->commandRegister);
+ return CL2_OK;
+ } /* cl2_set_iit */
+
+
+/*******************************************************************************
+* cl2_start_firmware - start firmware
+* """"""""""""""""""
+*
+* Command starts card firmware
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_start_firmware
+ (
+ sCAN_CARD *card /* Pointer to card structure */
+ )
+ {
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ unican_writew((U16)cmCL2_START_FIRMWARE + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_start_firmware */
+
+
+/*******************************************************************************
+* cl2_set_rec_mode - set receive mode
+* """"""""""""""""
+*
+* Command sets card receive mode. This enable reception of standard
+* or extended frames according to CAN 2.0A and 2.0B specifications.
+* If value of mode is TRUE, card receives extended frames, if mode
+* is FALSE, card receives standard massage format (default).
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_set_rec_mode
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ BOOLEAN1 mode /* Mode - TRUE=ext, FALSE=std */
+ )
+ {
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ unican_writew((U16)mode, card->dataPtr);
+ unican_writew((U16)cmCL2_SET_REC_MODE + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_set_rec_mode */
+
+
+/*******************************************************************************
+* cl2_clr_rx_buffer - clear RX buffer
+* """""""""""""""""
+*
+* Command clears receive (rx) buffer. All messages stored in
+* rx buffer will be lost.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_clr_rx_buffer
+ (
+ sCAN_CARD *card /* Pointer to card structure */
+ )
+ {
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ card->rxBufPtr = card->rxBufBase;
+ unican_writew((U16)cmCL2_CLR_RX_BUFFER + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_clr_rx_buffer */
+
+
+/*******************************************************************************
+* cl2_clr_sync_buffer - clear synchronous buffer
+* """""""""""""""""""
+*
+* Command clears synchronous send buffer. All messages stored
+* in synchronous buffer will be lost.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_clr_sync_buffer
+ (
+ sCAN_CARD *card /* Pointer to card structure */
+ )
+ {
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ card->syncTxBufPtr = card->syncTxBufBase;
+ unican_writew((U16)cmCL2_CLR_SYNC_BUFFER + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_clr_sync_buffer */
+
+
+/*******************************************************************************
+* cl2_clr_async_buffer - clear asynchronous buffer
+* """"""""""""""""""""
+*
+* Command clears asynchronnous send buffer. All messages stored
+* in async buffer will be lost.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_clr_async_buffer
+ (
+ sCAN_CARD *card /* Pointer to card structure */
+ )
+ {
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ card->asyncTxBufPtr = card->syncTxBufBase + card->syncTxBufSize*16;
+ unican_writew((U16)cmCL2_CLR_ASYNC_BUFFER + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_clr_async_buffer */
+
+
+/*******************************************************************************
+* cl2_send_time_sync - send time synchronization
+* """"""""""""""""""
+*
+* Command forces the card to start the High Resolution Synchronization
+* Protocol according to the CANopen Communication profile. The SYNC
+* mode has to be enabled (cl2_sync_mode) otherwise this command has
+* no effect.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_send_time_sync
+ (
+ sCAN_CARD *card /* Pointer to card structure */
+ )
+ {
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ unican_writew((U16)cmCL2_SEND_TIME_SYNC + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_send_time_sync */
+
+
+/*******************************************************************************
+* cl2_set_time_cobid - set time COB-ID
+* """"""""""""""""""
+*
+* Command sets the COB-ID for high resolution synchronization
+* frame. The synchronization can be then made by means of
+* cl2_send_time_sync command.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_set_time_cobid
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ U32 COBID /* HRS frame COB-ID */
+ )
+ {
+ U16 cobidL, cobidH;
+ U16 *ptr = (U16 *)card->dataPtr;
+
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+
+ if ( COBID & CL2_TMP_EXHIGH ) /* standard or extended format? */
+ { /* 2.0B frame */
+ COBID <<= 3;
+ cobidL = (U16)(COBID & 0x0000FFFFL);
+ cobidH = (U16)((COBID & 0xFFFF0000L)>>16);
+ cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));
+ *ptr++ = cobidH;
+ cobidL = ((cobidL >> 8) & 0x00FF) | (((cobidL << 8) & 0xFF00));
+ *ptr++ = cobidL;
+ *ptr = CL2_TMP_EX2;
+ }
+ else
+ { /* 2.0A frame */
+ COBID <<= 5;
+ cobidH = (U16)(COBID & 0x0000FFFFL);
+ cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));
+ *ptr++ = cobidH;
+ *ptr++ = 0;
+ *ptr = 0;
+ }
+
+ unican_writew((U16)cmCL2_SET_TIME_COBID + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_set_time_cobid */
+
+
+/*******************************************************************************
+* cl2_set_receive_limit - set limit for receive signaling
+* """""""""""""""""""""
+*
+* Command is used to set the receive limit signalized by bit
+* RL (in CL2.H CL2_X_DATA_IN_RBUF) of the Status Register.
+* This bit is set when more then the limit number of frames
+* was received since the last interrupt was generated (in interrupt
+* mode) or since the Status Register was last time read.
+*
+* RETURNS:
+* CL2_OK
+* CL2_COMMAND_BUSY - previous command not completed
+* CL2_BAD_PARAM - bad command parameter
+*/
+eCL2_RESULT cl2_set_receive_limit
+ (
+ sCAN_CARD *card, /* pointer to card structure */
+ U16 limit /* limit of messages in receive buffer */
+ )
+ {
+ if ( limit > 127 ) return CL2_BAD_PARAM;
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ unican_writew(limit, card->dataPtr);
+ unican_writew((U16)cmCL2_SET_RECEIVE_LIMIT + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_set_receive_limit */
+
+
+/*******************************************************************************
+* cl2_download_rtr_list - download rtr list
+* """""""""""""""""""""
+*
+* Command downloads a list of up to 64 RTR frames. These frames are
+* periodically transmitted by the card. The parameters, how often
+* frames are send and in which SYNC period is defined by period and
+* subperiod in sRTR_FRAME structure.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+* CL2_BAD_PARAM - bad command parameter
+*
+*/
+eCL2_RESULT cl2_download_rtr_list
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ sRTR_LIST *rtrList /* RTR list */
+ )
+ {
+ U16 *ptrTmp = (U16*)card->dataPtr;
+ sRTR_FRAME *ptrRTR = rtrList->data;
+ U16 tmpU16;
+ U32 COBID;
+ U16 cobidH, cobidL, i;
+
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID ) return
+ CL2_COMMAND_BUSY;
+ if ( rtrList->nb > 64 ) return CL2_BAD_PARAM;
+
+ *ptrTmp++ = (U16)rtrList->nb;
+ for ( i = 0; i < rtrList->nb; i++ )
+ {
+ if ( ptrRTR->period < ptrRTR->subperiod ) return CL2_BAD_PARAM;
+ if ( ptrRTR->subperiod == 0 ) ptrRTR->subperiod = 1;
+ tmpU16 = (ptrRTR->period & 0x00FF) + ((ptrRTR->subperiod & 0x00FF)<<8);
+ *ptrTmp++ = tmpU16;
+ COBID = ptrRTR->cob_id;
+
+ if ( COBID & CL2_TMP_EXHIGH ) /* standard or extended format? */
+ { /* 2.0B frame */
+ COBID <<= 3;
+ cobidL = (U16)(COBID & 0x0000FFFFL);
+ cobidH = (U16)((COBID & 0xFFFF0000L)>>16);
+ cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));
+ *ptrTmp++ = cobidH;
+ cobidL = ((cobidL >> 8) & 0x00FF) | (((cobidL << 8) & 0xFF00));
+ *ptrTmp++ = cobidL;
+ }
+ else
+ { /* 2.0A frame */
+ COBID <<= 5;
+ cobidH = (U16)(COBID & 0x0000FFFFL);
+ cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));
+ *ptrTmp++ = cobidH;
+ *ptrTmp++ = 0;
+ }
+
+ *ptrTmp++ = 0x0000; /* rezerva */
+ ptrRTR++;
+ }
+
+ unican_writew((U16)cmCL2_DOWNLOAD_RTR_LIST + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_download_rtrlist */
+
+
+/*******************************************************************************
+* cl2_subscribe_rtr - subscribe RTR frame
+* """""""""""""""""
+*
+* Command subscribes RTR frame. Incoming RTR frames which were
+* subscribed are accepted, while other are ignored. Up to 10
+* RTR frames can be subscribed.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+* CL2_BAD_PARAM - bad command parameter
+*
+*/
+eCL2_RESULT cl2_subscribe_rtr
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ sCAN_MESSAGE *canMessage, /* RTR frame */
+ U16 RTRnumber /* number of RTR */
+ )
+ {
+ U16 *ptrU16 = (U16*)card->dataPtr;
+ U32 COBID;
+ U16 cobidH, cobidL;
+
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ if ( RTRnumber > 9 ) return CL2_BAD_PARAM;
+
+ card->rtrSub[RTRnumber] = canMessage->COB_ID;
+ *ptrU16 = RTRnumber;
+ ptrU16++;
+ COBID = canMessage->COB_ID;
+
+ if ( COBID & CL2_TMP_EXHIGH ) /* standard or extended format? */
+ { /* 2.0B frame */
+ COBID <<= 3;
+ cobidL = (U16)(COBID & 0x0000FFFFL);
+ cobidH = (U16)((COBID & 0xFFFF0000L)>>16);
+ cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));
+ *ptrU16++ = cobidH;
+ cobidL = ((cobidL >> 8) & 0x00FF) | (((cobidL << 8) & 0xFF00));
+ *ptrU16++ = cobidL;
+ *ptrU16 = (U16)CL2_EXT_FRAME;
+ }
+ else
+ { /* 2.0A frame */
+ COBID <<= 5;
+ cobidH = (U16)(COBID & 0x0000FFFFL);
+ cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));
+ *ptrU16++ = cobidH;
+ *ptrU16++ = 0;
+ *ptrU16 = 0;
+ }
+
+ unican_writew((U16)cmCL2_SUBSCRIBE_RTR + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_subscribe_rtr */
+
+
+/*******************************************************************************
+* cl2_desubscribe_rtr - desubscribe rtr frame
+* """""""""""""""""""
+*
+* Command desubscribes RTR frame. Card will not accept RTR frames
+* with this identifier.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+* CL2_BAD_PARAM - bad command parameter
+*
+*/
+eCL2_RESULT cl2_desubscribe_rtr
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ sCAN_MESSAGE *canMessage /* RTR frame */
+ )
+ {
+ U16 i;
+
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+
+ for ( i = 0; i < 10; i++ )
+ {
+ if ( card->rtrSub[i] == canMessage->COB_ID )
+ {
+ card->rtrSub[i] = 0xFFFFFFFFL;
+ break;
+ }
+ }
+
+ if ( i >= 10 ) return CL2_BAD_PARAM;
+
+ unican_writew(i, card->dataPtr);
+ unican_writew((U16)cmCL2_DESUBSCRIBE_RTR + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_desubscribe_rtr */
+
+
+
+/*******************************************************************************
+* cl2_set_sync_cobid - set COB-ID
+* """"""""""""""""""
+*
+* Command sets COB-ID of SYNC frame. In active SYNC mode, the SYNC
+* frame with this COB-ID is periodically sent with period defined
+* by cl2_set_sync_period command.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_set_sync_cobid
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ U32 COBID /* COB-ID */
+ )
+ {
+ U16 cobidL, cobidH;
+ U16 *ptr = (U16 *)card->dataPtr;
+
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+
+ if ( COBID & CL2_TMP_EXHIGH ) /* standard or extended format? */
+ { /* 2.0B frame */
+ COBID <<= 3;
+ cobidL = (U16)(COBID & 0x0000FFFFL);
+ cobidH = (U16)((COBID & 0xFFFF0000L)>>16);
+ cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));
+ *ptr++ = cobidH;
+ cobidL = ((cobidL >> 8) & 0x00FF) | (((cobidL << 8) & 0xFF00));
+ *ptr++ = cobidL;
+ *ptr = CL2_TMP_EX2;
+ }
+ else
+ { /* 2.0A frame */
+ COBID <<= 5;
+ cobidH = (U16)(COBID & 0x0000FFFFL);
+ cobidH = ((cobidH >> 8) & 0x00FF) | (((cobidH << 8) & 0xFF00));
+ *ptr++ = cobidH;
+ *ptr++ = 0;
+ *ptr = 0;
+ }
+
+ unican_writew(((U16)cmCL2_SET_COBID + CL2_COMMAND_VALID), card->commandRegister);
+ return CL2_OK;
+ } /* cl2_set_sync_cobid */
+
+
+/*******************************************************************************
+* cl2_set_sync_period - set SYNC period
+* """""""""""""""""""
+*
+* Coomand sets the SYNC frame send period in active SYNC mode in
+* x100 us. The period range is from 0 to 0xFFFF (SYNC period can
+* be set from 100us to 6.5535s).
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_set_sync_period
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ U16 period /* period in x100 us */
+ )
+ {
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ unican_writew((U16)period, card->dataPtr);
+ unican_writew((U16)cmCL2_SET_SYNC_PERIOD + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_set_sync_period */
+
+
+/*******************************************************************************
+* cl2_set_sync_window - set SYNC window
+* """""""""""""""""""
+*
+* Command sets the SYNC window length. Only during this time period
+* after SYNC frame was send or receive the frames from the synchronous
+* send buffer can be sent.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_set_sync_window
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ U16 window /* period in x100 us */
+ )
+ {
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ unican_writew((U16)window, card->dataPtr);
+ unican_writew((U16)cmCL2_SET_SYNC_WINDOW + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_set_sync_window */
+
+
+/*******************************************************************************
+* cl2_set_bitrate - set CAN bit-rate
+* """""""""""""""
+*
+* Command switches the bus bit-rate. There are some predefined
+* constants CL2_BITRATE_XXXX.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previous command not completed
+*
+*/
+eCL2_RESULT cl2_set_bitrate
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ U16 bitrate /* CAN bitrate */
+ )
+ {
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ unican_writew(bitrate, card->dataPtr);
+ unican_writew((U16)cmCL2_SET_BITRATE + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_set_bitrate */
+
+
+/*******************************************************************************
+* cl2_bus_reset - resets CAN controller
+* """""""""""""
+*
+* Command resets CAN controller
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_COMMAND_BUSY - previously command not completed
+*
+*/
+eCL2_RESULT cl2_bus_reset
+ (
+ sCAN_CARD *card
+ )
+ {
+ if ( unican_readw(card->commandRegister) & CL2_COMMAND_VALID )
+ return CL2_COMMAND_BUSY;
+ unican_writew((U16)cmCL2_BUS_RESET + CL2_COMMAND_VALID, card->commandRegister);
+ return CL2_OK;
+ } /* cl2_bus_reset */
+
+
+/*******************************************************************************
+* cl2_send_sync - sends synchronous frame
+* """""""""""""
+*
+* Command stores massage in synchronous send buffer.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_HW_QUEUE_FULL - synchronous send buffer is full
+* CL2_BAD_PARAM - bad command parameter
+* CL2_HW_FAILURE - error in HW configuration
+*
+*/
+eCL2_RESULT cl2_send_sync
+ (
+ sCAN_CARD *card, /* pointer to card */
+ sCAN_MESSAGE *message /* massage to be sent */
+ )
+ {
+ U32 cobid;
+ U16 cobidL,cobidH;
+ U16 *ptrU16 = (U16*)card->syncTxBufPtr;
+ U16 tmpU16;
+ int i;
+ int timeStamp = 0;
+
+ if ( card->syncTxBufSize==0 ) return CL2_HW_FAILURE;
+ if ( message->dataLength > 8 ) return CL2_BAD_PARAM;
+ if ( *ptrU16 & CL2_FRAME_VALID ) return CL2_HW_QUEUE_FULL;
+
+ cobid = message->COB_ID;
+ if ( (message->dataType & CL2_EXT_FRAME) || (cobid & CL2_TMP_EXHIGH) )
+ { /* 2.0B frame */
+ cobid <<= 3;
+ cobidL = (U16)(cobid & 0x0000FFFFL);
+ cobidH = (U16)((cobid & 0xFFFF0000L)>>16);
+ }
+ else
+ { /* 2.0A frame */
+ cobid <<= 5;
+ cobidL = 0;
+ cobidH = (U16)(cobid & 0x0000FFFFL);
+ }
+ ptrU16++;
+ tmpU16 = (cobidH & 0x00FF) + (cobidL & 0xFF00);
+ *ptrU16++ = tmpU16;
+
+ tmpU16 = (((U16)message->dataLength) << 12) + (cobidL & 0x00FF);
+ if ( !(message->dataType & CL2_REMOTE_FRAME) ) tmpU16 |= CL2_TMP_RF;
+ if ( (message->dataType & CL2_EXT_FRAME) ||
+ (message->COB_ID & CL2_TMP_EXHIGH) )
+ tmpU16 |= CL2_TMP_EX;
+ *ptrU16++ = tmpU16;
+
+ for ( i = 0; i < message->dataLength; )
+ {
+ tmpU16 = (U16)message->data[i]; i++;
+ if ( i == message->dataLength )
+ {
+ timeStamp = 1;
+ tmpU16 |= ((message->timeStamp & 0x00FF)<<8);
+ *ptrU16++ = tmpU16;
+ }
+ else
+ {
+ tmpU16 |= ((U16)message->data[i]<<8); i++;
+ *ptrU16++ = tmpU16;
+ }
+ }
+ if ( timeStamp )
+ {
+ tmpU16 = (message->timeStamp>>8) & 0x00FF;
+ *ptrU16 = tmpU16;
+ }
+ else
+ {
+ *ptrU16 = message->timeStamp;
+ }
+
+ tmpU16 = (((U16)cobidH) & 0xFF00) | CL2_MESSAGE_VALID;
+ unican_writew(tmpU16, card->syncTxBufPtr);
+
+ if ( (card->syncTxBufBase + card->syncTxBufSize*16) <=
+ (card->syncTxBufPtr += 16) )
+ {
+ card->syncTxBufPtr = card->syncTxBufBase;
+ }
+ return CL2_OK;
+ } /* cl2_send_sync */
+
+
+/*******************************************************************************
+* cl2_send_async - sends asynchronous frame
+* """"""""""""""
+*
+* Command stores message in asynchronous send buffer.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_HW_QUEUE_FULL - asynchronous buffer full
+* CL2_HW_FAILURE - error in HW configuration
+* CL2_BAD_PARAM - bad command parameter
+*
+*/
+eCL2_RESULT cl2_send_async
+ (
+ sCAN_CARD *card, /* pointer to card */
+ sCAN_MESSAGE *message /* message to be sent */
+ )
+ {
+ U32 cobid;
+ U16 cobidL,cobidH;
+ U16 *ptrU16 = (U16*)card->asyncTxBufPtr;
+ U16 tmpU16;
+ int i;
+ int timeStamp = 0;
+
+ if ( card->asyncTxBufSize==0 ) return CL2_HW_FAILURE;
+ if ( message->dataLength > 8 ) return CL2_BAD_PARAM;
+ if ( *ptrU16 & CL2_FRAME_VALID ) return CL2_HW_QUEUE_FULL;
+
+ cobid = message->COB_ID;
+ if ( (message->dataType & CL2_EXT_FRAME) || (cobid & CL2_TMP_EXHIGH) )
+ { /* 2.0B frame */
+ cobid <<= 3;
+ cobidL = (U16)(cobid & 0x0000FFFFL);
+ cobidH = (U16)((cobid & 0xFFFF0000L)>>16);
+ }
+ else
+ { /* 2.0A frame */
+ cobid <<= 5;
+ cobidL = 0;
+ cobidH = (U16)(cobid & 0x0000FFFFL);
+ }
+ ptrU16++;
+ tmpU16 = (cobidH & 0x00FF ) + (cobidL & 0xFF00);
+ *ptrU16++ = tmpU16;
+
+ tmpU16 = (((U16)message->dataLength) << 12) + (cobidL & 0x00FF);
+ if ( !(message->dataType & CL2_REMOTE_FRAME) ) tmpU16 |= CL2_TMP_RF;
+ if ( (message->dataType & CL2_EXT_FRAME) ||
+ (message->COB_ID & CL2_TMP_EXHIGH ) )
+ tmpU16 |= CL2_TMP_EX;
+ *ptrU16++ = tmpU16;
+
+ for ( i = 0; i < message->dataLength; )
+ {
+ tmpU16 = (U16)message->data[i]; i++;
+ if ( i == message->dataLength )
+ {
+ timeStamp = 1;
+ tmpU16 |= ((message->timeStamp & 0x00FF)<<8);
+ *ptrU16++ = tmpU16;
+ }
+ else
+ {
+ tmpU16 |= ((U16)message->data[i]<<8); i++;
+ *ptrU16++ = tmpU16;
+ }
+ }
+ if ( timeStamp )
+ {
+ tmpU16 = (message->timeStamp>>8) & 0x00FF;
+ *ptrU16 = tmpU16;
+ }
+ else
+ {
+ *ptrU16 = message->timeStamp;
+ }
+
+ tmpU16 = (((U16)cobidH) & 0xFF00) | CL2_MESSAGE_VALID;
+ unican_writew(tmpU16, card->asyncTxBufPtr);
+
+ if ( (card->asyncTxBufBase + card->asyncTxBufSize*16) <=
+ (card->asyncTxBufPtr += 16) )
+ {
+ card->asyncTxBufPtr = card->asyncTxBufBase;
+ }
+ return CL2_OK;
+ } /* cl2_send_async */
+
+
+/*******************************************************************************
+* cl2_get_status - reads card status
+* """"""""""""""
+*
+* Command reads card status register. If data in status register
+* are valid (status valid flag is set), the value of status is read
+* and stored in status and sCAN_CARD structure.
+*
+* RETURNS:
+* CL2_OK - command completed successfuly
+* CL2_NO_REQUEST - status is not valid
+*
+*/
+eCL2_RESULT cl2_get_status
+ (
+ sCAN_CARD *card, /* pointer to card */
+ U16 *status /* card status word */
+ )
+ {
+ U16 *ptr;
+
+ ptr = (U16*)(card->baseAddressPtr + CL2_STATUS_REGISTER);
+ *status = *ptr;
+ if ( (*status & CL2_STATUS_VALID_FLAG) )
+ {
+ *ptr = *status & ~CL2_STATUS_VALID_FLAG;
+ card->status = *status;
+ return CL2_OK;
+ }
+ return CL2_NO_REQUEST;
+ } /* cl2_get_status */
+
+
+/*******************************************************************************
+* cl2_get_error - reads card error
+* """""""""""""
+*
+* Command reads card error register. If data in error register
+* are valid (error register valid flag is set), the value of error
+* register is read and stored in error and sCAN_CARD structure.
+*
+* RETURNS:
+* Cl2_OK - command completed successfuly
+*
+*/
+eCL2_RESULT cl2_get_error
+ (
+ sCAN_CARD *card, /* pointer to card */
+ U16 *error /* card error word */
+ )
+ {
+ U16 *ptr;
+
+ ptr = (U16*)(card->baseAddressPtr + CL2_ERROR_REGISTER);
+ *error = *ptr;
+ card->error |= *error;
+ *ptr = 0x0000;
+ return CL2_OK;
+ } /* cl2_get_error */
+
+
+/*******************************************************************************
+* cl2_receive_data - reads received frame
+* """"""""""""""""
+*
+* Command reads new messages received by a card.
+*
+* RETURNS:
+* CL2_OK - command commpleted successfuly
+* CL2_NO_REQUEST - there is no new message
+*
+*/
+eCL2_RESULT cl2_receive_data
+ (
+ sCAN_CARD *card, /* Pointer to card structure */
+ sCAN_MESSAGE *canMessage /* Message */
+ )
+ {
+ U16 *ptrU16 = (U16*)card->rxBufPtr;
+ U16 tmpU16;
+ U16 i;
+
+ tmpU16 = *ptrU16++;
+ if ( !(tmpU16 & CL2_MESSAGE_VALID) ) return CL2_NO_REQUEST;
+ canMessage->COB_ID = ((U32)(tmpU16 & 0xFF00 )) << 16;
+ tmpU16 = *ptrU16++;
+ canMessage->COB_ID |= ((U32)( tmpU16 & 0x00FF )) << 16;
+ canMessage->COB_ID |= (U32)( tmpU16 & 0xFF00 );
+ tmpU16 = *ptrU16++;
+ canMessage->COB_ID |= (U32)( tmpU16 & 0x00FF );
+ canMessage->dataType = (U8)(( tmpU16 & 0xFF00 ) >> 8);
+
+ if ( canMessage->dataType & CL2_EXT_FRAME )
+ { /* 2.0B frame */
+ canMessage->COB_ID >>= 3;
+ /* canMessage->COB_ID |= CL2_TMP_EXHIGH; */
+ }
+ else
+ { /* 2.0A frame */
+ canMessage->COB_ID >>= 21;
+ }
+ canMessage->dataLength = (U8)( (tmpU16 >> 12) & 0x000F );
+ /* if ( !(tmpU16 & CL2_TMP_RF) ) canMessage->dataType |= CL2_REMOTE_FRAME; */
+ for ( i = 0; i < canMessage->dataLength; )
+ {
+ tmpU16 = *ptrU16++;
+ canMessage->data[i++] = (U8)( tmpU16 );
+ canMessage->data[i++] = (U8)( tmpU16 >> 8 );
+ }
+ if ( canMessage->dataLength & 0x01 )
+ { /* odd */
+ canMessage->timeStamp = ( (*ptrU16 & 0x00FF) | (tmpU16 & 0xFF00) );
+ }
+ else /* even */
+ {
+ canMessage->timeStamp = *ptrU16 << 8 | *ptrU16 >> 8;
+ }
+ unican_writew(0x0000, card->rxBufPtr);
+
+ /* increment rx-buffer pointer */
+ if ( (card->rxBufBase + card->rxBufSize*16 ) <= (card->rxBufPtr += 16) )
+ {
+ card->rxBufPtr = card->rxBufBase;
+ }
+
+ return CL2_OK;
+ } /* cl2_receive_data */
+
+
+/* **************************************************************** *
+ * END OF CL2.C *
+ * **************************************************************** */
+
+