Files
poky/meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-pch-can.patch

10766 lines
280 KiB
Diff

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