mirror of
https://git.yoctoproject.org/poky
synced 2026-02-24 18:39:40 +01:00
10766 lines
280 KiB
Diff
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
|