From 5e8c7c54a9b297dae0081dd19a7bb94e23040a3d Mon Sep 17 00:00:00 2001 From: Joshua Lock Date: Tue, 18 May 2010 14:51:13 +0100 Subject: linux-moblin: add 2.6.33.2 kernel from MeeGo 1.0 Signed-off-by: Joshua Lock --- .../linux-2.6.34-pch-can.patch | 10765 +++++++++++++++++++ 1 file changed, 10765 insertions(+) create mode 100644 meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-can.patch (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-can.patch') 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 +Subject: OKI Semiconductor PCH CAN driver + +This driver implements CAN controls for PCH. + +Signed-off-by: Masayuki Ohtake +Acked-by: Wang Qi + +--- + 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. ++ * ++ *
++ */ ++ ++/* ++ * History: ++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. ++ * All rights reserved. ++ * ++ * created: ++ * WIPRO 03/07/2009 ++ * modified: ++ * WIPRO 05/08/2009 ++ * ++ * ++ */ ++ ++/* includes */ ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ ++
++*/ ++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) ++ ++
++*/ ++static int ioh_can_rx_enable_all(int handle); ++ ++/*! @ingroup HALLayerAPI ++ @fn static int ioh_can_tx_enable_all(int handle) ++ ++
++*/ ++static int ioh_can_tx_enable_all(int handle); ++ ++/*! @ingroup HALLayerFacilitators ++ @var restartMode ++ @brief The variable used to store the restart mode. ++ ++
++*/ ++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. ++ ++
++*/ ++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 ++ ++
++*/ ++struct ioh_can_timing can_rec_timing[] = { ++ /* */ ++ /* 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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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
++ - Handle to the device --> Handle creation ++ successful. ++ - @ref IOH_CAN_NULL --> Handle creation failed. ++ ++ @see ++ - ioh_can_probe ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++ ++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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. ++ * ++ *
++ */ ++ ++/* ++ * 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. ++ ++
++*/ ++#define MAX_CAN_DEVICES (1) ++ ++/*! @ingroup HALLayer ++ @def MAX_BITRATE ++ @brief The maximum bitrate(Kbps) that can be programmed for the ++ CAN device. ++ ++
++*/ ++#define MAX_BITRATE (0x3e8) ++ ++/*! @ingroup HALLayer ++ @def NUM_NODES ++ @brief The maximum number of software FIFO nodes. ++ ++
++*/ ++#define NUM_NODES (2000) /* Maximum number of ++ Software FIFO nodes. */ ++ ++/*! @ingroup HALLayer ++ @def MAX_MSG_OBJ ++ @brief The maximum number of message objects available. ++ ++
++*/ ++#define MAX_MSG_OBJ (32) ++ ++/*! @ingroup HALLayer ++ @def MSG_OBJ_RX ++ @brief The receive message object flag. ++ ++
++*/ ++#define MSG_OBJ_RX (0) ++ ++/*! @ingroup HALLayer ++ @def MSG_OBJ_TX ++ @brief The transmit message object flag. ++ ++
++*/ ++#define MSG_OBJ_TX (1) ++ ++/*! @ingroup HALLayer ++ @def ENABLE ++ @brief The enable flag. ++ ++
++*/ ++#define ENABLE (1) ++ ++/*! @ingroup HALLayer ++ @def DISABLE ++ @brief The disable flag. ++ ++
++*/ ++#define DISABLE (0) ++ ++/* bit position of important controller bits. */ ++/*! @ingroup HALLayer ++ @def CAN_CTRL_INIT ++ @brief The INIT bit of CANCONT register. ++ ++
++*/ ++#define CAN_CTRL_INIT (0x0001) ++ ++/*! @ingroup HALLayer ++ @def CAN_CTRL_IE ++ @brief The IE bit of CANCONT register. ++ ++
++*/ ++#define CAN_CTRL_IE (0x0002) ++ ++/*! @ingroup HALLayer ++ @def CAN_CTRL_IE_SIE_EIE ++ @brief The IE + SIE + EIE bits of CANCONT register. ++ ++
++*/ ++#define CAN_CTRL_IE_SIE_EIE (0x000e) ++ ++/*! @ingroup HALLayer ++ @def CAN_CTRL_OPT ++ @brief The OPT bit of CANCONT register. ++ ++
++*/ ++#define CAN_CTRL_OPT (0x0080) ++ ++/*! @ingroup HALLayer ++ @def CAN_OPT_SILENT ++ @brief The Silent bit of CANOPT register. ++ ++
++*/ ++#define CAN_OPT_SILENT (0x0008) ++ ++/*! @ingroup HALLayer ++ @def CAN_CTRL_CCE ++ @brief The configuration change bit of CANCONT register. ++ ++
++*/ ++#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. ++ ++
++*/ ++#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. ++ ++
++*/ ++#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. ++ ++
++*/ ++#define CAN_CMASK_ALL (0xff) ++ ++/*! @ingroup HALLayer ++ @def CAN_CMASK_RDWR ++ @brief The RD/WR bit of the CMASK register. ++ ++
++*/ ++#define CAN_CMASK_RDWR (0x80) ++ ++/*! @ingroup HALLayer ++ @def CAN_CMASK_ARB ++ @brief The ARB bit of the CMASK register. ++ ++
++*/ ++#define CAN_CMASK_ARB (0x20) ++ ++/*! @ingroup HALLayer ++ @def CAN_CMASK_CTRL ++ @brief The CTRL bit of the CMASK register. ++ ++
++*/ ++#define CAN_CMASK_CTRL (0x10) ++ ++/*! @ingroup HALLayer ++ @def CAN_CMASK_MASK ++ @brief The MASK bit of the CMASK register. ++ ++
++*/ ++#define CAN_CMASK_MASK (0x40) ++ ++/*! @ingroup HALLayer ++ @def CAN_CMASK_CLPNT ++ @brief The ClrintPnd bit of the CMASK register. ++ ++
++*/ ++#define CAN_CMASK_CLPNT (0x08) ++ ++/*! @ingroup HALLayer ++ @def CAN_CMASK_NEWINT ++ @brief The TxRqst/NewDat bit for the CMASK register. ++ ++
++*/ ++#define CAN_CMASK_NEWINT (0x04) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF_MCONT_NEWDAT ++ @brief The NewDat bit of the MCONT register. ++ ++
++*/ ++#define CAN_IF_MCONT_NEWDAT (0x8000) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF_MCONT_INTPND ++ @brief The IntPnd bit of the MCONT register. ++ ++
++*/ ++#define CAN_IF_MCONT_INTPND (0x2000) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF_MCONT_UMASK ++ @brief The UMask bit of the MCONT register. ++ ++
++*/ ++#define CAN_IF_MCONT_UMASK (0x1000) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF_MCONT_TXIE ++ @brief The TxIE bit of the MCONT register. ++ ++
++*/ ++#define CAN_IF_MCONT_TXIE (0x0800) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF_MCONT_RXIE ++ @brief The RxIE bit of the MCONT register. ++ ++
++*/ ++#define CAN_IF_MCONT_RXIE (0x0400) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF_MCONT_RMTEN ++ @brief The RmtEn bit of the MCONT register. ++ ++
++*/ ++#define CAN_IF_MCONT_RMTEN (0x0200) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF_MCONT_TXRQXT ++ @brief The TxRqst bit of the MCONT register. ++ ++
++*/ ++#define CAN_IF_MCONT_TXRQXT (0x0100) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF_MCONT_EOB ++ @brief The E0B bit of the MCONT register. ++ ++
++*/ ++#define CAN_IF_MCONT_EOB (0x0080) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF_MCONT_MSGLOST ++ @brief The MsgLst bit of the MCONT register. ++ ++
++*/ ++#define CAN_IF_MCONT_MSGLOST (0x4000) ++ ++/*! @ingroup HALLayer ++ @def CAN_MASK2_MDIR_MXTD ++ @brief The MXtd and Mdir bit of the MASK2 register. ++ ++
++*/ ++#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. ++ ++
++*/ ++#define CAN_ID2_MSGVAL_XTD_DIR (0xe000) ++ ++/*! @ingroup HALLayer ++ @def CAN_ID2_MSGVAL_DIR ++ @brief The MsgVal and Dir bits of the ID2 register. ++ ++
++*/ ++#define CAN_ID2_MSGVAL_DIR (0xa000) ++ ++/*! @ingroup HALLayer ++ @def CAN_ID2_DIR ++ @brief The Dir bit of the ID2 register. ++ ++
++*/ ++#define CAN_ID2_DIR (0x2000) ++ ++/*! @ingroup HALLayer ++ @def CAN_ID_MSGVAL ++ @brief The MsgVal bit of the ID2 register. ++ ++
++*/ ++#define CAN_ID_MSGVAL (0x8000) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF_MASK2_MDIR ++ @brief The MDir bit of the MASK2 register. ++ ++
++*/ ++#define CAN_IF_MASK2_MDIR ((u32)1 << 14) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF_MASK2_MXTD ++ @brief The MXtd bit of the MASK2 register. ++ ++
++*/ ++#define CAN_IF_MASK2_MXTD ((u32)1 << 15) ++ ++/*! @ingroup HALLayer ++ @def CAN_STATUS_INT ++ @brief The status interrupt value of the CAN device. ++ ++
++*/ ++#define CAN_STATUS_INT (0x8000) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF_CREQ_BUSY ++ @brief The Busy flag bit of the CREQ register. ++ ++
++*/ ++#define CAN_IF_CREQ_BUSY (0x8000) ++ ++/*! @ingroup HALLayer ++ @def CAN_ID2_XTD ++ @brief The Xtd bit of ID2 register. ++ ++
++*/ ++#define CAN_ID2_XTD (0x4000) ++ ++/*! @ingroup HALLayer ++ @def CAN_SRST_BIT ++ @brief The SRST bit of the Soft reset register. ++ ++
++*/ ++#define CAN_SRST_BIT (0x0001) ++ ++/* CAN register offset */ ++ /* CAN registers */ ++/*! @ingroup HALLayer ++ @def CAN_CONT_OFFSET ++ @brief The offset of CAN control register ++ ++
++*/ ++#define CAN_CONT_OFFSET (0x00) /*Can Control register */ ++ ++/*! @ingroup HALLayer ++ @def CAN_STAT_OFFSET ++ @brief The offset of CAN status register. ++ ++
++*/ ++#define CAN_STAT_OFFSET (0x04) ++ ++/*! @ingroup HALLayer ++ @def CAN_ERRC_OFFSET ++ @brief The offset of CAN Error counter register ++ ++
++*/ ++#define CAN_ERRC_OFFSET (0x08) ++ ++/*! @ingroup HALLayer ++ @def CAN_BITT_OFFSET ++ @brief The offset of CAN timing register. ++ ++
++*/ ++#define CAN_BITT_OFFSET (0x0c) ++ ++/*! @ingroup HALLayer ++ @def CAN_INT_OFFSET ++ @brief The offset of CAN interrupt register. ++ ++
++*/ ++#define CAN_INT_OFFSET (0x010) ++ ++/*! @ingroup HALLayer ++ @def CAN_OPT_OFFSET ++ @brief The offset of CAN Option register ++ ++
++*/ ++#define CAN_OPT_OFFSET (0x14) /*Extended function register */ ++ ++/*! @ingroup HALLayer ++ @def CAN_BRPE_OFFSET ++ @brief The offset of BRPE register. ++ ++
++*/ ++#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. ++ ++
++*/ ++#define CAN_IF1_CREQ_OFFSET (0x020) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF1_CMASK_OFFSET ++ @brief The offset of IF1 Command Mask register. ++ ++
++*/ ++#define CAN_IF1_CMASK_OFFSET (0x024) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF1_ID1_OFFSET ++ @brief The offset of IF1 ID1 register. ++ ++
++*/ ++#define CAN_IF1_ID1_OFFSET (0x030) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF1_ID2_OFFSET ++ @brief The offset of IF1 ID2 register. ++ ++
++*/ ++#define CAN_IF1_ID2_OFFSET (0x034) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF1_MCONT_OFFSET ++ @brief The offset of IF1 Message control register. ++ ++
++*/ ++#define CAN_IF1_MCONT_OFFSET (0x038) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF1_DATAA1_OFFSET ++ @brief The offset of IF1 DATAA1 register. ++ ++
++*/ ++#define CAN_IF1_DATAA1_OFFSET (0x03C) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF1_DATAA2_OFFSET ++ @brief The offset of IF1 DATAA2 register. ++ ++
++*/ ++#define CAN_IF1_DATAA2_OFFSET (0x040) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF1_DATAB1_OFFSET ++ @brief The offset of IF1 DATAB1 register. ++ ++
++*/ ++#define CAN_IF1_DATAB1_OFFSET (0x044) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF1_DATAB2_OFFSET ++ @brief The offset of IF1 DATAB2 register. ++ ++
++*/ ++#define CAN_IF1_DATAB2_OFFSET (0x048) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF1_MASK1_OFFSET ++ @brief The offset of IF1 MASK1 register. ++ ++
++*/ ++#define CAN_IF1_MASK1_OFFSET (0x028) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF1_MASK2_OFFSET ++ @brief The offset of IF1 MASK2 register. ++ ++
++*/ ++#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. ++ ++
++*/ ++#define CAN_IF2_CREQ_OFFSET (0x080) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF2_CMASK_OFFSET ++ @brief The offset of IF2 Command mask register. ++ ++
++*/ ++#define CAN_IF2_CMASK_OFFSET (0x084) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF2_ID1_OFFSET ++ @brief The offset of IF2 ID1 register. ++ ++
++*/ ++#define CAN_IF2_ID1_OFFSET (0x090) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF2_ID2_OFFSET ++ @brief The offset of IF2 ID2 register. ++ ++
++*/ ++#define CAN_IF2_ID2_OFFSET (0x094) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF2_MCONT_OFFSET ++ @brief The offset of IF2 Message control register. ++ ++
++*/ ++#define CAN_IF2_MCONT_OFFSET (0x098) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF2_DATAA1_OFFSET ++ @brief The offset of IF2 DATAA1 register. ++ ++
++*/ ++#define CAN_IF2_DATAA1_OFFSET (0x09c) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF2_DATAA2_OFFSET ++ @brief The offset of IF2 DATAA2 register. ++ ++
++*/ ++#define CAN_IF2_DATAA2_OFFSET (0x0a0) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF2_DATAB1_OFFSET ++ @brief The offset of IF2 DATAB1 register. ++ ++
++*/ ++#define CAN_IF2_DATAB1_OFFSET (0x0a4) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF2_DATAB2_OFFSET ++ @brief The offset of IF2 DATAB2 register. ++ ++
++*/ ++#define CAN_IF2_DATAB2_OFFSET (0x0a8) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF2_MASK1_OFFSET ++ @brief The offset of IF2 MASK1 register. ++ ++
++*/ ++#define CAN_IF2_MASK1_OFFSET (0x088) ++ ++/*! @ingroup HALLayer ++ @def CAN_IF2_MASK2_OFFSET ++ @brief The offset of IF2 MASK2 register. ++ ++
++*/ ++#define CAN_IF2_MASK2_OFFSET (0x08c) ++ ++ /* Transmission request registers */ ++/*! @ingroup HALLayer ++ @def CAN_TREQ1_OFFSET ++ @brief The offset of the CAN Transmission request register1. ++ ++
++*/ ++#define CAN_TREQ1_OFFSET (0x100) ++ ++/*! @ingroup HALLayer ++ @def CAN_TREQ2_OFFSET ++ @brief The offset of the CAN Transmission request register2. ++ ++
++*/ ++#define CAN_TREQ2_OFFSET (0x104) ++ ++ /* Soft Reset register. */ ++/*! @ingroup HALLayer ++ @def CAN_SRST_OFFSET ++ @brief The offset of the CAN Soft reset register. ++ ++
++*/ ++#define CAN_SRST_OFFSET (0x1FC) ++ ++ /* macros for shift operations. */ ++/*! @ingroup HALLayer ++ @def BIT_SHIFT_ONE ++ @brief Bit shift by one. ++ ++
++*/ ++#define BIT_SHIFT_ONE (1) ++ ++/*! @ingroup HALLayer ++ @def BIT_SHIFT_TWO ++ @brief Bit shift by two. ++ ++
++*/ ++#define BIT_SHIFT_TWO (2) ++ ++/*! @ingroup HALLayer ++ @def BIT_SHIFT_THREE ++ @brief Bit shift by three. ++ ++
++*/ ++#define BIT_SHIFT_THREE (3) ++ ++/*! @ingroup HALLayer ++ @def BIT_SHIFT_FOUR ++ @brief Bit shift by four. ++ ++
++*/ ++#define BIT_SHIFT_FOUR (4) ++ ++/*! @ingroup HALLayer ++ @def BIT_SHIFT_FIVE ++ @brief Bit shift by five. ++ ++
++*/ ++#define BIT_SHIFT_FIVE (5) ++ ++/*! @ingroup HALLayer ++ @def BIT_SHIFT_SIX ++ @brief Bit shift by six. ++ ++
++*/ ++#define BIT_SHIFT_SIX (6) ++ ++/*! @ingroup HALLayer ++ @def BIT_SHIFT_SEVEN ++ @brief Bit shift by seven. ++ ++
++*/ ++#define BIT_SHIFT_SEVEN (7) ++ ++/*! @ingroup HALLayer ++ @def BIT_SHIFT_EIGHT ++ @brief Bit shift by eight. ++ ++
++*/ ++#define BIT_SHIFT_EIGHT (8) ++ ++/*! @ingroup HALLayer ++ @def BIT_SHIFT_TWELVE ++ @brief Bit shift by twelve. ++ ++
++*/ ++#define BIT_SHIFT_TWELVE (12) ++ ++/*! @ingroup HALLayer ++ @def BIT_SHIFT_THIRTEEN ++ @brief Bit shift by thirteen. ++ ++
++*/ ++#define BIT_SHIFT_THIRTEEN (13) ++ ++/*! @ingroup HALLayer ++ @def BIT_SHIFT_FOURTEEN ++ @brief Bit shift by fourteen. ++ ++
++*/ ++#define BIT_SHIFT_FOURTEEN (14) ++ ++/*! @ingroup HALLayer ++ @def BIT_SHIFT_FIFTEEN ++ @brief Bit shift by fifteen. ++ ++
++*/ ++#define BIT_SHIFT_FIFTEEN (15) ++ ++/*! @ingroup HALLayer ++ @def BIT_SHIFT_SIXTEEN ++ @brief Bit shift by sixteen. ++ ++
++*/ ++#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. ++ ++
++*/ ++#define BIT_BITT_BRP (0) ++ ++/*! @ingroup HALLayer ++ @def BIT_BITT_SJW ++ @brief The SJW start bit position of the CANBITT register. ++ ++
++*/ ++#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. ++ ++
++*/ ++#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. ++ ++
++*/ ++#define BIT_BITT_TSEG2 (12) ++ ++/*! @ingroup HALLayer ++ @def BIT_IF1_MCONT_RXIE ++ @brief The RxIE bit position of the MCONT register. ++ ++
++*/ ++#define BIT_IF1_MCONT_RXIE (10) ++ ++/*! @ingroup HALLayer ++ @def BIT_IF2_MCONT_TXIE ++ @brief The TxIE bit position of the MCONT register. ++ ++
++*/ ++#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. ++ ++
++*/ ++#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. ++ ++
++*/ ++#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. ++ ++
++*/ ++#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. ++ ++
++*/ ++#define MSK_BITT_BRP (0x3f) ++ ++/*! @ingroup HALLayer ++ @def MSK_BITT_SJW ++ @brief The mask value for SJW bits. ++ ++
++*/ ++#define MSK_BITT_SJW (0xc0) ++ ++/*! @ingroup HALLayer ++ @def MSK_BITT_TSEG1 ++ @brief The mask value for time segment bits (before a sampling ++ point). ++ ++
++*/ ++#define MSK_BITT_TSEG1 (0xf00) ++ ++/*! @ingroup HALLayer ++ @def MSK_BITT_TSEG2 ++ @brief The mask value for time segment bits (after a sampling ++ point) ++ ++
++*/ ++#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. ++ ++
++*/ ++#define MSK_BRPE_BRPE (0x3c0) ++ ++/*! @ingroup HALLayer ++ @def MSK_BRPE_GET ++ @brief The mask for Baud Rate prescalar bits of CANBRPE ++ register. ++ ++
++*/ ++#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. ++ ++
++*/ ++#define MSK_CTRL_IE_SIE_EIE (0x07) ++ ++/*! @ingroup HALLayer ++ @def MSK_MCONT_TXIE ++ @brief The Mask value for TxIE bit of the MCONT register. ++ ++
++*/ ++#define MSK_MCONT_TXIE (0x08) ++ ++/*! @ingroup HALLayer ++ @def MSK_MCONT_RXIE ++ @brief The Mask value for RxIE bit of the MCONT register. ++ ++
++*/ ++#define MSK_MCONT_RXIE (0x10) ++ ++/*! @ingroup HALLayer ++ @def MSK_ALL_THREE ++ @brief The mask value for the first three bits of any register. ++ ++
++*/ ++#define MSK_ALL_THREE (0x07) ++ ++/*! @ingroup HALLayer ++ @def MSK_ALL_FOUR ++ @brief The mask value for the first four bits of any register. ++ ++
++*/ ++#define MSK_ALL_FOUR (0x0f) ++ ++/*! @ingroup HALLayer ++ @def MSK_ALL_EIGHT ++ @brief The mask value for the first eight bits of any register. ++ ++
++*/ ++#define MSK_ALL_EIGHT (0xff) ++ ++/*! @ingroup HALLayer ++ @def MSK_ALL_ELEVEN ++ @brief The mask value for the first eleven bits of any ++ register. ++ ++
++*/ ++#define MSK_ALL_ELEVEN (0x7ff) ++ ++/*! @ingroup HALLayer ++ @def MSK_ALL_THIRTEEN ++ @brief The mask value for the first thirteen bits of any ++ register. ++ ++
++*/ ++#define MSK_ALL_THIRTEEN (0x1fff) ++ ++/*! @ingroup HALLayer ++ @def MSK_ALL_SIXTEEN ++ @brief The mask value for the first sixteen bits of any ++ register. ++ ++
++*/ ++#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. ++ ++
++*/ ++#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. ++ ++
++*/ ++#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 ++ ++
++*/ ++#define IOH_CAN_NO_TX_BUFF (1) ++ ++/*! @ingroup HALLayer ++ @def ERROR_COUNT ++ @brief The maximum error counter value. ++ ++ @see ++ - ioh_can_get_error_stats ++ ++
++*/ ++#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. ++ ++
++*/ ++ ++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) ++ ++
++*/ ++int ioh_can_create(u8 *io_base); ++ ++/*! @ingroup HALlayerAPI ++ @fn void ioh_can_destroy(int handle ++ ++
++*/ ++void ioh_can_destroy(int handle); ++ ++/*! @ingroup HALlayerAPI ++ @fn int ioh_can_set_run_mode( ++ int handle,enum ioh_can_run_mode mode) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++int ioh_can_int_pending(int handle); ++ ++/*! @ingroup HALlayerAPI ++ @fn void ioh_can_int_clr( ++ int handle,u32 mask) ++ ++
++*/ ++void ioh_can_int_clr(int handle, u32 mask); ++ ++/*! @ingroup HALlayerAPI ++ @fn int ioh_can_clear_buffers( ++ int handle) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++int ioh_can_get_int_enables(int handle, u32 *enables); ++ ++/*! @ingroup HALlayerAPI ++ @fn int ioh_can_release(int handle) ++ ++
++*/ ++int ioh_can_release(int handle); ++ ++/*! @ingroup HALlayerAPI ++ @fn int ioh_can_set_rx_buffer_link( ++ int handle,u32 buffer_num,u32 set) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++int ioh_can_get_buffer_status(int handle); ++ ++/*! @ingroup HALlayerAPI ++ @fn int ioh_can_rx_init_filter( ++ int handle,u32 buff_num) ++ ++
++*/ ++int ioh_can_rx_init_filter(int handle, u32 buff_num); ++ ++/*! @ingroup HALlayerAPI ++ @fn int ioh_can_rx_disable_all( ++ int handle) ++ ++
++*/ ++int ioh_can_rx_disable_all(int handle); ++ ++/*! @ingroup HALlayerAPI ++ @fn int ioh_can_tx_disable_all( ++ int handle) ++ ++
++*/ ++int ioh_can_tx_disable_all(int handle); ++ ++/*! @ingroup HALlayerAPI ++ @fn int ioh_can_set_rx_enable( ++ int handle,u32 buff_num,u32 set) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++irqreturn_t ioh_can_handler(int irq, void *dev_id); ++ ++/*! @ingroup HALlayerAPI ++ @fn void icp_can_log_message(u32 status) ++ ++
++*/ ++void icp_can_log_message(u32 status); ++ ++/*! @ingroup HALlayerAPI ++ @fn int ioh_can_reset(struct ioh_can_os *can_os) ++ ++
++*/ ++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) ++ ++
++*/ ++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) ++ ++
++*/ ++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. ++ * ++ *
++ */ ++ ++/* ++ * History: ++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. ++ * All rights reserved. ++ * ++ * created: ++ * WIPRO 03/07/2009 ++ * modified: ++ * WIPRO 05/08/2009 ++ * ++ */ ++ ++/* includes */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ ++
++*/ ++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. ++ ++
++*/ ++#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. ++ ++
++*/ ++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. ++ ++
++ ++*/ ++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. ++ ++
++*/ ++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. ++ ++
++*/ ++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. ++ ++
++*/ ++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. ++ ++
++*/ ++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 ++ ++
++*/ ++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. ++ * ++ *
++ */ ++ ++/* ++ * 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. ++ ++
++*/ ++ ++/*! @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. ++ ++
++*/ ++/*! @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. ++ ++
++*/ ++/*! @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. ++ ++
++*/ ++/*! @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. ++ ++
++*/ ++/*! @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. ++ ++
++*/ ++ ++/*! @defgroup PCILayerAPI ++ @ingroup PCILayer ++ @brief This group contains the API(functions) used as the PCI ++ interface between the Kernel subsystem and the ++ module. ++ ++
++*/ ++ ++/*! @defgroup PCILayerFacilitators ++ @ingroup PCILayer ++ @brief This group contains the data structures used by the PCI ++ Layer APIs for their functionalities. ++ ++
++*/ ++ ++/*! @defgroup InterfaceLayerAPI ++ @ingroup InterfaceLayer ++ @brief This group contains the API(functions) used as the ++ Driver ++ interface between the Kernel subsystem and the ++ module. ++ ++
++*/ ++/*! @defgroup InterfaceLayerFacilitators ++ @ingroup InterfaceLayer ++ @brief This group contains the data structures used by the ++ Driver ++ interface APIs for their functionalities. ++ ++
++*/ ++ ++/*! @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. ++ ++
++*/ ++ ++/*! @defgroup UtilitiesAPI ++ @ingroup Utilities ++ @brief This group contains the APIs(functions) used by other ++ functions ++ in their operations. ++ ++
++*/ ++ ++/*! @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 ++ ++
++*/ ++#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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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. ++ ++
++*/ ++#define MAGIC (0x88) ++ ++/*! @ingroup InterfaceLayer ++ @def IOCTL_CAN_RESET ++ @brief The IOCTL command for CAN reset. ++ ++ @see ++ - ioh_can_ioctl ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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. ++ ++
++*/ ++#define IOH_CAN_SUCCESS (0) /* CAN success return value. */ ++ ++/*! @ingroup InterfaceLayer ++ @def IOH_CAN_FAIL ++ @brief The value returned by certain functions on failure. ++ ++
++*/ ++#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. ++ * ++ *
++ */ ++ ++/* ++ * History: ++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. ++ * All rights reserved. ++ * ++ * created: ++ * WIPRO 03/07/2009 ++ * modified: ++ * WIPRO 05/08/2009 ++ * ++ */ ++ ++/* includes */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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. ++ ++
++ */ ++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. ++ ++
++ */ ++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 ++ ++
++ */ ++#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 ++ ++
++*/ ++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. ++ ++
++*/ ++#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. ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++
++*/ ++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 ++
++*/ ++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. ++
++*/ ++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. ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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. ++ ++
++*/ ++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. ++ * ++ *
++ */ ++ ++/* ++ * 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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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. ++ * ++ *
++ */ ++ ++/* ++ * History: ++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. ++ * All rights reserved. ++ * ++ * created: ++ * WIPRO 03/07/2009 ++ * modified: ++ * WIPRO 05/08/2009 ++ * ++ */ ++ ++/* includes */ ++#include ++#include ++#include ++ ++#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. ++ ++
++*/ ++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. ++ ++
++*/ ++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 ++ ++
++ ++*/ ++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 ++ ++
++ ++*/ ++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 ++ ++
++*/ ++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 ++ ++
++*/ ++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 ++ ++
++ ++*/ ++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. ++ * ++ *
++ */ ++ ++/* ++ * 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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#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 ++ ++
++*/ ++#define IOH_CAN_FIFO_FULL (2) ++ ++/*! @ingroup Utilities ++ @def IOH_CAN_NULL ++ @brief Denoting NULL value. ++ ++ @see ++ - ioh_can_create ++ - create_can_fifo ++
++*/ ++#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. ++ ++
++*/ ++int check_can_fifo_status(int handle); ++ ++/*! @ingroup UtilitiesAPI ++ @fn int create_can_fifo(unsigned int num_nodes) ++ @brief Creates the CAN FIFO. ++ ++
++*/ ++int create_can_fifo(unsigned int num_nodes); ++ ++/*! @ingroup UtilitiesAPI ++ @fn void delete_can_fifo(int handle) ++ @brief Deletes the software FIFO. ++ ++
++*/ ++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. ++ ++
++*/ ++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. ++ ++
++*/ ++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 -- cgit v1.2.3