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