summaryrefslogtreecommitdiff
path: root/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-can.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-can.patch')
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-can.patch10765
1 files changed, 10765 insertions, 0 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-can.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-can.patch
new file mode 100644
index 000000000..1d7d8d281
--- /dev/null
+++ b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-can.patch
@@ -0,0 +1,10765 @@
+From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
+Subject: OKI Semiconductor PCH CAN driver
+
+This driver implements CAN controls for PCH.
+
+Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
+Acked-by: Wang Qi <qi.wang@intel.com>
+
+---
+ drivers/net/can/Kconfig | 5 ++
+ drivers/net/can/Makefile | 1
+ drivers/net/can/pch_can/Makefile | 7
+ drivers/net/can/pch_can/pch_can_hal.c | 4785
+ drivers/net/can/pch_can/pch_can_hal.h | 1407
+ drivers/net/can/pch_can/pch_can_main.c | 1681
+ drivers/net/can/pch_can/pch_can_main.h | 826
+ drivers/net/can/pch_can/pch_can_pci.c | 1134
+ drivers/net/can/pch_can/pch_can_pci.h | 105
+ drivers/net/can/pch_can/pch_can_utils.c | 397
+ drivers/net/can/pch_can/pch_can_utils.h | 127
+ drivers/net/can/pch_can/pch_common.h | 146
+ drivers/net/can/pch_can/pch_debug.h | 60
++++++++++++++++++++++++++++++++ 13 files changed, 10682 insertions(+)
+diff -urN linux-2.6.33-rc3/drivers/net/can/Kconfig topcliff-2.6.33-rc3/drivers/net/can/Kconfig
+--- linux-2.6.33-rc3/drivers/net/can/Kconfig 2010-01-06 09:02:46.000000000 +0900
++++ topcliff-2.6.33-rc3/drivers/net/can/Kconfig 2010-03-05 11:04:53.000000000 +0900
+@@ -79,4 +79,9 @@
+ a problem with CAN support and want to see more of what is going
+ on.
+
++config PCH_CAN
++ tristate "PCH CAN"
++ ---help---
++ for PCH CAN
++
+ endmenu
+diff -urN linux-2.6.33-rc3/drivers/net/can/Makefile topcliff-2.6.33-rc3/drivers/net/can/Makefile
+--- linux-2.6.33-rc3/drivers/net/can/Makefile 2010-01-06 09:02:46.000000000 +0900
++++ topcliff-2.6.33-rc3/drivers/net/can/Makefile 2010-03-05 23:15:46.000000000 +0900
+@@ -15,5 +15,6 @@
+ obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o
+ obj-$(CONFIG_CAN_MCP251X) += mcp251x.o
+ obj-$(CONFIG_CAN_BFIN) += bfin_can.o
++obj-$(CONFIG_PCH_CAN) += pch_can/
+
+ ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
+diff -urN linux-2.6.33-rc3/drivers/net/can/pch_can/Makefile topcliff-2.6.33-rc3/drivers/net/can/pch_can/Makefile
+--- linux-2.6.33-rc3/drivers/net/can/pch_can/Makefile 1970-01-01 09:00:00.000000000 +0900
++++ topcliff-2.6.33-rc3/drivers/net/can/pch_can/Makefile 2010-03-05 23:32:20.000000000 +0900
+@@ -0,0 +1,7 @@
++ifeq ($(CONFIG_CAN_DEBUG),y)
++EXTRA_CFLAGS += -DDEBUG
++endif
++
++obj-$(CONFIG_PCH_CAN) += pch_can.o
++
++pch_can-objs := pch_can_utils.o pch_can_hal.o pch_can_pci.o pch_can_main.o
+diff -urN linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_hal.c topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_hal.c
+--- linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_hal.c 1970-01-01 09:00:00.000000000 +0900
++++ topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_hal.c 2010-03-10 20:03:53.000000000 +0900
+@@ -0,0 +1,4785 @@
++/*!
++ * @file ioh_can_hal.c
++ * @brief Provides the function definition for CAN HAL APIs.
++ * @version 1.0
++ * @section
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * <hr>
++ */
++
++/*
++ * History:
++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
++ * All rights reserved.
++ *
++ * created:
++ * WIPRO 03/07/2009
++ * modified:
++ * WIPRO 05/08/2009
++ *
++ *
++ */
++
++/* includes */
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++
++#include "pch_common.h"
++#include "pch_debug.h"
++#include "pch_can_main.h"
++#include "pch_can_hal.h"
++#include "pch_can_utils.h"
++#include "pch_can_pci.h"
++
++#define COUNTER_LIMIT (0xFFFF)
++
++/*! @ingroup Global
++ @var ioh_msg_obj_conf
++ @brief This variable is used to store the configuration
++ (receive /transmit) of the available message
++ objects.
++ @remarks This variable is used for storing the message object
++ configuration related information. It includes
++ the
++ information about which message object is used
++ as
++ Receiver and Transmitter.
++ @note The information is filled during the probe stage of
++ the device.
++
++ @see
++ - ioh_can_probe
++
++ <hr>
++*/
++unsigned int ioh_msg_obj_conf[MAX_MSG_OBJ] = {
++ 3, 3, 3, 3,
++ 3, 3, 3, 3,
++ 3, 3, 3, 3,
++ 3, 3, 3, 3,
++ 3, 3, 3, 3,
++ 3, 3, 3, 3,
++ 3, 3, 3, 3,
++ 3, 3, 3, 3
++};
++
++/*! @ingroup HALLayerAPI
++ @fn static int ioh_can_rx_enable_all(int handle)
++
++ <hr>
++*/
++static int ioh_can_rx_enable_all(int handle);
++
++/*! @ingroup HALLayerAPI
++ @fn static int ioh_can_tx_enable_all(int handle)
++
++ <hr>
++*/
++static int ioh_can_tx_enable_all(int handle);
++
++/*! @ingroup HALLayerFacilitators
++ @var restartMode
++ @brief The variable used to store the restart mode.
++
++ <hr>
++*/
++static enum ioh_can_auto_restart restartMode = CAN_MANUAL;
++
++/*! @ingroup InterfaceLayer
++ @struct can_hw
++ @brief This structure defines format for the storage of base
++ address.
++
++ <hr>
++*/
++struct can_hw {
++ unsigned char *io_base; /* Device registers */
++};
++
++/* Array to store the timing settings. */
++/*! @ingroup Global
++ @var can_rec_timing
++ @brief This variable is used to store the time
++ settings of the CAN device.
++ @remarks This variable is used for storing the timing
++ related information depending upon the
++ clock rate of the CAN device. It is used for
++ setting the baud rate of the CAN device.
++
++ @see
++ - ioh_can_pci_init
++ - ioh_can_set_baud_simple
++
++ <hr>
++*/
++struct ioh_can_timing can_rec_timing[] = {
++ /*<Baud rate> <BRP> <TS1> <TS2> <SJW> */
++ /* settings for 62.5MHz */
++ {0xa, 0x250, 0x7, 0x0, 0x0, 0x0, 0x0}, /**< 10 kbits/s */
++ {0x14, 0x8D, 0xB, 0x5, 0x0, 0x0, 0x0}, /**< 20 kbits/s */
++ {0x32, 0x5C, 0x7, 0x0, 0x0, 0x0, 0x0}, /**< 50 kbits/s */
++ {0x7d, 0x18, 0xC, 0x5, 0x0, 0x0, 0x0}, /**< 125 kbits/s */
++ {0xfa, 0x18, 0x7, 0x0, 0x0, 0x0, 0x0}, /**< 250 kbits/s */
++ {0x1f4, 0x8, 0x9, 0x2, 0x0, 0x0, 0x0}, /**< 500 kbits/s */
++ {0x320, 0x5, 0x8, 0x2, 0x0, 0x0, 0x0}, /**< 800 kbits/s */
++ {0x3e8, 0x2, 0xC, 0x6, 0x0, 0x0, 0x0}, /**< 1000 kbits/s */
++
++ /* settings for 24MHz */
++ {0xa, 0xCF, 0x7, 0x0, 0x0, 0x0, 0x0}, /**< 10 kbits/s */
++ {0x14, 0x57, 0x7, 0x0, 0x0, 0x0, 0x0}, /**< 20 kbits/s */
++ {0x32, 0xF, 0x7, 0x0, 0x0, 0x0, 0x0}, /**< 50 kbits/s */
++ {0x7d, 0xF, 0x8, 0x1, 0x0, 0x0, 0x0}, /**< 125 kbits/s */
++ {0xfa, 0x7, 0x8, 0x1, 0x0, 0x0, 0x0}, /**< 250 kbits/s */
++ {0x1f4, 0x3, 0x8, 0x1, 0x0, 0x0, 0x0}, /**< 500 kbits/s */
++ {0x320, 0x2, 0x7, 0x0, 0x0, 0x0, 0x0}, /**< 800 kbits/s */
++ {0x3e8, 0x1, 0x8, 0x1, 0x0, 0x0, 0x0}, /**< 1000 kbits/s */
++
++ /* settings for 50MHz */
++ {0xa, 0xFA, 0xC, 0x5, 0x1, 0x0, 0x0}, /**< 10 kbits/s */
++ {0x14, 0x7D, 0xC, 0x5, 0x1, 0x0, 0x0}, /**< 20 kbits/s */
++ {0x32, 0x32, 0xF, 0x2, 0x0, 0x0, 0x0}, /**< 50 kbits/s */
++ {0x7d, 0x19, 0xC, 0x1, 0x0, 0x0, 0x0}, /**< 125 kbits/s */
++ {0xfa, 0xA, 0xF, 0x2, 0x0, 0x0, 0x0}, /**< 250 kbits/s */
++ {0x1f4, 0x5, 0xF, 0x2, 0x0, 0x0, 0x0}, /**< 500 kbits/s */
++ {0x320, 0x5, 0x8, 0x2, 0x1, 0x0, 0x0}, /**< 800 kbits/s */
++ {0x3e8, 0x2, 0xF, 0x7, 0x0, 0x0, 0x0} /**< 1000 kbits/s */
++ /* Add the new clock settings here. */
++};
++
++/* The offset to the settings array depending on the clock rate entries.*/
++
++/*! @ingroup HALLayer
++ @def IOH_CAN_CLOCK_DEFAULT_OFFSET
++ @brief The default clock rate offset to the @ref
++ can_rec_timing array.
++ @see ioh_can_set_baud_simple
++
++ <hr>
++*/
++#define IOH_CAN_CLOCK_DEFAULT_OFFSET (0)
++/*! @ingroup HALLayer
++ @def IOH_CAN_CLOCK_62_5_OFFSET
++ @brief The offset to the @ref can_rec_timing array when the
++ clock
++ rate is 62.5MHz.
++ @see ioh_can_set_baud_simple
++
++ <hr>
++*/
++#define IOH_CAN_CLOCK_62_5_OFFSET (0)
++/*! @ingroup HALLayer
++ @def IOH_CAN_CLOCK_24_OFFSET
++ @brief The offset to the @ref can_rec_timing array when the
++ clock
++ rate is 24MHz.
++ @see ioh_can_set_baud_simple
++
++ <hr>
++*/
++#define IOH_CAN_CLOCK_24_OFFSET (8)
++
++/*! @ingroup HALLayer
++ @def IOH_CAN_CLOCK_50_OFFSET
++ @brief The offset to the @ref can_rec_timing array when the
++ clock
++ rate is 24MHz.
++ @see ioh_can_set_baud_simple
++
++ <hr>
++*/
++#define IOH_CAN_CLOCK_50_OFFSET (16)
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_create(u8 * io_base)
++ @brief Creates a device handle for the other APIs.
++ @remarks
++ This function creates a device handle that can
++ be used by
++ other HAL APIs for accessing the device
++ specific resources.
++ The main tasks performed by this function are :
++ - Allocates memory for the handle.
++ - Creates the handle and returns it to the
++ called function.
++
++ @param io_base [@ref IN] The remapped address
++ for handle creation.
++
++ @retval int <br>
++ - Handle to the device --> Handle creation
++ successful.
++ - @ref IOH_CAN_NULL --> Handle creation failed.
++
++ @see
++ - ioh_can_probe
++
++ <hr>
++*/
++int ioh_can_create(u8 *io_base)
++{
++ struct can_hw *can = NULL;
++ int retval = (int) IOH_CAN_NULL;
++
++ if (io_base == NULL) {
++ IOH_LOG(KERN_ERR, "ioh_can_create -> Invalid IO Base\n");
++ }
++
++ else {
++ /* Allocates memory for the handle. */
++ can = (struct can_hw *) CAN_MEM_ALLOC(sizeof(struct can_hw));
++
++ if (can == NULL) { /* Allocation failed */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_create -> CAN Memory allocation \
++ failed\n");
++ } else { /* Allocation successful */
++
++ can->io_base = io_base;
++ retval = (int) can;
++ IOH_DEBUG
++ ("ioh_can_create -> Handle Creation successful.\n");
++ }
++ }
++
++ IOH_DEBUG("ioh_can_create -> Return value: %x\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn void ioh_can_destroy(int handle)
++ @brief Destroys (frees) the device handle.
++ @remarks This function destroys the previously created handle of
++ the
++ device. It also de-allocates the memory
++ allocated during the
++ handle creation. The main tasks performed by
++ this function
++ are :
++ - Verifies whether the passed argument is valid.
++ - If valid frees the allocated memory whose
++ reference is
++ provided by the passed argument.
++
++ @param handle [@ref IN] The device handle to be
++ destroyed.
++
++ @retval None.
++
++ @see
++ - ioh_can_remove
++
++ <hr>
++*/
++void ioh_can_destroy(int handle)
++{
++ struct can_hw *can = (struct can_hw *) handle;
++
++ if (handle != (int) 0) {
++ /*Free the memory for the handle. */
++ CAN_MEM_FREE(can);
++ IOH_DEBUG("ioh_can_destroy -> Free successful.\n");
++ } else {
++ IOH_LOG(KERN_ERR, "ioh_can_destroy -> Invalid handle.\n");
++ }
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_set_run_mode(
++ int handle,enum ioh_can_run_mode mode)
++ @brief Set run/stop mode of the CAN device.
++ @remarks This API set the CAN device in RUN/STOP mode. It does
++ this only if the passed arguments are valid.
++ The main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid. If invalid
++ error status code is returned.
++ - Depending on the mode to be set, suitably
++ sets/resets the
++ INIT bit of the CANCONT register.
++ --> RUM Mode : Resets the INIT bit.
++ --> STOP Mode: Sets the INIT bit.
++
++ @param handle [@ref IN] Handle to the device.
++ @param mode [@ref IN] The mode to be set.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_suspend
++ - ioh_can_resume
++
++ <hr>
++*/
++int ioh_can_set_run_mode(int handle, enum ioh_can_run_mode mode)
++{
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress = NULL;
++
++ if (handle == (int) 0) { /* handle invalid */
++ IOH_LOG(KERN_ERR, "ioh_can_set_run_mode -> Invalid Handle \n");
++ retval = IOH_CAN_FAIL;
++ }
++
++ else {
++ /* Retrieving base address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ switch (mode) {
++ case IOH_CAN_RUN:
++ IOH_CAN_BIT_CLEAR((can_baseaddress + CAN_CONT_OFFSET),
++ CAN_CTRL_INIT);
++ IOH_DEBUG
++ ("ioh_can_set_run_mode -> Can set to RUN Mode.\n");
++ break;
++
++ case IOH_CAN_STOP:
++ IOH_CAN_BIT_SET((can_baseaddress + CAN_CONT_OFFSET),
++ CAN_CTRL_INIT);
++ IOH_DEBUG
++ ("ioh_can_set_run_mode -> Can set to STOP Mode.\n");
++ break;
++
++ default:
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_run_mode -> Invalid run mode.\n");
++ retval = IOH_CAN_FAIL;
++ break;
++ }
++ }
++
++ IOH_DEBUG("ioh_can_set_run_mode -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_get_run_mode(int handle,enum
++ ioh_can_run_mode *mode)
++ @brief This function gets current the run/stop mode of the CAN
++ device.
++ @remarks Retrieves the current mode(RUN/STOP) of the device
++ by checking the corresponding settings on the
++ hardware.
++ The main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid. If invalid
++ returns the error status code.
++ - Depending on the INIT bit value of the CANCONT
++ register
++ the appropriate mode is copied to the
++ passed mode
++ reference variable passed as argument.
++
++ INIT bit value 0: RUN Mode.
++ INIT bit value 1: STOP mode.
++
++ @param handle [@ref IN] The handle to the device.
++ @param mode [@ref OUT] The current mode of the device.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_suspend
++
++ <hr>
++*/
++int ioh_can_get_run_mode(int handle, enum ioh_can_run_mode *mode)
++{
++ u32 reg_val;
++ struct can_hw *can;
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++
++ if ((handle == (int) 0) || (mode == NULL)) { /* if invalid
++ parameter. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_run_mode -> Invalid parameter.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the remap address for access. */
++ can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ reg_val = IOH_READ_LONG(can_baseaddress + CAN_CONT_OFFSET);
++
++ /* Checking the Init bit of Can Control Register.
++ Init Bit 1 -> Stop
++ Init Bit 0 -> Run
++ */
++ if ((reg_val & CAN_CTRL_INIT) != 0) {
++ *mode = IOH_CAN_STOP;
++ IOH_DEBUG
++ ("ioh_can_get_run_mode -> Mode is IOH_CAN_STOP\n");
++ } else {
++ *mode = IOH_CAN_RUN;
++ IOH_DEBUG
++ ("ioh_can_get_run_mode -> Mode is IOH_CAN_RUN\n");
++ }
++ }
++
++ IOH_DEBUG("ioh_can_get_run_mode -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_set_arbiter_mode(
++ int handle,enum ioh_can_arbiter mode)
++ @brief This function sets the arbiter mode of the CAN device.
++ @remarks Sets the arbiter mode of the CAN device. The main tasks
++ performed by this function are :
++ - Validates whether the passed arguments and
++ mode are valid.
++ If invalid returns the error status code.
++ - Sets the arbiter mode.
++ @note Only Fixed Priority mode is supported.
++
++ @param handle [@ref IN] The handle to the device.
++ @param mode [@ref IN] The arbiter mode to be set.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++int ioh_can_set_arbiter_mode(int handle, enum ioh_can_arbiter mode)
++{
++ int retval = IOH_CAN_SUCCESS;
++
++ if (handle == (int) 0) { /* if invalid handle */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_arbiter_mode -> Invalid Handle\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* IOH CAN Controller supports only IOH_CAN_FIXED_PRIORITY
++ arbiter mode.
++ */
++ switch (mode) {
++ case IOH_CAN_FIXED_PRIORITY:
++ IOH_DEBUG("ioh_can_set_arbiter_mode -> FIXED "
++ "PRIORITY is set for Arbiter mode\n");
++ break;
++
++ case IOH_CAN_ROUND_ROBIN:
++ default:
++ IOH_DEBUG("ioh_can_set_arbiter_mode -> "
++ "Invalid arbiter mode\n");
++ retval = IOH_CAN_FAIL;
++ break;
++ }
++ }
++
++ IOH_DEBUG("ioh_can_set_arbiter_mode -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_get_arbiter_mode(
++ int handle,enum ioh_can_arbiter *mode
++ @brief This function gets the arbiter mode of the CAN device.
++ @remarks Gets the current arbiter mode of the CAN device. The
++ main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid returns the error status code.
++ - Copies the current arbiter mode to the passed
++ mode reference variable.
++ @note Only Fixed Priority mode is supported.
++
++ @param handle [@ref IN] The handle to the device.
++ @param mode [@ref OUT] The current arbiter mode of the
++ device.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++int ioh_can_get_arbiter_mode(int handle, enum ioh_can_arbiter *mode)
++{
++ int retval = IOH_CAN_SUCCESS;
++
++ if ((handle == (int) 0) || (mode == NULL)) { /* if invalid
++ parameter. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_arbiter_mode -> Invalid parameter\n");
++ retval = IOH_CAN_FAIL;
++ }
++
++ else {
++ /* IOH CAN Controller supports only IOH_CAN_FIXED_PRIORITY
++ arbiter mode.
++ */
++ *mode = IOH_CAN_FIXED_PRIORITY;
++ IOH_DEBUG("ioh_can_get_arbiter_mode -> Arbiter Mode "
++ "is IOH_CAN_FIXED_PRIORITY\n");
++ }
++
++ IOH_DEBUG("ioh_can_get_arbiter_mode returns %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_set_restart_mode(int handle,enum
++ ioh_can_auto_restart mode)
++ @brief This function sets the restart mode of the CAN device.
++ @remarks Sets the restart mode of the CAN device. The main
++ tasks performed by this function are :
++ - Validates whether the passed arguments and
++ mode are valid.
++ If invalid returns the error status code.
++ - Updates the current restart mode variable
++ @ref restartMode
++ to given mode.
++
++ @param handle [@ref IN] The handle to the device.
++ @param mode [@ref IN] The restart mode to be set.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_open
++
++ <hr>
++*/
++int ioh_can_set_restart_mode(int handle,
++ enum ioh_can_auto_restart mode)
++{
++ int retval = IOH_CAN_SUCCESS;
++
++ if (handle == (int) 0) { /* if invalid handle. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_restart_mode -> Invalid Handle\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ switch (mode) {
++ case CAN_MANUAL:
++ restartMode = CAN_MANUAL;
++ IOH_DEBUG
++ ("ioh_can_set_restart_mode -> Value of variable "
++ " restartMode = 0. CAN_MANUAL mode set.\n");
++ break;
++
++ case CAN_AUTO:
++ restartMode = CAN_AUTO;
++ IOH_DEBUG
++ ("ioh_can_set_restart_mode -> Value of variable "
++ " restartMode = 1. CAN_AUTO mode set.\n");
++ break;
++
++ default:
++ IOH_DEBUG
++ ("ioh_can_set_restart_mode -> Invalid restart \
++ mode\n");
++ retval = IOH_CAN_FAIL;
++ break;
++ }
++ }
++
++ IOH_DEBUG("ioh_can_set_restart_mode returns %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_get_restart_mode(
++ int handle,enum ioh_can_auto_restart *mode)
++ @brief This function gets the restart mode of the CAN device.
++ @remarks Retrieves the currently set restart mode. The main tasks
++ performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid returns the error status code.
++ - Copies the current restart mode from the
++ variable @ref restartMode
++ to the passed mode reference variable.
++
++ @param handle [@ref IN] The handle to the device.
++ @param mode [@ref OUT] Reference to current restart
++ mode.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_callback
++
++ <hr>
++*/
++int ioh_can_get_restart_mode(int handle,
++ enum ioh_can_auto_restart *mode)
++{
++ int retval = IOH_CAN_SUCCESS;
++
++ if ((handle == (int) 0) || (mode == NULL)) { /* if invalid
++ parameter. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_restart_mode -> Invalid parameter.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ if (CAN_AUTO == restartMode) { /* Auto restart mode */
++ *mode = CAN_AUTO;
++ IOH_DEBUG
++ ("ioh_can_get_restart_mode -> Mode CAN_AUTO. \n");
++ } else { /* Manual restart mode. */
++
++ *mode = CAN_MANUAL;
++ IOH_DEBUG
++ ("ioh_can_get_restart_mode -> Mode CAN_MANUAL. \n");
++ }
++ }
++
++ IOH_DEBUG("ioh_can_get_restart_mode returns: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_set_listen_mode(
++ int handle, enum ioh_can_listen_mode mode
++ @brief This function sets the listen/active mode of the CAN device.
++ @remarks Sets the listen mode of the CAN device. The main tasks
++ performed by this function are :
++ - Validates whether the passed arguments and
++ mode are valid.
++ If invalid returns the error status code.
++ - Depending on the obatined mode appropriately
++ set/reset the
++ Silent bit of the CANOPT register.
++ Active Mode: Reset Silent bit.
++ Silent Mode: Set Silent bit.
++
++ @param handle [@ref IN] The handle to the device.
++ @param mode [@ref OUT] The listen mode to be set.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_open
++
++ <hr>
++*/
++int ioh_can_set_listen_mode(int handle, enum ioh_can_listen_mode mode)
++{
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++
++ if (handle == (int) 0) { /* invalid handle. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_listen_mode -> Invalid Handle\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /* Setting for Bit3 of Can Extended function register for
++ appropriate mode.
++ Silent bit = 0 (Active mode)
++ Silent bit = 1 (Silent mode)
++ */
++ switch (mode) {
++ case IOH_CAN_LISTEN:
++ IOH_CAN_BIT_SET((can_baseaddress + CAN_CONT_OFFSET),
++ CAN_CTRL_OPT);
++ IOH_CAN_BIT_SET((can_baseaddress + CAN_OPT_OFFSET),
++ CAN_OPT_SILENT);
++ IOH_DEBUG
++ ("ioh_can_set_listen_mode -> IOH_CAN_LISTEN \
++ mode set.\n");
++ break;
++
++ case IOH_CAN_ACTIVE:
++ IOH_CAN_BIT_SET((can_baseaddress + CAN_CONT_OFFSET),
++ CAN_CTRL_OPT);
++ IOH_CAN_BIT_CLEAR((can_baseaddress + CAN_OPT_OFFSET),
++ CAN_OPT_SILENT);
++ IOH_DEBUG
++ ("ioh_can_set_listen_mode ->IOH_CAN_ACTIVE \
++ mode set.\n");
++ break;
++
++ default:
++ IOH_DEBUG
++ ("ioh_can_set_listen_mode ->Invalid listen mode\n");
++ retval = IOH_CAN_FAIL;
++ break;
++ }
++ }
++
++ IOH_DEBUG("ioh_can_set_listen_mode -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_get_listen_mode(
++ int handle,enum ioh_can_listen_mode *mode)
++ @brief This function gets the listen/active mode of the CAN device.
++ @remarks Retrieves the currently set listen mode of the CAN
++ device.
++ The main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ - Depending on the Silent bit value of the
++ CANOPT register
++ appropriately copy the mode to mode reference
++ variable.
++ Silent bit 0: Active Mode.
++ Silent bit 1: Silent mode.
++
++ @param handle [@ref IN] The handle to the device.
++ @param mode [@ref OUT] Reference to the current listen
++ mode.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_suspend
++
++ <hr>
++*/
++int ioh_can_get_listen_mode(int handle, enum ioh_can_listen_mode *mode)
++{
++ u32 reg_val;
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++
++ if ((handle == (int) 0) || (mode == NULL)) { /* if invalid
++ parameters. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_listen_mode -> Invalid Parameter\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Attaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ reg_val = IOH_READ_LONG(can_baseaddress + CAN_OPT_OFFSET);
++
++ /* Checking for Bit3 of Can Extended function register
++ for silent mode
++ Silent bit = 0 (Active mode)
++ Silent bit = 1 (Silent mode)
++ */
++
++ if ((reg_val & CAN_OPT_SILENT) != 0) {
++ *mode = IOH_CAN_LISTEN;
++ IOH_DEBUG
++ ("ioh_can_get_listen_mode -> Mode is listen\n");
++ } else {
++ *mode = IOH_CAN_ACTIVE;
++ IOH_DEBUG
++ ("ioh_can_get_listen_mode -> Mode is active\n");
++ }
++ }
++
++ IOH_DEBUG("ioh_can_get_listen_mode -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_set_int_custom(
++ int handle, u32 interrupts
++ @brief This function sets which interrupts to enable.
++ @remarks Sets the specified interrupts. The maisn tasks
++ performed by this funation are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid return the error status code.
++ - Depending on the obtained value set/reset the
++ IE, SIE
++ and EIE bits of the CANCONT register.
++
++ @param handle [@ref IN] The handle to the device.
++ @param interrupts [@ref IN] The interrupts to be set.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_resume
++
++ <hr>
++*/
++int ioh_can_set_int_custom(int handle, u32 interrupts)
++{
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++
++ if (handle == (int) 0) { /* invalid handle. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_int_custom -> Invalid Handle.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /* Clearing the IE, SIE and EIE bits of Can control register. */
++ IOH_CAN_BIT_CLEAR((can_baseaddress + CAN_CONT_OFFSET),
++ CAN_CTRL_IE_SIE_EIE);
++
++ /* Appropriately setting them. */
++ IOH_CAN_BIT_SET((can_baseaddress + CAN_CONT_OFFSET),
++ ((interrupts & MSK_CTRL_IE_SIE_EIE) <<
++ BIT_SHIFT_ONE));
++ IOH_DEBUG("ioh_can_set_int_custom -> Interrupts set.\n");
++ }
++
++ IOH_DEBUG("ioh_can_set_int_custom -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_get_int_enables(
++ int handle,u32 *enables)
++ @brief This function retrieves interrupt enabled for the CAN
++ device.
++ @remarks Retrieves the currently enabled interrupts. The main
++ tasks performed by this function are ..
++ - Validates whether the passed arguments are
++ valid.
++ If invalid returns the error status code.
++ - Depending on the value of the IE, SIE and EIE
++ bits
++ of the CANCONT register, determine which
++ interrupts are
++ enabled and return information accordingly.
++ The interrupts
++ are enabled if the corresponding bit is set to
++ 1.
++
++ @param handle [@ref IN] The handle to the device.
++ @param enables [@ref OUT] The currently enabled
++ interrupts.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_suspend
++
++ <hr>
++*/
++int ioh_can_get_int_enables(int handle, u32 *enables)
++{
++ u32 reg_ctrl_val;
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++
++ if ((handle == (int) 0) || (enables == NULL)) { /* Invalid
++ parameters. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_int_enables -> Invalid Parameter.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /* Reading the Can control register. */
++ reg_ctrl_val = IOH_READ_LONG(can_baseaddress + CAN_CONT_OFFSET);
++
++ /* Obtaining the status of IE, SIE and EIE interrupt bits. */
++ *enables =
++ (((reg_ctrl_val & CAN_CTRL_IE_SIE_EIE) >> BIT_SHIFT_ONE));
++ IOH_DEBUG("ioh_can_get_int_enables -> Interrupt enabled "
++ "value: %d\n", *enables);
++ }
++
++ IOH_DEBUG("ioh_can_get_int_enables -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_set_int_enables(
++ int handle,enum ioh_can_interrupt interrupt)
++ @brief Sets interrupts.
++ @remarks This function enables the desired interrupts of the CAN
++ device.
++ The main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid returns the error status code.
++ - Depending on the obtained enum constants the
++ EI, SIE and
++ EIE bits of the CANCONT register are set/reset.
++
++ @param handle [@ref IN] The handle to the device.
++ @param interrupt [@ref IN] The interrupt to be enabled.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_suspend
++ - ioh_can_open
++ - ioh_can_msg_tx
++
++ <hr>
++*/
++int ioh_can_set_int_enables(int handle,
++ enum ioh_can_interrupt interrupt_no)
++{
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++
++ if (handle == (int) 0) { /* invalid handle. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_int_enables -> Invalid Handle.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++
++ /* Obatining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /*
++ Appropriately setting the IE, SIE and EIE bits of Can control
++ register.
++ */
++ switch (interrupt_no) {
++ case CAN_ENABLE:
++ IOH_CAN_BIT_SET((can_baseaddress + CAN_CONT_OFFSET),
++ CAN_CTRL_IE);
++ IOH_DEBUG
++ ("ioh_can_set_int_enables -> CAN_ENABLE (IE) \
++ interrupt set.\n");
++ break;
++
++ case CAN_DISABLE:
++ IOH_CAN_BIT_CLEAR((can_baseaddress + CAN_CONT_OFFSET),
++ CAN_CTRL_IE);
++ IOH_DEBUG
++ ("ioh_can_set_int_enables -> CAN_DIABLE (IE) \
++ interrupt reset.\n");
++ break;
++
++ case CAN_ALL:
++ IOH_CAN_BIT_SET((can_baseaddress + CAN_CONT_OFFSET),
++ CAN_CTRL_IE_SIE_EIE);
++ IOH_DEBUG
++ ("ioh_can_set_int_enables -> CAN_ALL (IE,SIE,EIE) \
++ interrupt set.\n");
++ break;
++
++ case CAN_NONE:
++ IOH_CAN_BIT_CLEAR((can_baseaddress + CAN_CONT_OFFSET),
++ CAN_CTRL_IE_SIE_EIE);
++ IOH_DEBUG
++ ("ioh_can_set_int_enables -> CAN_NONE (IE,SIE,EIE) \
++ interrupt reset.\n");
++ break;
++
++ default:
++ IOH_DEBUG
++ ("ioh_can_set_int_enables -> Invalid parameter \
++ interrupt.\n");
++ retval = IOH_CAN_FAIL;
++ break;
++ }
++ }
++
++ IOH_DEBUG("ioh_can_set_int_enables -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn static int ioh_can_rx_enable_all(int handle)
++ @brief This function enables all receive message objects of the CAN
++ device.
++ @remarks Enables all the receive message objects. The main tasks
++ performed by this function are :
++ - Validates whether the passed arguments are
++ valid. If invalid returns the error status
++ code.
++ - Enables all the message objects which are
++ configured as receive objects by invoking
++ @ref ioh_can_set_rx_enable.
++ - If enabling of at least one message object is
++ successful,
++ it returns success status code.
++
++
++ @param handle [@ref IN] The handle to the device.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_open
++ - ioh_can_callback
++
++ <hr>
++*/
++static int ioh_can_rx_enable_all(int handle)
++{
++ u32 counter = 0;
++ int retval = IOH_CAN_SUCCESS;
++ u32 i;
++
++ if (handle == (int) 0) { /* invalid handle. */
++ IOH_LOG(KERN_ERR, "ioh_can_rx_enable_all -> Invalid Handle.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Traversing to obtain the object configured as receivers. */
++ for (i = 0; i < (ioh_can_tx_buf_size + ioh_can_rx_buf_size);
++ i++) {
++ if (ioh_msg_obj_conf[i] == MSG_OBJ_RX) {
++ /* Here i is the index, however (i+1) is object
++ number. */
++ retval =
++ ioh_can_set_rx_enable(handle, (i + 1),
++ ENABLE);
++
++ if (IOH_CAN_FAIL == retval) {
++ IOH_DEBUG
++ ("ioh_can_rx_enable_all -> Cannot "
++ "Enable receive object%u\n",
++ i + 1);
++ counter++;
++ } else {
++ IOH_DEBUG("ioh_can_rx_enable_all -> "
++ "Enabled receive object %u \n",
++ i + 1);
++ }
++ }
++ }
++
++ /* If enabling of all the receive object failed. */
++ if (counter == ioh_can_rx_buf_size) {
++ retval = IOH_CAN_FAIL;
++ IOH_LOG(KERN_ERR, "ioh_can_rx_enable_all failed. \n");
++ }
++ }
++
++ IOH_DEBUG("ioh_can_rx_enable_all -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_rx_disable_all(int handle)
++ @brief This function disables all receive message objects of the
++ CAN device.
++ @remarks Disables all the receive message object. The main tasks
++ performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Disables all the receive message objects by
++ invoking
++ @ref ioh_can_set_rx_enable.
++
++ @param handle [@ref IN] The handle to the device.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_suspend
++ - ioh_can_callback
++
++ <hr>
++*/
++int ioh_can_rx_disable_all(int handle)
++{
++ u32 counter = 0;
++ int retval = IOH_CAN_SUCCESS;
++ u32 i;
++
++ if (handle == (int) 0) { /* invalid handle. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_rx_disable_all -> Invalid Handle.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Traversing to obtain the object configured as receivers. */
++ for (i = 0; i < (ioh_can_rx_buf_size + ioh_can_tx_buf_size);
++ i++) {
++ if (ioh_msg_obj_conf[i] == MSG_OBJ_RX) {
++ /* Here i is the index, however (i+1) is the
++ object number. */
++ retval =
++ ioh_can_set_rx_enable(handle, (i + 1),
++ DISABLE);
++
++ if (IOH_CAN_FAIL == retval) {
++ IOH_DEBUG("ioh_can_rx_disable_all -> \
++ Disabling of Rx " \
++ "buffer %u failed.\n", (i + 1));
++ counter++;
++ } else {
++ IOH_DEBUG("ioh_can_rx_disable_all -> \
++ Disabled receive " \
++ "object %u \n", i + 1);
++ }
++ }
++ }
++
++ /* If disabling of all the receive object failed. */
++ if (counter == ioh_can_rx_buf_size) {
++ retval = IOH_CAN_FAIL;
++ IOH_LOG(KERN_ERR, "ioh_can_rx_disable_all failed. \n");
++ }
++ }
++
++ IOH_DEBUG("ioh_can_rx_disable_all -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn static int ioh_can_tx_enable_all(int handle)
++ @brief This function enables all transmit buffers of the CAN
++ device.
++ @remarks Enables all the transmit message object. The main tasks
++ performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid returns the error status code.
++ - Enables all the message objects configured as
++ transmit
++ objects by invoking @ref ioh_can_set_tx_enable.
++ - If enabling of at least on message object is
++ successful,
++ it returns success status code.
++
++ @param handle [@ref IN] The handle to the device.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_open
++ - ioh_can_callback
++
++ <hr>
++*/
++static int ioh_can_tx_enable_all(int handle)
++{
++ u32 counter = 0;
++ int retval = IOH_CAN_SUCCESS;
++ u32 i;
++
++ if (handle == (int) 0) { /* invalid handle. */
++ IOH_LOG(KERN_ERR, "ioh_can_tx_enable_all -> Invalid Handle.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Traversing to obtain the object configured as transmit
++ object. */
++ for (i = 0; i < (ioh_can_tx_buf_size + ioh_can_rx_buf_size);
++ i++) {
++ if (ioh_msg_obj_conf[i] == MSG_OBJ_TX) {
++ /* Here i denotes the index, however (i+1) is
++ the object number. */
++ retval =
++ ioh_can_set_tx_enable(handle, (i + 1),
++ ENABLE);
++
++ if (IOH_CAN_FAIL == retval) {
++ counter++;
++ IOH_DEBUG("ioh_can_tx_enable_all -> \
++ Cannot Enable " \
++ "transmit object %u\n", (i + 1));
++ } else {
++ IOH_DEBUG("ioh_can_tx_enable_all -> \
++ Enabled transmit " \
++ "object %u\n", (i + 1));
++ }
++ }
++ }
++
++ /* If enabling of all transmit object failed. */
++ if (counter == ioh_can_rx_buf_size) {
++ IOH_LOG(KERN_ERR, "ioh_can_tx_enable_all failed.\n");
++ retval = IOH_CAN_FAIL;
++ }
++
++ }
++
++ IOH_DEBUG("ioh_can_tx_enable_all -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_tx_disable_all(int handle)
++ @brief This function enables all transmit buffers of the CAN device.
++ @remarks Disables all the transmit message objects. The main
++ tasks
++ performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Disables all the message object configured as
++ transmit
++ objects by invoking @ref ioh_can_set_tx_enable.
++
++ @param handle [@ref IN] The handle to the device.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_suspend
++ - ioh_can_callback
++
++ <hr>
++*/
++int ioh_can_tx_disable_all(int handle)
++{
++ u32 counter = 0;
++ int retval = IOH_CAN_SUCCESS;
++ u32 i;
++
++ if (handle == (int) 0) { /* invalid handle. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_tx_disable_all -> Invalid Handle.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Traversing to obtain the object configured as transmit
++ object. */
++ for (i = 0; i < (ioh_can_tx_buf_size + ioh_can_tx_buf_size);
++ i++) {
++ if (ioh_msg_obj_conf[i] == MSG_OBJ_TX) {
++ /* Here i denotes the index, however (i+1) is
++ the object number. */
++
++ /*Disabling. */
++ retval =
++ ioh_can_set_tx_enable(handle, (i + 1),
++ DISABLE);
++
++ if (IOH_CAN_FAIL == retval) {
++ IOH_DEBUG("ioh_can_tx_disable_all -> \
++ Disabling Tx " \
++ "buffer %u failed.\n", (i + 1));
++ counter++;
++ } else {
++ IOH_DEBUG("ioh_can_tx_disable_all -> \
++ Disabled transmit " \
++ "object %u \n", (i + 1));
++ }
++ }
++ }
++
++ /* If disabling of all the transmit object failed. */
++ if (counter == ioh_can_tx_buf_size) {
++ IOH_LOG(KERN_ERR, "ioh_can_tx_disable_all -> \
++ ioh_can_tx_disable_all failed.\n");
++ retval = IOH_CAN_FAIL;
++ }
++ }
++
++ IOH_DEBUG("ioh_can_tx_disable_all -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_rx_init_filter(
++ int handle,u32 buff_num)
++ @brief This function sets the receive filter for a receive buffer
++ of the CAN device.
++ @remarks Initializes the filters for a specific receive message
++ object.
++ The main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid returns error status code.
++ - Initializes the default filter settings for
++ the
++ obtained receive object by invoking @ref
++ ioh_can_set_rx_filter.
++ @note The default filter settings is done so that the receive
++ object can receive frames with any IDs.
++
++ @param handle [@ref IN] The handle to the device.
++ @param buff_num [@ref IN] The message object number.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_open
++
++ <hr>
++*/
++int ioh_can_rx_init_filter(int handle, u32 buff_num)
++{
++ int retval = IOH_CAN_SUCCESS;
++ struct ioh_can_rx_filter filter;
++
++ if (handle == (int) 0) { /* if invalid handle. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_rx_init_filter -> Invalid Handle.\n");
++ retval = IOH_CAN_FAIL;
++ }
++ /* if invalid buffer number. */
++ else if ((ioh_msg_obj_conf[buff_num - 1] != MSG_OBJ_RX) ||
++ (buff_num > (ioh_can_tx_buf_size + ioh_can_rx_buf_size))) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_rx_init_filter -> Invalid buffer no:%d\n",
++ buff_num);
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Set all Rx filters to allow all msgs. */
++ filter.amr.id = (u32) 0;
++ filter.amr.id_ext = (u32) 0;
++
++ filter.aidr.id = (u32) 0;
++ filter.aidr.id_ext = (u32) 0;
++
++ filter.num = buff_num;
++ filter.umask = 1;
++
++ retval = ioh_can_set_rx_filter(handle, &filter);
++ }
++
++ IOH_DEBUG("ioh_can_rx_init_filter -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_set_rx_enable(
++ int handle,u32 buff_num,u32 set)
++ @brief This function enables or disables a particular receive
++ buffer of the CAN device.
++ @remarks Enables/Disables a specific receive message object. The
++ main
++ tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Depending on whether the message object has to
++ enabled/disabled
++ the MsgVal and the RxIE bit of the message
++ object are
++ set/reset.
++ To Enable :Set MsgVal and RxIE bits.
++ To Disable: Reset MsgVal and RxIE bits.
++
++ @param handle [@ref IN] The handle to the device.
++ @param buff_num [@ref IN] Message object number.
++ @param set [@ref IN] Enable/Disable flag.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_rx_enable_all
++ - ioh_can_rx_disable_all
++
++ <hr>
++*/
++int ioh_can_set_rx_enable(int handle, u32 buff_num, u32 set)
++{
++ u32 counter;
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress = NULL;
++ u32 if1_creq;
++
++ if (handle == (int) 0) { /* invalid handle. */
++ IOH_LOG(KERN_ERR, "ioh_can_set_rx_enable -> Invalid Handle.\n");
++ retval = IOH_CAN_FAIL;
++ }
++ /* if invalid buffer number. */
++ else if ((ioh_msg_obj_conf[buff_num - 1] != MSG_OBJ_RX) ||
++ (buff_num > (ioh_can_tx_buf_size + ioh_can_rx_buf_size))) {
++ IOH_LOG(KERN_ERR, "ioh_can_set_rx_enable -> Message object %u "
++ "not configured for receive.\n", buff_num);
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /*Reading the receive buffer data from RAM to Interface1
++ registers */
++ IOH_WRITE_LONG(CAN_CMASK_RX_TX_GET,
++ (can_baseaddress + CAN_IF1_CMASK_OFFSET));
++ IOH_WRITE_LONG(buff_num,
++ (can_baseaddress + CAN_IF1_CREQ_OFFSET));
++
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if1_creq = \
++ (IOH_READ_LONG(can_baseaddress + CAN_IF1_CREQ_OFFSET))
++ & CAN_IF_CREQ_BUSY;
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++
++ if ((counter == 0)) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_rx_enable -> Cannot read "
++ "the message buffer object %u.\n", buff_num);
++ retval = IOH_CAN_FAIL;
++ }
++
++ else { /*Reading successful */
++
++ /*Setting the IF1MASK1 register to access MsgVal and
++ RxIE bits */
++ IOH_WRITE_LONG((CAN_CMASK_RDWR | CAN_CMASK_ARB |
++ CAN_CMASK_CTRL),
++ (can_baseaddress +
++ CAN_IF1_CMASK_OFFSET));
++
++ if (set == ENABLE) {
++ /*Setting the MsgVal and RxIE bits */
++ IOH_CAN_BIT_SET((can_baseaddress +
++ CAN_IF1_MCONT_OFFSET),
++ CAN_IF_MCONT_RXIE);
++ IOH_CAN_BIT_SET((can_baseaddress +
++ CAN_IF1_ID2_OFFSET),
++ CAN_ID_MSGVAL);
++
++ IOH_DEBUG
++ ("ioh_can_set_rx_enable -> Enabled receive "
++ "message buffer %u.\n", buff_num);
++ } else if (set == DISABLE) {
++ /*Resetting the MsgVal and RxIE bits */
++ IOH_CAN_BIT_CLEAR((can_baseaddress +
++ CAN_IF1_MCONT_OFFSET),
++ CAN_IF_MCONT_RXIE);
++ IOH_CAN_BIT_CLEAR((can_baseaddress +
++ CAN_IF1_ID2_OFFSET),
++ CAN_ID_MSGVAL);
++
++ IOH_DEBUG
++ ("ioh_can_set_rx_enable -> Disabled receive "
++ "message buffer %u", buff_num);
++ }
++
++ /*Updating the changes to the message object. */
++ IOH_WRITE_LONG(buff_num,
++ (can_baseaddress + CAN_IF1_CREQ_OFFSET));
++
++ /*Confirming the write by checking the busy bit. */
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if1_creq = \
++ (IOH_READ_LONG(
++ can_baseaddress + \
++ CAN_IF1_CREQ_OFFSET)) \
++ & CAN_IF_CREQ_BUSY;
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++
++ if ((counter == 0)) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_rx_enable -> Write failed.\n");
++ retval = IOH_CAN_FAIL;
++ }
++ }
++ }
++
++ IOH_DEBUG("ioh_can_set_rx_enable -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_get_rx_enable(
++ int handle,u32 buff_num,u32 *enable)
++ @brief This function gets the enable state of a receive buffer.
++ @remarks Retrieves the current state(Enabled/disabled) of a
++ receive message object.
++ The main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Depending on the value of the MsgVal and the
++ RxIE bits, the
++ enable/disable status is determined and passed
++ to the function
++ calling this function.
++ MsgVal and RxIE bits set :
++ The receive message object is enabled.
++ MsgVal and RxIE bits reset:
++ The receive message object is disabled.
++
++ @param handle [@ref IN] The handle to the device.
++ @param buff_num [@ref IN] The message object number.
++ @param enable [@ref OUT] The reference to the
++ enable/disable flag.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_suspend
++
++ <hr>
++*/
++int ioh_can_get_rx_enable(int handle, u32 buff_num, u32 *enable)
++{
++ u8 *can_baseaddress;
++ int retval = IOH_CAN_SUCCESS;
++ u32 counter;
++ u32 if1_creq;
++
++ if ((handle == (int) 0) || (enable == NULL)) { /* invalid parameter. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_rx_enable -> Invalid Parameter.\n");
++ retval = IOH_CAN_FAIL;
++ }
++ /* Invalid buffer number. */
++ else if ((ioh_msg_obj_conf[buff_num - 1] != MSG_OBJ_RX) ||
++ (buff_num > (ioh_can_tx_buf_size + ioh_can_rx_buf_size))) {
++ IOH_LOG(KERN_ERR, "ioh_can_get_rx_enable -> Message object %u "
++ "not configured for receive.\n", buff_num);
++ retval = IOH_CAN_FAIL;
++ }
++
++ else {
++ /* Obtaining the remap address fro access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ IOH_WRITE_LONG(CAN_CMASK_RX_TX_GET,
++ (can_baseaddress + CAN_IF1_CMASK_OFFSET));
++ IOH_WRITE_LONG(buff_num,
++ (can_baseaddress + CAN_IF1_CREQ_OFFSET));
++
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if1_creq = \
++ (IOH_READ_LONG((can_baseaddress + CAN_IF1_CREQ_OFFSET)))
++ & CAN_IF_CREQ_BUSY;
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ if (counter == 0) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_rx_enable -> Read Failed.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ if (((IOH_READ_LONG
++ (can_baseaddress +
++ CAN_IF1_ID2_OFFSET)) & CAN_ID_MSGVAL)
++ &&
++ ((IOH_READ_LONG
++ (can_baseaddress +
++ CAN_IF1_MCONT_OFFSET)) & CAN_IF_MCONT_RXIE)) {
++ *enable = ENABLE;
++
++ IOH_DEBUG
++ ("ioh_can_get_rx_enable -> Receive message "
++ "buffer %u is enabled.\n", buff_num);
++ } else {
++ *enable = DISABLE;
++
++ IOH_DEBUG
++ ("ioh_can_get_rx_enable -> Receive Message "
++ "buffer %u is disabled.\n", buff_num);
++ }
++ }
++
++ }
++
++ IOH_DEBUG("ioh_can_get_rx_enable -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_set_tx_enable(
++ int handle, u32 buff_num,u32 set)
++ @brief This function enables/disables a transmit message object.
++ @remarks Enables/Disables a specific transmit message object. The
++ main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Depending whether to enable/disable the
++ transmit object the
++ MsgVal and TxIE bits are set/reset.
++ To Enable : Set the MsgVal and TxIE
++ bits.
++ To disable: Reset the MsgVal and
++ RxIE bits.
++
++ @param handle [@ref IN] The handle to the device.
++ @param buff_num [@ref IN] The message object number.
++ @param set [@ref IN] Enable/Disable flag.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_tx_enable_all
++ - ioh_can_tx_disable_all
++
++ <hr>
++*/
++int ioh_can_set_tx_enable(int handle, u32 buff_num, u32 set)
++{
++ u8 *can_baseaddress;
++ int retval = IOH_CAN_SUCCESS;
++ u32 counter;
++ u32 if1_creq;
++
++ if (handle == (int) 0) { /* invalid handle. */
++ IOH_LOG(KERN_ERR, "ioh_can_set_tx_enable -> Invalid Handle");
++ retval = IOH_CAN_FAIL;
++ }
++ /* invalid buffer number. */
++ else if ((ioh_msg_obj_conf[buff_num - 1] != MSG_OBJ_TX) ||
++ (buff_num > (ioh_can_rx_buf_size + ioh_can_tx_buf_size))) {
++ IOH_LOG(KERN_ERR, "ioh_can_set_tx_enable -> Message object %u "
++ "not configured for transmit.\n", buff_num);
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /*Reading the Message buffer from Message RAM to Interface2
++ registers. */
++ IOH_WRITE_LONG(CAN_CMASK_RX_TX_GET,
++ (can_baseaddress + CAN_IF1_CMASK_OFFSET));
++ IOH_WRITE_LONG(buff_num,
++ (can_baseaddress + CAN_IF1_CREQ_OFFSET));
++
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if1_creq = \
++ (IOH_READ_LONG(can_baseaddress + CAN_IF1_CREQ_OFFSET)) &
++ CAN_IF_CREQ_BUSY;
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ if ((counter == 0)) {
++ IOH_LOG(KERN_ERR, "ioh_can_set_tx_enable -> Reading "
++ "transmit buffer failed.\n");
++ retval = IOH_CAN_FAIL;
++ } else { /*Reading successful. */
++
++ /*Setting the IF2CMASK register for accessing the MsgVal
++ and TxIE bits */
++ IOH_WRITE_LONG((CAN_CMASK_RDWR | CAN_CMASK_ARB |
++ CAN_CMASK_CTRL),
++ (can_baseaddress +
++ CAN_IF1_CMASK_OFFSET));
++
++ if (set == ENABLE) {
++ /*Setting the MsgVal and TxIE bits */
++ IOH_CAN_BIT_SET((can_baseaddress +
++ CAN_IF1_MCONT_OFFSET),
++ CAN_IF_MCONT_TXIE);
++ IOH_CAN_BIT_SET((can_baseaddress +
++ CAN_IF1_ID2_OFFSET),
++ CAN_ID_MSGVAL);
++
++ IOH_DEBUG
++ ("ioh_can_set_tx_enable -> Enabled transmit "
++ "message buffer %u\n", buff_num);
++ } else if (set == DISABLE) {
++ /*Resetting the MsgVal and TxIE bits. */
++ IOH_CAN_BIT_CLEAR((can_baseaddress +
++ CAN_IF1_MCONT_OFFSET),
++ CAN_IF_MCONT_TXIE);
++ IOH_CAN_BIT_CLEAR((can_baseaddress +
++ CAN_IF1_ID2_OFFSET),
++ CAN_ID_MSGVAL);
++
++ IOH_DEBUG
++ ("ioh_can_set_tx_enable -> Disabled transmit "
++ "message buffer %u\n", buff_num);
++ }
++
++ /*Updating the changes to the message buffer. */
++ IOH_WRITE_LONG(buff_num,
++ (can_baseaddress + CAN_IF1_CREQ_OFFSET));
++
++ /*Confirming the updation. */
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if1_creq = \
++ (IOH_READ_LONG(
++ can_baseaddress + CAN_IF1_CREQ_OFFSET))
++ & CAN_IF_CREQ_BUSY;
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ if ((counter == 0)) { /*Updation failed. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_tx_enable -> Write failed.\n");
++ retval = IOH_CAN_FAIL;
++ }
++ }
++ }
++
++ IOH_DEBUG("ioh_can_set_tx_enable -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_get_tx_enable(
++ int handle,u32 buff_num,u32 *enable)
++ @brief This function gets the enable/disable status of a transmit
++ buffer.
++ @remarks Retrieves the current state(enabled/disabled) of a
++ transmit message object.
++ The main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Depending on the value of the MsgVal and the
++ TxIE bits, the
++ enable/disable status of the message object is
++ determined and
++ passed to the function calling this function.
++ MsgVal and TxIE bits set -->
++ The transmit object is enabled.
++ MsgVal and TxIE bit reset-->
++ The transmit object is disabled.
++
++ @param handle [@ref IN] The handle to the device.
++ @param buff_num [@ref IN] The message object number.
++ @param enable [@ref OUT] The reference to the
++ enable/disable flag.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_suspend
++
++ <hr>
++*/
++int ioh_can_get_tx_enable(int handle, u32 buff_num, u32 *enable)
++{
++ u8 *can_baseaddress;
++ int retval = IOH_CAN_SUCCESS;
++ u32 counter;
++ u32 if1_creq;
++
++ if ((handle == (int) 0) || (enable == NULL)) { /* invalid
++ parameters. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_tx_enable -> Invalid Parameter.\n");
++ retval = IOH_CAN_FAIL;
++ }
++ /* invalid buffer number. */
++ else if ((ioh_msg_obj_conf[buff_num - 1] != MSG_OBJ_TX) ||
++ (buff_num > (ioh_can_rx_buf_size + ioh_can_tx_buf_size))) {
++ IOH_LOG(KERN_ERR, "ioh_can_get_tx_enable -> Invalid Message "
++ "object %u.\n", buff_num);
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the buffer number for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ IOH_WRITE_LONG(CAN_CMASK_RX_TX_GET,
++ (can_baseaddress + CAN_IF1_CMASK_OFFSET));
++ IOH_WRITE_LONG(buff_num,
++ (can_baseaddress + CAN_IF1_CREQ_OFFSET));
++
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if1_creq = \
++ (IOH_READ_LONG(can_baseaddress + CAN_IF1_CREQ_OFFSET)) &
++ CAN_IF_CREQ_BUSY;
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ if (counter == 0) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_tx_enable -> Read Failed.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ if (((IOH_READ_LONG
++ (can_baseaddress +
++ CAN_IF1_ID2_OFFSET)) & CAN_ID_MSGVAL)
++ &&
++ ((IOH_READ_LONG
++ (can_baseaddress +
++ CAN_IF1_MCONT_OFFSET)) & CAN_IF_MCONT_TXIE)) {
++ *enable = ENABLE;
++
++ IOH_DEBUG
++ ("ioh_can_get_rx_enable -> Transmit message "
++ "buffer %u is enabled.\n", buff_num);
++ } else {
++ *enable = DISABLE;
++
++ IOH_DEBUG
++ ("ioh_can_get_rx_enable -> Transmit message "
++ "buffer %u is disabled.\n", buff_num);
++ }
++ }
++ }
++
++ IOH_DEBUG("ioh_can_get_tx_enable -> Return value: %d.\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_int_pending(int handle)
++ @brief This function returns whether or not interrupts are pending
++ for the CAN device.
++ @remarks Retrieves the pending interrupts. The main tasks
++ performed by this function are :
++ - Validates whether the passed arguments are
++ valid. If
++ invalid error status code is returned.
++ - Reads the value of the CANINT register and
++ returns it to the function calling this
++ function.
++
++ @param handle [@ref IN] The handle to the device.
++
++ @retval int
++ - 0 --> No interrupts are pending
++ - >0 --> Interrupts are pending.
++ - @ref IOH_CAN_FAIL --> Operation failed.
++
++ @see
++ - ioh_can_handler
++
++ <hr>
++*/
++int ioh_can_int_pending(int handle)
++{
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++
++ if (handle == (int) 0) { /* invalid handle. */
++ IOH_LOG(KERN_ERR, "ioh_can_int_pending -> Invalid Handle.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obatining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ retval = (IOH_READ_LONG(can_baseaddress + CAN_INT_OFFSET) &
++ MSK_ALL_SIXTEEN);
++ }
++
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_set_baud_simple(
++ int handle, enum ioh_can_baud baud)
++ @brief This function sets the baud rate of the CAN device.
++ @remarks Sets the Timing baud settings of the CAN device. The
++ main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Depending on the baud rate passed and the
++ clock rate
++ the CANBITT and CANBRPE register values are
++ determined and written to these registers.
++
++ @param handle [@ref IN] The handle to the device.
++ @param baud [@ref IN] The baud settings to be done.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_open
++
++ <hr>
++*/
++int ioh_can_set_baud_simple(int handle, enum ioh_can_baud baud)
++{
++ u32 reg_val;
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++
++ if (handle == (int) 0) { /* invalid handle. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_baud_simple -> Invalid Handle.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ u32 offset;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /* Setting the CCE bit of Can control register for accessing the
++ Timing Register. */
++ IOH_CAN_BIT_SET((can_baseaddress + CAN_CONT_OFFSET),
++ CAN_CTRL_CCE);
++
++ /* Calculating the offset of the settings array for the current
++ clock. */
++ switch (ioh_can_clock) {
++ case 62500:
++ offset = IOH_CAN_CLOCK_62_5_OFFSET;
++ break;
++
++ case 24000:
++ offset = IOH_CAN_CLOCK_24_OFFSET;
++ break;
++
++ case 50000:
++ offset = IOH_CAN_CLOCK_50_OFFSET;
++ break;
++
++ /* The default section will not be invoked since
++ the clock frequency
++ has been validated at the module init procedure.
++ */
++ default:
++ offset = IOH_CAN_CLOCK_DEFAULT_OFFSET;
++ break;
++ }
++
++ /* Getting the appropriate register value. */
++ reg_val =
++ (((can_rec_timing[baud + offset].
++ cfg_bitrate & MSK_BITT_BRP) << BIT_BITT_BRP) |
++ (can_rec_timing[baud + offset].
++ cfg_tseg1 << BIT_BITT_TSEG1) | (can_rec_timing[baud +
++ offset].
++ cfg_tseg2 <<
++ BIT_BITT_TSEG2) |
++ (can_rec_timing[baud + offset].cfg_sjw << BIT_BITT_SJW));
++
++ /* Writing to Can Timing register. */
++ IOH_WRITE_LONG(reg_val, (can_baseaddress + CAN_BITT_OFFSET));
++ /* Writing to the CAN BRP register. */
++ IOH_WRITE_LONG(((can_rec_timing[baud + offset].
++ cfg_bitrate & MSK_BRPE_BRPE) >> BIT_BRPE_BRPE),
++ (can_baseaddress + CAN_BRPE_OFFSET));
++
++ /* Resetting the CCE bit of the Can control register. */
++ IOH_CAN_BIT_CLEAR((can_baseaddress + CAN_CONT_OFFSET),
++ CAN_CTRL_CCE);
++
++ IOH_DEBUG("ioh_can_set_baud_simple -> Timing Baud set.\n");
++ IOH_DEBUG("cfg_bitrate : %u\n",
++ can_rec_timing[baud + offset].cfg_bitrate);
++ IOH_DEBUG("cfg_tseg1 : %u\n",
++ can_rec_timing[baud + offset].cfg_tseg1);
++ IOH_DEBUG("cfg_tseg2 : %u\n",
++ can_rec_timing[baud + offset].cfg_tseg2);
++ IOH_DEBUG("cfg_sjw : %u\n",
++ can_rec_timing[baud + offset].cfg_sjw);
++ }
++
++ IOH_DEBUG("ioh_can_set_baud_simple -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_set_baud_custom(
++ int handle,struct ioh_can_timing *timing)
++ @brief This function sets a custom baud rate for the CAN device.
++ @remarks Sets the user specified Timing baud settings. The main
++ tasks
++ performed by this function are :
++ - Validates whether the passed arguments are
++ valid. If
++ invalid error status code is returned.
++ - Depending on the user provided settings the
++ CANBITT and CANBRPE
++ register values are determined and written to
++ these registers.
++
++ @param handle [@ref IN] The handle to the device.
++ @param timing [@ref IN] The reference to the timing
++ settings.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_resume
++
++ <hr>
++*/
++int ioh_can_set_baud_custom(int handle, struct ioh_can_timing *timing)
++{
++ u32 reg_val;
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++
++ if ((handle == (int) 0) || (timing == NULL)) { /* invalid parameter. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_baud_custom -> Invalid parameter.\n");
++ retval = IOH_CAN_FAIL;
++ }
++ /* max is MAX_BITRATE */
++ else if (timing->bitrate > MAX_BITRATE) {
++ IOH_LOG(KERN_ERR, "ioh_can_set_baud_custom -> Bit rate %x "
++ "is invalid.\n", timing->bitrate);
++ retval = IOH_CAN_FAIL;
++ }
++
++ else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /* Setting the CCE bit of Can control register for accessing the
++ Can Timing register. */
++ IOH_CAN_BIT_SET((can_baseaddress + CAN_CONT_OFFSET),
++ CAN_CTRL_CCE);
++
++ /* Obtaining the appropriate register value. */
++ reg_val =
++ (((timing->
++ cfg_bitrate & MSK_BITT_BRP) << BIT_BITT_BRP) | (timing->
++ cfg_tseg1
++ <<
++ BIT_BITT_TSEG1)
++ | (timing->cfg_tseg2 << BIT_BITT_TSEG2) | (timing->
++ cfg_sjw <<
++ BIT_BITT_SJW));
++
++ /* Writing to the timing register. */
++ IOH_WRITE_LONG(reg_val, (can_baseaddress + CAN_BITT_OFFSET));
++ /* Writing to the BRP register. */
++ IOH_WRITE_LONG(((timing->
++ cfg_bitrate & MSK_BRPE_BRPE) >> BIT_BRPE_BRPE),
++ (can_baseaddress + CAN_BRPE_OFFSET));
++
++ /* Resetting the CCE bit. */
++ IOH_CAN_BIT_CLEAR((can_baseaddress + CAN_CONT_OFFSET),
++ CAN_CTRL_CCE);
++
++ IOH_DEBUG("ioh_can_set_baud_custom -> Timing baud set.\n");
++ IOH_DEBUG("cfg_bitrate : %u\n", timing->cfg_bitrate);
++ IOH_DEBUG("cfg_tseg1 : %u\n", timing->cfg_tseg1);
++ IOH_DEBUG("cfg_tseg2 : %u\n", timing->cfg_tseg2);
++ IOH_DEBUG("cfg_sjw : %u\n", timing->cfg_sjw);
++ }
++
++ IOH_DEBUG("ioh_can_set_baud_custom -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_get_baud(
++ int handle,struct ioh_can_timing *timing)
++ @brief This function gets the baud rate for the CAN device.
++ @remarks Retrieves the currently set timing baud settings. The
++ main tasks
++ performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Depending on the CANBITT and CANBRPE register
++ values
++ the different fields of the timing structure is
++ filled
++ and returned to the function calling this
++ function.
++
++ @param handle [@ref IN] The handle to the device.
++ @param timing [@ref OUT] The reference to the timing baud
++ settings.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_suspend
++
++ <hr>
++*/
++int ioh_can_get_baud(int handle, struct ioh_can_timing *timing)
++{
++ u32 timing_bitt_reg;
++ u32 timing_brpe_reg;
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++
++ if ((handle == (int) 0) || (timing == NULL)) { /* invalid
++ parameters. */
++ IOH_LOG(KERN_ERR, "ioh_can_get_baud -> Invalid Parameter.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ timing_bitt_reg =
++ IOH_READ_LONG(can_baseaddress + CAN_BITT_OFFSET);
++ timing_brpe_reg =
++ IOH_READ_LONG(can_baseaddress + CAN_BRPE_OFFSET);
++
++ /* Separating the individual part from the values read. */
++ timing->cfg_bitrate = ((timing_bitt_reg & MSK_BITT_BRP) |
++ ((timing_brpe_reg & MSK_BRPE_GET) <<
++ BIT_BRPE_BRPE));
++ timing->cfg_tseg1 =
++ (timing_bitt_reg & MSK_BITT_TSEG1) >> BIT_BITT_TSEG1;
++ timing->cfg_tseg2 =
++ (timing_bitt_reg & MSK_BITT_TSEG2) >> BIT_BITT_TSEG2;
++ timing->cfg_sjw =
++ (timing_bitt_reg & MSK_BITT_SJW) >> BIT_BITT_SJW;
++
++ IOH_DEBUG
++ ("ioh_can_get_baud -> The timing structure filled \
++ successfully.\n");
++ IOH_DEBUG("cfg_bitrate : %u\n", timing->cfg_bitrate);
++ IOH_DEBUG("cfg_tseg1 : %u\n", timing->cfg_tseg1);
++ IOH_DEBUG("cfg_tseg2 : %u\n", timing->cfg_tseg2);
++ IOH_DEBUG("cfg_sjw : %u\n", timing->cfg_sjw);
++ }
++
++ IOH_DEBUG("ioh_can_get_baud -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_set_rx_filter(
++ int handle,struct ioh_can_rx_filter *filter)
++ @brief This function sets the receive filter for a receive buffer
++ of the CAN device.
++ @remarks Sets the receive filter for a specific receive message
++ object.
++ The main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Depending on the obtained filter settings, the
++ acceptance
++ filter settings of the receive message object is
++ updated.
++
++ @param handle [@ref IN] The handle to the device.
++ @param filter [@ref IN] the reference to the filter
++ settings
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_rx_init_filter
++ - ioh_can_resume
++
++ <hr>
++*/
++int ioh_can_set_rx_filter(int handle, struct ioh_can_rx_filter *filter)
++{
++ u32 reg1;
++ u32 reg2;
++ u32 counter;
++ u8 *can_baseaddress = NULL;
++ int retval = IOH_CAN_SUCCESS;
++ u32 if1_creq;
++
++ if ((handle == (int) 0) || (filter == NULL)) { /* invalid
++ parameters. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_rx_filter -> Invalid Parameter.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ IOH_WRITE_LONG(CAN_CMASK_RX_TX_GET, \
++ (can_baseaddress + CAN_IF1_CMASK_OFFSET));
++ /*Setting the CMASK for reading */
++ IOH_WRITE_LONG(filter->num, \
++ (can_baseaddress + CAN_IF1_CREQ_OFFSET));
++ /*Setting CREQ to specified Msg Obj. */
++
++ /*Confirming the read completion. */
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if1_creq = \
++ (IOH_READ_LONG(can_baseaddress + CAN_IF1_CREQ_OFFSET)) &
++ CAN_IF_CREQ_BUSY;
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ if ((counter == 0)) { /*Read Unsuccessful. */
++ IOH_LOG(KERN_ERR, "ioh_can_set_rx_filter -> Reading "
++ "of message buffer %u failed.\n", filter->num);
++ retval = IOH_CAN_FAIL;
++ } else { /*read successful. */
++
++ IOH_CAN_BIT_CLEAR((can_baseaddress + \
++ CAN_IF1_ID2_OFFSET), \
++ MSK_ALL_THIRTEEN);
++ /*Clearing the bit 0- 12 of ID2 */
++ IOH_CAN_BIT_CLEAR((can_baseaddress + \
++ CAN_IF1_ID2_OFFSET), \
++ CAN_ID2_XTD);
++ /*Clearing XTD bit */
++
++ if ((filter->aidr.id_ext == 1)) { /*Extended ID */
++ reg1 = filter->aidr.id & MSK_ALL_SIXTEEN;
++ /*ID1 value. */
++ /*ID2 value with XTD bit set. */
++ reg2 =
++ (((filter->aidr.
++ id & (MSK_ALL_THIRTEEN <<
++ BIT_SHIFT_SIXTEEN))
++ >> BIT_SHIFT_SIXTEEN) | CAN_ID2_XTD);
++ } else { /*Standard ID */
++
++ reg1 = 0; /*ID1 value */
++ reg2 = ((filter->aidr.id & MSK_ALL_ELEVEN) << \
++ BIT_SHIFT_TWO); /*ID2 value */
++ }
++
++ IOH_WRITE_LONG(reg1, (can_baseaddress + \
++ CAN_IF1_ID1_OFFSET)); /*Writing ID1 */
++ IOH_CAN_BIT_SET((can_baseaddress + \
++ CAN_IF1_ID2_OFFSET), reg2); /*Writing ID2 */
++
++ if (filter->umask == 1) {
++ /*If mask has to be set. */
++ IOH_CAN_BIT_CLEAR((can_baseaddress + \
++ CAN_IF1_MASK2_OFFSET), MSK_ALL_THIRTEEN);
++ /*Clearing bit 0-12 */
++ IOH_CAN_BIT_CLEAR((can_baseaddress + \
++ CAN_IF1_MASK2_OFFSET), CAN_MASK2_MDIR_MXTD);
++ /*Clearing Mdir & MXtd */
++
++ if (filter->amr.id_ext == 1) {
++ /*Extended Mask */
++ reg1 = filter->amr.id & MSK_ALL_SIXTEEN;
++ /*Mask1 value */
++ /*Mask2 value with MXtd set */
++ reg2 =
++ (((filter->amr.
++ id & (MSK_ALL_THIRTEEN <<
++ BIT_SHIFT_SIXTEEN))
++ >> BIT_SHIFT_SIXTEEN) |
++ CAN_IF_MASK2_MXTD);
++ } else {
++ reg1 = 0; /*Mask1 value */
++ reg2 = ((filter->amr.id & \
++ MSK_ALL_ELEVEN) << BIT_SHIFT_TWO);
++ /*Mask2 Value */
++ }
++
++ IOH_WRITE_LONG(reg1, \
++ (can_baseaddress + CAN_IF1_MASK1_OFFSET));
++ /*Writing MASK1 */
++ IOH_CAN_BIT_SET((can_baseaddress + \
++ CAN_IF1_MASK2_OFFSET), reg2);
++ /*Writing MASK2 */
++ IOH_CAN_BIT_SET((can_baseaddress + \
++ CAN_IF1_MCONT_OFFSET), CAN_IF_MCONT_UMASK);
++ /*Setting Umask bit */
++ } else {
++ IOH_CAN_BIT_CLEAR((can_baseaddress + \
++ CAN_IF1_MCONT_OFFSET), CAN_IF_MCONT_UMASK);
++ /*Resetting Umask bit. */
++ }
++
++ /*Setting CMASK for writing */
++ IOH_WRITE_LONG((CAN_CMASK_RDWR | CAN_CMASK_MASK |
++ CAN_CMASK_ARB | CAN_CMASK_CTRL),
++ (can_baseaddress +
++ CAN_IF1_CMASK_OFFSET));
++ IOH_WRITE_LONG(filter->num, (can_baseaddress + \
++ CAN_IF1_CREQ_OFFSET));
++ /*Setting CREQ for specified sg Obj. */
++
++ /*Confirming the write completion. */
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if1_creq = \
++ (IOH_READ_LONG
++ (can_baseaddress + CAN_IF1_CREQ_OFFSET))
++ & CAN_IF_CREQ_BUSY;
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ if (counter == 0) { /*Write failed */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_rx_filter -> \
++ Write failed.\n");
++ retval = IOH_CAN_FAIL;
++ } else { /*Write successful. */
++
++ IOH_DEBUG
++ ("ioh_can_set_rx_filter -> Filter set \
++ successful "
++ "for message object %u.\n", filter->num);
++ }
++ }
++ }
++
++ IOH_DEBUG("ioh_can_set_rx_filter -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_set_rx_buffer_link(
++ int handle,u32 buffer_num,u32 seti)
++ @brief This function sets receive buffer linking of the CAN device.
++ @remarks Enables/disables the buffer link for specific receive
++ buffer.
++ The main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Depending on whether to enable/disable buffer
++ link the EOB
++ bit of the message object is set/reset.
++ Enable buffer link : Reset the EOB
++ bit.
++ Disable buffer link: Set the EOB bit.
++
++ @param handle [@ref IN] The handle to the device.
++ @param buffer_num [@ref IN] The message object number.
++ @param set [@ref IN] The enable/disable flag.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_resume
++
++ <hr>
++*/
++int ioh_can_set_rx_buffer_link(int handle, u32 buffer_num, u32 set)
++{
++ u32 counter;
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++ u32 if1_creq;
++
++ if (handle == (int) 0) { /* if invalid handle. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_rx_buffer_link -> Invalid handle.\n");
++ retval = IOH_CAN_FAIL;
++ }
++ /* invalid buffer nummber. */
++ else if ((ioh_msg_obj_conf[buffer_num - 1] != MSG_OBJ_RX)
++ || (buffer_num > (ioh_can_rx_buf_size + \
++ ioh_can_tx_buf_size))) {
++ IOH_LOG(KERN_ERR, "ioh_can_set_rx_buffer_link -> Invalid "
++ "buffer number %u.\n", buffer_num);
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /* Reading the corresponding object. */
++ IOH_WRITE_LONG(CAN_CMASK_RX_TX_GET,
++ (can_baseaddress + CAN_IF1_CMASK_OFFSET));
++ IOH_WRITE_LONG(buffer_num,
++ (can_baseaddress + CAN_IF1_CREQ_OFFSET));
++
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if1_creq = \
++ IOH_READ_LONG((can_baseaddress + CAN_IF1_CREQ_OFFSET)) &
++ CAN_IF_CREQ_BUSY;
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ /* Confirming read. */
++ if ((counter == 0)) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_rx_buffer_link -> Read failed\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ IOH_WRITE_LONG((CAN_CMASK_RDWR | CAN_CMASK_CTRL),
++ (can_baseaddress +
++ CAN_IF1_CMASK_OFFSET));
++
++ /*
++ Setting/Resetting the EOD bit for Buffer link
++ operation.
++ EOB bit = 1 -> Buffer link disabled.
++ EOB bit = 0 -> Biffer link enabled.
++ */
++ if (set == ENABLE) {
++ IOH_CAN_BIT_CLEAR((can_baseaddress +
++ CAN_IF1_MCONT_OFFSET),
++ CAN_IF_MCONT_EOB);
++ IOH_DEBUG
++ ("ioh_can_set_rx_buffer_link -> \
++ Buffer Link enabled.\n");
++ } else {
++ IOH_CAN_BIT_SET((can_baseaddress +
++ CAN_IF1_MCONT_OFFSET),
++ CAN_IF_MCONT_EOB);
++ IOH_DEBUG
++ ("ioh_can_set_rx_buffer_link -> \
++ Buffer Link disabled.\n");
++ }
++
++ IOH_WRITE_LONG(buffer_num,
++ (can_baseaddress + CAN_IF1_CREQ_OFFSET));
++
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if1_creq = \
++ IOH_READ_LONG(
++ can_baseaddress + CAN_IF1_CREQ_OFFSET)
++ & CAN_IF_CREQ_BUSY;
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ if (counter == 0) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_set_rx_buffer_link -> \
++ Write failed.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ IOH_DEBUG
++ ("ioh_can_set_rx_buffer_link -> \
++ Write successful.\n");
++ retval = IOH_CAN_SUCCESS;
++ }
++
++ }
++ }
++
++ IOH_DEBUG("ioh_can_set_rx_buffer_link -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_get_rx_buffer_link(
++ int handle,u32 buffer_num,u32 *link)
++ @brief This function gets receive buffer linking of the CAN device.
++ @remarks Retrieves the current buffer link state(
++ enabled/disabled) of a receive object.
++ The main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Depending on the value of the EOB bit, the
++ enable/disable
++ status of the buffer link of the message object
++ is determined
++ and returned to the function calling this
++ function.
++ EOB bit set : Buffer link disabled.
++ EOB bit reset: Buffer link enabled.
++
++ @param handle [@ref IN] The handle to the device.
++ @param buffer_num [@ref IN] The message object number.
++ @param link [@ref OUT] The reference to the buffer link
++ state.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_suspend
++
++ <hr>
++*/
++int ioh_can_get_rx_buffer_link(int handle, u32 buffer_num,
++ u32 *link)
++{
++ u32 reg_val;
++ u32 counter;
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++ u32 if1_creq;
++
++ if ((handle == (int) 0) || (link == NULL)) { /* invalid
++ parameters. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_rx_buffer_link -> Invalid Parameter.\n");
++ retval = IOH_CAN_FAIL;
++ } else if ((ioh_msg_obj_conf[buffer_num - 1] != MSG_OBJ_RX) ||
++ (buffer_num > (ioh_can_rx_buf_size + ioh_can_tx_buf_size))) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_rx_buffer_link -> Invalid buffer "
++ "number %u.\n", buffer_num);
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obatining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /* Reading the corresponding message object. */
++ IOH_WRITE_LONG(CAN_CMASK_RX_TX_GET,
++ (can_baseaddress + CAN_IF1_CMASK_OFFSET));
++ IOH_WRITE_LONG(buffer_num,
++ (can_baseaddress + CAN_IF1_CREQ_OFFSET));
++
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if1_creq = \
++ (IOH_READ_LONG((can_baseaddress + CAN_IF1_CREQ_OFFSET))
++ & CAN_IF_CREQ_BUSY);
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ /* Confirming read. */
++ if ((counter == 0)) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_rx_buffer_link -> Read Failed.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Checking for the EOB bit.
++ EOB bit = 1 -> Buffer link disabled.
++ EOB bit = 0 -> Biffer link enabled.
++ */
++ reg_val =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF1_MCONT_OFFSET);
++ *link = (reg_val & CAN_IF_MCONT_EOB) ? DISABLE : ENABLE;
++
++ IOH_DEBUG("ioh_can_get_rx_buffer_link -> EOB bit = "
++ "%d\n",
++ (reg_val & CAN_IF_MCONT_EOB) >>
++ BIT_SHIFT_SEVEN);
++ IOH_DEBUG
++ ("ioh_can_get_rx_buffer_link -> Buffer Link = "
++ "%u (1 - Set ,0 -> not set)\n", *link);
++ }
++ }
++
++ IOH_DEBUG("ioh_can_get_rx_buffer_link -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_get_rx_filter(
++ int handle,struct ioh_can_rx_filter *filter)
++ @brief This function sets the receive filter for a receive buffer
++ of the CAN device.
++ @remarks Retrieves the current receive filter settings of a
++ receive object.
++ The main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Depending on the settings of the acceptance
++ filter the
++ filter structure is filled and returned to the
++ function calling this function.
++
++ @param handle [@ref IN] The handle to the device.
++ @param filter [@ref OUT] the reference to the filter
++ settings.
++
++ @retval
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ success.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_can_suspend
++ <hr>
++*/
++int ioh_can_get_rx_filter(int handle, struct ioh_can_rx_filter *filter)
++{
++ u32 reg_val1;
++ u32 reg_val2;
++ u32 counter;
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++ u32 if1_creq;
++
++ if ((handle == (int) 0) || (filter == NULL)) { /* if invalid
++ parameters. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_rx_filter -> Invalid Parameter.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /*Preparing to read the specified Msg Obj. */
++ IOH_WRITE_LONG(CAN_CMASK_RX_TX_GET,
++ (can_baseaddress + CAN_IF1_CMASK_OFFSET));
++ IOH_WRITE_LONG(filter->num,
++ (can_baseaddress + CAN_IF1_CREQ_OFFSET));
++
++ /*Confirming the read completion. */
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if1_creq = \
++ (IOH_READ_LONG(can_baseaddress + CAN_IF1_CREQ_OFFSET)) &
++ CAN_IF_CREQ_BUSY;
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ if ((counter == 0)) { /*Read unsuccessful. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_rx_filter -> Reading of receive \
++ buffer %u failed.\n",
++ filter->num);
++ retval = IOH_CAN_FAIL;
++ } else { /*read successful. */
++
++ /*Checking for Umask */
++ reg_val1 =
++ IOH_READ_LONG((can_baseaddress +
++ CAN_IF1_MCONT_OFFSET));
++ filter->umask =
++ ((CAN_IF_MCONT_UMASK & reg_val1) >>
++ BIT_SHIFT_TWELVE);
++
++ if (1 == filter->umask) { /*If Umask is set */
++ /* Getting the Mask data. */
++
++ /* Reading MASK2 register. */
++ reg_val1 =
++ IOH_READ_LONG((can_baseaddress +
++ CAN_IF1_MASK2_OFFSET));
++
++ if ((CAN_IF_MASK2_MXTD & reg_val1) != 0) {
++ /* Extended Mask set.
++ Mask ID is 29 bits */
++ reg_val2 =
++ IOH_READ_LONG((can_baseaddress +
++ CAN_IF1_MASK1_OFFSET));
++
++ /* Extracting the 16 MSB bits of the
++ 29bit ID. */
++ reg_val2 = reg_val2 & MSK_ALL_SIXTEEN;
++ /* Extracting the remaing 13 bits */
++ reg_val1 = reg_val1 & MSK_ALL_THIRTEEN;
++
++ /* Combing them to a single 29bit ID. */
++ reg_val1 =
++ reg_val1 << BIT_SHIFT_SIXTEEN;
++ reg_val1 = reg_val1 | reg_val2;
++
++ filter->amr.id = reg_val1;
++ filter->amr.id_ext = 1;
++ } else { /*Standard Mask 11bit Mask ID */
++
++ /* Extracting the 13 bits of MASK2
++ register. */
++ reg_val1 = reg_val1 & MSK_ALL_THIRTEEN;
++
++ /* Modifying it to represent 11bit Mask
++ ID */
++ reg_val1 = reg_val1 >> BIT_SHIFT_TWO;
++
++ filter->amr.id = reg_val1;
++ filter->amr.id_ext = 0;
++ }
++ }
++
++ reg_val1 =
++ IOH_READ_LONG((can_baseaddress +
++ CAN_IF1_ID2_OFFSET));
++
++ if ((CAN_ID2_XTD & reg_val1) != 0) { /*Extended ID
++ 29bits */
++ reg_val2 =
++ IOH_READ_LONG((can_baseaddress +
++ CAN_IF1_ID1_OFFSET));
++
++ /* Extracting the 16 MSB bits of the 29bit
++ ID. */
++ reg_val2 = reg_val2 & MSK_ALL_SIXTEEN;
++ /* Extracting the remaining 13 bit. */
++ reg_val1 = reg_val1 & MSK_ALL_THIRTEEN;
++
++ /* Combining them to represent 29bit ID. */
++ reg_val1 = reg_val1 << BIT_SHIFT_SIXTEEN;
++ reg_val1 = reg_val1 | reg_val2;
++
++ filter->aidr.id = reg_val1;
++ filter->aidr.id_ext = 1;
++ } else { /*Standard Id 11bits. */
++
++ /* Extracting the 13 bits of ID2 register */
++ reg_val1 = reg_val1 & MSK_ALL_THIRTEEN;
++ /* Modifying it to represent the 11 bit ID */
++ reg_val1 = reg_val1 >> BIT_SHIFT_TWO;
++
++ filter->aidr.id = reg_val1;
++ filter->aidr.id_ext = 0;
++ }
++
++ IOH_DEBUG("ioh_can_get_rx_filter -> Successfully read "
++ "the filter of Msg Obj %u.\n", filter->num);
++ }
++ }
++
++ IOH_DEBUG("ioh_can_get_rx_filter -> Return value: %d.\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_open(
++ int handle,enum ioh_can_listen_mode listen,enum ioh_can_arbiter arbiter)
++ @brief This function opens the CAN device for read/write.
++ @remarks Opens and initializes the CAN hardware devices for use.
++ The main tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Configures the Receive and Transmit message
++ objects.
++ - Initializes the acceptance filter setting of
++ the
++ Receive message objects.
++ - Enables all the Receive and Transmit message
++ objects.
++ - Sets the baud rate to 500Kbps.
++ - Sets the restart mode to Auto.
++ - Sets the CAN device to RUN mode.
++
++ @param handle [@ref IN] The handle to the device.
++ @param listen [@ref IN] The listen mode to be set.
++ @param arbiter [@ref IN] The arbiter mode to be set.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_candev_open
++
++ <hr>
++*/
++int ioh_can_open(int handle, enum ioh_can_listen_mode listen,
++ enum ioh_can_arbiter arbiter)
++{
++ int retval;
++ s32 i;
++
++ if (handle == (int) 0) { /* invalid handle. */
++ IOH_LOG(KERN_ERR, "ioh_can_open -> Invalid handle.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ do {
++
++ /* Stopping the Can device. */
++ retval = ioh_can_set_run_mode(handle, IOH_CAN_STOP);
++ if (retval == IOH_CAN_FAIL) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_open -> ioh_can_set_run_mode "
++ "failed(returned %d).\n", retval);
++
++ break;
++ }
++ IOH_DEBUG
++ ("ioh_can_open -> ioh_can_set_run_mode invoked \
++ successfully.\n");
++
++ /* Clearing all the message object buffers. */
++ retval = ioh_can_clear_buffers(handle);
++ if (retval == IOH_CAN_FAIL) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_open -> ioh_can_clear_buffers "
++ "failed(returned %d).\n", retval);
++ break;
++ }
++ IOH_DEBUG
++ ("ioh_can_open -> ioh_can_clear_buffers invoked "
++ "successfully(returned %d).\n", retval);
++
++ /* Configuring the respective message object as either
++ receive/transmit object. */
++ ioh_can_config_rx_tx_buffers(handle);
++ IOH_DEBUG
++ ("ioh_can_open -> ioh_can_config_rx_tx_buffers "
++ "invoked successfully.\n");
++
++ /* Initializing filters for receive object. */
++ for (i = 0;
++ i < (ioh_can_tx_buf_size + ioh_can_rx_buf_size);
++ i++) {
++ if (ioh_msg_obj_conf[i] == MSG_OBJ_RX) {
++ /* Here i denotes the index, however
++ the object number is (i+1) */
++ retval =
++ ioh_can_rx_init_filter(handle,
++ (i + 1));
++
++ if (retval != IOH_CAN_SUCCESS) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_rx_init_filter "
++ "failed for msg obj:%d\n",
++ (i + 1));
++ break;
++ }
++ }
++ }
++ if (retval != IOH_CAN_SUCCESS)
++ break;
++ IOH_DEBUG("ioh_can_open -> ioh_can_rx_init_filter "
++ "invoked successfully.\n");
++
++ /* Enabling all receive objects. */
++ retval = ioh_can_rx_enable_all(handle);
++
++ if (retval == IOH_CAN_FAIL) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_open -> ioh_can_rx_enable_all "
++ "failed(returned %d).\n", retval);
++ break;
++ }
++ IOH_DEBUG("ioh_can_open -> ioh_can_rx_enable_all "
++ "invoked successfully(returned %d).\n",
++ retval);
++
++ /* Enabling all transmit objects. */
++ retval = ioh_can_tx_enable_all(handle);
++
++ if (retval == IOH_CAN_FAIL) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_open -> ioh_can_tx_enable_all "
++ "failed(returned %d).\n", retval);
++ break;
++ }
++ IOH_DEBUG("ioh_can_open -> ioh_can_tx_enable_all "
++ "invoked successfully(returned %d).\n",
++ retval);
++
++ /* Setting the Baud Timing. */
++ retval =
++ ioh_can_set_baud_simple(handle, IOH_CAN_BAUD_500);
++ if (retval == IOH_CAN_FAIL) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_open -> ioh_can_set_baud_simple "
++ "failed(returned %d).\n", retval);
++ break;
++ }
++ IOH_DEBUG("ioh_can_open -> ioh_can_set_baud_simple "
++ "invoked successfully(returned %d).\n",
++ retval);
++
++ /* Setting the arbiter mode. */
++ retval = ioh_can_set_arbiter_mode(handle, arbiter);
++ if (retval == IOH_CAN_FAIL) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_open -> ioh_can_set_arbiter_mode "
++ "failed(returned %d).\n", retval);
++ break;
++ }
++ IOH_DEBUG
++ ("ioh_can_open -> ioh_can_set_arbiter_mode invoked "
++ "successfully(returned %d).\n", retval);
++
++ /* Setting the listen mode. */
++ retval = ioh_can_set_listen_mode(handle, listen);
++ if (retval == IOH_CAN_FAIL) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_open -> ioh_can_set_listen_mode "
++ "failed(returned %d).\n", retval);
++ break;
++ }
++ IOH_DEBUG("ioh_can_open -> ioh_can_set_listen_mode "
++ "invoked successfully(returned %d).\n",
++ retval);
++
++ /* Enabling the interrupts. */
++ retval = ioh_can_set_int_enables(handle, CAN_ALL);
++ if (retval == IOH_CAN_FAIL) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_open -> ioh_can_set_int_enables "
++ "failed(returned %d).\n", retval);
++ break;
++ }
++ IOH_DEBUG("ioh_can_open -> ioh_can_set_int_enables "
++ "invoked successfully(returned %d).\n",
++ retval);
++
++ /* Setting the restart mode. */
++ retval = ioh_can_set_restart_mode(handle, CAN_AUTO);
++ if (retval == IOH_CAN_FAIL) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_open -> ioh_can_set_restart_mode "
++ "failed(returned %d).\n", retval);
++ break;
++ }
++ IOH_DEBUG("ioh_can_open -> ioh_can_set_restart_mode "
++ "invoked successfully(returned %d).\n",
++ retval);
++
++ /* Setting the CAN to run mode. */
++ retval = ioh_can_set_run_mode(handle, IOH_CAN_RUN);
++ if (retval == IOH_CAN_FAIL) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_open -> ioh_can_set_run_mode "
++ "failed(returned %d).\n", retval);
++ break;
++ }
++ IOH_DEBUG("ioh_can_open -> ioh_can_set_set_run_mode "
++ "invoked successfully(returned %d).\n",
++ retval);
++
++ } while (false);
++ }
++
++ IOH_DEBUG("ioh_can_open returns %d.\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_release(int handle)
++ @brief This function releases (closes) the CAN device. Call to
++ close an opened CAN device.
++ @remarks De-initializes the CAN device. The main tasks performed
++ by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Sets the CAN device to STOP mode.
++ - Disables the interrupts.
++ - Disables all the receive message objects.
++ - Disables all the transmit message objects.
++
++ @param handle [@ref IN] The handle to the device.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_candev_close
++
++ <hr>
++*/
++int ioh_can_release(int handle)
++{
++ int retval = IOH_CAN_SUCCESS;
++
++ if (handle == (int) 0) {
++ IOH_LOG(KERN_ERR, "ioh_can_release -> Invalid handle.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ do {
++ /* Stooping the CAN device. */
++ retval = ioh_can_set_run_mode(handle, IOH_CAN_STOP);
++
++ if (IOH_CAN_FAIL == retval) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_release -> ioh_can_set_run_mode "
++ "failed(returned %d).\n", retval);
++ break;
++ }
++ IOH_DEBUG
++ ("ioh_can_release -> ioh_can_set_run_mode invoked "
++ "successfully(returned %d).\n", retval);
++
++ /* Disabling the interrupts. */
++ retval = ioh_can_set_int_enables(handle, CAN_NONE);
++
++ if (IOH_CAN_FAIL == retval) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_release -> ioh_can_set_int_enables "
++ "failed(returned %d).\n", retval);
++ break;
++ }
++ IOH_DEBUG
++ ("ioh_can_release -> ioh_can_set_int_enables invoked "
++ "successfully(returned %d).\n", retval);
++
++ /* Disabling all the receive object. */
++ retval = ioh_can_rx_disable_all(handle);
++ if (IOH_CAN_FAIL == retval) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_release -> ioh_can_rx_disable_all "
++ "failed(returned %d).\n", retval);
++ break;
++ }
++ IOH_DEBUG
++ ("ioh_can_release -> ioh_can_rx_disable_all invoked "
++ "successfully(returned %d).\n", retval);
++
++ /* Disabling all the transmit object. */
++ retval = ioh_can_tx_disable_all(handle);
++ if (IOH_CAN_FAIL == retval) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_release -> ioh_can_tx_disable_all "
++ "failed(returned %d).\n", retval);
++ break;
++ }
++ IOH_DEBUG
++ ("ioh_can_release -> ioh_can_tx_disable_all invoked "
++ "successfully(returned %d).\n", retval);
++
++ } while (false);
++ }
++
++ IOH_DEBUG("ioh_can_release returns %d.\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn void ioh_can_int_clr(int handle,u32 mask)
++ @brief This function clears interrupt(s) from the CAN device.
++ @remarks Clears the interrupt. The main tasks performed by this
++ function are :
++ - If the interrupt is status interrupt, clear it
++ by reading the CANSTAT register.
++ - If the interrupt is message object interrupt
++ clear it by
++ determining whether it is a transmit/receive
++ message
++ object and appropriately clearing the IntPnd,
++ NewDat and
++ TxRqst bits.
++
++ @param handle [@ref IN] The handle to the device.
++ @param mask [@ref IN] The interrupts to be cleared.
++
++ @retval None.
++
++ @see
++ - ioh_can_callback
++
++ <hr>
++*/
++void ioh_can_int_clr(int handle, u32 mask)
++{
++ u32 counter;
++#ifdef DEBUG
++ u32 rtr;
++#endif
++ u8 *can_baseaddress;
++ u32 if2_creq;
++
++ if ((handle != (int) 0) && (mask != 0)) { /* if valid
++ parameters. */
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /* Clearing status interrupt. */
++ if (mask == CAN_STATUS_INT) {
++ IOH_READ_LONG((can_baseaddress + CAN_STAT_OFFSET));
++ IOH_DEBUG
++ ("ioh_can_int_clr -> Status Interrupt cleared.\n");
++ } else if ((mask > 0) && (mask <= MAX_MSG_OBJ)) {
++ /*Clear interrupt for transmit object */
++ if (ioh_msg_obj_conf[mask - 1] == MSG_OBJ_TX) {
++#ifdef DEBUG
++ /* Checking if the transmission is for remote
++ frame. */
++ rtr =
++ ((IOH_READ_LONG
++ ((can_baseaddress +
++ CAN_IF2_ID2_OFFSET)) & CAN_ID2_DIR) ==
++ 0);
++
++ if (rtr == 1) {
++
++ IOH_DEBUG
++ ("ioh_can_int_clr -> Remote frame \
++ transmission "
++ "interrupt cleared for message \
++ object "
++ "%d.\n", mask);
++ } else {
++ IOH_DEBUG
++ ("ioh_can_int_clr -> \
++ Data frame transmission "
++ "interrupt cleared for message \
++ object "
++ "%d.\n", mask);
++ }
++#endif
++
++ /*Setting CMASK for clearing interrupts for
++ frame transmission. */
++ IOH_WRITE_LONG((CAN_CMASK_RDWR | CAN_CMASK_CTRL
++ | CAN_CMASK_ARB),
++ (can_baseaddress +
++ CAN_IF2_CMASK_OFFSET));
++
++ /* Resetting the ID registers. */
++ IOH_CAN_BIT_SET((can_baseaddress +
++ CAN_IF2_ID2_OFFSET),
++ (CAN_ID2_DIR |
++ (MSK_ALL_ELEVEN << 2)));
++ IOH_WRITE_LONG(0x0,
++ (can_baseaddress +
++ CAN_IF2_ID1_OFFSET));
++
++ /*Claring NewDat, TxRqst & IntPnd */
++ IOH_CAN_BIT_CLEAR((can_baseaddress +
++ CAN_IF2_MCONT_OFFSET),
++ (CAN_IF_MCONT_NEWDAT |
++ CAN_IF_MCONT_INTPND |
++ CAN_IF_MCONT_TXRQXT));
++
++ IOH_WRITE_LONG(mask,
++ (can_baseaddress +
++ CAN_IF2_CREQ_OFFSET));
++
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if2_creq = \
++ (IOH_READ_LONG
++ (can_baseaddress
++ + CAN_IF2_CREQ_OFFSET)
++ & CAN_IF_CREQ_BUSY);
++ if (if2_creq == 0)
++ break;
++
++ counter--;
++ }
++
++
++ }
++ /*Clear interrupt for receive object */
++ else if (ioh_msg_obj_conf[mask - 1] == MSG_OBJ_RX) {
++#ifdef DEBUG
++ /* Checking if the reception is for remote
++ frame. */
++ rtr =
++ ((IOH_READ_LONG
++ ((can_baseaddress +
++ CAN_IF2_ID2_OFFSET)) & CAN_ID2_DIR) !=
++ 0);
++
++ if (rtr == 1) { /*if remote frame. */
++ IOH_DEBUG
++ ("ioh_can_int_clr -> Remote frame \
++ reception "
++ "interrupt cleared for message \
++ object "
++ "%d.\n", mask);
++ } else {
++ IOH_DEBUG
++ ("ioh_can_int_clr -> Data frame \
++ reception "
++ "interrupt cleared for message \
++ object "
++ "%d.\n", mask);
++ }
++#endif
++
++ /*Setting CMASK for clearing the reception
++ interrupts. */
++ IOH_WRITE_LONG((CAN_CMASK_RDWR | CAN_CMASK_CTRL
++ | CAN_CMASK_ARB),
++ (can_baseaddress +
++ CAN_IF2_CMASK_OFFSET));
++
++ /* Clearing the Dir bit. */
++ IOH_CAN_BIT_CLEAR((can_baseaddress +
++ CAN_IF2_ID2_OFFSET),
++ CAN_ID2_DIR);
++
++ /*Clearing NewDat & IntPnd */
++ IOH_CAN_BIT_CLEAR((can_baseaddress +
++ CAN_IF2_MCONT_OFFSET),
++ (CAN_IF_MCONT_NEWDAT |
++ CAN_IF_MCONT_INTPND));
++
++ IOH_WRITE_LONG(mask,
++ (can_baseaddress +
++ CAN_IF2_CREQ_OFFSET));
++
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if2_creq = \
++ IOH_READ_LONG
++ (can_baseaddress +
++ CAN_IF2_CREQ_OFFSET)
++ & CAN_IF_CREQ_BUSY;
++ if (if2_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ }
++ }
++ }
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_msg_tx(
++ int handle,struct ioh_can_msg *msg)
++ @brief This function transmits a CAN message.
++ @remarks Sends a message object for transmission. The main
++ tasks performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Transmits the obtained message object data by
++ appropriately
++ filling the currently available transmit message
++ object.
++
++ @param handle [@ref IN] The handle to the device.
++ @param msg [@ref IN] The message to be
++ transmitted.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++ - @ref IOH_CAN_NO_TX_BUFF --> No transmit buffer
++ object is available.
++
++ @see
++ - ioh_can_write
++
++ <hr>
++*/
++int ioh_can_msg_tx(int handle, struct ioh_can_msg *msg)
++{
++ u32 id1 = 0;
++ u32 id2 = 0;
++ u32 data_a1 = 0;
++ u32 data_a2 = 0;
++ u32 data_b1 = 0;
++ u32 data_b2 = 0;
++ u32 tx_disable_counter = 0;
++ u32 buffer_status = 0;
++ u32 tx_buffer_avail = 0;
++ u32 status;
++ u32 i;
++ u32 counter;
++ enum ioh_can_run_mode run_mode;
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++ u32 if1_creq;
++
++ if ((handle == (int) 0) || (msg == NULL)) { /* If invalid
++ parameters. */
++ IOH_LOG(KERN_ERR, "ioh_can_msg_tx -> Invalid Parameter.\n");
++ retval = IOH_CAN_FAIL;
++ }
++
++ else {
++ /* Obatining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /*Getting the current CAN mode. */
++ (void)ioh_can_get_run_mode(handle, &run_mode);
++
++ /*If CAN is in STOP mode. */
++ if (run_mode != IOH_CAN_RUN) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_msg_tx -> CAN stopped on transmit \
++ attempt.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ unsigned long flags;
++ /* Attaining the lock. */
++ spin_lock_irqsave(&can_os->tx_spinlock, flags);
++
++ /*Getting the message object status. */
++ buffer_status = (u32) ioh_can_get_buffer_status(handle);
++
++ /*Getting the free transmit message object. */
++ for (i = 0;
++ i < (ioh_can_rx_buf_size + ioh_can_tx_buf_size);
++ i++) {
++ if ((ioh_msg_obj_conf[i] == MSG_OBJ_TX)) {
++ /* Checking whether the object is \
++ enabled. */
++ (void)ioh_can_get_tx_enable(handle,
++ (i + 1),
++ &status);
++
++ if ((ENABLE == status)) {
++ if ((((buffer_status >> i) & 1)
++ == 0)) {
++ tx_buffer_avail =
++ (i + 1);
++ break;
++ }
++ } else {
++ tx_disable_counter++;
++ }
++ }
++ }
++
++ /*If no transmit object available. */
++ if (tx_buffer_avail == 0) {
++ IOH_DEBUG
++ ("ioh_can_msg_tx -> tx_disable_counter "
++ "= %d.\n", tx_disable_counter);
++ /* If no object is enabled. */
++ if ((tx_disable_counter == \
++ ioh_can_tx_buf_size)){
++ retval = IOH_CAN_FAIL;
++ IOH_LOG(KERN_ERR,
++ "ioh_can_msg_tx -> \
++ All transmit buffers "
++ "are disabled.\n");
++ } else {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_msg_tx -> \
++ No transmit buffer free.\n");
++ retval = IOH_CAN_NO_TX_BUFF;
++ }
++ } else {
++ IOH_DEBUG
++ ("ioh_can_msg_tx -> \
++ Transmit buffer obtained.\n");
++
++ /*Reading the message object from the Message
++ RAM to the Interface register. */
++ IOH_WRITE_LONG(CAN_CMASK_RX_TX_GET,
++ (can_baseaddress +
++ CAN_IF1_CMASK_OFFSET));
++ IOH_WRITE_LONG(tx_buffer_avail,
++ (can_baseaddress +
++ CAN_IF1_CREQ_OFFSET));
++
++ /*Confirming the read. */
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if1_creq = \
++ (IOH_READ_LONG
++ (can_baseaddress +
++ CAN_IF1_CREQ_OFFSET)) &
++ CAN_IF_CREQ_BUSY;
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ /*If Read not successful. */
++ if (counter == 0) {
++ (void)ioh_can_set_tx_enable(handle,
++ tx_buffer_avail,
++ ENABLE);
++ retval = IOH_CAN_FAIL;
++ } else {
++ /*Setting the CMASK register. */
++ IOH_CAN_BIT_SET((can_baseaddress +
++ CAN_IF1_CMASK_OFFSET),
++ CAN_CMASK_ALL);
++
++ /*If ID extended is set. */
++ if (msg->ide == 1) {
++ /* Setting 29 bit ID with XTD
++ bit set. */
++ id1 =
++ (msg->id & MSK_ALL_SIXTEEN);
++ id2 =
++ ((msg->
++ id & (MSK_ALL_THIRTEEN <<
++ BIT_SHIFT_SIXTEEN))
++ >> BIT_SHIFT_SIXTEEN);
++
++ id2 |= CAN_ID2_XTD;
++ } else {
++ /* Setting 11bit ID with XTD bit
++ reset. */
++ id1 = 0;
++ id2 =
++ ((msg->
++ id & MSK_ALL_ELEVEN) <<
++ BIT_SHIFT_TWO);
++ }
++ IOH_CAN_BIT_CLEAR((can_baseaddress +
++ CAN_IF1_ID1_OFFSET),
++ MSK_ALL_SIXTEEN);
++ IOH_CAN_BIT_CLEAR((can_baseaddress +
++ CAN_IF1_ID2_OFFSET),
++ (MSK_ALL_THIRTEEN |
++ CAN_ID2_XTD));
++
++ IOH_CAN_BIT_SET((can_baseaddress +
++ CAN_IF1_ID1_OFFSET),
++ id1);
++ IOH_CAN_BIT_SET((can_baseaddress +
++ CAN_IF1_ID2_OFFSET),
++ id2);
++
++ /* If remote frame has to be
++ transmitted.. */
++ if (msg->rtr == 1) {
++ IOH_CAN_BIT_CLEAR(\
++ (can_baseaddress + CAN_IF1_ID2_OFFSET), CAN_ID2_DIR);
++ msg->dlc = 0;
++
++ IOH_DEBUG
++ ("ioh_can_msg_tx -> \
++ Transmitting a "
++ "remote frame.\n");
++ } else { /* Data frame
++ transmission. */
++
++ msg->dlc &= MSK_ALL_FOUR;
++
++ IOH_DEBUG
++ ("ioh_can_msg_tx -> \
++ Transmitting a "
++ "data frame.\n");
++ }
++
++ /*Writing the data and the DLC */
++ switch (msg->dlc) {
++ case 0:
++ break;
++
++ case 1:
++ data_a1 = msg->data[0];
++ break;
++ case 2:
++ data_a1 = msg->data[0];
++ data_a1 |=
++ (((u32) msg->
++ data[1]) <<
++ BIT_SHIFT_EIGHT);
++ break;
++ case 3:
++ data_a1 = msg->data[0];
++ data_a1 |=
++ (((u32) msg->
++ data[1]) <<
++ BIT_SHIFT_EIGHT);
++ data_a2 = msg->data[2];
++ break;
++ case 4:
++ data_a1 = msg->data[0];
++ data_a1 |=
++ (((u32) msg->
++ data[1]) <<
++ BIT_SHIFT_EIGHT);
++ data_a2 = msg->data[2];
++ data_a2 |=
++ (((u32) msg->
++ data[3]) <<
++ BIT_SHIFT_EIGHT);
++ break;
++ case 5:
++ data_a1 = msg->data[0];
++ data_a1 |=
++ (((u32) msg->
++ data[1]) <<
++ BIT_SHIFT_EIGHT);
++ data_a2 = msg->data[2];
++ data_a2 |=
++ (((u32) msg->
++ data[3]) <<
++ BIT_SHIFT_EIGHT);
++ data_b1 = msg->data[4];
++ break;
++ case 6:
++ data_a1 = msg->data[0];
++ data_a1 |=
++ (((u32) msg->
++ data[1]) <<
++ BIT_SHIFT_EIGHT);
++ data_a2 = msg->data[2];
++ data_a2 |=
++ (((u32) msg->
++ data[3]) <<
++ BIT_SHIFT_EIGHT);
++ data_b1 = msg->data[4];
++ data_b1 |=
++ (((u32) msg->
++ data[5]) <<
++ BIT_SHIFT_EIGHT);
++ break;
++ case 7:
++ data_a1 = msg->data[0];
++ data_a1 |=
++ (((u32) msg->
++ data[1]) <<
++ BIT_SHIFT_EIGHT);
++ data_a2 = msg->data[2];
++ data_a2 |=
++ (((u32) msg->
++ data[3]) <<
++ BIT_SHIFT_EIGHT);
++ data_b1 = msg->data[4];
++ data_b1 |=
++ (((u32) msg->
++ data[5]) <<
++ BIT_SHIFT_EIGHT);
++ data_b2 = msg->data[6];
++ break;
++ case 8:
++ default:
++ data_a1 = msg->data[0];
++ data_a1 |=
++ (((u32) msg->
++ data[1]) <<
++ BIT_SHIFT_EIGHT);
++ data_a2 = msg->data[2];
++ data_a2 |=
++ (((u32) msg->
++ data[3]) <<
++ BIT_SHIFT_EIGHT);
++ data_b1 = msg->data[4];
++ data_b1 |=
++ (((u32) msg->
++ data[5]) <<
++ BIT_SHIFT_EIGHT);
++ data_b2 = msg->data[6];
++ data_b2 |=
++ (((u32) msg->
++ data[7]) <<
++ BIT_SHIFT_EIGHT);
++ break;
++
++ }
++
++ /* Writing the DATA registers. */
++ IOH_WRITE_LONG(data_a1,
++ (can_baseaddress +
++ CAN_IF1_DATAA1_OFFSET));
++ IOH_WRITE_LONG(data_a2,
++ (can_baseaddress +
++ CAN_IF1_DATAA2_OFFSET));
++ IOH_WRITE_LONG(data_b1,
++ (can_baseaddress +
++ CAN_IF1_DATAB1_OFFSET));
++ IOH_WRITE_LONG(data_b2,
++ (can_baseaddress +
++ CAN_IF1_DATAB2_OFFSET));
++
++ /* Updating the size of the data. */
++ IOH_CAN_BIT_CLEAR((can_baseaddress +
++ CAN_IF1_MCONT_OFFSET),
++ MSK_ALL_FOUR);
++ IOH_CAN_BIT_SET((can_baseaddress +
++ CAN_IF1_MCONT_OFFSET),
++ msg->dlc);
++
++ /*Clearing IntPend, NewDat & TxRqst */
++ IOH_CAN_BIT_CLEAR((can_baseaddress + \
++ CAN_IF1_MCONT_OFFSET),\
++ (CAN_IF_MCONT_NEWDAT | \
++ CAN_IF_MCONT_INTPND | \
++ CAN_IF_MCONT_TXRQXT));
++
++ /*Setting NewDat, TxRqst bits */
++ IOH_CAN_BIT_SET((can_baseaddress +
++ CAN_IF1_MCONT_OFFSET),
++ (CAN_IF_MCONT_NEWDAT |
++ CAN_IF_MCONT_TXRQXT));
++
++ /*Writing the updation to the Message
++ object. */
++ IOH_WRITE_LONG(tx_buffer_avail,
++ (can_baseaddress +
++ CAN_IF1_CREQ_OFFSET));
++
++ /*Confirming the updation. */
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if1_creq = \
++ (IOH_READ_LONG
++ (can_baseaddress +
++ CAN_IF1_CREQ_OFFSET))
++ & CAN_IF_CREQ_BUSY;
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ if ((counter == 0)) {
++ retval = IOH_CAN_FAIL;
++ } else {
++ IOH_DEBUG
++ ("ioh_can_msg_tx -> \
++ Updation of transmit "
++ "buffer successful.\n");
++ IOH_DEBUG
++ ("ioh_can_msg_tx -> \
++ Message object enabled "
++ "for transmission.\n");
++
++ }
++
++ } /*if message read object successful */
++ } /* if transmit buffer available */
++
++ /* Releasing the lock. */
++ spin_unlock_irqrestore(&can_os->tx_spinlock, flags);
++ } /*if device in run mode */
++ } /* if parameters valid */
++
++ IOH_DEBUG("ioh_can_msg_tx -> Return value: %d.\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_clear_buffers(int handle)
++ @brief Clears the message objects.
++ @remarks This function clears all transmit and receive buffers of the
++ CAN device.
++
++ @param handle [@ref IN] The handle to the device.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_open
++
++ <hr>
++*/
++int ioh_can_clear_buffers(int handle)
++{
++ u32 i;
++ u32 rx_buff_num;
++ u32 tx_buff_num;
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++
++ if (handle == (int) 0) { /* if handle invalid. */
++ IOH_LOG(KERN_ERR, "ioh_can_clear_buffers -> Invalid Handle.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obatining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ IOH_WRITE_LONG(CAN_CMASK_RX_TX_SET,
++ (can_baseaddress + CAN_IF1_CMASK_OFFSET));
++ IOH_WRITE_LONG(CAN_CMASK_RX_TX_SET,
++ (can_baseaddress + CAN_IF2_CMASK_OFFSET));
++
++ IOH_WRITE_LONG(MSK_ALL_SIXTEEN,
++ (can_baseaddress + CAN_IF1_MASK1_OFFSET));
++ IOH_WRITE_LONG(MSK_ALL_SIXTEEN,
++ (can_baseaddress + CAN_IF1_MASK2_OFFSET));
++ IOH_WRITE_LONG(MSK_ALL_SIXTEEN,
++ (can_baseaddress + CAN_IF2_MASK1_OFFSET));
++ IOH_WRITE_LONG(MSK_ALL_SIXTEEN,
++ (can_baseaddress + CAN_IF2_MASK2_OFFSET));
++
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF1_ID1_OFFSET));
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF1_ID2_OFFSET));
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF2_ID1_OFFSET));
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF2_ID2_OFFSET));
++
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF1_MCONT_OFFSET));
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF2_MCONT_OFFSET));
++
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF1_DATAA1_OFFSET));
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF1_DATAA2_OFFSET));
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF1_DATAB1_OFFSET));
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF1_DATAB2_OFFSET));
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF2_DATAA1_OFFSET));
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF2_DATAA2_OFFSET));
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF2_DATAB1_OFFSET));
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF2_DATAB2_OFFSET));
++
++ for (i = 1; i <= (MAX_MSG_OBJ / 2); i++) {
++ rx_buff_num = 2 * i;
++ tx_buff_num = (2 * i) - 1;
++
++ IOH_WRITE_LONG(rx_buff_num,
++ (can_baseaddress + CAN_IF1_CREQ_OFFSET));
++ IOH_WRITE_LONG(tx_buff_num,
++ (can_baseaddress + CAN_IF2_CREQ_OFFSET));
++
++ mdelay(10);
++
++ IOH_DEBUG
++ ("ioh_can_clear_buffers -> \
++ Cleared receive object %d "
++ "and tranmit object %d.\n", rx_buff_num,
++ tx_buff_num);
++ }
++ }
++
++ IOH_DEBUG("ioh_can_clear_buffers returns %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_get_buffer_status(int handle)
++ @brief This function gets the buffer status of the CAN device.
++ @remarks Retrieves the message object status. The main tasks
++ performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Reads the values of the CANTREQ1 and CANTREQ2
++ registers
++ and returns it to the function calling this
++ function as
++ 32 bit value representing TxRqst bit of each
++ message object.
++
++ @param handle [@ref IN] The handle to the device.
++
++ @retval int
++ - 0 --> All transmit buffers available
++ - >0 --> Some transmit buffers are not available.
++ - @ref IOH_CAN_FAIL --> If the operation fails.
++
++ @see
++ ioh_can_msg_tx
++
++ <hr>
++*/
++int ioh_can_get_buffer_status(int handle)
++{
++ u32 reg_treq1;
++ u32 reg_treq2;
++ int retval = IOH_CAN_SUCCESS;
++ u8 *can_baseaddress;
++
++ if (handle == (int) 0) { /* if handle invalid. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_buffer_status -> Invalid Handle.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /* Reading the transmission request registers. */
++ reg_treq1 =
++ (IOH_READ_LONG(can_baseaddress + CAN_TREQ1_OFFSET) &
++ MSK_ALL_SIXTEEN);
++ reg_treq2 =
++ ((IOH_READ_LONG(can_baseaddress + CAN_TREQ2_OFFSET) &
++ MSK_ALL_SIXTEEN) << BIT_SHIFT_SIXTEEN);
++
++ retval = (reg_treq1 | reg_treq2);
++ }
++
++ IOH_DEBUG("ioh_can_get_buffer_status -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_rx_dequeue(
++ int handle,struct ioh_can_msg *msg,u32 buff_num)
++ @brief This function gets a pending message from the CAN device.
++ @remarks Retrieves the message from a received message object.
++
++ @param handle [@ref IN] The handle to the device.
++ @param msg [@ref OUT] Reference to the received
++ message object.
++ @param buff_num [@ref IN] The message object number.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_callback
++
++ <hr>
++*/
++int ioh_can_rx_dequeue(int handle, struct ioh_can_msg *msg,
++ u32 buff_num)
++{
++ s32 i;
++ u32 reg;
++ int retval = IOH_CAN_FAIL;
++ u8 *can_baseaddress;
++
++ if ((handle == (int) 0) || (msg == NULL)) { /* invalid
++ parameters. */
++ IOH_LOG(KERN_ERR, "ioh_can_rx_dequeue -> Invalid Parameter.\n");
++ }
++ /* invalid buffer number. */
++
++ else if ((ioh_msg_obj_conf[buff_num - 1] != MSG_OBJ_RX) ||
++ (buff_num > (ioh_can_rx_buf_size + ioh_can_tx_buf_size))) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_rx_dequeue -> Invalid Buffer number.\n");
++ }
++
++ else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ msg->ide = 0;
++ msg->id = 0;
++ msg->dlc = 0;
++ for (i = 0; i < IOH_CAN_MSG_DATA_LEN; i++)
++ msg->data[i] = 0;
++
++ /* Read the ID type. */
++ msg->ide =
++ ((IOH_READ_LONG(can_baseaddress + CAN_IF2_ID2_OFFSET)) &
++ CAN_ID2_XTD)
++ >> BIT_SHIFT_FOURTEEN;
++
++ /* Extracting the ID. */
++ if (msg->ide == 1) { /* Extended 29bit ID. */
++ msg->id =
++ (IOH_READ_LONG(can_baseaddress + CAN_IF2_ID1_OFFSET)
++ & MSK_ALL_SIXTEEN);
++ msg->id |=
++ (((IOH_READ_LONG
++ (can_baseaddress +
++ CAN_IF2_ID2_OFFSET)) & MSK_ALL_THIRTEEN) <<
++ BIT_SHIFT_SIXTEEN);
++ } else { /* Standard 11bit ID. */
++
++ msg->id =
++ (((IOH_READ_LONG
++ (can_baseaddress +
++ CAN_IF2_ID2_OFFSET)) & (MSK_ALL_ELEVEN <<
++ BIT_SHIFT_TWO)) >>
++ BIT_SHIFT_TWO);
++ }
++
++ /* Getting the size of the data and the Remote frame bit. */
++ if (msg->rtr == 1) {
++ msg->dlc = 0;
++
++ IOH_DEBUG("ioh_can_rx_dequeue -> Remote frame "
++ "read with message id: %x.\n", msg->id);
++ } else {
++ msg->dlc =
++ ((IOH_READ_LONG
++ (can_baseaddress + CAN_IF2_MCONT_OFFSET))
++ & MSK_ALL_FOUR);
++
++ IOH_DEBUG("ioh_can_rx_dequeue -> Data frame "
++ "read with message id: %x.\n", msg->id);
++ }
++
++ /* Reading back the data. */
++ switch (msg->dlc) {
++ case 0:
++ break;
++
++ case 1:
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAA1_OFFSET);
++ msg->data[0] = reg & MSK_ALL_EIGHT;
++ break;
++
++ case 2:
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAA1_OFFSET);
++ msg->data[0] = reg & MSK_ALL_EIGHT;
++ msg->data[1] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++ break;
++
++ case 3:
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAA1_OFFSET);
++ msg->data[0] = reg & MSK_ALL_EIGHT;
++ msg->data[1] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAA2_OFFSET);
++ msg->data[2] = reg & MSK_ALL_EIGHT;
++ break;
++
++ case 4:
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAA1_OFFSET);
++ msg->data[0] = reg & MSK_ALL_EIGHT;
++ msg->data[1] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAA2_OFFSET);
++ msg->data[2] = reg & MSK_ALL_EIGHT;
++ msg->data[3] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++ break;
++
++ case 5:
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAA1_OFFSET);
++ msg->data[0] = reg & MSK_ALL_EIGHT;
++ msg->data[1] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAA2_OFFSET);
++ msg->data[2] = reg & MSK_ALL_EIGHT;
++ msg->data[3] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAB1_OFFSET);
++ msg->data[4] = reg & MSK_ALL_EIGHT;
++ break;
++
++ case 6:
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAA1_OFFSET);
++ msg->data[0] = reg & MSK_ALL_EIGHT;
++ msg->data[1] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAA2_OFFSET);
++ msg->data[2] = reg & MSK_ALL_EIGHT;
++ msg->data[3] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAB1_OFFSET);
++ msg->data[4] = reg & MSK_ALL_EIGHT;
++ msg->data[5] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++ break;
++
++ case 7:
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAA1_OFFSET);
++ msg->data[0] = reg & MSK_ALL_EIGHT;
++ msg->data[1] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAA2_OFFSET);
++ msg->data[2] = reg & MSK_ALL_EIGHT;
++ msg->data[3] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAB1_OFFSET);
++ msg->data[4] = reg & MSK_ALL_EIGHT;
++ msg->data[5] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAB2_OFFSET);
++ msg->data[6] = reg & MSK_ALL_EIGHT;
++ break;
++
++ case 8:
++ default:
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAA1_OFFSET);
++ msg->data[0] = reg & MSK_ALL_EIGHT;
++ msg->data[1] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAA2_OFFSET);
++ msg->data[2] = reg & MSK_ALL_EIGHT;
++ msg->data[3] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAB1_OFFSET);
++ msg->data[4] = reg & MSK_ALL_EIGHT;
++ msg->data[5] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++
++ reg =
++ IOH_READ_LONG(can_baseaddress +
++ CAN_IF2_DATAB2_OFFSET);
++ msg->data[6] = reg & MSK_ALL_EIGHT;
++ msg->data[7] =
++ ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
++ >> BIT_SHIFT_EIGHT);
++
++ break;
++ }
++ retval = IOH_CAN_SUCCESS;
++ }
++
++ IOH_DEBUG("ioh_can_rx_dequeue -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn void ioh_can_config_rx_tx_buffers(int handle)
++ @brief This function configures receive and transmit buffers.
++ @remarks Configures the receive and the transmit buffers.
++
++ @param handle [@ref IN] The handle to the device.
++
++ @retval None.
++
++ @see
++ - ioh_can_open
++ - ioh_can_resume
++
++ <hr>
++*/
++void ioh_can_config_rx_tx_buffers(int handle)
++{
++ u32 i;
++ u32 counter;
++ u8 *can_baseaddress;
++ u32 if1_creq;
++ u32 if2_creq;
++
++ if (handle != (int) 0) { /* if handle valid. */
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /*For accssing MsgVal, ID and EOB bit */
++ IOH_WRITE_LONG((CAN_CMASK_RDWR | CAN_CMASK_ARB |
++ CAN_CMASK_CTRL),
++ (can_baseaddress + CAN_IF1_CMASK_OFFSET));
++ IOH_WRITE_LONG((CAN_CMASK_RDWR | CAN_CMASK_ARB |
++ CAN_CMASK_CTRL),
++ (can_baseaddress + CAN_IF2_CMASK_OFFSET));
++
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF1_ID1_OFFSET));
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF1_ID2_OFFSET));
++ /*Resetting DIR bit for reception */
++ IOH_WRITE_LONG(0x0, (can_baseaddress + CAN_IF2_ID1_OFFSET));
++ IOH_WRITE_LONG((CAN_ID2_DIR | (MSK_ALL_ELEVEN << 2)), \
++ (can_baseaddress + CAN_IF2_ID2_OFFSET));
++ /*Setting DIR bit for transmission */
++
++ IOH_WRITE_LONG(CAN_IF_MCONT_EOB, \
++ (can_baseaddress + CAN_IF1_MCONT_OFFSET));
++ /*Setting EOB bit for receiver */
++ IOH_WRITE_LONG(CAN_IF_MCONT_EOB, \
++ (can_baseaddress + CAN_IF2_MCONT_OFFSET));
++ /*Setting EOB bit for transmitter */
++
++ for (i = 0; i < (ioh_can_tx_buf_size + ioh_can_rx_buf_size);
++ i++) {
++ counter = COUNTER_LIMIT;
++ /* Configure the receive message objects */
++ if (ioh_msg_obj_conf[i] == MSG_OBJ_RX) {
++
++ IOH_WRITE_LONG((i + 1),
++ (can_baseaddress +
++ CAN_IF1_CREQ_OFFSET));
++
++ while (counter) {
++ if1_creq = \
++ (ioread32
++ (can_baseaddress +
++ CAN_IF1_CREQ_OFFSET))
++ & CAN_IF_CREQ_BUSY;
++ if (if1_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ if ((counter == 0)) {
++ IOH_DEBUG
++ ("ioh_can_config_rx_tx_buffers -> \
++ Config failed "
++ "for receive message object %u\n",
++ (i + 1));
++ }
++ }
++ /* Configure the transmit message objects */
++ else if (ioh_msg_obj_conf[i] == MSG_OBJ_TX) {
++ IOH_WRITE_LONG((i + 1),
++ (can_baseaddress +
++ CAN_IF2_CREQ_OFFSET));
++
++ while (counter) {
++ if2_creq = \
++ (ioread32
++ (can_baseaddress +
++ CAN_IF2_CREQ_OFFSET))
++ & CAN_IF_CREQ_BUSY;
++ if (if2_creq == 0)
++ break;
++
++ counter--;
++ }
++
++
++
++ if ((counter == 0)) {
++ IOH_DEBUG
++ ("ioh_can_config_rx_tx_buffers -> \
++ Config failed "
++ "for transmit message object %u\n",
++ (i + 1));
++ }
++ }
++
++ }
++ }
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_get_error_stats(
++ int handle,struct ioh_can_error *error
++ @brief This function gets the error statics of the CAN device.
++ @remarks Retrieves the error status. The main tasks performed by
++ this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - Depending on the value of the CANERRC register
++ the
++ error status structure is filled and returned to
++ the function
++ calling this function.
++
++ @param handle [@ref IN] The handle to the device.
++ @param error [@ref OUT] The reference to the error
++ status.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++int ioh_can_get_error_stats(int handle, struct ioh_can_error *error)
++{
++ u8 *can_baseaddress;
++ u32 reg_val;
++ int retval = IOH_CAN_SUCCESS;
++
++ if ((handle == (int) 0) || (error == NULL)) { /* invalid
++ parameters. */
++ IOH_LOG(KERN_ERR,
++ "ioh_can_get_error_stats -> Invalid Parameter.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) handle;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /* Reading the error count register. */
++ reg_val = IOH_READ_LONG(can_baseaddress + CAN_ERRC_OFFSET);
++
++ error->rxgte96 = 0;
++ error->txgte96 = 0;
++
++ error->rx_err_cnt =
++ (reg_val & MSK_ES_RXERRCNT) >> BIT_ES_RXERRCNT;
++ error->tx_err_cnt =
++ (reg_val & MSK_ES_TXERRCNT) >> BIT_ES_TXERRCNT;
++
++ /* receive error count > 96 */
++ if (error->rx_err_cnt >= ERROR_COUNT)
++ error->rxgte96 = 1;
++ /* transmit error count > 96. */
++ if (error->tx_err_cnt >= ERROR_COUNT)
++ error->txgte96 = 1;
++
++ /* Reading the Can status register. */
++ reg_val = IOH_READ_LONG(can_baseaddress + CAN_STAT_OFFSET);
++
++ /* EPass */
++ if ((reg_val & (1 << BIT_SHIFT_FIVE)) != 0)
++ error->error_stat = 1;
++ /* Buss Off */
++ else if ((reg_val & (1 << BIT_SHIFT_SEVEN)) != 0)
++ error->error_stat = 3;
++ else
++ error->error_stat = 0;
++
++ IOH_DEBUG("rxgte96 (Rx > 96) : %u\n", error->rxgte96);
++ IOH_DEBUG("txgte96 (Rx > 96) : %u\n", error->txgte96);
++ IOH_DEBUG("error_stat : %u\n", error->error_stat);
++ IOH_DEBUG("rx_err_cnt : %u\n", error->rx_err_cnt);
++ IOH_DEBUG("tx_err_cnt : %u\n", error->tx_err_cnt);
++ }
++
++ IOH_DEBUG("ioh_can_get_error_stats -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn int ioh_can_reset(struct ioh_can_os *can_os)
++ @brief Performs soft reset.
++ @remarks Resets the CAN device. The main tasks
++ performed by this function are :
++ - Validates whether the passed arguments are
++ valid.
++ If invalid error status code is returned.
++ - The CAN device is reset by setting the SRST
++ bit of the
++ Soft Reset register.
++
++ @param can_os [@ref IN] Reference to the system
++ structure.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> If the operation is
++ successful.
++ - @ref IOH_CAN_FAIL --> If the operation
++ fails.
++
++ @see
++ - ioh_can_ioctl
++ - ioh_candev_open
++
++ <hr>
++
++*/
++int ioh_can_reset(struct ioh_can_os *can_os)
++{
++ int retval = IOH_CAN_SUCCESS;
++#ifndef FPGA
++ u8 *can_baseaddress;
++
++ if ((can_os == NULL)) {
++ IOH_LOG(KERN_ERR, "ioh_can_reset -> Invalid parameter.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Obtaining the remap address for access. */
++ struct can_hw *can = (struct can_hw *) can_os->can;
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /* write to sw reset register */
++ IOH_WRITE_LONG(1, (can_baseaddress + CAN_SRST_OFFSET));
++ IOH_WRITE_LONG(0, (can_baseaddress + CAN_SRST_OFFSET));
++
++ IOH_DEBUG("ioh_can_reset -> Reset successful.\n");
++ }
++#endif
++
++ IOH_DEBUG("ioh_can_reset -> Return value: %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn irqreturn_t ioh_can_handler(
++ int irq, void *dev_id
++ @brief Handles the CAN interrupts.
++ @remarks Handles the interrupt. the main task perforemd by
++ this function is :
++ - Checks whether an interrupt is encontered.
++ If encountered
++ the callback function is invoked.
++
++ @param irq [@ref IN] The interrupt number.
++ @param dev_id [@ref IN] Reference to the device
++ structure.
++
++ @retval irqreturn_t
++ - IRQ_HANDLED --> CAN interrupt has been handled.
++ - IRQ_NONE --> No CAn interrupt source.
++
++ @see
++ - ioh_candev_open
++
++ <hr>
++*/
++irqreturn_t ioh_can_handler(int irq, void *dev_id)
++{
++ irqreturn_t retval = IRQ_NONE;
++
++ struct ioh_can_os *can_os = (struct ioh_can_os *) dev_id;
++ u32 int_stat;
++
++ IOH_DEBUG("ioh_can_handler -> Invoked.\n");
++
++ int_stat = ioh_can_int_pending(can_os->can);
++ IOH_DEBUG("ioh_can_handler -> ioh_can_int_pending "
++ "returned value: %x\n", int_stat);
++
++ if ((can_os != NULL) && (int_stat > 0)) {
++ can_os->int_stat = int_stat;
++ (*can_os->can_callback) (can_os);
++
++ IOH_DEBUG("ioh_can_handler -> Callback function "
++ "invoked successfully.\n");
++
++ retval = IRQ_HANDLED;
++ }
++
++ return retval;
++}
++
++/*! @ingroup HALLayerAPI
++ @fn void ioh_can_log_message(u32 status)
++ @brief Logs the error messages.
++ @remarks Logs the error messages according to the error bits set.
++
++ @param status [@ref IN] Error status.
++
++ @retval None.
++
++ @see
++ - ioh_can_callback
++
++ <hr>
++*/
++void ioh_can_log_message(u32 status)
++{
++
++ switch ((status & MSK_ALL_THREE)) {
++
++ case 0:
++ IOH_DEBUG("ioh_can_log_message -> No Error\n");
++ break;
++ case 1:
++ IOH_LOG(KERN_ERR, "ioh_can_log_message -> Stuff Error\n");
++ break;
++ case 2:
++ IOH_LOG(KERN_ERR, "ioh_can_log_message -> Form Error.\n");
++ break;
++ case 3:
++ IOH_LOG(KERN_ERR, "ioh_can_log_message -> Ack Error\n");
++ break;
++ case 4:
++ IOH_LOG(KERN_ERR, "ioh_can_log_message -> Bit 1 Error\n");
++ break;
++ case 5:
++ IOH_LOG(KERN_ERR, "ioh_can_log_message -> Bit 0 Error.\n");
++ break;
++ case 6:
++ IOH_LOG(KERN_ERR, "ioh_can_log_message -> Crc Error\n");
++ break;
++ case 7:
++ IOH_LOG(KERN_ERR, "ioh_can_log_message -> Undefined Error\n");
++ break;
++ default:
++ break;
++ }
++}
++
++/*! @ingroup HALLayer
++ @fn void ioh_can_entcb(
++ void(*ioh_can_cb)(struct ioh_can_os *),struct ioh_can_os * p_can_os)
++ @brief Registers the call back function.
++ @remarks Registers the callback function for further use.
++
++ @param ioh_can_cb [@ref IN] Reference to the callback
++ function.
++ @param p_can_os [@ref IN] Reference to the device
++ structure.
++
++ @retval None.
++
++ @see
++ - ioh_candev_open
++
++ <hr>
++*/
++void ioh_can_entcb(void (*ioh_can_cb) (struct ioh_can_os *), \
++ struct ioh_can_os *p_can_os)
++{
++ if ((NULL != ioh_can_cb) && (NULL != p_can_os)) {
++ p_can_os->can_callback = ioh_can_cb;
++ IOH_DEBUG("ioh_can_entcb -> Callback function "
++ "set successful.\n");
++ } else {
++ IOH_LOG(KERN_ERR, "ioh_can_entcb -> Callback function set "
++ "unsuccessful.\n");
++ }
++
++}
++
++/*! @ingroup HALLayerAPI
++ @fn void ioh_can_callback(
++ struct ioh_can_os * can_os)
++ @brief The callback function.
++ @remarks The callback function to handle the interrupt.
++
++ @param can_os [@ref IN] Reference to the device
++ structure.
++
++ @retval None.
++
++ @see
++ - ioh_candev_open
++
++ <hr>
++*/
++void ioh_can_callback(struct ioh_can_os *can_os)
++{
++ u32 int_stat;
++ u32 reg;
++ u32 reg_stat;
++ u32 counter;
++ u8 *can_baseaddress;
++ struct ioh_can_msg receive_msg;
++ struct can_hw *can = (struct can_hw *) (can_os->can);
++ int retval = IOH_CAN_SUCCESS;
++ u32 if2_creq;
++
++ can_baseaddress = (u8 *) (can->io_base);
++
++ /* Get the interrupt status */
++ int_stat = can_os->int_stat;
++ can_os->int_stat = 0;
++
++ /*Checking for status interrupt */
++ if (CAN_STATUS_INT == int_stat) {
++ /* Reading of the CANSTAT register. */
++ reg_stat = IOH_READ_LONG((can_baseaddress + CAN_STAT_OFFSET));
++ reg_stat = reg_stat & MSK_ALL_EIGHT;
++ IOH_DEBUG("ioh_can_callback -> Status Register: %x.\n",
++ reg_stat);
++
++ /* If recovered from Bus-Off interrupt. */
++ if ((reg_stat == 0) && (can_os->bus_off_interrupt == 1)) {
++ can_os->bus_off_interrupt = 0;
++ (void)ioh_can_tx_enable_all(can_os->can);
++ (void)ioh_can_rx_enable_all(can_os->can);
++
++ IOH_LOG(KERN_ERR, "ioh_can_callback -> Bus off "
++ "stage recovered.\n");
++ } else {
++ /*Bus off interrupt. */
++ if (reg_stat & ((u32) 1 << BIT_SHIFT_SEVEN)) {
++ if (can_os->bus_off_interrupt == 0) {
++ enum ioh_can_auto_restart restart_mode \
++ = 0;
++
++ IOH_LOG(KERN_ERR,
++ "ioh_can_callback -> Bus off "
++ "interrupt.\n");
++
++ (void)ioh_can_tx_disable_all(can_os->
++ can);
++ (void)ioh_can_rx_disable_all(can_os->
++ can);
++
++ (void)ioh_can_get_restart_mode(can_os->
++ can,
++ &restart_mode);
++
++ if (CAN_AUTO == restart_mode) {
++ can_os->bus_off_interrupt = 1;
++
++ (void)
++ ioh_can_set_run_mode
++ (can_os->can, IOH_CAN_RUN);
++ IOH_DEBUG("ioh_can_callback -> "
++ "Device restarted.\n");
++ }
++ }
++ }
++ /*EWarn interrupt. */
++ if ((reg_stat & ((u32) 1 << BIT_SHIFT_SIX)) != 0) {
++ IOH_DEBUG
++ ("ioh_can_callback -> EWarn interrupt.\n");
++ }
++ /*EPass interrupt. */
++ if ((reg_stat & ((u32) 1 << BIT_SHIFT_FIVE)) != 0) {
++ IOH_DEBUG
++ ("ioh_can_callback -> EPass interrupt.\n");
++ }
++ /*RxOK interrupt. */
++ if ((reg_stat & ((u32) 1 << BIT_SHIFT_FOUR)) != 0) {
++ IOH_DEBUG
++ ("ioh_can_callback -> RxOK interrupt.\n");
++ reg_stat =
++ reg_stat & ~((u32) 1 << BIT_SHIFT_FOUR);
++ }
++ /*TxOK interrupt */
++ if ((reg_stat & ((u32) 1 << BIT_SHIFT_THREE)) != 0) {
++ IOH_DEBUG
++ ("ioh_can_callback -> TxOK interrupt.\n");
++ reg_stat =
++ reg_stat & ~((u32) 1 << BIT_SHIFT_THREE);
++ }
++ /*Error status */
++ ioh_can_log_message((reg_stat & MSK_ALL_THREE));
++ reg_stat = reg_stat & ~(MSK_ALL_THREE);
++
++ /*Clearing status register interrupt bits. */
++ IOH_WRITE_LONG(reg_stat,
++ (can_baseaddress + CAN_STAT_OFFSET));
++
++ int_stat = ioh_can_int_pending(can_os->can);
++ }
++ }
++
++ /*Message object interrupt. */
++ if ((int_stat > 0) && (int_stat <= MAX_MSG_OBJ)) {
++ /*Reading the messsage object from the Message RAM to the
++ interface registers. */
++ IOH_WRITE_LONG(CAN_CMASK_RX_TX_GET,
++ (can_baseaddress + CAN_IF2_CMASK_OFFSET));
++ IOH_WRITE_LONG((int_stat),
++ (can_baseaddress + CAN_IF2_CREQ_OFFSET));
++
++ /*Confirming the read. */
++ counter = COUNTER_LIMIT;
++ while (counter) {
++ if2_creq = \
++ (IOH_READ_LONG(can_baseaddress + CAN_IF2_CREQ_OFFSET)) &
++ CAN_IF_CREQ_BUSY;
++
++ if (if2_creq == 0)
++ break;
++
++ counter--;
++ }
++
++ if (counter > 0) { /* If read successful. */
++ /* Reading the MCONT register. */
++ reg =
++ IOH_READ_LONG((can_baseaddress +
++ CAN_IF2_MCONT_OFFSET));
++ reg &= MSK_ALL_SIXTEEN;
++
++ /* If MsgLost bit set. */
++ if ((reg & CAN_IF_MCONT_MSGLOST) != 0) {
++ IOH_CAN_BIT_CLEAR((can_baseaddress +
++ CAN_IF2_MCONT_OFFSET),
++ CAN_IF_MCONT_MSGLOST);
++
++ IOH_LOG(KERN_ERR,
++ "ioh_can_callback -> \
++ Message object %d has "
++ "been overwritten.\n", int_stat);
++ }
++
++ /* Read the direction bit for determination of remote
++ frame during reception. */
++ receive_msg.rtr =
++ ((IOH_READ_LONG
++ ((can_baseaddress +
++ CAN_IF2_ID2_OFFSET)) & CAN_ID2_DIR) != 0);
++
++ /* Clearing interrupts. */
++ ioh_can_int_clr(can_os->can, int_stat);
++ IOH_DEBUG
++ ("ioh_can_callback -> \
++ ioh_can_int_clr invoked successfully.\n");
++
++ /*Hanlde reception interrupt */
++ if (MSG_OBJ_RX == ioh_msg_obj_conf[int_stat - 1]) {
++ /*If new data arrived */
++ if ((reg & CAN_IF_MCONT_NEWDAT) != 0) {
++ /*Reading the message object content. */
++ retval =
++ ioh_can_rx_dequeue(can_os->can,
++ &receive_msg,
++ int_stat);
++
++ if ((IOH_CAN_SUCCESS == retval)) {
++ /*Inserting the message object
++ into the FIFO. */
++ retval =
++ write_can_fifo(can_os->
++ rx_fifo,
++ &receive_msg);
++
++ /*If insertion successful and
++ if the read call is waiting. */
++ if ((IOH_CAN_SUCCESS == retval)
++ && (can_os->
++ read_wait_flag == 1)) {
++ can_os->read_wait_flag =
++ 0;
++ wake_up_interruptible
++ (&can_os->
++ read_wait_queue);
++ }
++ }
++ IOH_DEBUG
++ ("ioh_can_callback -> \
++ Reception interrupt "
++ "handled for receive "
++ "message object %u.\n", int_stat);
++ }
++
++ }
++ /*Hanlde transmission interrupt */
++ else if (MSG_OBJ_TX == ioh_msg_obj_conf[int_stat - 1]) {
++ /*If the write system call is waiting. */
++ if (1 == can_os->write_wait_flag) {
++ can_os->write_wait_flag = 0;
++ wake_up_interruptible(&can_os->
++ write_wait_queue);
++ }
++
++ IOH_DEBUG
++ ("ioh_can_callback -> Transmission interrupt "
++ "handled for transmit "
++ "message object %u.\n", int_stat);
++ }
++ }
++ }
++}
+diff -urN linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_hal.h topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_hal.h
+--- linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_hal.h 1970-01-01 09:00:00.000000000 +0900
++++ topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_hal.h 2010-03-10 08:57:34.000000000 +0900
+@@ -0,0 +1,1407 @@
++/*!
++ * @file ioh_can_hal.h
++ * @brief Provides the macro definitions used by the HAL Layer APIs.
++ * @version 1.0
++ * @section
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * <hr>
++ */
++
++/*
++ * History:
++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
++ * All rights reserved.
++ *
++ * created:
++ * WIPRO 03/07/2009
++ * modified:
++ * WIPRO 05/08/2009
++ *
++ */
++
++#ifndef __IOH_CAN_HAL_H__
++#define __IOH_CAN_HAL_H__
++
++/*! @ingroup HALLayer
++ @def MAX_CAN_DEVICES
++ @brief The maximum number of devices supported by this driver.
++
++ <hr>
++*/
++#define MAX_CAN_DEVICES (1)
++
++/*! @ingroup HALLayer
++ @def MAX_BITRATE
++ @brief The maximum bitrate(Kbps) that can be programmed for the
++ CAN device.
++
++ <hr>
++*/
++#define MAX_BITRATE (0x3e8)
++
++/*! @ingroup HALLayer
++ @def NUM_NODES
++ @brief The maximum number of software FIFO nodes.
++
++ <hr>
++*/
++#define NUM_NODES (2000) /* Maximum number of
++ Software FIFO nodes. */
++
++/*! @ingroup HALLayer
++ @def MAX_MSG_OBJ
++ @brief The maximum number of message objects available.
++
++ <hr>
++*/
++#define MAX_MSG_OBJ (32)
++
++/*! @ingroup HALLayer
++ @def MSG_OBJ_RX
++ @brief The receive message object flag.
++
++ <hr>
++*/
++#define MSG_OBJ_RX (0)
++
++/*! @ingroup HALLayer
++ @def MSG_OBJ_TX
++ @brief The transmit message object flag.
++
++ <hr>
++*/
++#define MSG_OBJ_TX (1)
++
++/*! @ingroup HALLayer
++ @def ENABLE
++ @brief The enable flag.
++
++ <hr>
++*/
++#define ENABLE (1)
++
++/*! @ingroup HALLayer
++ @def DISABLE
++ @brief The disable flag.
++
++ <hr>
++*/
++#define DISABLE (0)
++
++/* bit position of important controller bits. */
++/*! @ingroup HALLayer
++ @def CAN_CTRL_INIT
++ @brief The INIT bit of CANCONT register.
++
++ <hr>
++*/
++#define CAN_CTRL_INIT (0x0001)
++
++/*! @ingroup HALLayer
++ @def CAN_CTRL_IE
++ @brief The IE bit of CANCONT register.
++
++ <hr>
++*/
++#define CAN_CTRL_IE (0x0002)
++
++/*! @ingroup HALLayer
++ @def CAN_CTRL_IE_SIE_EIE
++ @brief The IE + SIE + EIE bits of CANCONT register.
++
++ <hr>
++*/
++#define CAN_CTRL_IE_SIE_EIE (0x000e)
++
++/*! @ingroup HALLayer
++ @def CAN_CTRL_OPT
++ @brief The OPT bit of CANCONT register.
++
++ <hr>
++*/
++#define CAN_CTRL_OPT (0x0080)
++
++/*! @ingroup HALLayer
++ @def CAN_OPT_SILENT
++ @brief The Silent bit of CANOPT register.
++
++ <hr>
++*/
++#define CAN_OPT_SILENT (0x0008)
++
++/*! @ingroup HALLayer
++ @def CAN_CTRL_CCE
++ @brief The configuration change bit of CANCONT register.
++
++ <hr>
++*/
++#define CAN_CTRL_CCE (0x0040)
++
++/*! @ingroup HALLayer
++ @def CAN_CMASK_RX_TX_SET
++ @brief The CMASK value used for writing the TX/RX message
++ object to the message RAM.
++
++ <hr>
++*/
++#define CAN_CMASK_RX_TX_SET (0x00f3)
++
++/*! @ingroup HALLayer
++ @def CAN_CMASK_RX_TX_GET
++ @brief The CMASK value used for reading the TX/RX message
++ object from the message RAM.
++
++ <hr>
++*/
++#define CAN_CMASK_RX_TX_GET (0x0073)
++
++/*! @ingroup HALLayer
++ @def CAN_CMASK_ALL
++ @brief The value for setting all the bits
++ of the CMASK register.
++
++ <hr>
++*/
++#define CAN_CMASK_ALL (0xff)
++
++/*! @ingroup HALLayer
++ @def CAN_CMASK_RDWR
++ @brief The RD/WR bit of the CMASK register.
++
++ <hr>
++*/
++#define CAN_CMASK_RDWR (0x80)
++
++/*! @ingroup HALLayer
++ @def CAN_CMASK_ARB
++ @brief The ARB bit of the CMASK register.
++
++ <hr>
++*/
++#define CAN_CMASK_ARB (0x20)
++
++/*! @ingroup HALLayer
++ @def CAN_CMASK_CTRL
++ @brief The CTRL bit of the CMASK register.
++
++ <hr>
++*/
++#define CAN_CMASK_CTRL (0x10)
++
++/*! @ingroup HALLayer
++ @def CAN_CMASK_MASK
++ @brief The MASK bit of the CMASK register.
++
++ <hr>
++*/
++#define CAN_CMASK_MASK (0x40)
++
++/*! @ingroup HALLayer
++ @def CAN_CMASK_CLPNT
++ @brief The ClrintPnd bit of the CMASK register.
++
++ <hr>
++*/
++#define CAN_CMASK_CLPNT (0x08)
++
++/*! @ingroup HALLayer
++ @def CAN_CMASK_NEWINT
++ @brief The TxRqst/NewDat bit for the CMASK register.
++
++ <hr>
++*/
++#define CAN_CMASK_NEWINT (0x04)
++
++/*! @ingroup HALLayer
++ @def CAN_IF_MCONT_NEWDAT
++ @brief The NewDat bit of the MCONT register.
++
++ <hr>
++*/
++#define CAN_IF_MCONT_NEWDAT (0x8000)
++
++/*! @ingroup HALLayer
++ @def CAN_IF_MCONT_INTPND
++ @brief The IntPnd bit of the MCONT register.
++
++ <hr>
++*/
++#define CAN_IF_MCONT_INTPND (0x2000)
++
++/*! @ingroup HALLayer
++ @def CAN_IF_MCONT_UMASK
++ @brief The UMask bit of the MCONT register.
++
++ <hr>
++*/
++#define CAN_IF_MCONT_UMASK (0x1000)
++
++/*! @ingroup HALLayer
++ @def CAN_IF_MCONT_TXIE
++ @brief The TxIE bit of the MCONT register.
++
++ <hr>
++*/
++#define CAN_IF_MCONT_TXIE (0x0800)
++
++/*! @ingroup HALLayer
++ @def CAN_IF_MCONT_RXIE
++ @brief The RxIE bit of the MCONT register.
++
++ <hr>
++*/
++#define CAN_IF_MCONT_RXIE (0x0400)
++
++/*! @ingroup HALLayer
++ @def CAN_IF_MCONT_RMTEN
++ @brief The RmtEn bit of the MCONT register.
++
++ <hr>
++*/
++#define CAN_IF_MCONT_RMTEN (0x0200)
++
++/*! @ingroup HALLayer
++ @def CAN_IF_MCONT_TXRQXT
++ @brief The TxRqst bit of the MCONT register.
++
++ <hr>
++*/
++#define CAN_IF_MCONT_TXRQXT (0x0100)
++
++/*! @ingroup HALLayer
++ @def CAN_IF_MCONT_EOB
++ @brief The E0B bit of the MCONT register.
++
++ <hr>
++*/
++#define CAN_IF_MCONT_EOB (0x0080)
++
++/*! @ingroup HALLayer
++ @def CAN_IF_MCONT_MSGLOST
++ @brief The MsgLst bit of the MCONT register.
++
++ <hr>
++*/
++#define CAN_IF_MCONT_MSGLOST (0x4000)
++
++/*! @ingroup HALLayer
++ @def CAN_MASK2_MDIR_MXTD
++ @brief The MXtd and Mdir bit of the MASK2 register.
++
++ <hr>
++*/
++#define CAN_MASK2_MDIR_MXTD (0xc000)
++
++/*! @ingroup HALLayer
++ @def CAN_ID2_MSGVAL_XTD_DIR
++ @brief The MsgVal, Xtd and Dir bits of the ID2 register.
++
++ <hr>
++*/
++#define CAN_ID2_MSGVAL_XTD_DIR (0xe000)
++
++/*! @ingroup HALLayer
++ @def CAN_ID2_MSGVAL_DIR
++ @brief The MsgVal and Dir bits of the ID2 register.
++
++ <hr>
++*/
++#define CAN_ID2_MSGVAL_DIR (0xa000)
++
++/*! @ingroup HALLayer
++ @def CAN_ID2_DIR
++ @brief The Dir bit of the ID2 register.
++
++ <hr>
++*/
++#define CAN_ID2_DIR (0x2000)
++
++/*! @ingroup HALLayer
++ @def CAN_ID_MSGVAL
++ @brief The MsgVal bit of the ID2 register.
++
++ <hr>
++*/
++#define CAN_ID_MSGVAL (0x8000)
++
++/*! @ingroup HALLayer
++ @def CAN_IF_MASK2_MDIR
++ @brief The MDir bit of the MASK2 register.
++
++ <hr>
++*/
++#define CAN_IF_MASK2_MDIR ((u32)1 << 14)
++
++/*! @ingroup HALLayer
++ @def CAN_IF_MASK2_MXTD
++ @brief The MXtd bit of the MASK2 register.
++
++ <hr>
++*/
++#define CAN_IF_MASK2_MXTD ((u32)1 << 15)
++
++/*! @ingroup HALLayer
++ @def CAN_STATUS_INT
++ @brief The status interrupt value of the CAN device.
++
++ <hr>
++*/
++#define CAN_STATUS_INT (0x8000)
++
++/*! @ingroup HALLayer
++ @def CAN_IF_CREQ_BUSY
++ @brief The Busy flag bit of the CREQ register.
++
++ <hr>
++*/
++#define CAN_IF_CREQ_BUSY (0x8000)
++
++/*! @ingroup HALLayer
++ @def CAN_ID2_XTD
++ @brief The Xtd bit of ID2 register.
++
++ <hr>
++*/
++#define CAN_ID2_XTD (0x4000)
++
++/*! @ingroup HALLayer
++ @def CAN_SRST_BIT
++ @brief The SRST bit of the Soft reset register.
++
++ <hr>
++*/
++#define CAN_SRST_BIT (0x0001)
++
++/* CAN register offset */
++ /* CAN registers */
++/*! @ingroup HALLayer
++ @def CAN_CONT_OFFSET
++ @brief The offset of CAN control register
++
++ <hr>
++*/
++#define CAN_CONT_OFFSET (0x00) /*Can Control register */
++
++/*! @ingroup HALLayer
++ @def CAN_STAT_OFFSET
++ @brief The offset of CAN status register.
++
++ <hr>
++*/
++#define CAN_STAT_OFFSET (0x04)
++
++/*! @ingroup HALLayer
++ @def CAN_ERRC_OFFSET
++ @brief The offset of CAN Error counter register
++
++ <hr>
++*/
++#define CAN_ERRC_OFFSET (0x08)
++
++/*! @ingroup HALLayer
++ @def CAN_BITT_OFFSET
++ @brief The offset of CAN timing register.
++
++ <hr>
++*/
++#define CAN_BITT_OFFSET (0x0c)
++
++/*! @ingroup HALLayer
++ @def CAN_INT_OFFSET
++ @brief The offset of CAN interrupt register.
++
++ <hr>
++*/
++#define CAN_INT_OFFSET (0x010)
++
++/*! @ingroup HALLayer
++ @def CAN_OPT_OFFSET
++ @brief The offset of CAN Option register
++
++ <hr>
++*/
++#define CAN_OPT_OFFSET (0x14) /*Extended function register */
++
++/*! @ingroup HALLayer
++ @def CAN_BRPE_OFFSET
++ @brief The offset of BRPE register.
++
++ <hr>
++*/
++#define CAN_BRPE_OFFSET (0x18)
++
++ /* Message interface one (IF1) registers */
++
++/*! @ingroup HALLayer
++ @def CAN_IF1_CREQ_OFFSET
++ @brief The offset of IF1 Command request register.
++
++ <hr>
++*/
++#define CAN_IF1_CREQ_OFFSET (0x020)
++
++/*! @ingroup HALLayer
++ @def CAN_IF1_CMASK_OFFSET
++ @brief The offset of IF1 Command Mask register.
++
++ <hr>
++*/
++#define CAN_IF1_CMASK_OFFSET (0x024)
++
++/*! @ingroup HALLayer
++ @def CAN_IF1_ID1_OFFSET
++ @brief The offset of IF1 ID1 register.
++
++ <hr>
++*/
++#define CAN_IF1_ID1_OFFSET (0x030)
++
++/*! @ingroup HALLayer
++ @def CAN_IF1_ID2_OFFSET
++ @brief The offset of IF1 ID2 register.
++
++ <hr>
++*/
++#define CAN_IF1_ID2_OFFSET (0x034)
++
++/*! @ingroup HALLayer
++ @def CAN_IF1_MCONT_OFFSET
++ @brief The offset of IF1 Message control register.
++
++ <hr>
++*/
++#define CAN_IF1_MCONT_OFFSET (0x038)
++
++/*! @ingroup HALLayer
++ @def CAN_IF1_DATAA1_OFFSET
++ @brief The offset of IF1 DATAA1 register.
++
++ <hr>
++*/
++#define CAN_IF1_DATAA1_OFFSET (0x03C)
++
++/*! @ingroup HALLayer
++ @def CAN_IF1_DATAA2_OFFSET
++ @brief The offset of IF1 DATAA2 register.
++
++ <hr>
++*/
++#define CAN_IF1_DATAA2_OFFSET (0x040)
++
++/*! @ingroup HALLayer
++ @def CAN_IF1_DATAB1_OFFSET
++ @brief The offset of IF1 DATAB1 register.
++
++ <hr>
++*/
++#define CAN_IF1_DATAB1_OFFSET (0x044)
++
++/*! @ingroup HALLayer
++ @def CAN_IF1_DATAB2_OFFSET
++ @brief The offset of IF1 DATAB2 register.
++
++ <hr>
++*/
++#define CAN_IF1_DATAB2_OFFSET (0x048)
++
++/*! @ingroup HALLayer
++ @def CAN_IF1_MASK1_OFFSET
++ @brief The offset of IF1 MASK1 register.
++
++ <hr>
++*/
++#define CAN_IF1_MASK1_OFFSET (0x028)
++
++/*! @ingroup HALLayer
++ @def CAN_IF1_MASK2_OFFSET
++ @brief The offset of IF1 MASK2 register.
++
++ <hr>
++*/
++#define CAN_IF1_MASK2_OFFSET (0x02c)
++
++ /* Message interface two (IF2) registers. */
++
++/*! @ingroup HALLayer
++ @def CAN_IF2_CREQ_OFFSET
++ @brief The offset of IF2 Command request register.
++
++ <hr>
++*/
++#define CAN_IF2_CREQ_OFFSET (0x080)
++
++/*! @ingroup HALLayer
++ @def CAN_IF2_CMASK_OFFSET
++ @brief The offset of IF2 Command mask register.
++
++ <hr>
++*/
++#define CAN_IF2_CMASK_OFFSET (0x084)
++
++/*! @ingroup HALLayer
++ @def CAN_IF2_ID1_OFFSET
++ @brief The offset of IF2 ID1 register.
++
++ <hr>
++*/
++#define CAN_IF2_ID1_OFFSET (0x090)
++
++/*! @ingroup HALLayer
++ @def CAN_IF2_ID2_OFFSET
++ @brief The offset of IF2 ID2 register.
++
++ <hr>
++*/
++#define CAN_IF2_ID2_OFFSET (0x094)
++
++/*! @ingroup HALLayer
++ @def CAN_IF2_MCONT_OFFSET
++ @brief The offset of IF2 Message control register.
++
++ <hr>
++*/
++#define CAN_IF2_MCONT_OFFSET (0x098)
++
++/*! @ingroup HALLayer
++ @def CAN_IF2_DATAA1_OFFSET
++ @brief The offset of IF2 DATAA1 register.
++
++ <hr>
++*/
++#define CAN_IF2_DATAA1_OFFSET (0x09c)
++
++/*! @ingroup HALLayer
++ @def CAN_IF2_DATAA2_OFFSET
++ @brief The offset of IF2 DATAA2 register.
++
++ <hr>
++*/
++#define CAN_IF2_DATAA2_OFFSET (0x0a0)
++
++/*! @ingroup HALLayer
++ @def CAN_IF2_DATAB1_OFFSET
++ @brief The offset of IF2 DATAB1 register.
++
++ <hr>
++*/
++#define CAN_IF2_DATAB1_OFFSET (0x0a4)
++
++/*! @ingroup HALLayer
++ @def CAN_IF2_DATAB2_OFFSET
++ @brief The offset of IF2 DATAB2 register.
++
++ <hr>
++*/
++#define CAN_IF2_DATAB2_OFFSET (0x0a8)
++
++/*! @ingroup HALLayer
++ @def CAN_IF2_MASK1_OFFSET
++ @brief The offset of IF2 MASK1 register.
++
++ <hr>
++*/
++#define CAN_IF2_MASK1_OFFSET (0x088)
++
++/*! @ingroup HALLayer
++ @def CAN_IF2_MASK2_OFFSET
++ @brief The offset of IF2 MASK2 register.
++
++ <hr>
++*/
++#define CAN_IF2_MASK2_OFFSET (0x08c)
++
++ /* Transmission request registers */
++/*! @ingroup HALLayer
++ @def CAN_TREQ1_OFFSET
++ @brief The offset of the CAN Transmission request register1.
++
++ <hr>
++*/
++#define CAN_TREQ1_OFFSET (0x100)
++
++/*! @ingroup HALLayer
++ @def CAN_TREQ2_OFFSET
++ @brief The offset of the CAN Transmission request register2.
++
++ <hr>
++*/
++#define CAN_TREQ2_OFFSET (0x104)
++
++ /* Soft Reset register. */
++/*! @ingroup HALLayer
++ @def CAN_SRST_OFFSET
++ @brief The offset of the CAN Soft reset register.
++
++ <hr>
++*/
++#define CAN_SRST_OFFSET (0x1FC)
++
++ /* macros for shift operations. */
++/*! @ingroup HALLayer
++ @def BIT_SHIFT_ONE
++ @brief Bit shift by one.
++
++ <hr>
++*/
++#define BIT_SHIFT_ONE (1)
++
++/*! @ingroup HALLayer
++ @def BIT_SHIFT_TWO
++ @brief Bit shift by two.
++
++ <hr>
++*/
++#define BIT_SHIFT_TWO (2)
++
++/*! @ingroup HALLayer
++ @def BIT_SHIFT_THREE
++ @brief Bit shift by three.
++
++ <hr>
++*/
++#define BIT_SHIFT_THREE (3)
++
++/*! @ingroup HALLayer
++ @def BIT_SHIFT_FOUR
++ @brief Bit shift by four.
++
++ <hr>
++*/
++#define BIT_SHIFT_FOUR (4)
++
++/*! @ingroup HALLayer
++ @def BIT_SHIFT_FIVE
++ @brief Bit shift by five.
++
++ <hr>
++*/
++#define BIT_SHIFT_FIVE (5)
++
++/*! @ingroup HALLayer
++ @def BIT_SHIFT_SIX
++ @brief Bit shift by six.
++
++ <hr>
++*/
++#define BIT_SHIFT_SIX (6)
++
++/*! @ingroup HALLayer
++ @def BIT_SHIFT_SEVEN
++ @brief Bit shift by seven.
++
++ <hr>
++*/
++#define BIT_SHIFT_SEVEN (7)
++
++/*! @ingroup HALLayer
++ @def BIT_SHIFT_EIGHT
++ @brief Bit shift by eight.
++
++ <hr>
++*/
++#define BIT_SHIFT_EIGHT (8)
++
++/*! @ingroup HALLayer
++ @def BIT_SHIFT_TWELVE
++ @brief Bit shift by twelve.
++
++ <hr>
++*/
++#define BIT_SHIFT_TWELVE (12)
++
++/*! @ingroup HALLayer
++ @def BIT_SHIFT_THIRTEEN
++ @brief Bit shift by thirteen.
++
++ <hr>
++*/
++#define BIT_SHIFT_THIRTEEN (13)
++
++/*! @ingroup HALLayer
++ @def BIT_SHIFT_FOURTEEN
++ @brief Bit shift by fourteen.
++
++ <hr>
++*/
++#define BIT_SHIFT_FOURTEEN (14)
++
++/*! @ingroup HALLayer
++ @def BIT_SHIFT_FIFTEEN
++ @brief Bit shift by fifteen.
++
++ <hr>
++*/
++#define BIT_SHIFT_FIFTEEN (15)
++
++/*! @ingroup HALLayer
++ @def BIT_SHIFT_SIXTEEN
++ @brief Bit shift by sixteen.
++
++ <hr>
++*/
++#define BIT_SHIFT_SIXTEEN (16)
++
++/* bit position of certain controller bits. */
++
++/*! @ingroup HALLayer
++ @def BIT_BITT_BRP
++ @brief The Baud Pre-scalar start bit position of the CANBITT
++ register.
++
++ <hr>
++*/
++#define BIT_BITT_BRP (0)
++
++/*! @ingroup HALLayer
++ @def BIT_BITT_SJW
++ @brief The SJW start bit position of the CANBITT register.
++
++ <hr>
++*/
++#define BIT_BITT_SJW (6)
++
++/*! @ingroup HALLayer
++ @def BIT_BITT_TSEG1
++ @brief The start bit position of the time segment before a
++ sampling point
++ of the CANBITT register.
++
++ <hr>
++*/
++#define BIT_BITT_TSEG1 (8)
++
++/*! @ingroup HALLayer
++ @def BIT_BITT_TSEG2
++ @brief The start bit position of the time segment after a
++ sampling point
++ of the CANBITT register.
++
++ <hr>
++*/
++#define BIT_BITT_TSEG2 (12)
++
++/*! @ingroup HALLayer
++ @def BIT_IF1_MCONT_RXIE
++ @brief The RxIE bit position of the MCONT register.
++
++ <hr>
++*/
++#define BIT_IF1_MCONT_RXIE (10)
++
++/*! @ingroup HALLayer
++ @def BIT_IF2_MCONT_TXIE
++ @brief The TxIE bit position of the MCONT register.
++
++ <hr>
++*/
++#define BIT_IF2_MCONT_TXIE (11)
++
++/*! @ingroup HALLayer
++ @def BIT_BRPE_BRPE
++ @brief The shift value for extracting the extended baud
++ rate prescalar for the CANBRPE register.
++
++ <hr>
++*/
++#define BIT_BRPE_BRPE (6)
++
++/*! @ingroup HALLayer
++ @def BIT_ES_TXERRCNT
++ @brief The start bit position of the TX Error counter bits
++ of CANERRC register.
++
++ <hr>
++*/
++#define BIT_ES_TXERRCNT (0)
++
++/*! @ingroup HALLayer
++ @def BIT_ES_RXERRCNT
++ @brief The start bit position of the RX Error counter bits
++ of CANERRC register.
++
++ <hr>
++*/
++#define BIT_ES_RXERRCNT (8)
++
++/* macros used for masking. */
++
++/*! @ingroup HALLayer
++ @def MSK_BITT_BRP
++ @brief The mask value for extracting Baud Rate prescalar values
++ for CANBITT register
++ from the user provided value.
++
++ <hr>
++*/
++#define MSK_BITT_BRP (0x3f)
++
++/*! @ingroup HALLayer
++ @def MSK_BITT_SJW
++ @brief The mask value for SJW bits.
++
++ <hr>
++*/
++#define MSK_BITT_SJW (0xc0)
++
++/*! @ingroup HALLayer
++ @def MSK_BITT_TSEG1
++ @brief The mask value for time segment bits (before a sampling
++ point).
++
++ <hr>
++*/
++#define MSK_BITT_TSEG1 (0xf00)
++
++/*! @ingroup HALLayer
++ @def MSK_BITT_TSEG2
++ @brief The mask value for time segment bits (after a sampling
++ point)
++
++ <hr>
++*/
++#define MSK_BITT_TSEG2 (0x7000)
++
++/*! @ingroup HALLayer
++ @def MSK_BRPE_BRPE
++ @brief The mask value for extracting Baud Rate prescalar value
++ for
++ CANBRPE register from user provided value.
++
++ <hr>
++*/
++#define MSK_BRPE_BRPE (0x3c0)
++
++/*! @ingroup HALLayer
++ @def MSK_BRPE_GET
++ @brief The mask for Baud Rate prescalar bits of CANBRPE
++ register.
++
++ <hr>
++*/
++#define MSK_BRPE_GET (0x0f)
++
++/*! @ingroup HALLayer
++ @def MSK_CTRL_IE_SIE_EIE
++ @brief The mask value for IE, SIE and EIE bits of the CANCONT
++ register.
++
++ <hr>
++*/
++#define MSK_CTRL_IE_SIE_EIE (0x07)
++
++/*! @ingroup HALLayer
++ @def MSK_MCONT_TXIE
++ @brief The Mask value for TxIE bit of the MCONT register.
++
++ <hr>
++*/
++#define MSK_MCONT_TXIE (0x08)
++
++/*! @ingroup HALLayer
++ @def MSK_MCONT_RXIE
++ @brief The Mask value for RxIE bit of the MCONT register.
++
++ <hr>
++*/
++#define MSK_MCONT_RXIE (0x10)
++
++/*! @ingroup HALLayer
++ @def MSK_ALL_THREE
++ @brief The mask value for the first three bits of any register.
++
++ <hr>
++*/
++#define MSK_ALL_THREE (0x07)
++
++/*! @ingroup HALLayer
++ @def MSK_ALL_FOUR
++ @brief The mask value for the first four bits of any register.
++
++ <hr>
++*/
++#define MSK_ALL_FOUR (0x0f)
++
++/*! @ingroup HALLayer
++ @def MSK_ALL_EIGHT
++ @brief The mask value for the first eight bits of any register.
++
++ <hr>
++*/
++#define MSK_ALL_EIGHT (0xff)
++
++/*! @ingroup HALLayer
++ @def MSK_ALL_ELEVEN
++ @brief The mask value for the first eleven bits of any
++ register.
++
++ <hr>
++*/
++#define MSK_ALL_ELEVEN (0x7ff)
++
++/*! @ingroup HALLayer
++ @def MSK_ALL_THIRTEEN
++ @brief The mask value for the first thirteen bits of any
++ register.
++
++ <hr>
++*/
++#define MSK_ALL_THIRTEEN (0x1fff)
++
++/*! @ingroup HALLayer
++ @def MSK_ALL_SIXTEEN
++ @brief The mask value for the first sixteen bits of any
++ register.
++
++ <hr>
++*/
++#define MSK_ALL_SIXTEEN (0xffff)
++
++/* Error */
++
++/*! @ingroup HALLayer
++ @def MSK_ES_TXERRCNT
++ @brief The mask value for the TX Error counter bits of the
++ CANERRC
++ register.
++
++ <hr>
++*/
++#define MSK_ES_TXERRCNT ((u32)0xff << BIT_ES_TXERRCNT) /* Tx err count */
++
++/*! @ingroup HALLayer
++ @def MSK_ES_RXERRCNT
++ @brief The mask value for the RX Error counter bits of the
++ CANERRC
++ register.
++
++ <hr>
++*/
++#define MSK_ES_RXERRCNT ((u32)0x7f << BIT_ES_RXERRCNT) /* Rx err count */
++
++#define IOH_CAN_BIT_SET(reg, bitmask) \
++ IOH_WRITE_LONG((IOH_READ_LONG((reg)) | ((u32)(bitmask))), (reg))
++#define IOH_CAN_BIT_CLEAR(reg, bitmask) \
++ IOH_WRITE_LONG((IOH_READ_LONG((reg)) & ~((u32)(bitmask))), (reg))
++
++/*! @ingroup HALLayer
++ @def IOH_CAN_NO_TX_BUFF
++ @brief The flag value for denoting the unavailability of the
++ transmit message
++ object.
++
++ @see
++ - ioh_can_msg_tx
++ - ioh_can_write
++
++ <hr>
++*/
++#define IOH_CAN_NO_TX_BUFF (1)
++
++/*! @ingroup HALLayer
++ @def ERROR_COUNT
++ @brief The maximum error counter value.
++
++ @see
++ - ioh_can_get_error_stats
++
++ <hr>
++*/
++#define ERROR_COUNT (96)
++
++/*! @ingroup HALLayer
++ @struct ioh_can_os
++ @brief Defines the fields for maintaining the CAN device
++ specific information.
++ @remarks This structure is used by the driver for internal uses.
++ It stores the details of the CAN device at a
++ particular
++ instance and uses this information for
++ performing
++ operations on it.
++
++ <hr>
++*/
++
++struct ioh_can_os {
++ int can; /**< CAN: device handle */
++ unsigned int opened; /**< Linux opened device */
++ unsigned int can_num; /**< Linux: CAN Number */
++ unsigned long pci_remap; /**< Linux: MMap regs */
++ struct pci_dev *dev; /**< Linux: PCI Device */
++ unsigned int irq; /**< Linux: IRQ */
++ int block_mode; /**< Blocking / non-blocking */
++ int rx_fifo; /**< Rx FIFO */
++ wait_queue_head_t read_wait_queue; /**< Linux: Read wait queue */
++ wait_queue_head_t write_wait_queue; /**< Linux: Write wait queue */
++ unsigned int write_wait_flag; /**< Linux: Write wait flag */
++ unsigned int read_wait_flag; /**< Linux: Read wait flag */
++ spinlock_t open_spinlock; /**< Linux: Open lock variable */
++ unsigned int is_suspending; /**< Linux: Is suspending state */
++ struct inode *inode; /**< Linux: inode */
++ struct ioh_can_timing timing; /**< CAN: timing */
++ enum ioh_can_run_mode run_mode; /**< CAN: run mode */
++ enum ioh_can_listen_mode listen_mode; /**< CAN: listen mode */
++ enum ioh_can_arbiter arbiter_mode; /**< CAN: arbiter mode */
++ unsigned int tx_enable[MAX_MSG_OBJ]; /**< CAN: Tx buffer state */
++ unsigned int rx_enable[MAX_MSG_OBJ]; /**< CAN: Rx buffer state */
++ unsigned int rx_link[MAX_MSG_OBJ]; /**< CAN: Rx link set */
++ unsigned int int_enables; /**< CAN: ints enabled */
++ unsigned int int_stat; /**< CAN: int status */
++ unsigned int bus_off_interrupt; /**< CAN: Buss off int flag */
++ struct ioh_can_rx_filter rx_filter[MAX_MSG_OBJ]; /**< CAN: Rx filters */
++ void (*can_callback) (struct ioh_can_os *); /**< CAN: callback function
++ pointer.*/
++ spinlock_t tx_spinlock; /**< CAN: transmission lock variable.*/
++};
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_create(u8 * io_base)
++
++ <hr>
++*/
++int ioh_can_create(u8 *io_base);
++
++/*! @ingroup HALlayerAPI
++ @fn void ioh_can_destroy(int handle
++
++ <hr>
++*/
++void ioh_can_destroy(int handle);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_set_run_mode(
++ int handle,enum ioh_can_run_mode mode)
++
++ <hr>
++*/
++int ioh_can_set_run_mode(int handle, enum ioh_can_run_mode mode);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_get_run_mode(
++ int handle,enum ioh_can_run_mode *mode)
++
++ <hr>
++*/
++int ioh_can_get_run_mode(int handle, enum ioh_can_run_mode *mode);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_set_listen_mode(
++ int handle,enum ioh_can_listen_mode mode)
++
++ <hr>
++*/
++int ioh_can_set_listen_mode(int handle,
++ enum ioh_can_listen_mode mode);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_get_listen_mode(
++ int handle,enum ioh_can_listen_mode *mode)
++
++ <hr>
++*/
++int ioh_can_get_listen_mode(int handle,
++ enum ioh_can_listen_mode *mode);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_set_arbiter_mode(
++ int handle,enum ioh_can_arbiter mode)
++
++ <hr>
++*/
++int ioh_can_set_arbiter_mode(int handle, enum ioh_can_arbiter mode);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_get_arbiter_mode(
++ int handle,enum ioh_can_arbiter *mode)
++
++ <hr>
++*/
++int ioh_can_get_arbiter_mode(int handle, enum ioh_can_arbiter *mode);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_set_restart_mode(
++ int handle,enum ioh_can_auto_restart mode)
++
++ <hr>
++*/
++int ioh_can_set_restart_mode(int handle,
++ enum ioh_can_auto_restart mode);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_get_restart_mode(
++ int handle,enum ioh_can_auto_restart *mode)
++
++ <hr>
++*/
++int ioh_can_get_restart_mode(int handle,
++ enum ioh_can_auto_restart *mode);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_set_baud_simple(
++ int handle,enum ioh_can_baud baud)
++
++ <hr>
++*/
++int ioh_can_set_baud_simple(int handle, enum ioh_can_baud baud);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_set_baud_custom(
++ int handle, struct ioh_can_timing *timing)
++
++ <hr>
++*/
++int ioh_can_set_baud_custom(int handle, struct ioh_can_timing *timing);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_get_baud(
++ int handle,struct ioh_can_timing *timing)
++
++ <hr>
++*/
++int ioh_can_get_baud(int handle, struct ioh_can_timing *timing);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_set_rx_filter(
++ int handle,struct ioh_can_rx_filter *filter
++
++ <hr>
++*/
++int ioh_can_set_rx_filter(int handle,
++ struct ioh_can_rx_filter *filter);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_get_rx_filter(
++ int handle,struct ioh_can_rx_filter *filter
++
++ <hr>
++*/
++int ioh_can_get_rx_filter(int handle,
++ struct ioh_can_rx_filter *filter);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_msg_tx(
++ int handle,struct ioh_can_msg *msg)
++
++ <hr>
++*/
++int ioh_can_msg_tx(int handle, struct ioh_can_msg *msg);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_open(
++int handle,enum ioh_can_listen_mode listen,enum ioh_can_arbiter arbiter)
++
++ <hr>
++*/
++int ioh_can_open(int handle, enum ioh_can_listen_mode listen,
++ enum ioh_can_arbiter arbiter);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_int_pending(int handle)
++
++ <hr>
++*/
++int ioh_can_int_pending(int handle);
++
++/*! @ingroup HALlayerAPI
++ @fn void ioh_can_int_clr(
++ int handle,u32 mask)
++
++ <hr>
++*/
++void ioh_can_int_clr(int handle, u32 mask);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_clear_buffers(
++ int handle)
++
++ <hr>
++*/
++int ioh_can_clear_buffers(int handle);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_rx_dequeue(
++ int handle,struct ioh_can_msg *msg,u32 buff_num)
++*/
++int ioh_can_rx_dequeue(int handle, struct ioh_can_msg *msg,
++ u32 buff_num);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_set_int_custom(
++ int handle,u32 interrupts)
++
++ <hr>
++*/
++int ioh_can_set_int_custom(int handle, u32 interrupts);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_set_int_enables(
++ int handle,enum ioh_can_interrupt interrupt)
++
++ <hr>
++*/
++int ioh_can_set_int_enables(int handle,
++ enum ioh_can_interrupt interrupt);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_get_int_enables(
++ int handle,u32 *enables)
++
++ <hr>
++*/
++int ioh_can_get_int_enables(int handle, u32 *enables);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_release(int handle)
++
++ <hr>
++*/
++int ioh_can_release(int handle);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_set_rx_buffer_link(
++ int handle,u32 buffer_num,u32 set)
++
++ <hr>
++*/
++int ioh_can_set_rx_buffer_link(int handle, u32 buffer_num,
++ u32 set);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_get_rx_buffer_link(
++ int handle,u32 buffer_num,u32 *link)
++
++ <hr>
++*/
++int ioh_can_get_rx_buffer_link(int handle, u32 buffer_num,
++ u32 *link);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_get_buffer_status(
++ int handle)
++
++ <hr>
++*/
++int ioh_can_get_buffer_status(int handle);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_rx_init_filter(
++ int handle,u32 buff_num)
++
++ <hr>
++*/
++int ioh_can_rx_init_filter(int handle, u32 buff_num);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_rx_disable_all(
++ int handle)
++
++ <hr>
++*/
++int ioh_can_rx_disable_all(int handle);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_tx_disable_all(
++ int handle)
++
++ <hr>
++*/
++int ioh_can_tx_disable_all(int handle);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_set_rx_enable(
++ int handle,u32 buff_num,u32 set)
++
++ <hr>
++*/
++int ioh_can_set_rx_enable(int handle, u32 buff_num, u32 set);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_get_rx_enable(
++ int handle,u32 buff_num,u32 *enable)
++
++ <hr>
++*/
++int ioh_can_get_rx_enable(int handle, u32 buff_num, u32 *enable);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_set_tx_enable(
++ int handle, u32 buff_num,u32 set)
++
++ <hr>
++*/
++int ioh_can_set_tx_enable(int handle, u32 buff_num, u32 set);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_get_tx_enable(
++ int handle,u32 buff_num,u32 *enable)
++
++ <hr>
++*/
++int ioh_can_get_tx_enable(int handle, u32 buff_num, u32 *enable);
++
++/*! @ingroup HALlayerAPI
++ @fn void ioh_can_config_rx_tx_buffers(
++ int handle)
++
++ <hr>
++*/
++void ioh_can_config_rx_tx_buffers(int handle);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_get_error_stats(
++ int handle,struct ioh_can_error *error)
++
++ <hr>
++*/
++int ioh_can_get_error_stats(int handle, struct ioh_can_error *error);
++
++/*! @ingroup HALlayerAPI
++ @fn irqreturn_t ioh_can_handler(
++ int irq, void *dev_id)
++
++ <hr>
++*/
++irqreturn_t ioh_can_handler(int irq, void *dev_id);
++
++/*! @ingroup HALlayerAPI
++ @fn void icp_can_log_message(u32 status)
++
++ <hr>
++*/
++void icp_can_log_message(u32 status);
++
++/*! @ingroup HALlayerAPI
++ @fn int ioh_can_reset(struct ioh_can_os *can_os)
++
++ <hr>
++*/
++int ioh_can_reset(struct ioh_can_os *can_os);
++
++/*! @ingroup HALlayerAPI
++ @fn void ioh_can_entcb(
++ void(*ioh_can_cb)(struct ioh_can_os *),struct ioh_can_os * p_can_os)
++
++ <hr>
++*/
++void ioh_can_entcb(void (*ioh_can_cb) (struct ioh_can_os *),
++ struct ioh_can_os *p_can_os);
++
++/*! @ingroup HALlayerAPI
++ @fn void ioh_can_callback(struct ioh_can_os * can_os)
++
++ <hr>
++*/
++void ioh_can_callback(struct ioh_can_os *can_os);
++#endif /* __IOH_CAN_HAL_H__ */
+diff -urN linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_main.c topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_main.c
+--- linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_main.c 1970-01-01 09:00:00.000000000 +0900
++++ topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_main.c 2010-03-10 08:57:34.000000000 +0900
+@@ -0,0 +1,1681 @@
++/*!
++ * @file ioh_can_main.c
++ * @brief Provides the function definition for the CAN driver functions.
++ * @version 1.0
++ * @section
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * <hr>
++ */
++
++/*
++ * History:
++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
++ * All rights reserved.
++ *
++ * created:
++ * WIPRO 03/07/2009
++ * modified:
++ * WIPRO 05/08/2009
++ *
++ */
++
++/* includes */
++#include <linux/module.h>
++#include <linux/cdev.h>
++#include <linux/fs.h>
++#include <linux/uaccess.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++#include <linux/wait.h>
++#include <linux/io.h>
++#include <linux/sched.h>
++
++#include "pch_common.h"
++#include "pch_debug.h"
++#include "pch_can_main.h"
++#include "pch_can_hal.h"
++#include "pch_can_utils.h"
++#include "pch_can_pci.h"
++
++/*** Function prototypes ***/
++static int ioh_candev_open(struct inode *inode, struct file *file);
++static int ioh_candev_close(struct inode *inode, struct file *file);
++static ssize_t ioh_can_read(struct file *filep, char __user * buf, size_t count,
++ loff_t *f_pos);
++static ssize_t ioh_can_write(struct file *filp, const char __user * buf,
++ size_t count, loff_t *f_pos);
++static int ioh_can_ioctl(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++static void can_ioctl_buff_size(unsigned int ctl_code, size_t *in_size,
++ size_t *out_size);
++
++/*********/
++
++/*! @ingroup InterfaceLayerFacilitators
++ @struct file_ops
++ @brief Kernel structure for holding references to CAN driver
++ methods.
++ Used during the CAN driver registeration.
++ @see
++ - ioh_can_probe
++
++ <hr>
++*/
++const struct file_operations file_ops = {
++ .owner = THIS_MODULE,
++ .read = ioh_can_read,
++ .write = ioh_can_write,
++ .ioctl = ioh_can_ioctl,
++ .open = ioh_candev_open,
++ .release = ioh_candev_close
++};
++
++#ifdef DEBUG
++/*! @ingroup Debug
++ @def IOCTL_CAN_DEBUG
++ @brief Included for debugging the CAN Driver API.
++ @remarks It provides an ioctl command through which,
++ the device registers can be read/write.
++ The argument for the command is the structure
++ shown below.
++
++ @note Can be used only when the DEBUG flag is set during
++ compiling.
++
++ <br>
++*/
++#define IOCTL_CAN_DEBUG (40)
++
++/*! @ingroup Debug
++ @struct debug
++ @brief Included for passing the debug commands to the
++ CAN Driver.
++ @remarks It provides a format for specifying the required
++ debug operation commands and associated
++ paramters
++ to the Driver.
++ @note Can be used only when the DEBUG flag is set during
++ compiling.
++
++ <br>
++*/
++struct debug {
++ unsigned char cmd; /**< (1: Read) (2: Write). */
++ unsigned short offset; /**< Offset of th register. */
++ unsigned long value; /**< Read Value/Value to be written */
++};
++
++#endif
++
++/*! @ingroup InterfaceLayerAPI
++ @fn static int ioh_candev_open(
++ struct inode *inode, struct file *file)
++ @brief Implements the open functionalities of the CAN driver.
++ @remarks
++ This function is used as the open function of
++ the driver. The main
++ tasks performed by this function are :
++ - Confirms that at a time only one device is
++ using the CAN device.
++ - Initializes the CAN device to be used by the
++ driver.
++ - Initializes the driver data structures for
++ further use.
++ @note This function is invoked by the kernel subsystem when a
++ process
++ issues an open system call on the associated
++ device driver.
++
++ @param inode [@ref INOUT] Reference to the inode structure
++ of the device file.
++ @param file [@ref INOUT] Reference to the file structure
++ of the device file.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> Operation successful.
++ - EBUSY --> Device already opened.
++ - -ENOMEM --> request_irq error status code.
++ - -EBUSY --> request_irq error status code.
++ - -ENOSYS --> request_irq error status code.
++ - @ref IOH_CAN_FAIL --> ioh_can_open fails/
++ create_can_fifo fails.
++
++ <hr>
++
++*/
++static int ioh_candev_open(struct inode *inode, struct file *file)
++{
++ int retval = IOH_CAN_SUCCESS;
++ struct ioh_can_os *dev_can_os = \
++ (struct ioh_can_os *)&(can_os[iminor(inode)]);
++ unsigned long flags;
++
++ /* Attaining lock for open. */
++ spin_lock_irqsave(&(dev_can_os->open_spinlock), flags);
++
++ /* Check if CAN is already open */
++ if (0 == (dev_can_os->opened)) {
++ /* Resetting the hardware. */
++/* (void)ioh_can_reset(dev_can_os); */
++/* IOH_DEBUG("ioh_candev_open -> Function ioh_can_reset invoked " \
++ "successfully.\n");
++*/
++ /* Initializing the CAN hardware. */
++ retval = ioh_can_open(dev_can_os->can,
++ file->
++ f_flags & O_RDONLY ? IOH_CAN_LISTEN :
++ IOH_CAN_ACTIVE, IOH_CAN_FIXED_PRIORITY);
++
++ if (retval != IOH_CAN_SUCCESS) {
++ IOH_LOG(KERN_ERR,
++ "ioh_candev_open -> ioh_can_open failed "
++ "(returned %d).\n", retval);
++ } else {
++ IOH_DEBUG
++ ("ioh_candev_open -> \
++ ioh_can_open invoked successfully "
++ "(returned %d).\n", retval);
++
++ dev_can_os->rx_fifo = create_can_fifo(NUM_NODES);
++
++ if (!(dev_can_os->rx_fifo)) {
++ IOH_LOG(KERN_ERR,
++ "ioh_candev_open -> create_can_fifo "
++ "failed.\n");
++
++ (void)ioh_can_release(dev_can_os->can);
++ IOH_DEBUG
++ ("ioh_candev_open -> ioh_can_release invoked "
++ "successfully.\n");
++
++ retval = IOH_CAN_FAIL;
++ } else {
++ IOH_DEBUG
++ ("ioh_candev_open -> create_can_fifo invoked "
++ "successfully.\n");
++
++ /* Registering the callback function for
++ interrupt handling. */
++ ioh_can_entcb(ioh_can_callback, dev_can_os);
++ IOH_DEBUG
++ ("ioh_candev_open -> ioh_can_entcb invoked \
++ successfully.\n");
++
++ /* Regsitering the interrupt. */
++ retval =
++ request_irq(dev_can_os->irq,
++ ioh_can_handler, IRQF_SHARED,
++ "can", &can_os[iminor(inode)]
++ );
++
++ if (0 != retval) {
++ (void)ioh_can_release(dev_can_os->can);
++ delete_can_fifo(dev_can_os->rx_fifo);
++ dev_can_os->rx_fifo = 0;
++ dev_can_os->can_callback = NULL;
++
++ IOH_LOG(KERN_ERR,
++ "ioh_candev_open -> \
++ request_irq failed on irq %d"
++ "(returned %d).\n",
++ dev_can_os->irq, retval);
++ } else {
++ IOH_DEBUG
++ ("ioh_candev_open -> request_irq \
++ invoked "
++ "successfully(returned %d).\n",
++ retval);
++
++ /* Assuming that no bus off
++ interrupt. */
++ dev_can_os->bus_off_interrupt = 0;
++ dev_can_os->write_wait_flag = 0;
++
++ /* Setting the block mode. */
++ dev_can_os->block_mode = 1;
++
++ dev_can_os->inode = inode;
++ dev_can_os->opened = 1;
++
++ /* Storing the can structure for further
++ use. */
++ file->private_data = dev_can_os;
++
++ retval = IOH_CAN_SUCCESS;
++ }
++ }
++ }
++ } else {
++ retval = -EBUSY;
++ IOH_LOG(KERN_ERR,
++ "ioh_candev_open -> CAN device already open.\n");
++ }
++
++ spin_unlock_irqrestore(&(dev_can_os->open_spinlock), flags);
++
++ IOH_DEBUG("ioh_candev_open returns %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup InterfaceLayerAPI
++ @fn static int ioh_candev_close(struct inode *inode,
++ struct file *file)
++ @brief Implements the close functionalities of the CAN driver.
++ @remarks This function is used as the close function of the
++ driver. The main
++ tasks performed by this function are :
++ - De-initializes the CAN device hardware so that
++ the device can be closed.
++ - Releases the resources attained during the
++ opening of the device.
++ - Re-initializes the data structures so that it
++ can be used further.
++ @note This function is invoked by the Kernel subsystem when an
++ application issues a close system call on the
++ associated device file.
++
++ @param inode [@ref INOUT] Reference to the inode structure
++ of the
++ device file.
++ @param file [@ref INOUT] Reference to the file structure
++ of the
++ device file.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> The close
++ operation was successful.
++
++ <hr>
++*/
++static int ioh_candev_close(struct inode *inode, struct file *file)
++{
++ int retval;
++ struct ioh_can_os *can_os = (struct ioh_can_os *) file->private_data;
++
++ /* Attaining the lock for close. */
++ spin_lock(&(can_os->open_spinlock));
++
++ retval = ioh_can_release(can_os->can);
++ IOH_DEBUG("ioh_candev_close -> ioh_can_release invoked successfully"
++ "(returned %d).\n", retval);
++
++ (void)ioh_can_set_int_enables(can_os->can, CAN_DISABLE);
++
++ free_irq(can_os->irq, &(can_os[iminor(can_os->inode)]));
++ IOH_DEBUG("ioh_candev_close -> free_irq invoked successfully.\n");
++
++ /* Delete FIFO. */
++ delete_can_fifo(can_os->rx_fifo);
++ IOH_DEBUG
++ ("ioh_candev_close -> delete_can_fifo invoked successfully.\n");
++
++ /* Resetting the open flag. */
++ can_os->opened = 0;
++ file->private_data = NULL;
++ can_os->rx_fifo = 0;
++ can_os->can_callback = NULL;
++
++ /* Releasing the lock. */
++ spin_unlock(&(can_os->open_spinlock));
++
++ if (retval != IOH_CAN_SUCCESS) {
++ IOH_LOG(KERN_ERR, "ioh_candev_close -> Release failed "
++ "on CAN device %d.\n", iminor(inode));
++
++ }
++
++ IOH_DEBUG("ioh_candev_close returns %d.\n", IOH_CAN_SUCCESS);
++ return IOH_CAN_SUCCESS;
++}
++
++/*! @ingroup InterfaceLayerAPI
++ @fn static ssize_t ioh_can_read(
++ struct file *filp, char __user *buf,
++ size_t count,loff_t *f_pos)
++ @brief Implements the read functionalities of the CAN driver.
++ @remarks This function is used as the read function of the
++ driver. The main tasks of this function are :
++ - Reads the received message data from the
++ software FIFO if it
++ is available and copies it to the user process
++ for further
++ use.
++ - If the CAN device is in blocking mode and if
++ no data is
++ available, this function waits until the
++ message data is
++ available within the software FIFO.
++ @note This function is invoked by the Kernel subsystem when a
++ process
++ issues read system call on the associated device
++ file.
++
++ @param filp [@ref INOUT] Reference to the file structure
++ of the device file.
++ @param buf [@ref OUT] Reference to the
++ user level buffer for
++ updating the read data.
++ @param count [@ref IN] The size to be read.
++ @param f_pos [@ref INOUT] Not used.
++
++ @retval ssize_t
++ - Size of the message object
++ --> Read operation successful.
++ - -ENOMEM --> copy_to_user fails.
++ - -EAGAIN --> Device in suspended
++ mode/non blocking
++ read with software FIFO
++ empty.
++ - -EIO --> read_can_fifo fails/read
++ wait in blocking mode
++ fails.
++ - -EINVAL --> Parameter buf/count is not
++ valid.
++
++ <hr>
++*/
++static ssize_t ioh_can_read(struct file *filp, char __user * buf, size_t count,
++ loff_t *f_pos)
++{
++ ssize_t retval = IOH_CAN_SUCCESS; /* Return status value. */
++ struct ioh_can_msg msg; /* Msg variable for reading. */
++ struct ioh_can_os *can_os = (struct ioh_can_os *) filp->private_data;
++
++ /* If device susupended */
++ if ((can_os->is_suspending) == 1) {
++ IOH_LOG(KERN_ERR, "ioh_can_read -> Device suspended.\n");
++ retval = -EAGAIN;
++ }
++ /* If invalid parameters. */
++ else if ((buf == NULL) || (count < sizeof(struct ioh_can_msg))) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_read -> Invalid parameter for read.\n");
++ retval = -EINVAL;
++ }
++ /* If NON_BLOCK mode and FIFO(software) empty. */
++ else if (((can_os->block_mode == 0))
++ && (check_can_fifo_status(can_os->rx_fifo) ==
++ IOH_CAN_FIFO_EMPTY)) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_read -> Buffer empty and device in non-block \
++ mode.\n");
++ retval = -EAGAIN;
++ }
++
++ /* If block mode and FIFO(software) empty. */
++ else if ((can_os->block_mode == 1)
++ && (check_can_fifo_status(can_os->rx_fifo) ==
++ IOH_CAN_FIFO_EMPTY)) {
++ IOH_DEBUG
++ ("ioh_can_read -> \
++ Waiting for FIFO to be filled with data.\n");
++ /* Preparing to wait. */
++ can_os->read_wait_flag = 1;
++ retval = wait_event_interruptible(can_os->read_wait_queue,
++ (check_can_fifo_status
++ (can_os->rx_fifo) !=
++ IOH_CAN_FIFO_EMPTY));
++
++ /* Wait fails. */
++ if (-ERESTARTSYS == retval) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_read -> \
++ Wait_event_interruptible failed on read.\n");
++ retval = -EIO;
++ }
++ }
++
++ if (IOH_CAN_SUCCESS == retval) {
++ retval = read_can_fifo(can_os->rx_fifo, &msg);
++
++ if (retval) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_read -> Read from FIFO failed.\n");
++ retval = -EIO;
++ } else {
++ IOH_DEBUG
++ ("ioh_can_read -> Read from FIFO successful.\n");
++ IOH_DEBUG("ioh_can_read -> The read message is: \n");
++ IOH_DEBUG("Msg ID : 0x%x\n", msg.id);
++ IOH_DEBUG("EXT ID : %x\n", msg.ide);
++ IOH_DEBUG("Msg Size : %hu\n", msg.dlc);
++ IOH_DEBUG("Rment : %hu\n", msg.rtr);
++ IOH_DEBUG("Dat Byt1 : 0x%x\n", msg.data[0]);
++ IOH_DEBUG("Dat Byt2 : 0x%x\n", msg.data[1]);
++ IOH_DEBUG("Dat Byt3 : 0x%x\n", msg.data[2]);
++ IOH_DEBUG("Dat Byt4 : 0x%x\n", msg.data[3]);
++ IOH_DEBUG("Dat Byt5 : 0x%x\n", msg.data[4]);
++ IOH_DEBUG("Dat Byt6 : 0x%x\n", msg.data[5]);
++ IOH_DEBUG("Dat Byt7 : 0x%x\n", msg.data[6]);
++ IOH_DEBUG("Dat Byt8 : 0x%x\n", msg.data[7]);
++
++ retval = copy_to_user(buf, &msg, sizeof(msg));
++
++ if (retval) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_read -> \
++ Copy to user failed for CAN.\n");
++ retval = -ENOMEM;
++ } else {
++ retval = sizeof(struct ioh_can_msg);
++ }
++ }
++ }
++
++ IOH_DEBUG("ioh_can_read -> Return Value: %d.\n", retval);
++ return retval;
++}
++
++/*! @ingroup InterfaceLayerAPI
++ @fn ssize_t ioh_can_write(
++ struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
++ @brief Implements the write functionalities of the CAN Driver.
++ @remarks This function is used as the write function of the
++ driver.
++ The main tasks performed by this function are :
++ - Obtains the data from the user process and
++ updates it into the
++ hardware buffers (if available) for
++ transmission as message objects.
++ - If the CAN device is in Blocking mode and if
++ no transmit message
++ object is available, then this function waits
++ until a transmit
++ buffer is available for transmission.
++ @note This function is invoked by the Kernel subsystem when a
++ process issues a write system call on the
++ associated device file.
++
++ @param filp [@ref INOUT] Reference to the file structure
++ of the device file
++ @param buf [@ref IN] Reference to the
++ user level buffer containing
++ data to be written(transmitted).
++ @param count [@ref IN] Size of the data to be
++ written.
++ @param f_pos [@ref INOUT] Not Used.
++
++ @retval ssize_t
++ - Size of the message object
++ --> Write is successful.
++ - -ENOMEM --> copy_from_user error status code
++ - -EAGAIN --> Device in suspended mode.
++ - -EIO --> Non-blocking write fails
++ - -EINVAL --> Size of CAN message not valid.
++ - @ref IOH_CAN_FAIL --> Transmit fails.
++
++ <hr>
++*/
++ssize_t ioh_can_write(struct file *filp, const char __user *buf, size_t count,
++ loff_t *f_pos)
++{
++ struct ioh_can_msg msg; /* The message object for writing. */
++ int err; /* error variable. */
++ struct ioh_can_os *can_os = (struct ioh_can_os *) filp->private_data;
++ ssize_t ret;
++
++ /* If device suspended. */
++ if ((can_os->is_suspending) == 1) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_write -> Device is in suspend mode.\n");
++ IOH_DEBUG("ioh_can_write returns %d\n", -EAGAIN);
++ return -EAGAIN;
++ }
++
++ /* if invalid count. */
++ if (count != sizeof(struct ioh_can_msg)) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_write -> Write user buffer size invalid "
++ "for CAN.\n");
++ IOH_DEBUG("ioh_can_write returns %d\n", -EINVAL);
++ return -EINVAL;
++ }
++
++ err = copy_from_user(&msg, buf, count);
++
++ if (err) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_write -> Copy from user failed for CAN in "
++ "write operation.\n");
++ IOH_DEBUG("ioh_can_write returns %d\n", -ENOMEM);
++ return -ENOMEM;
++ }
++
++ /* The wait flag. */
++ can_os->write_wait_flag = 1;
++
++ /* Transmitting the message. */
++ err = ioh_can_msg_tx(can_os->can, &msg);
++
++ if ((err != IOH_CAN_SUCCESS)) {
++ /* Transmission failed due to unavailability of transmit object
++ and it is block mode. */
++ if ((IOH_CAN_NO_TX_BUFF == err) && (can_os->block_mode == 1)) {
++ IOH_DEBUG
++ ("ioh_can_write -> Waiting for transmit message "
++ "object.\n");
++
++ /* Prpearing to wait. */
++ err = wait_event_interruptible(can_os->write_wait_queue,
++ can_os->
++ write_wait_flag == 0);
++
++ if (-ERESTARTSYS == err) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_write -> \
++ Write wait failed.\n");
++ IOH_DEBUG("ioh_can_write returns %d\n",
++ -EAGAIN);
++ return -EAGAIN;
++ }
++
++ /* Transmitting again. */
++ err = ioh_can_msg_tx(can_os->can, &msg);
++
++ /* If again error. */
++ if (err != IOH_CAN_SUCCESS) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_write -> Transmit failed "
++ "after 2 attempts.\n");
++ IOH_DEBUG("ioh_can_write returns %d\n",
++ IOH_CAN_FAIL);
++ return IOH_CAN_FAIL;
++ }
++ } else { /* If failed due to some other reasons. */
++
++ IOH_LOG(KERN_ERR,
++ "ioh_can_write -> Write from CAN device "
++ "failed %d.\n", -EIO);
++ IOH_DEBUG("ioh_can_write returns %d\n", -EIO);
++ return -EIO;
++ }
++ }
++ IOH_DEBUG
++ ("ioh_can_write -> Message send for transmission successfully.\n");
++ IOH_DEBUG("The transmitted Message is :\n");
++ IOH_DEBUG("Msg ID : 0x%x\n", msg.id);
++ IOH_DEBUG("EXT ID : %hu\n", msg.ide);
++ IOH_DEBUG("Msg Size : %hu\n", msg.dlc);
++ IOH_DEBUG("Rment : %hu\n", msg.rtr);
++ IOH_DEBUG("Dat Byt1 : 0x%x\n", msg.data[0]);
++ IOH_DEBUG("Dat Byt2 : 0x%x\n", msg.data[1]);
++ IOH_DEBUG("Dat Byt3 : 0x%x\n", msg.data[2]);
++ IOH_DEBUG("Dat Byt4 : 0x%x\n", msg.data[3]);
++ IOH_DEBUG("Dat Byt5 : 0x%x\n", msg.data[4]);
++ IOH_DEBUG("Dat Byt6 : 0x%x\n", msg.data[5]);
++ IOH_DEBUG("Dat Byt7 : 0x%x\n", msg.data[6]);
++ IOH_DEBUG("Dat Byt8 : 0x%x\n", msg.data[7]);
++
++ IOH_DEBUG("ioh_can_write -> Write from CAN device successful "
++ "( returns %d).", sizeof(struct ioh_can_msg));
++
++ ret = sizeof(struct ioh_can_msg);
++ return ret;
++}
++
++/*! @ingroup InterfaceLayerAPI
++ @fn static int ioh_can_ioctl(
++struct inode *inode, struct file *filp, unsigned int cmd,unsigned long arg)
++ @brief Implements the ioctl functionalities of the CAN driver.
++ @remarks This function is used as the ioctl function of the
++ Driver.
++ The main tasks performed by this function are :
++ - Checks for the validity of the obtained IOCTL
++ command.
++ - Performs the associated operation for the
++ valid IOCTL
++ command by invoking the corresponding HAL
++ APIs.
++ - Copies the data if required back to the user
++ process.
++ @note This function is invoked by the Kernel subsystem when
++ a process issues an ioctl system call on the
++ associated
++ device file.
++
++ @param inode [@ref INOUT] Reference to the inode
++ structure of the device
++ file.
++ @param filp [@ref INOUT] Reference to the file
++ structure of the device
++ file.
++ @param cmd [@ref IN] The ioctl command to be
++ executed.
++ @param arg [@ref INOUT] The argument reference
++ to be used.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> The operation was
++ successful.
++ - -ENOMEM --> copy_to_user/copy_from_user fails.
++ - -EAGAIN --> Memory allocation fails for input
++ /output buffer.
++ - @ref IOH_CAN_FAIL --> IOCTL fails.
++
++ <hr>
++*/
++static int ioh_can_ioctl
++ (struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg) {
++ struct ioh_can_os *can_os;
++ int retval = IOH_CAN_SUCCESS;
++ void *in = NULL;
++ void *out = NULL;
++ size_t in_buff_size = 0;
++ size_t out_buff_size = 0;
++ can_os = (struct ioh_can_os *) filp->private_data;
++
++ can_ioctl_buff_size(cmd, &in_buff_size, &out_buff_size);
++
++ if (can_os->is_suspending == 1) {
++ IOH_LOG(KERN_ERR, "ioh_can_ioctl -> Device suspended.\n");
++ retval = -EAGAIN;
++ }
++
++ if ((in_buff_size != 0) && (retval == IOH_CAN_SUCCESS)) {
++ in = kmalloc(in_buff_size, GFP_KERNEL);
++
++ if (in != NULL) {
++ retval = copy_from_user(in, (void *)arg, in_buff_size);
++ if (retval != 0) {
++ IOH_LOG(KERN_ERR, "ioh_can_ioctl -> Copy from "
++ "user failed.\n");
++ retval = -ENOMEM;
++ }
++ } else {
++ IOH_LOG(KERN_ERR, "ioh_can_ioctl -> Memory allocation "
++ "failed for input argument.\n");
++ retval = -EAGAIN;
++ }
++ }
++
++ if ((out_buff_size != 0) && (IOH_CAN_SUCCESS == retval)) {
++ out = kmalloc(out_buff_size, GFP_KERNEL);
++
++ if (out == NULL) {
++ IOH_LOG(KERN_ERR, "ioh_can_ioctl -> Memory allocation "
++ "failed for output argument.\n");
++ retval = -EAGAIN;
++ }
++ }
++
++ if (IOH_CAN_SUCCESS == retval) {
++ switch (cmd) {
++ case IOCTL_CAN_RESET:
++ IOH_DEBUG("ioh_can_ioctl -> IOCTL_CAN_RESET\n");
++ retval = ioh_can_reset(can_os);
++ break;
++
++ case IOCTL_CAN_RUN:
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_RUN\n");
++ retval = ioh_can_set_run_mode(can_os->can, IOH_CAN_RUN);
++ break;
++
++ case IOCTL_CAN_RUN_GET:
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_RUN_GET\n");
++ retval =
++ ioh_can_get_run_mode(can_os->can,
++ (enum ioh_can_run_mode *) out);
++ break;
++
++ case IOCTL_CAN_STOP:
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_STOP:\n");
++ retval =
++ ioh_can_set_run_mode(can_os->can, IOH_CAN_STOP);
++ break;
++
++ case IOCTL_CAN_SIMPLE:
++ {
++ enum ioh_can_run_mode curr_mode;
++ IOH_DEBUG("ioh_can_ioctl -> Command "
++ "received IOCTL_CAN_SIMPLE\n");
++
++ (void)ioh_can_get_run_mode(can_os->can,
++ &curr_mode);
++ if (curr_mode == IOH_CAN_RUN) {
++ (void)ioh_can_set_run_mode(can_os->can,
++ IOH_CAN_STOP);
++ }
++ retval =
++ ioh_can_set_baud_simple(can_os->can,
++ *((enum ioh_can_baud *)
++ in));
++ if (curr_mode == IOH_CAN_RUN) {
++ (void)ioh_can_set_run_mode(can_os->can,
++ IOH_CAN_RUN);
++ }
++ }
++ break;
++
++ case IOCTL_CAN_CUSTOM:
++ {
++ enum ioh_can_run_mode curr_mode;
++
++ IOH_DEBUG("ioh_can_ioctl -> Command "
++ "received IOCTL_CAN_CUSTOM\n");
++
++ (void)ioh_can_get_run_mode(can_os->can,
++ &curr_mode);
++ if (curr_mode == IOH_CAN_RUN) {
++ (void)ioh_can_set_run_mode(can_os->can,
++ IOH_CAN_STOP);
++ }
++ retval =
++ ioh_can_set_baud_custom(can_os->can,
++ (struct ioh_can_timing *)
++ in);
++ if (curr_mode == IOH_CAN_RUN) {
++ (void)ioh_can_set_run_mode(can_os->can,
++ IOH_CAN_RUN);
++ }
++ }
++ break;
++
++ case IOCTL_CAN_TIMING_GET:
++ IOH_DEBUG("ioh_can_ioctl -> IOCTL_CAN_TIMING_GET\n");
++ retval =
++ ioh_can_get_baud(can_os->can,
++ (struct ioh_can_timing *) out);
++ break;
++
++ case IOCTL_CAN_FILTER:
++ {
++ unsigned int buff_num = 0;
++ int i = 0;
++ unsigned int status = 0;
++ struct ioh_can_rx_filter *rx_filter =
++ (struct ioh_can_rx_filter *) in;
++
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_FILTER\n");
++
++ for (i = 0;
++ i <
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size); i++) {
++ if (ioh_msg_obj_conf[i] == 0) {
++ buff_num++;
++ if (buff_num ==
++ (rx_filter->num)) {
++ break;
++ }
++ }
++ }
++
++ if (i ==
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size)) {
++ IOH_DEBUG("ioh_can_ioctl -> InValid "
++ "message buffer.");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Here i is the index, however (i+1) is
++ object number. */
++ rx_filter->num = (i + 1);
++
++ (void)ioh_can_get_rx_enable(can_os->can,
++ rx_filter->
++ num,
++ &status);
++ if (status == ENABLE) {
++ (void)
++ ioh_can_set_rx_enable
++ (can_os->can,
++ rx_filter->num, DISABLE);
++ }
++ retval =
++ ioh_can_set_rx_filter(can_os->can,
++ rx_filter);
++ if (status == ENABLE) {
++ (void)
++ ioh_can_set_rx_enable
++ (can_os->can,
++ rx_filter->num, ENABLE);
++ }
++ }
++ }
++ break;
++
++ case IOCTL_CAN_FILTER_GET:
++ {
++ unsigned int buff_num = 0;
++ int i = 0;
++ unsigned int status = 0;
++ struct ioh_can_rx_filter *rx_filter =
++ (struct ioh_can_rx_filter *) out;
++
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_FILTER_GET\n");
++
++ rx_filter->num =
++ ((struct ioh_can_rx_filter *) in)->num;
++
++ for (i = 0;
++ i <
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size); i++) {
++ if (ioh_msg_obj_conf[i] == 0) {
++ buff_num++;
++ if (buff_num == rx_filter->num)
++ break;
++ }
++ }
++
++ if (i ==
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size)) {
++ IOH_DEBUG
++ ("ioh_can_ioctl -> InValid message "
++ "buffer %x.\n", rx_filter->num);
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Here i is the index, however (i+1) is
++ object number. */
++ rx_filter->num = (i + 1);
++
++ (void)ioh_can_get_rx_enable(can_os->can,
++ rx_filter->
++ num,
++ &status);
++
++ if (status == ENABLE) {
++ (void)
++ ioh_can_set_rx_enable
++ (can_os->can,
++ rx_filter->num, DISABLE);
++ }
++
++ retval =
++ ioh_can_get_rx_filter(can_os->can,
++ rx_filter);
++
++ if (status == ENABLE) {
++ (void)
++ ioh_can_set_rx_enable
++ (can_os->can,
++ rx_filter->num, ENABLE);
++ }
++
++ rx_filter->num = buff_num;
++
++ IOH_DEBUG("Rx Msg Obj : %u\n",
++ rx_filter->num);
++ IOH_DEBUG("ID : %u\n",
++ rx_filter->aidr.id);
++ IOH_DEBUG("Extended ID : %u\n",
++ rx_filter->aidr.id_ext);
++ IOH_DEBUG("Umask : %u\n",
++ rx_filter->umask);
++ IOH_DEBUG("Mask Id : %u\n",
++ rx_filter->amr.id);
++ IOH_DEBUG("Ext Mask : %u\n",
++ rx_filter->amr.id_ext);
++
++ }
++
++ }
++ break;
++
++ case IOCTL_CAN_BLOCK:
++ IOH_DEBUG
++ ("ioh_can_ioctl -> Command received \
++ IOCTL_CAN_BLOCK\n");
++ can_os->block_mode = 1;
++ retval = IOH_CAN_SUCCESS;
++ IOH_DEBUG
++ ("ioh_can_ioctl -> Block mode set successfully.\n");
++ break;
++
++ case IOCTL_CAN_NON_BLOCK:
++ IOH_DEBUG
++ ("ioh_can_ioctl -> Command received \
++ IOCTL_CAN_NON_BLOCK\n");
++ can_os->block_mode = 0;
++ retval = IOH_CAN_SUCCESS;
++ IOH_DEBUG
++ ("ioh_can_ioctl -> Non-Block mode set \
++ successfully.\n");
++ break;
++
++ case IOCTL_CAN_BLOCK_GET:
++ IOH_DEBUG
++ ("ioh_can_ioctl -> Command received \
++ IOCTL_CAN_BLOCK_GET\n");
++ *((unsigned int *)out) = can_os->block_mode;
++ retval = IOH_CAN_SUCCESS;
++ IOH_DEBUG("ioh_can_ioctl -> Mode: "
++ "%s\n",
++ (((unsigned int)(*(unsigned int *)out) ==
++ 1) ? "BLOCK" : "NON BLOCK"));
++ break;
++
++ case IOCTL_CAN_LISTEN:
++ {
++ enum ioh_can_run_mode curr_mode;
++
++ IOH_DEBUG
++ ("ioh_can_ioctl -> Command received \
++ IOCTL_CAN_LISTEN\n");
++
++ (void)ioh_can_get_run_mode(can_os->can,
++ &curr_mode);
++ if (curr_mode == IOH_CAN_RUN) {
++ (void)ioh_can_set_run_mode(can_os->can,
++ IOH_CAN_STOP);
++ }
++
++ retval =
++ ioh_can_set_listen_mode(can_os->can,
++ IOH_CAN_LISTEN);
++
++ if (curr_mode == IOH_CAN_RUN) {
++ (void)ioh_can_set_run_mode(can_os->can,
++ IOH_CAN_RUN);
++ }
++ }
++ break;
++
++ case IOCTL_CAN_ACTIVE:
++ {
++ enum ioh_can_run_mode curr_mode;
++
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_ACTIVE\n");
++
++ (void)ioh_can_get_run_mode(can_os->can,
++ &curr_mode);
++ if (curr_mode == IOH_CAN_RUN) {
++ (void)ioh_can_set_run_mode(can_os->can,
++ IOH_CAN_STOP);
++ }
++
++ retval =
++ ioh_can_set_listen_mode(can_os->can,
++ IOH_CAN_ACTIVE);
++
++ if (curr_mode == IOH_CAN_RUN) {
++ (void)ioh_can_set_run_mode(can_os->can,
++ IOH_CAN_RUN);
++ }
++ }
++ break;
++
++ case IOCTL_CAN_LISTEN_GET:
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_LISTEN_GET\n");
++ retval =
++ ioh_can_get_listen_mode(can_os->can,
++ (enum ioh_can_listen_mode *)
++ out);
++ break;
++
++ case IOCTL_CAN_ARBITER_ROUND_ROBIN:
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_ARBITER_ROUND_ROBIN\n");
++ retval =
++ ioh_can_set_arbiter_mode(can_os->can,
++ IOH_CAN_ROUND_ROBIN);
++ break;
++
++ case IOCTL_CAN_ARBITER_FIXED_PRIORITY:
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_ARBITER_FIXED_PRIORITY\n");
++ retval =
++ ioh_can_set_arbiter_mode(can_os->can,
++ IOH_CAN_FIXED_PRIORITY);
++ break;
++
++ case IOCTL_CAN_ARBITER_GET:
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_ARBITER_GET\n");
++ retval =
++ ioh_can_get_arbiter_mode(can_os->can,
++ (enum ioh_can_arbiter *) out);
++ break;
++
++ case IOCTL_CAN_ERROR_STATS_GET:
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_ERROR_STATS_GET\n");
++ retval =
++ ioh_can_get_error_stats(can_os->can,
++ (struct ioh_can_error *) out);
++ break;
++
++ case IOCTL_CAN_RESTART_MODE_AUTO:
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_RESTART_MODE_AUTO\n");
++ retval =
++ ioh_can_set_restart_mode(can_os->can, CAN_AUTO);
++ break;
++
++ case IOCTL_CAN_RESTART_MODE_MANUAL:
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_RESTART_MODE_MANUAL\n");
++ retval =
++ ioh_can_set_restart_mode(can_os->can, CAN_MANUAL);
++ break;
++
++ case IOCTL_CAN_RESTART_MODE_GET:
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_RESTART_MODE_GET\n");
++ retval =
++ ioh_can_get_restart_mode(can_os->can,
++ (enum ioh_can_auto_restart *)
++ out);
++ break;
++
++ case IOCTL_CAN_BUFFER_LINK_SET:
++ {
++ unsigned int buff_num = 0, msg_obj = 0;
++ int i = 0;
++ unsigned int status = 0;
++
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_BUFFER_LINK_SET\n");
++ for (i = 0;
++ (i <
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size)); i++) {
++ if (ioh_msg_obj_conf[i] == 0) {
++ buff_num++;
++ if (buff_num ==
++ (*(unsigned int *)in)) {
++ break;
++ }
++ }
++ }
++
++ if (i ==
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size)) {
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Here i is the index, however (i+1) is
++ object number. */
++ msg_obj = (i + 1);
++
++ (void)ioh_can_get_rx_enable(can_os->can,
++ msg_obj,
++ &status);
++
++ if (status == ENABLE) {
++ (void)
++ ioh_can_set_rx_enable
++ (can_os->can, msg_obj,
++ DISABLE);
++ }
++
++ IOH_DEBUG
++ ("ioctl -> Calling \
++ ioh_can_set_rx_buffer_link "
++ "for Rx buffer %d[%d]\n",
++ (*(int *)in), msg_obj);
++ retval =
++ ioh_can_set_rx_buffer_link(can_os->
++ can,
++ msg_obj,
++ ENABLE);
++
++ if (status == ENABLE) {
++ (void)
++ ioh_can_set_rx_enable
++ (can_os->can, msg_obj,
++ ENABLE);
++ }
++ }
++
++ }
++ break;
++
++ case IOCTL_CAN_BUFFER_LINK_CLEAR:
++ {
++ unsigned int buff_num = 0, msg_obj = 0;
++ int i = 0;
++ unsigned status = 0;
++
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_BUFFER_LINK_CLEAR\n");
++ for (i = 0;
++ (i <
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size)); i++) {
++ if (ioh_msg_obj_conf[i] == 0) {
++ buff_num++;
++ if (buff_num ==
++ (*(unsigned int *)in)) {
++ break;
++ }
++ }
++ }
++
++ if (i ==
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size)) {
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Here i is the index, however (i+1)
++ is object number. */
++ msg_obj = (i + 1);
++
++ (void)ioh_can_get_rx_enable(can_os->can,
++ msg_obj,
++ &status);
++
++ if (status == ENABLE) {
++ (void)
++ ioh_can_set_rx_enable
++ (can_os->can, msg_obj,
++ DISABLE);
++ }
++
++ IOH_DEBUG
++ ("ioctl -> Calling \
++ ioh_can_set_rx_buffer_link for "
++ "Rx buffer %d[%d]\n", (*(int *)in),
++ msg_obj);
++ retval =
++ ioh_can_set_rx_buffer_link(can_os->
++ can,
++ msg_obj,
++ DISABLE);
++
++ if (status == ENABLE) {
++ (void)
++ ioh_can_set_rx_enable
++ (can_os->can, msg_obj,
++ ENABLE);
++ }
++ }
++
++ }
++ break;
++
++ case IOCTL_CAN_BUFFER_LINK_GET:
++ {
++ unsigned int buff_num = 0, msg_obj = 0;
++ int i = 0;
++
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_BUFFER_LINK_GET\n");
++ for (i = 0;
++ i <
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size); i++) {
++ if (ioh_msg_obj_conf[i] == 0) {
++ buff_num++;
++ if (buff_num ==
++ (*(unsigned int *)in)) {
++ break;
++ }
++ }
++ }
++
++ if (i ==
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size)) {
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Here i is the index, however (i+1) is
++ object number. */
++ msg_obj = (i + 1);
++
++ IOH_DEBUG
++ ("ioctl -> Calling \
++ ioh_can_get_rx_buffer_link for "
++ "Rx buffer %d[%d]\n", (*(int *)in),
++ msg_obj);
++ retval =
++ ioh_can_get_rx_buffer_link(can_os->
++ can,
++ msg_obj,
++ (unsigned
++ int *)
++ out);
++
++ }
++ }
++ break;
++
++ case IOCTL_CAN_RX_ENABLE_SET:
++ {
++ unsigned int buff_num = 0, msg_obj = 0;
++ int i = 0;
++ unsigned int status = 0;
++
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_RX_ENABLE_SET\n");
++ for (i = 0;
++ i <
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size); i++) {
++ if (ioh_msg_obj_conf[i] == 0) {
++ buff_num++;
++ if (buff_num == (*(int *)in))
++ break;
++ }
++ }
++
++ if (i ==
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size)) {
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Here i is the index, however (i+1) is
++ object number. */
++ msg_obj = (i + 1);
++
++ (void)ioh_can_get_rx_enable(can_os->can,
++ msg_obj,
++ &status);
++ if (status == DISABLE) {
++ retval =
++ ioh_can_set_rx_enable
++ (can_os->can, msg_obj,
++ ENABLE);
++ }
++
++ }
++ }
++ break;
++
++ case IOCTL_CAN_RX_ENABLE_CLEAR:
++ {
++ unsigned int buff_num = 0, msg_obj = 0;
++ int i = 0;
++ unsigned int status = 0;
++
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_RX_ENABLE_CLEAR\n");
++ for (i = 0;
++ i <
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size); i++) {
++ if (ioh_msg_obj_conf[i] == 0) {
++ buff_num++;
++ if (buff_num == (*(int *)in))
++ break;
++ }
++ }
++
++ if (i ==
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size)) {
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Here i is the index, however (i+1) is
++ object number. */
++ msg_obj = (i + 1);
++
++ (void)ioh_can_get_rx_enable(can_os->can,
++ msg_obj,
++ &status);
++ if (status == ENABLE) {
++ retval =
++ ioh_can_set_rx_enable
++ (can_os->can, msg_obj,
++ DISABLE);
++ }
++
++ }
++ }
++ break;
++
++ case IOCTL_CAN_RX_ENABLE_GET:
++ {
++ unsigned int buff_num = 0, msg_obj = 0;
++ int i = 0;
++
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_RX_ENABLE_GET\n");
++ for (i = 0;
++ i <
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size); i++) {
++ if (ioh_msg_obj_conf[i] == 0) {
++ buff_num++;
++ if (buff_num == (*(int *)in))
++ break;
++ }
++ }
++
++ if (i ==
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size)) {
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Here i is the index, however (i+1) is
++ object number. */
++ msg_obj = (i + 1);
++
++ retval =
++ ioh_can_get_rx_enable(can_os->can,
++ msg_obj,
++ (unsigned int
++ *)out);
++
++ }
++ }
++ break;
++
++ case IOCTL_CAN_TX_ENABLE_SET:
++ {
++ unsigned int buff_num = 0, msg_obj = 0;
++ int i = 0;
++ unsigned int status = 0;
++
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_TX_ENABLE_SET\n");
++ for (i = 0;
++ i <
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size); i++) {
++ if (ioh_msg_obj_conf[i] == 1) {
++ buff_num++;
++ if (buff_num == (*(int *)in))
++ break;
++ }
++ }
++
++ if (i ==
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size)) {
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Here i is the index, however (i+1) is
++ object number. */
++ msg_obj = (i + 1);
++
++ (void)ioh_can_get_tx_enable(can_os->can,
++ msg_obj,
++ &status);
++ if (status == DISABLE) {
++ retval =
++ ioh_can_set_tx_enable
++ (can_os->can, msg_obj,
++ ENABLE);
++ }
++
++ }
++ }
++ break;
++
++ case IOCTL_CAN_TX_ENABLE_CLEAR:
++ {
++ unsigned int buff_num = 0, msg_obj = 0;
++ int i = 0;
++ unsigned int status = 0;
++
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_TX_ENABLE_CLEAR\n");
++ for (i = 0;
++ i <
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size); i++) {
++ if (ioh_msg_obj_conf[i] == 1) {
++ buff_num++;
++ if (buff_num == (*(int *)in))
++ break;
++ }
++ }
++
++ if (i ==
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size)) {
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Here i is the index, however (i+1) is
++ object number. */
++ msg_obj = (i + 1);
++
++ (void)ioh_can_get_tx_enable(can_os->can,
++ msg_obj,
++ &status);
++ if (status == ENABLE) {
++ retval =
++ ioh_can_set_tx_enable
++ (can_os->can, msg_obj,
++ DISABLE);
++ }
++
++ }
++ }
++ break;
++
++ case IOCTL_CAN_TX_ENABLE_GET:
++ {
++ unsigned int buff_num = 0, msg_obj = 0;
++ int i = 0;
++
++ IOH_DEBUG("ioh_can_ioctl -> Command received "
++ "IOCTL_CAN_TX_ENABLE_GET\n");
++ for (i = 0;
++ i <
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size); i++) {
++ if (ioh_msg_obj_conf[i] == 1) {
++ buff_num++;
++ if (buff_num == (*(int *)in))
++ break;
++ }
++ }
++
++ if (i ==
++ (ioh_can_tx_buf_size +
++ ioh_can_rx_buf_size)) {
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Here i is the index, however (i+1) is
++ object number. */
++ msg_obj = (i + 1);
++
++ retval =
++ ioh_can_get_tx_enable(can_os->can,
++ msg_obj,
++ (unsigned int
++ *)out);
++
++ }
++ }
++ break;
++
++#ifdef DEBUG
++ /* Inlcuded for debugging. */
++ case IOCTL_CAN_DEBUG:
++ {
++ struct debug in;
++ retval =
++ copy_from_user((void *)&in, (void *)arg,
++ sizeof(struct debug));
++
++ if (in.cmd == 1) { /* Read operation. */
++ in.value =
++ (ioread32
++ ((void __iomem *)(can_os->
++ pci_remap +
++ in.offset))
++ & MSK_ALL_SIXTEEN);
++ IOH_DEBUG("Offset: 0x%x\nRead value: "
++ "0x%x\n",
++ (unsigned int)(in.offset),
++ (unsigned int)(in.
++ value &
++ MSK_ALL_SIXTEEN));
++
++ retval =
++ copy_to_user((void *)arg,
++ (void *)&in,
++ sizeof(struct debug));
++
++ }
++
++ else if (in.cmd == 2) {
++ (void)iowrite32(in.value,
++ (void *)(can_os->
++ pci_remap +
++ in.offset));
++ if (in.value ==
++ ((ioread32
++ ((void *)(can_os->pci_remap +
++ in.offset)))
++ & MSK_ALL_SIXTEEN)) {
++ retval = IOH_CAN_SUCCESS;
++ } else {
++ retval = IOH_CAN_FAIL;
++ }
++
++ }
++
++ else {
++ retval = IOH_CAN_FAIL;
++ }
++
++ }
++ break;
++#endif
++
++ default:
++ IOH_DEBUG("Unrecognizined IOCTL, skipping 0x%x. \n",
++ cmd);
++ retval = -EINVAL;
++ break;
++ }
++
++ if ((out_buff_size != 0) && (IOH_CAN_SUCCESS == retval)) {
++ retval = copy_to_user((void *)arg, out, out_buff_size);
++ if (retval != 0) {
++ IOH_LOG(KERN_ERR, "Copy to user failed for "
++ "for CAN in IOCTL operation.\n");
++ retval = -ENOMEM;
++ } else {
++ retval = IOH_CAN_SUCCESS;
++ }
++ }
++
++ }
++
++ if (in != NULL)
++ kfree(in);
++ if (out != NULL)
++ kfree(out);
++
++ IOH_DEBUG("ioh_can_ioctl returns %d.\n", retval);
++ return retval;
++}
++
++/*! @ingroup InterfaceLayerAPI
++ @fn static void can_ioctl_buff_size(
++ unsigned int ctl_code,size_t *in_size,size_t *out_size)
++ @brief Calculates the size of memory required for the IN and
++ OUT arguments of a
++ specific ioctl command.
++ @remarks This function is used to obtain the size of the memory
++ space required to store the data for a
++ particular IOCTL
++ command.
++ @note For an invalid IOCTL command this function returns IN
++ and
++ OUT size as 0.
++
++ @param ctl_code [@ref IN] The ioctl command.
++ @param in_size [@ref OUT] The size of the IN argument.
++ @param out_size [@ref OUT] The size of the OUT argument.
++
++ @retval None
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++static void can_ioctl_buff_size(unsigned int ctl_code, size_t *in_size,
++ size_t *out_size)
++{
++ *in_size = 0;
++ *out_size = 0;
++
++ switch (ctl_code) {
++
++ case IOCTL_CAN_SIMPLE:
++ *in_size = sizeof(enum ioh_can_baud);
++ break;
++
++ case IOCTL_CAN_CUSTOM:
++ *in_size = sizeof(struct ioh_can_timing);
++ break;
++
++ case IOCTL_CAN_FILTER:
++ *in_size = sizeof(struct ioh_can_rx_filter);
++ break;
++
++ case IOCTL_CAN_RUN_GET:
++ *out_size = sizeof(enum ioh_can_run_mode);
++ break;
++
++ case IOCTL_CAN_TIMING_GET:
++ *out_size = sizeof(struct ioh_can_timing);
++ break;
++
++ case IOCTL_CAN_FILTER_GET:
++ *out_size = sizeof(struct ioh_can_rx_filter);
++ *in_size = sizeof(struct ioh_can_rx_filter);
++ break;
++
++ case IOCTL_CAN_BLOCK_GET:
++ *out_size = sizeof(unsigned int);
++ break;
++
++ case IOCTL_CAN_LISTEN_GET:
++ *out_size = sizeof(enum ioh_can_listen_mode);
++ break;
++
++ case IOCTL_CAN_ARBITER_GET:
++ *out_size = sizeof(enum ioh_can_arbiter);
++ break;
++
++ case IOCTL_CAN_ERROR_STATS_GET:
++ *out_size = sizeof(struct ioh_can_error);
++ break;
++
++ case IOCTL_CAN_RESTART_MODE_GET:
++ *out_size = sizeof(enum ioh_can_auto_restart);
++ break;
++
++ case IOCTL_CAN_BUFFER_LINK_SET:
++ case IOCTL_CAN_BUFFER_LINK_CLEAR:
++ case IOCTL_CAN_RX_ENABLE_SET:
++ case IOCTL_CAN_RX_ENABLE_CLEAR:
++ case IOCTL_CAN_TX_ENABLE_SET:
++ case IOCTL_CAN_TX_ENABLE_CLEAR:
++ *in_size = sizeof(unsigned int);
++ break;
++
++ case IOCTL_CAN_BUFFER_LINK_GET:
++ case IOCTL_CAN_RX_ENABLE_GET:
++ case IOCTL_CAN_TX_ENABLE_GET:
++ *in_size = sizeof(unsigned int);
++ *out_size = sizeof(unsigned int);
++ break;
++
++ default:
++ break;
++ }
++
++ IOH_DEBUG("can_ioctl_buff_size -> In size: %u "
++ "Out Size: %u.\n", *in_size, *out_size);
++ IOH_DEBUG("can_ioctl_buff_size -> Invoked successfully.\n");
++}
+diff -urN linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_main.h topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_main.h
+--- linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_main.h 1970-01-01 09:00:00.000000000 +0900
++++ topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_main.h 2010-03-10 08:57:34.000000000 +0900
+@@ -0,0 +1,826 @@
++/*!
++ * @file ioh_can_main.h
++ * @brief Provides the function declarations for CAN driver methods.
++ * @version 1.0
++ * @section
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * <hr>
++ */
++
++/*
++ * History:
++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
++ * All rights reserved.
++ *
++ * created:
++ * WIPRO 03/07/2009
++ * modified:
++ * WIPRO 05/08/2009
++ *
++ */
++
++#ifndef __IOH_CAN_MAIN_H__
++#define __IOH_CAN_MAIN_H__
++
++/*! @defgroup CAN
++ @brief Contains the different utilities used for implementing
++ the CAN module.
++*/
++
++/*! @defgroup Debug
++ @ingroup CAN
++ @brief Group containing the functionalities for debugging
++ the features of the module.
++ @remarks This group defines the functionalities that can be
++ used for debugging the different features of the
++ CAN. The main functionalities are of displaying
++ the
++ debug messages. For normal execution these
++ functionalities are disabled.
++
++ <hr>
++*/
++
++/*! @defgroup Global
++ @ingroup CAN
++ @brief This group describes the global entities within
++ the module.
++ @remarks This group includes all the global data structures
++ used within the modules. These are mainly used
++ to
++ store the device related information, so that it
++ can
++ be used by other functions of the modules.
++
++ <hr>
++*/
++/*! @defgroup PCILayer
++ @ingroup CAN
++ @brief This group describes the PCI layer interface
++ functionalities.
++ @remarks This group contains the functions and data structures
++ that are used to interface the module with PCI
++ Layer
++ subsystem of the Kernel. Most of the data
++ structures
++ and functions used within this group are Kernel
++ provided
++ ones.
++
++ <hr>
++*/
++/*! @defgroup InterfaceLayer
++ @ingroup CAN
++ @brief This group describes the Driver interface
++ functionalities.
++ @remarks This group contains the data structures and functions
++ used
++ to interface the module driver with the kernel
++ subsystem.
++
++ <hr>
++*/
++/*! @defgroup HALLayer
++ @ingroup CAN
++ @brief This group describes the hardware specific
++ functionalities.
++ @remarks This group contains the functions and data structures
++ used
++ by the module to communicate with the hardware.
++ These
++ functions are device specific and designed
++ according to the
++ device specifications.
++
++ <hr>
++*/
++/*! @defgroup Utilities
++ @ingroup CAN
++ @brief This group describes the utility functionalities.
++ @remarks This group contains the functions and data structures
++ used
++ to assist the other functionalities in their
++ operations.
++
++ <hr>
++*/
++
++/*! @defgroup PCILayerAPI
++ @ingroup PCILayer
++ @brief This group contains the API(functions) used as the PCI
++ interface between the Kernel subsystem and the
++ module.
++
++ <hr>
++*/
++
++/*! @defgroup PCILayerFacilitators
++ @ingroup PCILayer
++ @brief This group contains the data structures used by the PCI
++ Layer APIs for their functionalities.
++
++ <hr>
++*/
++
++/*! @defgroup InterfaceLayerAPI
++ @ingroup InterfaceLayer
++ @brief This group contains the API(functions) used as the
++ Driver
++ interface between the Kernel subsystem and the
++ module.
++
++ <hr>
++*/
++/*! @defgroup InterfaceLayerFacilitators
++ @ingroup InterfaceLayer
++ @brief This group contains the data structures used by the
++ Driver
++ interface APIs for their functionalities.
++
++ <hr>
++*/
++
++/*! @defgroup HALLayerAPI
++ @ingroup HALLayer
++ @brief This group contains the APIs(functions) used to interact
++ with
++ the hardware. These APIs act as an interface
++ between the
++ hardware and the other driver functions.
++
++ <hr>
++*/
++
++/*! @defgroup UtilitiesAPI
++ @ingroup Utilities
++ @brief This group contains the APIs(functions) used by other
++ functions
++ in their operations.
++
++ <hr>
++*/
++
++/*! @ingroup InterfaceLayer
++ @def IOH_CAN_MSG_DATA_LEN
++ @brief The length in bytes of the data part of the
++ CAN message object.
++ @note The maximum length of data that a message object
++ contains is 8bytes.
++
++ @see
++ - ioh_can_msg
++
++ <hr>
++*/
++#define IOH_CAN_MSG_DATA_LEN (8) /* CAN Msg data length */
++
++/*! @ingroup InterfaceLayer
++ @struct ioh_can_msg
++ @brief The structure defining the format of the CAN message.
++ @remarks This structure is used by the driver/user to specify
++ the message details. It is used during reading
++ and
++ transmitting of CAN message objects.
++
++ @see
++ - ioh_can_read
++ - ioh_can_write
++ - ioh_can_msg_tx
++ - ioh_can_rx_dequeue
++
++ <hr>
++*/
++struct ioh_can_msg {
++ unsigned short ide; /**< Standard/extended msg */
++ unsigned int id; /**< 11 or 29 bit msg id */
++ unsigned short dlc; /**< Size of data */
++ unsigned char data[IOH_CAN_MSG_DATA_LEN]; /**< Message pay load */
++ unsigned short rtr; /**< RTR message */
++};
++
++/*! @ingroup InterfaceLayer
++ @struct ioh_can_timing
++ @brief This structure defines the fields that are
++ used to define the CAN timing.
++ @remarks This structure is used by the user application
++ to specify the baud timing parameters which are
++ used to calculate the clock rate timing of the
++ CAN device.
++
++ @see
++ - IOCTL_CAN_CUSTOM
++ - IOCTL_CAN_TIMING_GET
++ - ioh_can_set_baud_custom
++ - ioh_can_get_baud
++
++ <hr>
++*/
++struct ioh_can_timing {
++ unsigned int bitrate; /**< Bitrate (kbps) */
++ unsigned int cfg_bitrate; /**< Bitrate */
++ unsigned int cfg_tseg1; /**< Tseg1 */
++ unsigned int cfg_tseg2; /**< Tseg2 */
++ unsigned int cfg_sjw; /**< Sync jump width */
++ unsigned int smpl_mode; /**< Sampling mode */
++ unsigned int edge_mode; /**< Edge R / D */
++};
++
++/*! @ingroup InterfaceLayer
++ @struct ioh_can_error
++ @brief This structure defines the format for a
++ CAN error status.
++ @remarks This structure is used by the driver to
++ specify the CAN device error status to the
++ user.
++
++ @see
++ - IOCTL_CAN_ERROR_STATS_GET
++ - ioh_can_get_error_stats
++ <hr>
++*/
++struct ioh_can_error {
++ unsigned int rxgte96; /**< Rx err cnt >=96 */
++ unsigned int txgte96; /**< Tx err cnt >=96 */
++ unsigned int error_stat; /**< Error state of CAN node
++ 00=error active (normal)
++ 01=error passive
++ 1x=bus off */
++ unsigned int rx_err_cnt; /**< Rx counter */
++ unsigned int tx_err_cnt; /**< Tx counter */
++};
++
++/*! @ingroup InterfaceLayer
++ @struct ioh_can_acc_filter
++ @brief This structure defines the format for specifying
++ the Mask/ID.
++ @remarks This structure is used for specifying the type of
++ ID or Mask (standard/extended).
++
++ @see
++ - ioh_can_rx_filter
++
++ <hr>
++*/
++struct ioh_can_acc_filter {
++ unsigned int id; /**< The id/mask data. */
++ unsigned int id_ext; /**< Standard/extended ID */
++ unsigned int rtr; /**< RTR message */
++};
++
++/*! @ingroup InterfaceLayer
++ @struct ioh_can_rx_filter
++ @brief This structure describes the ACR and AMR filter
++ for an Rx buffer.
++ @remarks This driver is used by the driver/user for specifying
++ the acceptance filter details.
++
++ @see
++ - IOCTL_CAN_FILTER
++ - IOCTL_CAN_FILTER_GET
++ - ioh_can_rx_init_filter
++ - ioh_can_set_rx_filter
++
++ <hr>
++*/
++struct ioh_can_rx_filter {
++ unsigned int num; /**< Filter number */
++ unsigned int umask; /**< UMask value */
++ struct ioh_can_acc_filter amr; /**< Acceptance Mask Reg */
++ struct ioh_can_acc_filter aidr; /**< Acceptance Control Reg */
++};
++
++/*! @ingroup InterfaceLayer
++ @enum ioh_can_listen_mode
++ @brief Identities the valid values for the Active/Listen
++ mode.
++ @remarks These enum constants are used to denote the
++ Active/Listen
++ mode of the CAN device. It is used both by the
++ user and
++ driver for specifying the corresponding mode.
++
++ @see
++ - IOCTL_CAN_LISTEN_GET
++ - ioh_can_set_listen_mode
++ - ioh_can_get_listen_mode
++
++ <hr>
++*/
++enum ioh_can_listen_mode {
++ IOH_CAN_ACTIVE = 0, /**< R/w to/from the CAN */
++ IOH_CAN_LISTEN /**< Only read from the CAN */
++};
++
++/*! @ingroup InterfaceLayer
++ @enum ioh_can_run_mode
++ @brief Identifies the valid values for the Run/Stop mode.
++ @remarks These enum constants are used by the driver and
++ user level application to specify the current
++ state(STOP/RUN) of the CAN device.
++
++ @see
++ - IOCTL_CAN_RUN_GET
++ - ioh_can_set_run_mode
++ - ioh_can_get_run_mode
++
++ <hr>
++*/
++enum ioh_can_run_mode {
++ IOH_CAN_STOP = 0, /**< CAN stopped */
++ IOH_CAN_RUN /**< CAN running */
++};
++
++/*! @ingroup InterfaceLayer
++ @enum ioh_can_arbiter
++ @brief Identifies the valid values for the arbitration mode.
++ @remarks These enum constants are used by the driver/user to
++ specify the arbitration/priority mode of the CAN
++ device.
++
++ @see
++ - IOCTL_CAN_ARBITER_GET
++ - ioh_can_set_arbiter_mode
++ - ioh_can_get_arbiter_mode
++
++ <hr>
++*/
++enum ioh_can_arbiter {
++ IOH_CAN_ROUND_ROBIN = 0, /**< Equal priority */
++ IOH_CAN_FIXED_PRIORITY /**< Buffer num priority */
++};
++
++/*! @ingroup InterfaceLayer
++ @enum ioh_can_auto_restart
++ @brief Identifies the valid values for the auto-restart mode.
++ @remarks These enum constants are used by the driver/user to
++ specify the restart mode of the CAN device.
++ @note If the restart mode is CAN_AUTO, the CAN device will
++ automatically recover from the BUS-OFF stage.
++ Else
++ the user would have to manually perform the
++ required
++ procedures.
++
++ @see
++ - IOCTL_CAN_RESTART_MODE_GET
++ - ioh_can_set_restart_mode
++ - ioh_can_get_restart_mode
++
++ <hr>
++*/
++enum ioh_can_auto_restart {
++ CAN_MANUAL = 0, /**< Manual restart */
++ CAN_AUTO /**< Automatic restart */
++};
++
++/*! @ingroup InterfaceLayer
++ @enum ioh_can_baud
++ @brief Identifies common baud rates.
++ @remarks These enum constants are used by the driver/user to
++ denote the standard baud rates used by the CAN
++ device.
++
++ @see
++ - IOCTL_CAN_SIMPLE
++ - ioh_can_set_baud_simple
++
++ <hr>
++*/
++enum ioh_can_baud {
++ IOH_CAN_BAUD_10 = 0, /**< 10 kbps */
++ IOH_CAN_BAUD_20, /**< 20 kbps */
++ IOH_CAN_BAUD_50, /**< 50 kbps */
++ IOH_CAN_BAUD_125, /**< 125 kbps */
++ IOH_CAN_BAUD_250, /**< 250 kbps */
++ IOH_CAN_BAUD_500, /**< 500 kbps */
++ IOH_CAN_BAUD_800, /**< 800 kbps */
++ IOH_CAN_BAUD_1000 /**< 1000 kbps */
++};
++
++/*! @ingroup InterfaceLayer
++ @enum ioh_can_interrupt
++ @brief Identifies interrupt enables/disables.
++ @remarks These enum constants are used by the driver
++ to enable/disable the different combination
++ of the interrupts supported by the CAN device.
++
++ @see
++ - ioh_can_set_int_enables
++
++ <hr>
++*/
++enum ioh_can_interrupt {
++ CAN_ENABLE, /**< Enable IE bit only */
++ CAN_DISABLE, /**< Disable IE bit only */
++ CAN_ALL, /**< All ints */
++ CAN_NONE /**< No ints */
++};
++
++/*! @ingroup InterfaceLayer
++ @def MAGIC
++ @brief The one byte constant used for the generation
++ of IOCTL commands.
++
++ <hr>
++*/
++#define MAGIC (0x88)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_RESET
++ @brief The IOCTL command for CAN reset.
++
++ @see
++ - ioh_can_ioctl
++ <hr>
++*/
++#define IOCTL_CAN_RESET _IO(MAGIC, 0)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_RUN
++ @brief The IOCTL command for setting the CAN in either RUN
++ mode.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_RUN _IO(MAGIC, 1)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_STOP
++ @brief The IOCTL command for setting the CAN in either STOP
++ mode.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_STOP _IO(MAGIC, 2)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_RUN_GET
++ @brief The IOCTL command to get the current mode (RUN/STOP) of
++ the CNA device.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_RUN_GET _IOR(MAGIC, 3, enum ioh_can_run_mode)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_FILTER
++ @brief The IOCTL command for setting the filter for a receive
++ buffer.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_FILTER _IOW(MAGIC, 4, struct ioh_can_rx_filter)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_FILTER_GET
++ @brief The IOCTL command for getting the current filter
++ settings
++ of a receive buffer.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_FILTER_GET _IOR(MAGIC, 5, struct ioh_can_rx_filter)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_CUSTOM
++ @brief The IOCTL command for setting the user specified time
++ settings for the CAN device.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_CUSTOM _IOW(MAGIC, 6, struct ioh_can_timing)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_SIMPLE
++ @brief The IOCTL command for setting the standard time settings
++ for the CAN device.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_SIMPLE _IOW(MAGIC, 7, enum ioh_can_baud)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_TIMING_GET
++ @brief The IOCTL command for getting the current CAN time
++ settings.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_TIMING_GET _IOR(MAGIC, 8, struct ioh_can_timing)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_BLOCK
++ @brief The IOCTL command for setting the block mode for the CAN
++ device.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_BLOCK _IO(MAGIC, 9)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_NON_BLOCK
++ @brief The IOCTL command for setting the non-block mode for the
++ CAN device.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_NON_BLOCK _IO(MAGIC, 10)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_BLOCK_GET
++ @brief The IOCTL command for getting the current block mode
++ settings
++ for the CAN device operations.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_BLOCK_GET _IOR(MAGIC, 11, u32)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_LISTEN
++ @brief The IOCTL command for setting the CAN device to listen
++ mode.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_LISTEN _IO(MAGIC, 12)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_ACTIVE
++ @brief The IOCTL command for setting the CAN device to active
++ mode.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_ACTIVE _IO(MAGIC, 13)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_LISTEN_GET
++ @brief The IOCTL command for getting the current listen mode of
++ the
++ CAN device.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_LISTEN_GET _IOR(MAGIC, 14, enum ioh_can_listen_mode)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_ARBITER_ROUND_ROBIN
++ @brief The IOCTL command to set the arbiter priority mode as
++ ROUND
++ ROBIN
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_ARBITER_ROUND_ROBIN _IO(MAGIC, 15)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_ARBITER_FIXED_PRIORITY
++ @brief The IOCTL command to set the arbiter priority mode as
++ FIXED
++ PRIORITY.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_ARBITER_FIXED_PRIORITY _IO(MAGIC, 16)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_ARBITER_GET
++ @brief The IOCTL command for getting the currently set arbiter
++ priority mode.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_ARBITER_GET _IOR(MAGIC, 17, enum ioh_can_arbiter)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_ERROR_STATS_GET
++ @brief The IOCTL command for getting the current error status
++ of the
++ CAN device.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_ERROR_STATS_GET _IOR(MAGIC, 18, struct ioh_can_error)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_BUFFER_LINK_CLEAR
++ @brief The IOCTL command to clear the link mode of a receive
++ buffer.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_BUFFER_LINK_CLEAR _IOW(MAGIC, 20, u32)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_BUFFER_LINK_GET
++ @brief The IOCTL command for getting the current link mode
++ settings
++ of a receive buffer.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_BUFFER_LINK_GET _IOWR(MAGIC, 21, u32)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_RX_ENABLE_SET
++ @brief The IOCTL command for enabling a receive buffer.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_RX_ENABLE_SET _IOW(MAGIC, 22, u32)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_RX_ENABLE_CLEAR
++ @brief The IOCTL command for disabling a receive buffer.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_RX_ENABLE_CLEAR _IOW(MAGIC, 23, u32)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_RX_ENABLE_GET
++ @brief The IOCTL command for getting the current enable status
++ of
++ a receive buffer.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_RX_ENABLE_GET _IOWR(MAGIC, 24, u32)
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_TX_ENABLE_SET
++ @brief The IOCTL command for enabling a transmit buffer.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_TX_ENABLE_SET _IOW(MAGIC, 25, u32)
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_TX_ENABLE_CLEAR
++ @brief The IOCTL command for disabling a transmit buffer.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_TX_ENABLE_CLEAR _IOW(MAGIC, 26, u32)
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_TX_ENABLE_GET
++ @brief The IOCTL command for getting the current enable status
++ of a transmit buffer.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_TX_ENABLE_GET _IOWR(MAGIC, 27, u32)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_RESTART_MODE_AUTO
++ @brief The IOCTL command to set the restart mode as AUTO.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_RESTART_MODE_AUTO _IO(MAGIC, 28)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_RESTART_MODE_MANUAL
++ @brief The IOCTL command to set the restart mode as MANUAL.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_RESTART_MODE_MANUAL _IO(MAGIC, 29)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_RESTART_MODE_GET
++ @brief The IOCTL command for getting the currently set restart
++ mode
++ of the CAN device.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_RESTART_MODE_GET _IOR(MAGIC, 30, enum ioh_can_auto_restart)
++
++/*! @ingroup InterfaceLayer
++ @def IOCTL_CAN_BUFFER_LINK_SET
++ @brief The IOCTL command to set the link mode of a receive
++ buffer.
++
++ @see
++ - ioh_can_ioctl
++
++ <hr>
++*/
++#define IOCTL_CAN_BUFFER_LINK_SET _IOW(MAGIC, 19, u32)
++
++/*! @ingroup InterfaceLayer
++ @def IOH_CAN_SUCCESS
++ @brief The value returned by certain functions on success.
++
++ <hr>
++*/
++#define IOH_CAN_SUCCESS (0) /* CAN success return value. */
++
++/*! @ingroup InterfaceLayer
++ @def IOH_CAN_FAIL
++ @brief The value returned by certain functions on failure.
++
++ <hr>
++*/
++#define IOH_CAN_FAIL (-1) /* CAN failure return value. */
++
++#endif /* ifndef __IOH_CAN_H__ */
+diff -urN linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_pci.c topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_pci.c
+--- linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_pci.c 1970-01-01 09:00:00.000000000 +0900
++++ topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_pci.c 2010-03-12 14:10:54.000000000 +0900
+@@ -0,0 +1,1134 @@
++/*!
++ * @file ioh_can_pci.c
++ * @brief Provides the function definition for the PCI Layer APIs.
++ * @version 1.0
++ * @section
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * <hr>
++ */
++
++/*
++ * History:
++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
++ * All rights reserved.
++ *
++ * created:
++ * WIPRO 03/07/2009
++ * modified:
++ * WIPRO 05/08/2009
++ *
++ */
++
++/* includes */
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/pci.h>
++#include <linux/cdev.h>
++#include <linux/fs.h>
++#include <linux/io.h>
++#include <linux/wait.h>
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++#include "pch_common.h"
++#include "pch_debug.h"
++#include "pch_can_main.h"
++#include "pch_can_hal.h"
++#include "pch_can_pci.h"
++
++MODULE_DESCRIPTION("Controller Area Network Driver");
++MODULE_LICENSE("GPL");
++MODULE_VERSION("0.94");
++
++/*** Module parameter variables ***/
++
++/*! @ingroup Global
++ @var ioh_can_rx_buf_size
++ @brief The number of message objects that has to be configured
++ as receive
++ objects.
++ @note The value can be specified during the loading of the
++ module. The default value is 16.
++
++ <hr>
++ */
++unsigned int ioh_can_rx_buf_size = 16;
++
++/*! @ingroup Global
++ @var ioh_can_tx_buf_size
++ @brief The number of message objects that has to be configured
++ as transmit
++ objects.
++ @note The value can be specified during the loading of the
++ module. The default value is 16.
++
++ <hr>
++ */
++unsigned int ioh_can_tx_buf_size = 16;
++
++/*! @ingroup Global
++ @var ioh_can_clock
++ @brief The clock rate frequency in KHz.
++ @note The value can be specified during the loading of the
++ module. The default value is 62500KHz (62.5MHz).
++ @see
++ - ioh_can_pci_init
++
++ <hr>
++ */
++#ifndef FPGA_BOARD
++int ioh_can_clock = 50000;
++#else
++int ioh_can_clock = 62500;
++#endif
++
++/*! @ingroup Global
++ @var major
++ @brief The major number to be allocated to the device driver.
++ @note The value can be specified during the loading of the
++ module. If no value is specified the default value is
++ 0 and the major number would be allocated dynamically.
++ @see
++ - ioh_can_probe
++
++ <hr>
++*/
++static int major;
++/*******/
++
++/*** global variables ***/
++/*! @ingroup Global
++ @var MODULE_NAME
++ @brief The name of the module.
++ @note This variable denotes the module name which is displayed
++ along
++ with the debug messages during logging of debug
++ messages.
++
++ <hr>
++*/
++#define MODULE_NAME "pch_can"
++/*! @ingroup Global
++ @var can_os
++ @brief The global variable used to store the device
++ information.
++ @note This variable is used to store the device specific
++ information,
++ that can be used by other module functions in
++ their course of operations.
++
++ <hr>
++*/
++struct ioh_can_os can_os[MAX_CAN_DEVICES];
++
++/********/
++
++/*** static variables *****/
++
++/*! @ingroup Global
++ @var ioh_can_major
++ @brief The global variable used to store the major number of
++ the device driver.
++ @note This variable is used to store the major number of the
++ device driver. If the major number is allocated
++ dynamically
++ then the kernel provided major number is stored
++ in it. During
++ static allocation the unique major number is
++ calculated with
++ the user provided major number and stored in it.
++
++ @see
++ - ioh_can_probe
++ - ioh_can_remove
++
++ <hr>
++*/
++static dev_t ioh_can_major; /* Device variable used to calculate the major
++ number. */
++
++/*! @ingroup Global
++ @var ioh_can_dev
++ @brief The global variable used to store the device driver
++ information.
++ @note This variable is used to store the device driver
++ specific information.
++ It is used during the registration of the device
++ driver.
++
++ @see
++ - ioh_can_probe
++ - ioh_can_remove
++
++ <hr>
++*/
++static struct cdev ioh_can_dev; /* char device reg'd by the driver */
++
++/*******/
++
++/*** Defining as module parameter. ***/
++
++module_param_named(major, major, int, 444);
++module_param_named(ioh_can_rx_buf_size, ioh_can_rx_buf_size, int, 444);
++module_param_named(ioh_can_tx_buf_size, ioh_can_tx_buf_size, int, 444);
++module_param_named(ioh_can_clock, ioh_can_clock, int, 444);
++
++/*****/
++
++/*** Function prototypes. ***/
++
++static int ioh_can_probe(struct pci_dev *dev, const struct pci_device_id *id);
++static void ioh_can_remove(struct pci_dev *dev);
++static int ioh_can_suspend(struct pci_dev *dev, pm_message_t state);
++static int ioh_can_resume(struct pci_dev *dev);
++static void ioh_can_shutdown(struct pci_dev *dev);
++
++/*****/
++
++/*! @ingroup PCILayerFacilitators
++ @struct ioh_can_pcidev_id
++ @brief Instance of Linux Kernel structure pci_device_id for
++ specifying the Vendor
++ and deviceID of the supported PCI device.
++ @remarks
++ This structure is the instance of the linux
++ kernel provided structure
++ pci_device_id. It is used to register the
++ vendor and device ID
++ of the PCI device with the kernel subsystem.
++ This structure is used by the kernel for module
++ registration for the
++ appropriate device during the device
++ recognization(probing). In short
++ it describes the devices for which this module
++ can be used. It forms
++ a part of the large structure
++ @ref ioh_can_pcidev used for module registration.
++ @note This driver is used as a part of another structure
++ @ref ioh_can_pcidev
++ @see
++ - ioh_can_pcidev
++ <hr>
++*/
++static const struct pci_device_id ioh_can_pcidev_id[] __devinitdata = {
++ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOH1_CAN)},
++ {}
++};
++
++MODULE_DEVICE_TABLE(pci, ioh_can_pcidev_id);
++
++/*! @ingroup PCILayerFacilitators
++ @struct ioh_can_pcidev
++ @brief Instance of the Linux Kernel structure pci_driver for
++ specifying the PCI Driver features to the
++ kernel subsystem.
++ @remarks
++ This structure is the instance of the Linux
++ kernel provided structure
++ pci_driver. It is used to register the PCI
++ driver features with the kernel subsystem.
++ This structure specifies the PCI driver features
++ such as the Name
++ of the Module, Entry point, Exit point and Power
++ Management functions for the driver.
++ @note This structure is used only during the registration and
++ un-registration of the PCI driver.
++ @see
++ - ioh_can_pci_init
++ - ioh_can_pci_exit
++ <hr>
++*/
++static struct pci_driver ioh_can_pcidev = {
++ .name = "ioh_can",
++ .id_table = ioh_can_pcidev_id,
++ .probe = ioh_can_probe,
++ .remove = __devexit_p(ioh_can_remove),
++#ifdef CONFIG_PM
++ .suspend = ioh_can_suspend,
++ .resume = ioh_can_resume,
++#endif
++ .shutdown = ioh_can_shutdown
++};
++
++/*! @ingroup PCILayerAPI
++ @fn static int ioh_can_pci_init(void)
++ @brief This function registers the module as a PCI Driver.
++ @remarks
++ This function is invoked during the loading of
++ the module. The main
++ tasks performed by this function are.
++ - Evaluates the validity of the parameter passed
++ during loading.
++ - Validates whether the obtained clock frequency
++ is valid.
++ - Registers the module as PCI driver module.
++
++ @note This function is called during the loading of the
++ device.
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> The loading of the
++ module successful.
++ - @ref IOH_CAN_FAIL --> The loading
++ of the module failed due to invalid
++ module parameters or invlaid clock frequency.
++ - -EEXIST --> pci_register_driver failed.
++ - -EINVAL --> pci_register_driver failed.
++ - -ENOMEM --> pci_register_driver failed.
++ <hr>
++*/
++static int __init ioh_can_pci_init(void)
++{
++ int retval;
++
++ IOH_DEBUG("ioh_can_pci_init -> Obtained parameters: \n"
++ "ioh_can_tx_buf_size = %d\n"
++ "ioh_can_rx_buf_size = %d\n"
++ "ioh_can_clock = %d\n"
++ "major = %d\n", ioh_can_tx_buf_size,
++ ioh_can_rx_buf_size, ioh_can_clock, major);
++
++ /* Checking if the total message objects to be used exceeds
++ the supported message object available and whether the obtained
++ clock frequency is greater than 0. */
++ if (((ioh_can_tx_buf_size + ioh_can_rx_buf_size) <= MAX_MSG_OBJ)
++ && (ioh_can_clock > 0)) {
++
++ /* Checking the validity of the clock variable. */
++ switch (ioh_can_clock) {
++ /* List of valid clock frequency
++ Add new clock frequency here
++ for validation.
++ */
++ case 62500:
++ case 24000:
++ case 50000:
++ retval = IOH_CAN_SUCCESS;
++ break;
++
++ default:
++ IOH_LOG(KERN_ERR,
++ "ioh_can_pci_init -> Invalid clock frequency "
++ "%u", ioh_can_clock);
++ retval = IOH_CAN_FAIL;
++ }
++
++ if (IOH_CAN_SUCCESS == retval) {
++
++ /* Register as a PCI driver. */
++ retval = pci_register_driver(&ioh_can_pcidev);
++
++ /* Registeration unsuccessful. */
++ if (0 != retval) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_pci_init -> \
++ pci_register_driver failed(returned %d).\n",
++ retval);
++ }
++ /* Registeration successful. */
++ else {
++ IOH_DEBUG
++ ("ioh_can_pci_init -> pci_register_driver \
++ successful(returned %d).\n",
++ retval);
++
++ IOH_DEBUG
++ ("ioh_can_pci_init invoked successfully.\n");
++ }
++ }
++ }
++ /* Message object exceeds the available message object. */
++ else {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_pci_init -> Invalid module parameters.\n\t"
++ "Expected Message objects to be configured <= %d"
++ " and clock frequency expected > 0\n", MAX_MSG_OBJ);
++
++ retval = IOH_CAN_FAIL;
++ }
++
++ IOH_DEBUG("ioh_can_pci_init returns %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup PCILayerAPI
++ @fn static int ioh_can_pci_exit(void)
++ @brief Un-registers the PCI Driver.
++ @note This function is called by the kernel subsystem during
++ unloading
++ of the module.
++ @remarks
++ This function is invoked when the module is
++ unloaded from the
++ kernel subsystem. The main tasks performed by
++ this function are.
++ - Un-registers the PCI Driver.
++
++ @retval None.
++
++ <hr>
++*/
++static void __exit ioh_can_pci_exit(void)
++{
++ /* Unregistering the registered PCI Driver. */
++ pci_unregister_driver(&ioh_can_pcidev);
++ IOH_DEBUG
++ ("ioh_can_pci_exit -> pci_unregister_driver invoked successfully.\n");
++
++ IOH_DEBUG("ioh_can_pci_exit invoked successfully. \n");
++}
++
++/*! @ingroup PCILayerAPI
++ @fn static int __devinit ioh_can_probe(
++ struct pci_dev *pdev, const struct pci_device_id *id)
++ @brief Implements the probe functionalities of the PCI Driver.
++ @remarks
++ This function is used as the probe function of
++ the PCI Driver.
++ The main tasks performed by this function are:
++ - Enables the PCI device and other associated
++ features such as interrupts.
++ - Attains the remapped section corresponding to
++ the device for user interaction.
++ - Registers a character device driver for
++ accessing the device.
++ - Initializes the driver specific data
++ structures for use by
++ other functions of the driver.
++ @note This function is called by the kernel subsystem only
++ when a supported PCI device has been detected.
++
++ @param pdev [@ref INOUT] Reference to the PCI
++ device descriptor.
++ @param id [@ref IN] Reference to the
++ supported PCI Device IDs
++ table.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> Probe has been
++ successful.
++ - @ref IOH_CAN_FAIL --> Probe operation
++ failed.
++ - -EIO --> pci_enable_device error
++ status code.
++ - -EINVAL --> pci_enable_device error
++ status code.
++ - -EBUSY --> pci_request_regions/
++ alloc_chrdev_region/
++ register_chrdev_region error status code.
++ - -ENOMEM --> pci_iomap fails/
++ alloc_chrdev_region/
++ register_chrdev_region/cdev_add error status
++ code.
++ - -ENODEV --> pci_iomap error status code.
++
++ @see
++ - ioh_can_pcidev
++
++ <hr>
++*/
++static int __devinit ioh_can_probe(struct pci_dev *pdev,
++ const struct pci_device_id *id)
++{
++ unsigned int can_num = 0; /* Variable to denote the CAN
++ structure index. */
++ int resources_allocated = false; /* Flag variables for denting
++ resource allocation. */
++ int driver_registered = false; /* Flag variable to denote driver
++ registration. */
++ int retval = IOH_CAN_SUCCESS; /* Variable storing the return
++ status value. */
++
++ {
++ do {
++ /* Enable the PCI device */
++ retval = pci_enable_device(pdev);
++ if (0 != retval) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_probe -> pci_enable_device failed"
++ "(returned %d).\n", retval);
++ IOH_DEBUG
++ ("ioh_can_probe -> Couldn't enable PCI device "
++ "with Vendor ID:0x%x and Device ID:0x%x. "
++ "Exiting\n", pdev->vendor, pdev->device);
++
++ break;
++ }
++ IOH_DEBUG
++ ("ioh_can_probe -> Enable PCI device successful"
++ "(returned %d).\n", retval);
++
++ /* Request the PCI regions. */
++ retval = pci_request_regions(pdev, DRIVER_NAME);
++ if (0 != retval) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_probe -> pci_request_regions "
++ "failed(returned %d).\n", retval);
++ break;
++ }
++ IOH_DEBUG
++ ("ioh_can_probe -> pci_request_regions successful"
++ "(returned %d).\n", retval);
++ resources_allocated = true;
++
++ /* Remap the PCI user space regions to kernel space. */
++ /* Wipro 1/13/2010 Use Mem BAR */
++ can_os[can_num].pci_remap =
++ (unsigned long)pci_iomap(pdev, 1, 0);
++ if (0 == can_os[can_num].pci_remap) {
++ IOH_LOG(KERN_ERR,
++ "pci_iomap failed(returned 0).\n");
++ retval = -ENOMEM;
++ break;
++ }
++ IOH_DEBUG
++ ("ioh_can_probe -> \
++ pci_iomap successful. Remap address: "
++ "%lu\n", can_os[can_num].pci_remap);
++
++ /* If major number is not given as module parameter. */
++ if (major == 0) {
++ /* Registering the driver. */
++ retval = alloc_chrdev_region(
++ &ioh_can_major, 0, 1, DRIVER_NAME);
++ if (0 != retval) {
++
++ IOH_LOG(KERN_ERR,
++ "ioh_can_probe -> alloc_chrdev_region "
++ "failed(returned %d).\n",
++ retval);
++ break;
++ }
++ IOH_DEBUG
++ ("ioh_can_probe -> alloc_chrdev_region \
++ successful"
++ "(returned %d).\n", retval);
++ } else { /* If major number is provided as module
++ parameter. */
++
++ /* Attaining a device id. */
++ ioh_can_major = MKDEV(major, 0);
++
++ /* Registering the driver. */
++ retval = register_chrdev_region(
++ ioh_can_major, 1, DRIVER_NAME);
++ if (0 != retval) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_probe -> \
++ register_chrdev_region "
++ "failed(returned %d).\n",
++ retval);
++ break;
++ }
++ IOH_DEBUG
++ ("ioh_can_probe -> register_chrdev_region \
++ successful"
++ "(returned %d).\n", retval);
++ }
++
++ /* Initializing the cdev structure. */
++ cdev_init(&ioh_can_dev, &file_ops);
++ ioh_can_dev.owner = THIS_MODULE;
++ ioh_can_dev.ops = &file_ops;
++
++ /* Adding the device to the system. */
++ retval = cdev_add(&ioh_can_dev, ioh_can_major, 1);
++ if (0 != retval) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_probe -> cdev_add failed"
++ "(returned %d).\n", retval);
++ unregister_chrdev_region(ioh_can_major, 1);
++ IOH_DEBUG
++ ("ioh_can_probe -> unregister_chrdev_region \
++ invoked successfully.\n");
++ break;
++ }
++ IOH_DEBUG
++ ("ioh_can_probe -> cdev_add successful(returned %d).\n",
++ retval);
++ driver_registered = true;
++
++ /* Filling in the details of the CAN into the can
++ structure. */
++ can_os[can_num].can_num = can_num; /* Can number
++ (index to the structure) */
++ can_os[can_num].irq = pdev->irq; /* IRQ allocated
++ to this device. */
++
++ /* Creating the device handle denoting the remap base
++ address. */
++ can_os[can_num].can =
++ ioh_can_create((void *)can_os[can_num].pci_remap);
++
++ /* If handle creation fails. */
++ if ((int) NULL == can_os[can_num].can) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_probe -> ioh_can_create failed.\n");
++ retval = IOH_CAN_FAIL;
++ break;
++ }
++ IOH_DEBUG
++ ("ioh_can_probe -> ioh_can_create successful.\n");
++
++ can_os[can_num].dev = pdev; /* Reference to
++ pci_device structure. */
++ can_os[can_num].opened = 0; /* Open flag denoting
++ the device usage. */
++ can_os[can_num].is_suspending = 0; /* Flag denoting
++ the suspend stage. */
++
++ /* Initializing the wait queues. */
++ init_waitqueue_head(&(can_os[can_num].read_wait_queue));
++ init_waitqueue_head(&
++ (can_os[can_num].write_wait_queue));
++
++ /* Initailzing the lock variables. */
++ spin_lock_init(&(can_os[can_num].open_spinlock));
++ spin_lock_init(&(can_os[can_num].tx_spinlock));
++ /* OKISEMI 090721 add */
++
++ /* Storing the reference to the structure for
++ use in other PCI functions.
++ */
++/* pdev->dev.driver_data = (void *)&(can_os[can_num]); */
++ dev_set_drvdata(&pdev->dev, (void *)&(can_os[can_num]));
++
++ {
++ /* Initializing the message object array to
++ identify the
++ objects used as receive and transmit
++ object.
++ According to this logic, the initial
++ objects will be
++ configured as receive objects followed by
++ transmit objects.
++
++ For example.
++ 1) Receive Object(R) : 16
++ Transmit Object(T): 16
++ -----------------------------------------------------------------
++ |R|R|R|R|R|R|R|R|R|R|R|R|R|R|R|R|T|T|T|T|T|T|T|T|T|T|T|T|T|T|T|T|
++ -----------------------------------------------------------------
++
++ 2) Receive Object(R) : 6
++ Transmit Object(T): 12
++ -----------------------------------------------------------------
++ |R|R|R|R|R|R|T|T|T|T|T|T|T|T|T|T|T|T|N|N|N|N|N|N|N|N|N|N|N|N|N|N|
++ -----------------------------------------------------------------
++
++ 3) Receive Object(R) : 18
++ Transmit Object(T): 5
++ -----------------------------------------------------------------
++ |R|R|R|R|R|R|R|R|R|R|R|R|R|R|R|R|R|R|T|T|T|T|T|N|N|N|N|N|N|N|N|N|
++ -----------------------------------------------------------------
++
++ The above figure shows 32 message object
++ starting from message object 1
++ to object 32, being used according to the
++ user specified receive and
++ transmit message object number.
++
++ Here R -> used as receive object.
++ T -> used as transmit object.
++ N -> not used.
++ */
++
++ int index;
++
++ for (index = 0; index < ioh_can_rx_buf_size;
++ index++) {
++ ioh_msg_obj_conf[index] = MSG_OBJ_RX;
++ }
++
++ for (index = index;
++ index <
++ (ioh_can_rx_buf_size +
++ ioh_can_tx_buf_size); index++) {
++ ioh_msg_obj_conf[index] = MSG_OBJ_TX;
++ }
++
++ }
++
++ retval = IOH_CAN_SUCCESS;
++ IOH_DEBUG("ioh_can_probe successful.\n");
++ } while (false);
++
++ /* If any of the process fails. */
++ if (IOH_CAN_SUCCESS != retval) {
++ /* If the resources are allocated. */
++ if (true == resources_allocated) {
++ if (0 != can_os[can_num].pci_remap) {
++ pci_iounmap(pdev,
++ (void *)can_os[can_num].
++ pci_remap);
++ IOH_DEBUG("ioh_can_probe -> "
++ "pci_iounmap invoked successfully.\n");
++ can_os[can_num].pci_remap = 0;
++ }
++
++ pci_release_regions(pdev);
++ IOH_DEBUG("ioh_can_probe -> "
++ "pci_release_regions invoked successfully.\n");
++ }
++
++ /* If driver has been registered. */
++ if (true == driver_registered) {
++ cdev_del(&ioh_can_dev);
++ IOH_DEBUG("ioh_can_probe -> "
++ "cdev_del invoked successfully.\n");
++ unregister_chrdev_region(ioh_can_major, 1);
++ IOH_DEBUG("ioh_can_probe -> "
++ "unregister_chrdev_region \
++ invoked successfully.\n");
++ }
++
++ pci_disable_device(pdev);
++ IOH_DEBUG("ioh_can_probe -> "
++ "pci_disable_region invoked successfully.\n");
++
++ IOH_DEBUG("ioh_can_probe failed.\n");
++ }
++
++ }
++
++ /* If probe fails retval contains the status code of the failed API.
++ If it is successful it contains IOH_CAN_SUCCESS(0).
++ */
++ IOH_DEBUG("ioh_can_probe returns %d\n", retval);
++ return retval;
++}
++
++/*! @ingroup PCILayerAPI
++ @fn static void __devexit ioh_can_remove(
++ struct pci_dev *pdev)
++ @brief Implements the remove functionalities of the PCI Driver.
++ @remarks
++ This function is used as the remove function of
++ the PCI Driver.
++ The main tasks performed by this function
++ include :
++ - Un-maps the remapped user space from kernel
++ space.
++ - Releases all the resources attained during
++ probe.
++ - Un-registers the character device driver
++ registered during probe.
++ @note This function is called by the kernel subsystem when the
++ supported
++ PCI device is removed/unloaded.
++
++ @param pdev [@ref INOUT] Reference to the PCI
++ device descriptor.
++
++ @retval None.
++
++ @see
++ - ioh_can_pcidev
++
++ <hr>
++*/
++static void __devexit ioh_can_remove(struct pci_dev *pdev)
++{
++/* struct ioh_can_os *can_os = pdev->dev.driver_data; */
++ struct ioh_can_os *can_os = \
++ (struct ioh_can_os *) dev_get_drvdata(&pdev->dev);
++
++ /* Unmapping the remmaped user space from kernel space. */
++ pci_iounmap(pdev, (void *)can_os->pci_remap);
++ IOH_DEBUG("ioh_can_remove -> pci_iounmap invoked successfully.\n");
++
++ /* Releasing the driver specific resources. */
++ ioh_can_destroy(can_os->can);
++ IOH_DEBUG("ioh_can_remove -> ioh_can_destroy invoked successfully.\n");
++
++ /* Releasing the acquired resources. */
++ pci_release_regions(pdev);
++ IOH_DEBUG
++ ("ioh_can_remove -> pci_release_regions invoked successfully.\n");
++
++ /* Removing the device */
++ cdev_del(&ioh_can_dev);
++ IOH_DEBUG("ioh_can_remove -> cdev_del invoked successfully.\n");
++
++ /* Unregistering the driver. */
++ unregister_chrdev_region(ioh_can_major, 1);
++ IOH_DEBUG
++ ("ioh_can_remove -> unregister_chrdev_region invoked successfully.\n");
++
++ /* disabling the device. */
++ pci_disable_device(pdev);
++ IOH_DEBUG
++ ("ioh_can_remove -> pci_disable_device invoked successfully.\n");
++}
++
++#ifdef CONFIG_PM
++/*! @ingroup PCILayerAPI
++ @fn static int ioh_can_suspend(struct pci_dev *pdev,
++ pm_message_t state)
++ @brief Implements the suspend functionalities of the PCI
++ Driver.
++ @remarks
++ This function is used as the suspend function of
++ the PCI driver.
++ The main tasks performed by this function are :
++ - Manipulates the power management of the
++ supported device during
++ system suspension.
++ - Maintains the crucial device data, so that the
++ state of the system
++ can be maintained during resumption.
++ @note This function is called by the Kernel Power Management
++ subsystem during system suspend operation.
++
++ @param pdev [@ref INOUT] Reference to the PCI
++ Device descriptor.
++ @param state [@ref IN] The state of the
++ PCI Device.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> The suspend
++ process was successful.
++ - -ENOMEM --> pci_save_state error status code
++
++ @see
++ - ioh_can_pci_dev
++
++ <hr>
++*/
++static int ioh_can_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++ int i; /* Counter variable. */
++ int retval; /* Return value. */
++/* struct ioh_can_os *can_os = pdev->dev.driver_data; */
++ struct ioh_can_os *can_os = \
++ (struct ioh_can_os *) dev_get_drvdata(&pdev->dev);
++
++ /* If the device is opened get the current run mode. */
++ if (1 == can_os->opened) {
++ /* Save the Run Mode. */
++ (void)ioh_can_get_run_mode(can_os->can, &(can_os->run_mode));
++ }
++
++ /* Stop the CAN controller */
++ (void)ioh_can_set_run_mode(can_os->can, IOH_CAN_STOP);
++
++ /* Indicate that we are aboutto/in suspend */
++ can_os->is_suspending = 1;
++
++ if (1 == can_os->opened) {
++ u32 buf_stat; /* Variable for reading the transmit buffer
++ status. */
++ u32 counter = 0xFFFFFF;
++
++ /*
++ Waiting for all transmission to complete.
++ This is done by checking the TXQST pending
++ register. The loop teriminates when no
++ transmission is pending.
++ */
++ while (counter) {
++ buf_stat = ioh_can_get_buffer_status(can_os->can);
++ if (buf_stat == 0)
++ break;
++
++ counter--;
++ }
++
++ if (counter > 0) {
++ IOH_DEBUG
++ ("ioh_can_suspend -> No transmission is pending.\n");
++ } else {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_suspend -> Transmission time "
++ "out.\n");
++ }
++
++ /* Free any waiting write threads */
++ can_os->write_wait_flag = 1;
++ wake_up_interruptible(&(can_os->write_wait_queue));
++
++ /* Save interrupt configuration and then disable them */
++ (void)ioh_can_get_int_enables(can_os->can,
++ &(can_os->int_enables));
++ (void)ioh_can_set_int_enables(can_os->can, CAN_DISABLE);
++
++ /* Save Tx buffer enable state */
++ for (i = 0; i < (ioh_can_tx_buf_size + ioh_can_rx_buf_size);
++ i++) {
++ if (ioh_msg_obj_conf[i] == MSG_OBJ_TX) {
++ /* Here i is the index, however (i+1) is object
++ number. */
++ (void)ioh_can_get_tx_enable(can_os->can,
++ (i + 1),
++ &(can_os->
++ tx_enable[i]));
++ }
++ }
++
++ /* Disable all Transmit buffers */
++ (void)ioh_can_tx_disable_all(can_os->can);
++
++ /* Save Rx buffer enable state */
++ for (i = 0; i < (ioh_can_tx_buf_size + ioh_can_rx_buf_size);
++ i++) {
++ if (ioh_msg_obj_conf[i] == MSG_OBJ_RX) {
++ /* Here i is the index, however (i+1) is object
++ number. */
++
++ (void)ioh_can_get_rx_enable(can_os->can,
++ (i + 1),
++ &(can_os->
++ rx_enable[i]));
++ (void)ioh_can_get_rx_buffer_link(can_os->can,
++ (i + 1),
++ &(can_os->
++ rx_link[i]));
++
++ /* Save Rx Filters */
++ can_os->rx_filter[i].num = (i + 1);
++ (void)ioh_can_get_rx_filter(can_os->can,
++ &(can_os->
++ rx_filter[i]));
++ }
++ }
++
++ /* Disable all Receive buffers */
++ (void)ioh_can_rx_disable_all(can_os->can);
++
++ /* Save Context */
++ (void)ioh_can_get_baud(can_os->can, &(can_os->timing));
++ /* Timing. */
++ (void)ioh_can_get_listen_mode(can_os->can, \
++ &(can_os->listen_mode));
++ /* Listen mode */
++ (void)ioh_can_get_arbiter_mode(can_os->can, \
++ &(can_os->arbiter_mode));
++ /* Arbiter mode */
++
++ }
++
++ retval = pci_save_state(pdev);
++
++ if (0 != retval) {
++ /* Indicate that we have not suspended */
++ can_os->is_suspending = 0;
++
++ IOH_LOG(KERN_ERR,
++ "ioh_can_suspend -> pci_save_state \
++ failed(returned %d).\n",
++ retval);
++ } else {
++ IOH_DEBUG
++ ("ioh_can_suspend -> pci_save_state successful(returned %d).\n",
++ retval);
++
++ (void)pci_enable_wake(pdev, PCI_D3hot, 0);
++ IOH_DEBUG
++ ("ioh_can_suspend -> pci_enable_wake invoked successfully.\n");
++
++ pci_disable_device(pdev);
++ IOH_DEBUG
++ ("ioh_can_suspend -> pci_disable_device invoked \
++ successfully.\n");
++
++ (void)pci_set_power_state(pdev, pci_choose_state(pdev, state));
++ IOH_DEBUG
++ ("ioh_can_suspend -> pci_set_power_state invoked \
++ successfully.\n");
++ }
++
++ IOH_DEBUG("ioh_can_suspend returns %d.\n", retval);
++ return retval;
++}
++
++/*! @ingroup PCILayerAPI
++ @fn static int ioh_can_resume(struct pci_dev *pdev)
++ @brief Implements the resume functionalities of the PCI Driver.
++ @remarks
++ This function is used as the resume function of
++ the PCI Driver.
++ The main tasks performed by this function
++ includes :
++ - Restores the regular power state of the device
++ to D0.
++ - Restores the same state of the device as that
++ was before
++ suspension.
++ @note This function is invoked by the Kernel Power Management
++ subsystem
++ during system resume operation.
++
++ @param pdev [@ref INOUT] Reference to the PCI
++ device descriptor.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> The resume
++ operation was successful.
++ - -EIO --> pci_enable_device error status code.
++ - -EINVAL --> pci_enable_device error status
++ code.
++ @see
++ - ioh_can_pci_dev
++
++ <hr>
++*/
++static int ioh_can_resume(struct pci_dev *pdev)
++{
++ int i; /* Counter variable. */
++ int retval; /* Return variable. */
++/* struct ioh_can_os *can_os = pdev->dev.driver_data; */
++ struct ioh_can_os *can_os = \
++ (struct ioh_can_os *) dev_get_drvdata(&pdev->dev);
++
++ (void)pci_set_power_state(pdev, PCI_D0);
++ IOH_DEBUG
++ ("ioh_can_resume -> pci_set_power_state invoked successfully.\n");
++
++ (void)pci_restore_state(pdev);
++ IOH_DEBUG
++ ("ioh_can_resume -> pci_restore_state invoked successfully.\n");
++
++ retval = pci_enable_device(pdev);
++ if (0 != retval) {
++ IOH_LOG(KERN_ERR,
++ "ioh_can_resume -> pci_enable_device failed(returned %d).\n",
++ retval);
++ }
++
++ else {
++ IOH_DEBUG
++ ("ioh_can_resume -> pci_enable_device invoked successfully"
++ "(returned %d)\n", retval);
++ (void)pci_enable_wake(pdev, PCI_D3hot, 0);
++
++ /* Disabling all interrupts. */
++ (void)ioh_can_set_int_enables(can_os->can, CAN_DISABLE);
++
++ /* Setting the CAN device in Stop Mode. */
++ (void)ioh_can_set_run_mode(can_os->can, IOH_CAN_STOP);
++
++ /* Configuring the transmit and receive buffers. */
++ ioh_can_config_rx_tx_buffers(can_os->can);
++ IOH_DEBUG
++ ("ioh_can_resume -> ioh_can_config_rx_tx_buffers invoked "
++ "successfully.\n");
++
++ if (1 == can_os->opened) {
++ /* Reset write file operation wait flag */
++ can_os->write_wait_flag = 0;
++
++ /* Restore the CAN state */
++ (void)ioh_can_set_baud_custom(\
++ can_os->can, &(can_os->timing));
++ /*Timing */
++ (void)ioh_can_set_listen_mode(\
++ can_os->can, can_os->listen_mode);
++ /*Listen/Active */
++ (void)ioh_can_set_arbiter_mode(\
++ can_os->can, can_os->arbiter_mode);
++ /*Arbiter mode */
++
++ /* Enabling the transmit buffer. */
++ for (i = 0;
++ i < (ioh_can_tx_buf_size + ioh_can_rx_buf_size);
++ i++) {
++ if (ioh_msg_obj_conf[i] == MSG_OBJ_TX) {
++ /* Here i is the index, however (i+1) is
++ object number. */
++ (void)ioh_can_set_tx_enable(can_os->can,
++ (i + 1),
++ can_os->
++ tx_enable
++ [i]);
++ }
++ }
++
++ /* Configuring the receive buffer and enabling them. */
++ for (i = 0;
++ i < (ioh_can_tx_buf_size + ioh_can_rx_buf_size);
++ i++) {
++ if (ioh_msg_obj_conf[i] == MSG_OBJ_RX) {
++ /* Here i is the index, however (i+1) is
++ object number. */
++
++ /* Restore buffer link */
++ (void)
++ ioh_can_set_rx_buffer_link(can_os->
++ can,
++ (i + 1),
++ can_os->
++ rx_link
++ [i]);
++
++ /* Restore Rx Filters */
++ can_os->rx_filter[i].num = (i + 1);
++ (void)ioh_can_set_rx_filter(can_os->can,
++ &(can_os->
++ rx_filter
++ [i]));
++
++ /* Restore buffer enables */
++ (void)ioh_can_set_rx_enable(can_os->can,
++ (i + 1),
++ can_os->
++ rx_enable
++ [i]);
++ }
++ }
++
++ /* Enable CAN Interrupts */
++ (void)ioh_can_set_int_custom(can_os->can,
++ can_os->int_enables);
++
++ /* Restore Run Mode */
++ (void)ioh_can_set_run_mode(can_os->can,
++ can_os->run_mode);
++ }
++ /*if opened */
++ can_os->is_suspending = 0;
++ } /*else */
++
++ IOH_DEBUG("ioh_can_resume returns %d\n", retval);
++ return retval;
++}
++#endif
++
++/*! @ingroup PCILayerAPI
++ @fn static void ioh_can_shutdown(
++ struct pci_dev * pdev)
++ @brief Implements the shutdown functionalities of the PCI
++ Driver.
++ @remarks
++ This function is used as the shutdown function
++ of the PCI Driver.
++ The main tasks performed by this function
++ include :
++ - Prepare the system to enter the shutdown
++ state.
++ @note This function is called by the kernel subsystem during
++ system shutdown.
++
++ @param pdev [@ref INOUT] Reference to the PCI
++ device descriptor.
++
++ @retval None.
++
++ <hr>
++*/
++static void ioh_can_shutdown(struct pci_dev *pdev)
++{
++ (void)ioh_can_suspend(pdev, PMSG_SUSPEND);
++}
++
++module_init(ioh_can_pci_init);
++module_exit(ioh_can_pci_exit);
+diff -urN linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_pci.h topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_pci.h
+--- linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_pci.h 1970-01-01 09:00:00.000000000 +0900
++++ topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_pci.h 2010-03-10 08:57:34.000000000 +0900
+@@ -0,0 +1,105 @@
++/*!
++ * @file ioh_can_pci.h
++ * @brief Provides the macro definitions used by the PCI Layer APIs.
++ * @version 1.0
++ * @section
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * <hr>
++ */
++
++/*
++ * History:
++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
++ * All rights reserved.
++ *
++ * created:
++ * WIPRO 03/07/2009
++ * modified:
++ * WIPRO 05/08/2009
++ *
++ */
++
++#ifndef __IOH_CAN_PCI_H__
++#define __IOH_CAN_PCI_H__
++
++/* The PCI vendor ID for the CAN device. */
++#ifdef PCI_VENDOR_ID_INTEL
++#undef PCI_VENDOR_ID_INTEL
++#endif
++
++/*! @ingroup PCILayer
++ @def PCI_VENDOR_ID_INTEL
++ @brief The Vendor ID of the supported device.
++ @remarks This ID is used during the registration of the
++ PCI Driver, so that whenever a PCI device with
++ specified Vendor ID is detected the
++ corresponding
++ registered functionalities are invoked.
++ @see
++ - ioh_can_pcidev_id
++
++ <hr>
++*/
++#ifndef FPGA_BOARD
++#define PCI_VENDOR_ID_INTEL (0x8086)
++#else
++#define PCI_VENDOR_ID_INTEL (0x10DB)
++#endif
++
++/* The PCI device ID for the CAN device . */
++/*! @ingroup PCILayer
++ @def PCI_DEVICE_ID_INTEL_IOH1_CAN
++ @brief The Device ID of the supported device.
++ @remarks This ID is used during the registration of the
++ PCI Driver, so that whenever a PCI device with
++ specified Device ID is detected the
++ corresponding
++ registered functionalities are invoked.
++ @see
++ - ioh_can_pcidev_id
++
++ <hr>
++*/
++#ifndef FPGA_BOARD
++#define PCI_DEVICE_ID_INTEL_IOH1_CAN (0x8818)
++#else
++#define PCI_DEVICE_ID_INTEL_IOH1_CAN (0x800A)
++#endif
++
++/* The driver name. */
++/*! @ingroup InterfaceLayer
++ @def DRIVER_NAME
++ @brief The Driver name
++ @see
++ - ioh_can_probe
++
++ <hr>
++*/
++#define DRIVER_NAME "can"
++
++/* external linkage */
++extern unsigned int ioh_msg_obj_conf[MAX_MSG_OBJ]; /* Array denoting the
++ usage of the respective message object. */
++extern struct ioh_can_timing can_rec_timing[]; /* Structure array for different
++ supported timing settings. */
++extern unsigned int ioh_can_rx_buf_size; /* The receive buffer size. */
++extern unsigned int ioh_can_tx_buf_size; /* The transmit buffer size. */
++extern int ioh_can_clock; /* The clock rate. */
++extern struct ioh_can_os can_os[MAX_CAN_DEVICES];
++ /* Structure to store the details of the CAN controller. */
++
++extern const struct file_operations file_ops; /* Structure to register the
++ character device driver. */
++#endif
+diff -urN linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_utils.c topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_utils.c
+--- linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_utils.c 1970-01-01 09:00:00.000000000 +0900
++++ topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_utils.c 2010-03-10 08:57:34.000000000 +0900
+@@ -0,0 +1,397 @@
++/*!
++ * @file ioh_can_utils.c
++ * @brief Provides the function definition for FIFO utility functions.
++ * @version 1.0
++ * @section
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * <hr>
++ */
++
++/*
++ * History:
++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
++ * All rights reserved.
++ *
++ * created:
++ * WIPRO 03/07/2009
++ * modified:
++ * WIPRO 05/08/2009
++ *
++ */
++
++/* includes */
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++
++#include "pch_common.h"
++#include "pch_debug.h"
++#include "pch_can_utils.h"
++
++/*! @ingroup Utilities
++ @struct can_fifo_item
++ @brief This structure describes the FIFO node items.
++ @remarks This structure is used to implement the
++ software FIFO. It describes a particular
++ node within the FIFO chain.
++
++ <hr>
++*/
++struct can_fifo_item {
++ struct ioh_can_msg msg; /**< The msg object */
++ struct can_fifo_item *next; /**< The next pointer. */
++};
++
++/*! @ingroup Utilities
++ @struct can_fifo
++ @brief This structure is used for maintaining the software
++ FIFO chain.
++ @remarks This structure maintains the reference to the FIFO
++ chain. It specifies which node within the FIFO
++ has to be read and written.
++
++ <hr>
++*/
++struct can_fifo {
++ struct can_fifo_item *head; /**< The node where insertion
++ can be done. */
++ struct can_fifo_item *tail; /**< The node where reading can
++ be done. */
++ unsigned int size; /**< The number of FIFO nodes. */
++};
++
++/*! @ingroup UtilitiesAPI
++ @fn int check_can_fifo_status(int handle)
++ @brief Checks the status (Empty/Full/Non-Empty) of the software
++ fifo.
++ @remarks Checks the status (Empty/Full/Non-Empty) of the software
++ fifo.
++ The main tasks performed by this API are :
++ - Checks the software FIFO status and returns
++ the values denoting
++ the status.
++ - The return values along with the specified
++ meaning is described
++ in the Return values Section.
++
++ @param handle [@ref IN] The handle to the device.
++
++ @retval int
++ - @ref IOH_CAN_FIFO_NOT_EMPTY --> FIFO is not empty.
++ - @ref IOH_CAN_FIFO_EMPTY --> FIFO is empty.
++ - @ref IOH_CAN_FIFO_FULL --> FIFO is full.
++
++ @see
++ - ioh_can_read
++
++ <hr>
++
++*/
++int check_can_fifo_status(int handle)
++{
++ int ret_val;
++ struct can_fifo *f = (struct can_fifo *) handle;
++
++ if (f->head == f->tail) {
++ ret_val = IOH_CAN_FIFO_EMPTY; /*FIFO empty */
++ IOH_DEBUG("check_can_fifo_status -> FIFO empty.\n");
++ } else if (f->head->next == f->tail) {
++ ret_val = IOH_CAN_FIFO_FULL; /*FIFO full */
++ IOH_DEBUG("check_can_fifo_status -> FIFO full.\n");
++ } else {
++ ret_val = IOH_CAN_FIFO_NOT_EMPTY; /* FIFO non empty. */
++ IOH_DEBUG("check_can_fifo_status -> FIFO non-empty.\n");
++ }
++
++ IOH_DEBUG("check_can_fifo_status returns %d\n", ret_val);
++ return ret_val;
++}
++
++/*! @ingroup UtilitiesAPI
++ @fn int create_can_fifo(unsigned int fifo_entries)
++ @brief Creates the CAN FIFO.
++ @remarks Creates the CAN FIFO depending on the argument value
++ passed.
++ The main tasks performed by this API are :
++ - Depending on obtained argument value allocates
++ memory for
++ the software FIFO nodes.
++ - If any of the memory allocation fails,
++ releases the allocated
++ memory.
++ - Updates the software FIFO related structures
++ with the
++ reference values so that the FIFO can
++ be accessed by other
++ APIs
++
++ @param fifo_entries [@ref IN] The number of FIFO nodes
++ to be created.
++
++ @retval int
++ - >0 --> Creation successful.
++ - @ref IOH_CAN_NULL --> Creation failed.
++
++ @see
++ - ioh_candev_open
++
++ <hr>
++
++*/
++int create_can_fifo(unsigned int fifo_entries)
++{
++ unsigned int i;
++ struct can_fifo_item *curr;
++ struct can_fifo *f;
++ int retval;
++
++ /* Allocating the Main start node. */
++ f = (struct can_fifo *) CAN_MEM_ALLOC(sizeof(struct can_fifo));
++
++ if (f == NULL) {
++ IOH_LOG(KERN_ERR,
++ "create_can_fifo -> msg queue allocation failed.\n");
++ retval = (int) IOH_CAN_NULL;
++ } else {
++ /* Allocating the first node. */
++ f->head =
++ (struct can_fifo_item *) CAN_MEM_ALLOC(\
++ sizeof(struct can_fifo_item));
++
++ if ((f->head == NULL)) { /* Failed. */
++ CAN_MEM_FREE(f);
++ retval = (int) IOH_CAN_NULL;
++ } else {
++ /* Initially empty. */
++ f->tail = f->head;
++ curr = f->head;
++
++ /* Rest of the nod ecreation Node creation. */
++ for (i = 1; i <= fifo_entries; i++) {
++ curr->next =
++ (struct can_fifo_item *)
++ CAN_MEM_ALLOC(sizeof(struct can_fifo_item));
++
++ /* If allocation failed. */
++ if ((curr->next == NULL)) {
++ IOH_LOG(KERN_ERR,
++ "create_can_fifo -> \
++ Allocation failed.\n");
++ i = (i - 1);
++ /* Freeing the already allocated
++ nodes. */
++ while (i > 0) {
++ curr = f->head;
++ f->head = curr->next;
++ CAN_MEM_FREE(curr);
++
++ i--;
++ }
++
++ /* Freeing the main start node. */
++ CAN_MEM_FREE(f);
++ f = NULL;
++ retval =
++ (int) IOH_CAN_NULL;
++ break;
++ }
++
++ curr = curr->next;
++ }
++
++ if (NULL != f) {
++ /*Making it circular. */
++ curr->next = f->head;
++ f->size = fifo_entries;
++
++ retval = (int) f;
++ IOH_DEBUG("create_can_fifo sucessful.\n");
++ }
++ }
++ }
++
++ IOH_DEBUG("create_can_fifo returns %u.\n", retval);
++ return retval;
++}
++
++/*! @ingroup UtilitiesAPI
++ @fn void delete_can_fifo(int handle)
++ @brief Deletes the software FIFO.
++ @remarks Deletes the previously created software FIFO nodes.
++ The main task performed by this API is :
++ - Releases all the memory allocated for FIFO
++ nodes.
++
++ @param handle [@ref IN] The handle to the device.
++
++ @retval None.
++
++ @see
++ - ioh_candev_close
++
++ <hr>
++*/
++void delete_can_fifo(int handle)
++{
++ unsigned int i;
++ struct can_fifo_item *curr = NULL;
++ struct can_fifo_item *next = NULL;
++ struct can_fifo *f = (struct can_fifo *) handle;
++
++ if (handle != (int) 0) { /* valid handle */
++ curr = f->head;
++
++ if (f->head != NULL) {
++ next = curr->next;
++
++ /* Freeing individual node. */
++ for (i = 0; i < f->size; i++) {
++ CAN_MEM_FREE(curr);
++ curr = next;
++ next = (struct can_fifo_item *) curr->next;
++ }
++ }
++
++ /* Free the START node. */
++ CAN_MEM_FREE(f);
++ } else {
++ IOH_LOG(KERN_ERR, "delete_can_fifo -> Invalid handle.\n");
++ }
++
++ IOH_DEBUG("delete_can_fifo successful.\n");
++}
++
++/*! @ingroup UtilitiesAPI
++ @fn int read_can_fifo(
++ int handle,struct ioh_can_msg *msg)
++ @brief Reads data from the software FIFO.
++ @remarks Reads data from the software FIFO when read system call
++ is issued. The main tasks performed by this API
++ are :
++ - Reads the node from the FIFO under the Read
++ reference locator.
++ - Advances the Read reference locator to the
++ next node to be
++ read.
++
++ @param handle [@ref IN] The handle to the device.
++ @param msg [@ref OUT] Reference to the read
++ message.
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> Operation successful.
++ - @ref IOH_CAN_FAIL --> Operation failed.
++
++ @see
++ - ioh_can_read
++
++ <hr>
++*/
++int read_can_fifo(int handle, struct ioh_can_msg *msg)
++{
++ int i;
++ int retval = IOH_CAN_SUCCESS;
++ struct can_fifo *f = (struct can_fifo *) handle;
++ struct ioh_can_msg msg_tmp;
++
++ if ((handle == (int) 0) || (msg == NULL)) { /* invalid parameters.*/
++ IOH_LOG(KERN_ERR, "read_can_fifo -> Invalid parameter.\n");
++ retval = IOH_CAN_FAIL;
++ } else if (f->head == f->tail) { /* Buffer Empty */
++ IOH_DEBUG("read_can_fifo -> FIFO empty.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Accessing the msg object in the FIFO. */
++ msg_tmp = f->tail->msg;
++
++ /* Filling in the msg object. */
++ msg->ide = msg_tmp.ide;
++ msg->id = msg_tmp.id;
++ msg->dlc = msg_tmp.dlc;
++ msg->rtr = msg_tmp.rtr;
++
++ for (i = 0; i < IOH_CAN_MSG_DATA_LEN; i++)
++ msg->data[i] = msg_tmp.data[i];
++
++ /* Proceeding the FIFO read pointer. */
++ f->tail = f->tail->next;
++ IOH_DEBUG("read_can_fifo successful.\n");
++ }
++
++ IOH_DEBUG("read_can_fifo returns %d.\n", retval);
++ return retval;
++}
++
++/*! @ingroup UtilitiesAPI
++ @fn int write_can_fifo(
++ int handle,struct ioh_can_msg *msg)
++ @brief Write data to the software FIFO.
++ @remarks Write data to the software FIFO when a message is
++ received.
++ The main tasks performed by this API are :
++ - Writes the obtained data to the FIFO node
++ under the Write
++ Reference locator.
++ - Advances the Write reference locator to the
++ next node to be written.
++
++ @param handle [@ref IN] The handle to the device.
++ @param msg [@ref IN] Reference to the data
++ to be written
++
++ @retval int
++ - @ref IOH_CAN_SUCCESS --> Operation successful.
++ - @ref IOH_CAN_FAIL --> Operation failed.
++
++ @see
++ - ioh_can_callback
++
++ <hr>
++
++*/
++int write_can_fifo(int handle, struct ioh_can_msg *msg)
++{
++ int i;
++ int retval = IOH_CAN_SUCCESS;
++ struct can_fifo *f = (struct can_fifo *) handle;
++ struct ioh_can_msg *msg_tmp;
++
++ if ((handle == (int) 0) || (msg == NULL)) { /* invalid parameters.*/
++ IOH_LOG(KERN_ERR, "write_can_fifo -> Invalid parameters.\n");
++ retval = IOH_CAN_FAIL;
++ } else if (f->head->next == f->tail) {
++ IOH_DEBUG("write_can_fifo -> FIFO Full.\n");
++ retval = IOH_CAN_FAIL;
++ } else {
++ /* Accessing the write node in the FIFO */
++ msg_tmp = &(f->head->msg);
++
++ /* Filling in the FIFO node. */
++ msg_tmp->ide = msg->ide;
++ msg_tmp->rtr = msg->rtr;
++ msg_tmp->id = msg->id;
++ msg_tmp->dlc = msg->dlc;
++
++ for (i = 0; i < IOH_CAN_MSG_DATA_LEN; i++)
++ msg_tmp->data[i] = msg->data[i];
++
++ /* Proceeding the write node. */
++ f->head = f->head->next;
++ IOH_DEBUG("write_can_fifo successful.\n");
++ }
++
++ IOH_DEBUG("write_can_fifo returns %d.\n", retval);
++ return retval;
++}
+diff -urN linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_utils.h topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_utils.h
+--- linux-2.6.33-rc3/drivers/net/can/pch_can/pch_can_utils.h 1970-01-01 09:00:00.000000000 +0900
++++ topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_can_utils.h 2010-03-10 08:57:34.000000000 +0900
+@@ -0,0 +1,127 @@
++/*!
++ * @file ioh_can_utils.h
++ * @brief Provides the function prototype of the Utilis Layer APIs.
++ * @version 1.0
++ * @section
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * <hr>
++ */
++
++/*
++ * History:
++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
++ * All rights reserved.
++ *
++ * created:
++ * WIPRO 03/07/2009
++ * modified:
++ * WIPRO 05/08/2009
++ *
++ */
++
++#ifndef __IOH_CAN_FIFO_H__
++#define __IOH_CAN_FIFO_H__
++
++#include "pch_can_main.h"
++
++#define CAN_MEM_ALLOC(size) (kmalloc((size), GFP_KERNEL))
++#define CAN_MEM_FREE(ptr) (kfree((ptr)))
++
++/*! @ingroup Utilities
++ @def IOH_CAN_FIFO_NOT_EMPTY
++ @brief Flag value denoting that the software fifo is not empty.
++ @see
++ - check_can_fifo_status
++ - ioh_can_read
++
++ <hr>
++*/
++#define IOH_CAN_FIFO_NOT_EMPTY (0)
++
++/*! @ingroup Utilities
++ @def IOH_CAN_FIFO_EMPTY
++ @brief Flag value denoting that the software fifo is empty.
++ @see
++ - check_can_fifo_status
++ - ioh_can_read
++
++ <hr>
++*/
++#define IOH_CAN_FIFO_EMPTY (1)
++
++/*! @ingroup Utilities
++ @def IOH_CAN_FIFO_FULL
++ @brief Flag value denoting that the software fifo is full.
++ @see
++ - check_can_fifo_status
++ - ioh_can_read
++
++ <hr>
++*/
++#define IOH_CAN_FIFO_FULL (2)
++
++/*! @ingroup Utilities
++ @def IOH_CAN_NULL
++ @brief Denoting NULL value.
++
++ @see
++ - ioh_can_create
++ - create_can_fifo
++ <hr>
++*/
++#define IOH_CAN_NULL (NULL)
++
++/*! @ingroup UtilitiesAPI
++ @fn int check_can_fifo_status(int handle)
++ @brief Checks the status (Empty/Full/Non-Empty) of the software
++ fifo.
++
++ <hr>
++*/
++int check_can_fifo_status(int handle);
++
++/*! @ingroup UtilitiesAPI
++ @fn int create_can_fifo(unsigned int num_nodes)
++ @brief Creates the CAN FIFO.
++
++ <hr>
++*/
++int create_can_fifo(unsigned int num_nodes);
++
++/*! @ingroup UtilitiesAPI
++ @fn void delete_can_fifo(int handle)
++ @brief Deletes the software FIFO.
++
++ <hr>
++*/
++void delete_can_fifo(int handle);
++
++/*! @ingroup UtilitiesAPI
++ @fn int read_can_fifo(int handle, struct ioh_can_msg *msg)
++ @brief Reads data from the software FIFO.
++
++ <hr>
++*/
++int read_can_fifo(int handle, struct ioh_can_msg *msg);
++
++/*! @ingroup UtilitiesAPI
++ @fn int write_can_fifo(int handle, struct ioh_can_msg *msg)
++ @brief Write data to the software FIFO.
++
++ <hr>
++*/
++int write_can_fifo(int handle, struct ioh_can_msg *msg);
++
++#endif /* __IOH_CAN_FIFO_H__ */
+diff -urN linux-2.6.33-rc3/drivers/net/can/pch_can/pch_common.h topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_common.h
+--- linux-2.6.33-rc3/drivers/net/can/pch_can/pch_common.h 1970-01-01 09:00:00.000000000 +0900
++++ topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_common.h 2010-03-09 05:56:11.000000000 +0900
+@@ -0,0 +1,146 @@
++/*!
++ * @file ioh_common.h
++ * @brief Provides the macro definitions used by all files.
++ * @version 1.0.0.0
++ * @section
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/*
++ * History:
++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
++ * All rights reserved.
++ *
++ * created:
++ * WIPRO 03/07/2009
++ * modified:
++ * WIPRO 05/08/2009
++ *
++ */
++
++#ifndef __IOH_COMMON_H__
++#define __IOH_COMMON_H__
++
++/*! @ingroup Global
++@def IOH_WRITE8
++@brief Macro for writing 8 bit data to an io/mem address
++*/
++#define IOH_WRITE8(val, addr) iowrite8((val), (void __iomem *)(addr))
++/*! @ingroup Global
++@def IOH_LOG
++@brief Macro for writing 16 bit data to an io/mem address
++*/
++#define IOH_WRITE16(val, addr) iowrite16((val), (void __iomem *)(addr))
++/*! @ingroup Global
++@def IOH_LOG
++@brief Macro for writing 32 bit data to an io/mem address
++*/
++#define IOH_WRITE32(val, addr) iowrite32((val), (void __iomem *)(addr))
++
++/*! @ingroup Global
++@def IOH_READ8
++@brief Macro for reading 8 bit data from an io/mem address
++*/
++#define IOH_READ8(addr) ioread8((void __iomem *)(addr))
++/*! @ingroup Global
++@def IOH_READ16
++@brief Macro for reading 16 bit data from an io/mem address
++*/
++#define IOH_READ16(addr) ioread16((void __iomem *)(addr))
++/*! @ingroup Global
++@def IOH_READ32
++@brief Macro for reading 32 bit data from an io/mem address
++*/
++#define IOH_READ32(addr) ioread32((void __iomem *)(addr))
++/*! @ingroup Global
++@def IOH_WRITE32_F
++@brief Macro for writing 32 bit data to an io/mem address
++*/
++#define IOH_WRITE32_F(val, addr) do \
++ { IOH_WRITE32((val), (addr)); (void)IOH_READ32((addr)); } while (0);
++
++/*! @ingroup Global
++@def IOH_WRITE_BYTE
++@brief Macro for writing 1 byte data to an io/mem address
++*/
++#define IOH_WRITE_BYTE IOH_WRITE8
++/*! @ingroup Global
++@def IOH_WRITE_WORD
++@brief Macro for writing 1 word data to an io/mem address
++*/
++#define IOH_WRITE_WORD IOH_WRITE16
++/*! @ingroup Global
++@def IOH_WRITE_LONG
++@brief Macro for writing long data to an io/mem address
++*/
++#define IOH_WRITE_LONG IOH_WRITE32
++
++/*! @ingroup Global
++@def IOH_READ_BYTE
++@brief Macro for reading 1 byte data from an io/mem address
++*/
++#define IOH_READ_BYTE IOH_READ8
++/*! @ingroup Global
++@def IOH_READ_WORD
++@brief Macro for reading 1 word data from an io/mem address
++*/
++#define IOH_READ_WORD IOH_READ16
++/*! @ingroup Global
++@def IOH_READ_LONG
++@brief Macro for reading long data from an io/mem address
++*/
++#define IOH_READ_LONG IOH_READ32
++
++/* Bit Manipulation Macros */
++
++/*! @ingroup Global
++@def IOH_READ_LONG
++@brief macro to set a specified bit(mask) at the
++ specified address
++*/
++#define IOH_SET_ADDR_BIT(addr, bitmask) IOH_WRITE_LONG((IOH_READ_LONG(addr) |\
++ (bitmask)), (addr))
++
++/*! @ingroup Global
++@def IOH_READ_LONG
++@brief macro to clear a specified bit(mask) at the specified address
++*/
++#define IOH_CLR_ADDR_BIT(addr, bitmask) IOH_WRITE_LONG((IOH_READ_LONG(addr) &\
++ ~(bitmask)), (addr))
++
++/*! @ingroup Global
++@def IOH_READ_LONG
++@brief macro to set a specified bitmask for a variable
++*/
++#define IOH_SET_BITMSK(var, bitmask) ((var) |= (bitmask))
++
++/*! @ingroup Global
++@def IOH_READ_LONG
++@brief macro to clear a specified bitmask for a variable
++*/
++#define IOH_CLR_BITMSK(var, bitmask) ((var) &= (~(bitmask)))
++
++/*! @ingroup Global
++@def IOH_READ_LONG
++@brief macro to set a specified bit for a variable
++*/
++#define IOH_SET_BIT(var, bit) ((var) |= (1<<(bit)))
++
++/*! @ingroup Global
++@def IOH_READ_LONG
++@brief macro to clear a specified bit for a variable
++*/
++#define IOH_CLR_BIT(var, bit) ((var) &= ~(1<<(bit)))
++
++#endif
+diff -urN linux-2.6.33-rc3/drivers/net/can/pch_can/pch_debug.h topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_debug.h
+--- linux-2.6.33-rc3/drivers/net/can/pch_can/pch_debug.h 1970-01-01 09:00:00.000000000 +0900
++++ topcliff-2.6.33-rc3/drivers/net/can/pch_can/pch_debug.h 2010-03-09 05:37:47.000000000 +0900
+@@ -0,0 +1,60 @@
++/*!
++ * @file ioh_debug.h
++ * @brief Provides the macro definitions used for debugging.
++ * @version 1.0.0.0
++ * @section
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/*
++ * History:
++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
++ * All rights reserved.
++ *
++ * created:
++ * WIPRO 03/07/2009
++ * modified:
++ * WIPRO 05/08/2009
++ *
++ */
++
++#ifndef __IOH_DEBUG_H__
++#define __IOH_DEBUG_H__
++
++#ifdef MODULE
++#define IOH_LOG(level, fmt, args...) printk(level "%s:" fmt "\n",\
++ THIS_MODULE->name, ##args)
++#else
++#define IOH_LOG(level, fmt, args...) printk(level "%s:" fmt "\n" ,\
++ __FILE__, ##args)
++#endif
++
++
++#ifdef DEBUG
++ #define IOH_DEBUG(fmt, args...) IOH_LOG(KERN_DEBUG, fmt, ##args)
++#else
++ #define IOH_DEBUG(fmt, args...)
++#endif
++
++#ifdef IOH_TRACE_ENABLED
++ #define IOH_TRACE IOH_DEBUG
++#else
++ #define IOH_TRACE(fmt, args...)
++#endif
++
++#define IOH_TRACE_ENTER IOH_TRACE("Enter %s", __func__)
++#define IOH_TRACE_EXIT IOH_TRACE("Exit %s", __func__)
++
++
++#endif