]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/unican_cl2.c
Interconnected OCERA configuration options with LinCAN boardlist.c compilation.
[lincan.git] / lincan / src / unican_cl2.c
diff --git a/lincan/src/unican_cl2.c b/lincan/src/unican_cl2.c
new file mode 100644 (file)
index 0000000..18a78e9
--- /dev/null
@@ -0,0 +1,1279 @@
+/******************************************************************************\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$
+Revision 1.1  2004/03/13 23:13:33  ppisa
+Interconnected OCERA configuration options with LinCAN boardlist.c compilation.
+\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 "anctypes.h"\r
+#include "cl2.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 = *((U16*)(card->baseAddressPtr));\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
+   *((U16*)(card->baseAddressPtr + CL2_RESET_REGISTER)) = 0x0000;\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 = *((U16*)(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
+   *((U16*)(card->baseAddressPtr + CL2_GEN_INT_REGISTER)) = 0x0000;\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
+   *((U16*)(card->baseAddressPtr + CL2_START_IT_REGISTER)) = 0x0000;\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
+   *((U16*)(card->baseAddressPtr + CL2_CLEAR_INT_REGISTER)) = 0x0000;\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   *((U16*)card->dataPtr) = mode;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_INT_MODE + CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID ) return\r
+      CL2_COMMAND_BUSY;\r
+   *((U16*)card->dataPtr) = (U16)onoff;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_IIT_MODE + CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   *((U16*)card->dataPtr) = (U16)onoff;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_SYNC_MODE + CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   *((U16*)card->dataPtr) = (U16)onoff;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_RTR_MODE + CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   *((U16*)card->dataPtr) = bufSize;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_BUF_SIZE + CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   *((U16*)card->dataPtr) = iit;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_SET_IIT + CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_START_FIRMWARE +\r
+                                    CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   *((U16*)card->dataPtr) = (U16)mode;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_SET_REC_MODE +\r
+                                    CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   card->rxBufPtr = card->rxBufBase;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_CLR_RX_BUFFER +\r
+                                     CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   card->syncTxBufPtr = card->syncTxBufBase;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_CLR_SYNC_BUFFER +\r
+                                    CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   card->asyncTxBufPtr = card->syncTxBufBase + card->syncTxBufSize*16;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_CLR_ASYNC_BUFFER +\r
+                                    CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID ) return\r
+      CL2_COMMAND_BUSY;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_SEND_TIME_SYNC +\r
+                                    CL2_COMMAND_VALID);\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 ( *(U16*)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
+   *((U16*)card->commandRegister) = ((U16)cmCL2_SET_TIME_COBID +\r
+                                     CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   *((U16*)card->dataPtr) = limit;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_SET_RECEIVE_LIMIT +\r
+                                    CL2_COMMAND_VALID);\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 ( *(U16*)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
+   *((U16*)card->commandRegister) = ((U16)cmCL2_DOWNLOAD_RTR_LIST +\r
+                                     CL2_COMMAND_VALID);\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 ( *(U16*)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
+   *((U16*)card->commandRegister) = ((U16)cmCL2_SUBSCRIBE_RTR +\r
+                                    CL2_COMMAND_VALID);\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 ( *(U16*)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
+   *((U16*)card->dataPtr) = i;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_DESUBSCRIBE_RTR +\r
+                                    CL2_COMMAND_VALID);\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 ( *(U16*)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
+   *((U16*)card->commandRegister) = ((U16)cmCL2_SET_COBID + CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   *((U16*)card->dataPtr) = (U16)period;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_SET_SYNC_PERIOD +\r
+                                    CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   *((U16*)card->dataPtr) = (U16)window;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_SET_SYNC_WINDOW +\r
+                                    CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   *((U16*)card->dataPtr) = bitrate;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_SET_BITRATE +\r
+                                    CL2_COMMAND_VALID);\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 ( *(U16*)card->commandRegister & CL2_COMMAND_VALID )\r
+      return CL2_COMMAND_BUSY;\r
+   *((U16*)card->commandRegister) = ((U16)cmCL2_BUS_RESET +\r
+                                    CL2_COMMAND_VALID);\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
+   *(U16*)card->syncTxBufPtr = tmpU16;\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
+   *(U16*)card->asyncTxBufPtr = tmpU16;\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
+   *(U16*)card->rxBufPtr = 0x0000;\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